contrib/bsddialog: Import version 0.3

New features overview:
 * Unicode. User interface handles multi-column characters. API can
   handle char* like a multibyte character string. Internally wide
   characters are used for keyboard input, to adapt word wrapping and
   dynamic text auto-sizing for multi-column characters.
 * Forms refactoring. Complete rewrite deleting libformw dependency.
 * Theme. New utility options to save and load custom theme at run-time.
 * TUI navigation. Added keys to navigate input components. Changed
   default focus behavior of input dialogs to be LGPL-dialog-like; a new
   option can set the previous whiptail-like behavior.

See /usr/src/contrib/bsddialog/CHANGELOG '2022-08-29 Version 0.3'
for more detailed information.

Merge commit '2c9fd7655ba54e7239f528e1af9fe09662de9b03'
This commit is contained in:
Alfonso S. Siciliano 2022-09-03 16:40:21 +02:00
commit b319d93437
No known key found for this signature in database
GPG Key ID: 3F9EEFACFD371E37
34 changed files with 2670 additions and 1164 deletions

View File

@ -7,6 +7,7 @@ examples_library/checklist
examples_library/datebox examples_library/datebox
examples_library/form examples_library/form
examples_library/formw examples_library/formw
examples_library/margin
examples_library/menu examples_library/menu
examples_library/mixedlist examples_library/mixedlist
examples_library/radiolist examples_library/radiolist
@ -19,6 +20,7 @@ examples_library/rangebox
examples_library/sade examples_library/sade
examples_library/timebox examples_library/timebox
examples_library/yesno examples_library/yesno
examples_library/u_msgbox
*.gz *.gz
lib/libbsddialog.so* lib/libbsddialog.so*
BSDDIALOG.geany BSDDIALOG.geany

View File

@ -1,4 +1,77 @@
2022-03-02 version 0.2 2022-08-29 Version 0.3
Utility:
* add: --textbox accepts options for the first button.
* add: --columns-per-row option for text autosizing.
* add: --load-theme option to read and set a custom theme at runtime.
* add: --save-theme option to save current theme.
* add: --bikeshed option for random settings.
* add: --switch-buttons enables focus switching: buttons / input
components. Available for: --form, --inputbox, --mixedform,
--passwordform, --passwordbox, --timebox and --datebox.
* change: rename --esc-cancelvalue to --esc-return-cancel.
* change: form field value is printed like multibyte charachter string,
previously widechar string.
* fix: --hline with empty string.
* fix: avoid to overlay the backtitle by setting a top margin.
* fix: avoid to overlay down shadow with menus and forms bottomdesc
by setting a down margin.
* fix: --form read-only flag with multiple fields.
Library:
* add: conf.auto_topmargin and conf.auto_downmargin.
* add: bsddialog_textbox() accepts conf.button.* for the first button.
* add: bsddialog_textbox() arrows and percentage.
* add: conf.text.cols_per_row to set a ratio for text autosizing.
* add: timebox and datebox arrows and focus background for boxes.
* add: timebox and datebox UP key to switch focus.
* add: bsddialog_init_notheme() in bsddialo_theme.h.
* add: bsddialog_hascolors() in bsddialo_theme.h.
* add: theme.form.bottomdesccolor and theme.menu.bottomdesccolor.
* add: conf.button.always_active to disable buttons/input-boxes switch.
* add: dynamic buttons margin.
- add: theme.button.minmargin and theme.button.maxmargin.
- delete: theme.button.hmargin.
* add: Unicode.
- UI handles multicolumn charachters: backtitle, title,
text (word wrapping, autosizing), menus (shortcuts, name, desc),
forms (label, field), textbox, mixedgauge (minilabel),
buttons (label, shortcuts), bottomtitle.
- API handles char* arguments like multibyte charachter string,
depending on the current locale.
- Internally wide charachters are used to get input from keyboard
and to adapt word wrapping and dynamic text autosizing to
muticolumn charachters.
* refactoring: (rewrite) form.c.
- delete: libformw dep implementing its features from scratch.
- delete: maxvaluelen >= valuelen constraint.
- delete: conf.form.enable_wchar, get always unicode (wchar) input.
- add: KEY_HOME, KEY_END, KEY_PPAGE, KEY_NPAGE keys in field.
- add: KEY_UP can move focus from buttons to fields.
- add: KEY_DOWN can move focus from item to buttons, if nitem is 1.
- add: conf.form.securembch secure multibyte charachter.
- add: BSDDIALOG_FIELDNOCOLOR for formitem.flags.
- add: BSDDIALOG_FIELDCURSOREND for formitem.flags.
- add: BSDDIALOG_FIELDEXTEND for formitem.flags.
- add: BSDDIALOG_FIELDSINGLEBYTE for formitem.flags.
- add: resizing and refresh after KEY_RESIZE (SIGWINCH).
- add: items scrolling.
- add: conf.form.value_wchar, value is wchar_t* instead of MB-char*.
- add: formheight autosizing.
- add: dynamic item position.
* fix: bsddialog_gauge() with fd < 0.
* fix: internal segmentation fault with disabled shadow.
* fix: bsddialog_gauge() refresh new text.
* fix: center position without shadow.
* fix: bsddialog_infobox() with zero text length.
* fix: text wrapping with more than 1024 words.
* fix: rename theme.shadow.h to theme.shadow.y.
* fix: rename theme.shadow.w to theme.shadow.x.
* fix: menurows autosize with fixed rows improving text_size().
* fix: messagebox.c scrolling and checksize without text.
2022-03-02 Version 0.2
Utility: Utility:
* add: (this) CHANGELOG. * add: (this) CHANGELOG.
@ -31,7 +104,7 @@
* improve: "menus" colors for accessibility. * improve: "menus" colors for accessibility.
2022-01-27 version 0.1 2022-01-27 Version 0.1
* Common-Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>, * Common-Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>,
--begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap, --begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap,

View File

@ -4,7 +4,7 @@
# Written in 2021 by Alfonso Sabato Siciliano # Written in 2021 by Alfonso Sabato Siciliano
OUTPUT= bsddialog OUTPUT= bsddialog
SOURCES= bsddialog.c SOURCES= bsddialog.c util_theme.c
OBJECTS= $(SOURCES:.c=.o) OBJECTS= $(SOURCES:.c=.o)
LIBPATH= ./lib LIBPATH= ./lib
LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so

View File

@ -4,7 +4,7 @@
# Written in 2021 by Alfonso Sabato Siciliano # Written in 2021 by Alfonso Sabato Siciliano
OUTPUT= bsddialog OUTPUT= bsddialog
SOURCES= bsddialog.c SOURCES= bsddialog.c util_theme.c
OBJECTS= ${SOURCES:.c=.o} OBJECTS= ${SOURCES:.c=.o}
LIBPATH= ${.CURDIR}/lib LIBPATH= ${.CURDIR}/lib
LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so

View File

@ -1,14 +1,13 @@
# BSDDialog 0.2 # BSDDialog 0.3
This project provides **bsddialog** and **libbsddialog**, an utility
This project provides **bsddialog** and **libbsddialog**, an utility and a and a library to build scripts and tools with TUI dialogs and widgets.
library to build scripts and tools with TUI dialogs and widgets.
## Intro ## Intro
Briefly: Briefly:
<https://www.freebsd.org/status/report-2021-04-2021-06/#_bsddialog_tui_widgets> <https://www.freebsd.org/status/report-2021-04-2021-06/bsddialog/>
Utility: Utility:
<https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html> <https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html>
@ -31,6 +30,15 @@ FreeBSD:
% ./bsddialog --msgbox "Hello World!" 8 20 % ./bsddialog --msgbox "Hello World!" 8 20
``` ```
Linux:
```
% git clone https://gitlab.com/alfix/bsddialog.git
% cd bsddialog
% make -f GNUMakefile
% ./bsddialog --msgbox "Hello World!" 8 20
```
Output: Output:
![screenshot](screenshot.png) ![screenshot](screenshot.png)
@ -101,6 +109,7 @@ in the _Public Domain_ to build new projects:
``` ```
% cd examples_library % cd examples_library
% sh compile % sh compile
% ./checklist
% ./datebox % ./datebox
% ./form % ./form
% ./infobox % ./infobox
@ -114,4 +123,10 @@ in the _Public Domain_ to build new projects:
% ./timebox % ./timebox
% ./yesno % ./yesno
``` ```
## TODO and Ideas
- menubar feature
- key callback
- Right-To-Left text

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd February 3, 2022 .Dd August 29, 2022
.Dt BSDDIALOG 1 .Dt BSDDIALOG 1
.Os .Os
.Sh NAME .Sh NAME
@ -74,6 +74,13 @@ Title on the top side of the screen.
Dialog horizontal position, 0 is the left screen side, -1 center. Dialog horizontal position, 0 is the left screen side, -1 center.
.It Fl Fl begin-y Ar y .It Fl Fl begin-y Ar y
Dialog vertical position, 0 is the top screen side, -1 center. Dialog vertical position, 0 is the top screen side, -1 center.
.It Fl Fl bikeshed
Random settings.
Colors.
Delimiter and margins around the title.
Buttons always active or TAB to switch focus with input components, see
.Fl Fl switch-buttons .
Zero padding with time or date output.
.It Fl Fl cancel-label Ar label .It Fl Fl cancel-label Ar label
Label for the Label for the
.Dq Cancel .Dq Cancel
@ -100,7 +107,7 @@ cyan.
.It Dq \eZ7 .It Dq \eZ7
white. white.
.It Dq \eZr .It Dq \eZr
reverse foreground and background colors. reverse foreground and background.
.It Dq \eZR .It Dq \eZR
disable reverse. disable reverse.
.It Dq \eZb .It Dq \eZb
@ -112,8 +119,11 @@ underline.
.It Dq \eZU .It Dq \eZU
disable underline. disable underline.
.It Dq \eZn .It Dq \eZn
restore to normal text. restore normal text.
.El .El
.It Fl Fl columns-per-row Ar columns
Try to set the number of columns for a row of text with autosizing; default
.Dv 10 .
.It Fl Fl cr-wrap .It Fl Fl cr-wrap
Replace new line with a space in Replace new line with a space in
.Ar text . .Ar text .
@ -141,7 +151,7 @@ Equivalent to
.Fl Fl default-no . .Fl Fl default-no .
.It Fl Fl disable-esc .It Fl Fl disable-esc
Disable ESC key to quit. Disable ESC key to quit.
.It Fl Fl esc-cancelvalue .It Fl Fl esc-return-cancel
Exits with the Exits with the
.Dq Cancel .Dq Cancel
button value if the ESC key is pressed. button value if the ESC key is pressed.
@ -197,8 +207,7 @@ Do not exit with unknown options.
.It Fl Fl insecure .It Fl Fl insecure
Print Print
.Sq * .Sq *
to hide passwords while typing, default space to hide passwords while typing; whitespace otherwise.
.Sq " " .
.It Fl Fl item-depth .It Fl Fl item-depth
Specify a margin for items, available for Checklist, Menu and Radiolist. Specify a margin for items, available for Checklist, Menu and Radiolist.
.It Fl Fl item-help .It Fl Fl item-help
@ -206,9 +215,12 @@ Set a help string for each element of a Checklist, Form, Menu, Mixedform,
Passwordform, Radiolist and Treeview to display at the bottom screen side. Passwordform, Radiolist and Treeview to display at the bottom screen side.
.It Fl Fl item-prefix .It Fl Fl item-prefix
Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview. Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview.
.It Fl Fl load-theme Ar file
Load theme from
.Ar file .
.It Fl Fl max-input Ar size .It Fl Fl max-input Ar size
Maximum length of the input for Maximum length of the input for
.Fl Fl input-box .Fl Fl inputbox
ans ans
.Fl Fl passwordbox , .Fl Fl passwordbox ,
default 2048. default 2048.
@ -262,6 +274,8 @@ Print Dialog height and widget at exit.
Print version. Print version.
.It Fl Fl quoted .It Fl Fl quoted
Quote items in output, default only when necessary. Quote items in output, default only when necessary.
.It Fl Fl save-theme Ar file
Save the current theme.
.It Fl Fl separate-output .It Fl Fl separate-output
Separate selected items with a new line and avoid to quote. Separate selected items with a new line and avoid to quote.
.It Fl Fl separator Ar sep .It Fl Fl separator Ar sep
@ -279,6 +293,18 @@ seconds to close the dialog.
Print input from user interface to standand error, default. Print input from user interface to standand error, default.
.It Fl Fl stdout .It Fl Fl stdout
Print input from user interface to standard output. Print input from user interface to standard output.
.It Fl Fl switch-buttons
enables focus switching between buttons and input components pressing TAB,
otherwise buttons are always active and ENTER key closes the dialog.
Suitable for:
.Fl Fl form ,
.Fl Fl inputbox ,
.Fl Fl mixedform ,
.Fl Fl passwordbox ,
.Fl Fl passwordform ,
.Fl Fl timebox
and
.Fl Fl datebox .
.It Fl Fl tab-len Ar spaces .It Fl Fl tab-len Ar spaces
Number of spaces to print a TAB in Number of spaces to print a TAB in
.Ar text . .Ar text .
@ -319,7 +345,7 @@ is the graphical height of the list, 0 for autosize.
.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar year Ar month Ar day .It Fl Fl datebox Ar text Ar rows Ar cols Op Ar year Ar month Ar day
Dialog to select a date. Dialog to select a date.
.It Fl Fl form Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \ .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 ... Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Oc ...
Dialog to get a list of strings via forms. Dialog to get a list of strings via forms.
A form has a A form has a
.Ar label .Ar label
@ -333,19 +359,21 @@ and
.Ar xfield .Ar xfield
with graphical length with graphical length
.Ar fieldlen , .Ar fieldlen ,
.Ar maxvaluelen .Ar maxletters
is the maximum input length. is the maximum input length.
The field can be customized, if The field can be customized, if
.Ar fieldlen .Ar fieldlen
is 0 its length is the absolute value of is negative the field is read only and its absolute value is the field length.
.Ar maxvaluelen , If
if .Ar maxletters
.Ar maxvaluelen is 0 it is the absolute value of
is negative the field is read only, .Ar fieldlen .
.Ar init .Ar init
is a default value. is a default value.
.Ar formrows .Ar formrows
is the graphical height of the list, has to be at least the number of forms. is the graphical height of the list,
.Dv 0
for autosize.
.It Fl Fl gauge Ar text Ar rows Ar cols Op Ar percentage .It Fl Fl gauge Ar text Ar rows Ar cols Op Ar percentage
Dialog with a bar to shows Dialog with a bar to shows
.Ar percentage , .Ar percentage ,
@ -374,7 +402,7 @@ The name of the selected item is printed to standard error.
.Ar menurows .Ar menurows
is the graphical height of the list, 0 for autosize. 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 \ .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 ... Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Ar flag Oc ...
Dialog to get a list of strings via forms. Dialog to get a list of strings via forms.
A form has a A form has a
.Ar label .Ar label
@ -388,7 +416,7 @@ at the position
.Ar yfield .Ar yfield
and and
.Ar xfield , .Ar xfield ,
.Ar maxvaluelen .Ar maxletters
is the maximum input length, is the maximum input length,
.Ar init .Ar init
is a default value, is a default value,
@ -396,7 +424,9 @@ is a default value,
can be 0 for normal field, 1 to hide the typed characters and 2 to set the can be 0 for normal field, 1 to hide the typed characters and 2 to set the
field read only. field read only.
.Ar formrows .Ar formrows
is the graphical height of the list, has to be at least the number of forms. is the graphical height of the list,
.Dv 0
for autosize.
.It Fl Fl mixedgauge Ar text Ar rows Ar cols Ar mainperc Oo Ar minilabel \ .It Fl Fl mixedgauge Ar text Ar rows Ar cols Ar mainperc Oo Ar minilabel \
Ar miniperc Oc ... Ar miniperc Oc ...
Dialog to show a main bar to represent Dialog to show a main bar to represent
@ -436,7 +466,8 @@ Dialog to get a password,
.Ar init .Ar init
is the default value. is the default value.
.It Fl Fl passwordform Ar text Ar rows Ar cols Ar formrows Oo Ar label \ .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 ... Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters \
Oc ...
Dialog to get a list of passwords, equivalent to Dialog to get a list of passwords, equivalent to
.Fl Fl form .Fl Fl form
except typed characters are hidden. except typed characters are hidden.
@ -531,14 +562,39 @@ Backtitle, title and message:
Yes-No Question and theme: Yes-No Question and theme:
.Dl bsddialog --theme blackwhite --yesno Question 10 30 .Dl bsddialog --theme blackwhite --yesno Question 10 30
.Pp .Pp
Save a custom theme:
.Dl bsddialog --save-theme mytheme.txt --infobox \*qSaving theme...\*q 0 0
.Pp
Load a custom theme:
.Dl bsddialog --load-theme mytheme.txt --infobox \*qCustom theme\*q 0 0
.Pp
Checklist: Checklist:
.Dl bsddialog --checklist Checklist 0 0 3 N1 \&D1 off N2 D2 on N3 D3 off .Dl bsddialog --checklist Checklist 0 0 3 N1 \&D1 off N2 D2 on N3 D3 off
.Pp .Pp
Mixedgauge:
.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 "\(dq" -1" L2 30
.Pp
Form: Form:
.Dl bsddialog --form Form 0 0 2 L1: 1 1 X 1 5 20 25 L2: 2 1 X 2 5 20 25 .Dl bsddialog --form Form 0 0 0 L1: 0 0 X 0 4 20 25 L2: 1 0 Y 1 4 20 25
.Pp
Bikeshed:
.Dl bsddialog --bikeshed --inputbox Example 0 0
.Pp
Mixedgauge:
.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 \*q -1\*q L2 30
.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
.Pp .Pp
Gauge script: Gauge script:
.Bd -literal -offset indent -compact .Bd -literal -offset indent -compact
@ -558,22 +614,6 @@ do
i=`expr $i + 1` i=`expr $i + 1`
done | bsddialog --title Gauge --gauge "Starting..." 10 70 done | bsddialog --title Gauge --gauge "Starting..." 10 70
.Ed .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 .Sh SEE ALSO
.Xr bsddialog 3 .Xr bsddialog 3
.Sh HISTORY .Sh HISTORY
@ -584,7 +624,99 @@ utility first appeared in
.Sh AUTHORS .Sh AUTHORS
.Nm bsddialog .Nm bsddialog
was written by was written by
.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com . .An Alfonso Sabato Siciliano
.Sh BUGS .Aq Mt asiciliano@FreeBSD.org .
Forms do not resize the dialog after a terminal change and do not provide .Pp
scrolling for items. .Nm bsddialog
provides a subset of the functionality described in the
.Nm dialog
manual.
The following features were reimplemented:
.Pp
Common options:
.Fl Fl ascii-lines ,
.Fl Fl backtitle ,
.Fl Fl cancel-label ,
.Fl Fl clear ,
.Fl Fl colors ,
.Fl Fl cr-wrap ,
.Fl Fl date-format ,
.Fl Fl defaultno ,
.Fl Fl default-button ,
.Fl Fl default-no ,
.Fl Fl default-item ,
.Fl Fl exit-label ,
.Fl Fl extra-button ,
.Fl Fl extra-label ,
.Fl Fl help ,
.Fl Fl help-button ,
.Fl Fl help-label ,
.Fl Fl help-status ,
.Fl Fl help-tags ,
.Fl Fl hfile ,
.Fl Fl hline ,
.Fl Fl ignore ,
.Fl Fl insecure ,
.Fl Fl item-help ,
.Fl Fl max-input ,
.Fl Fl no-cancel ,
.Fl Fl nocancel ,
.Fl Fl no-collapse ,
.Fl Fl no-items ,
.Fl Fl no-label ,
.Fl Fl no-lines ,
.Fl Fl no-nl-expand ,
.Fl Fl no-ok ,
.Fl Fl nook ,
.Fl Fl no-shadow ,
.Fl Fl no-tags ,
.Fl Fl ok-label ,
.Fl Fl output-fd ,
.Fl Fl output-separator ,
.Fl Fl print-maxsize ,
.Fl Fl print-size ,
.Fl Fl print-version ,
.Fl Fl quoted ,
.Fl Fl separate-output ,
.Fl Fl separator ,
.Fl Fl shadow ,
.Fl Fl single-quoted ,
.Fl Fl sleep ,
.Fl Fl stderr ,
.Fl Fl stdout ,
.Fl Fl tab-len ,
.Fl Fl time-format ,
.Fl Fl title ,
.Fl Fl trim ,
.Fl Fl version ,
.Fl Fl yes-label .
.Pp
Dialogs:
.Fl Fl checklist ,
.Fl Fl form ,
.Fl Fl gauge ,
.Fl Fl infobox ,
.Fl Fl inputbox ,
.Fl Fl menu ,
.Fl Fl mixedform ,
.Fl Fl mixedgauge ,
.Fl Fl msgbox ,
.Fl Fl passwordbox ,
.Fl Fl passwordform ,
.Fl Fl pause ,
.Fl Fl radiolist ,
.Fl Fl rangebox ,
.Fl Fl textbox ,
.Fl Fl timebox ,
.Fl Fl treeview ,
.Fl Fl yesno .
.Pp
Some feature differs in input, output, or behavior.
Compatibility is not a priority for future development.
.Sh THANKS TO
.An Baptiste Daroussin
.Aq Mt bapt@FreeBSD.org
and
.An \&Ed Maste
.Aq Mt emaste@FreeBSD.org
for suggestions, help, and testing.

View File

@ -39,7 +39,9 @@
#include <bsddialog.h> #include <bsddialog.h>
#include <bsddialog_theme.h> #include <bsddialog_theme.h>
#define BSDDIALOG_VERSION "0.2" #include "util_theme.h"
#define BSDDIALOG_VERSION "0.3"
enum OPTS { enum OPTS {
/* Common options */ /* Common options */
@ -47,16 +49,18 @@ enum OPTS {
BACKTITLE, BACKTITLE,
BEGIN_X, BEGIN_X,
BEGIN_Y, BEGIN_Y,
BIKESHED,
CANCEL_LABEL, CANCEL_LABEL,
CLEAR, CLEAR,
COLORS, COLORS,
COLUMNS_PER_ROW,
CR_WRAP, CR_WRAP,
DATE_FORMAT, DATE_FORMAT,
DEFAULT_BUTTON, DEFAULT_BUTTON,
DEFAULT_ITEM, DEFAULT_ITEM,
DEFAULT_NO, DEFAULT_NO,
DISABLE_ESC, DISABLE_ESC,
ESC_CANCELVALUE, ESC_RETURNCANCEL,
EXIT_LABEL, EXIT_LABEL,
EXTRA_BUTTON, EXTRA_BUTTON,
EXTRA_LABEL, EXTRA_LABEL,
@ -75,6 +79,7 @@ enum OPTS {
ITEM_DEPTH, ITEM_DEPTH,
ITEM_HELP, ITEM_HELP,
ITEM_PREFIX, ITEM_PREFIX,
LOAD_THEME,
MAX_INPUT, MAX_INPUT,
NO_CANCEL, NO_CANCEL,
NO_COLLAPSE, NO_COLLAPSE,
@ -91,12 +96,14 @@ enum OPTS {
PRINT_SIZE, PRINT_SIZE,
PRINT_VERSION, PRINT_VERSION,
QUOTED, QUOTED,
SAVE_THEME,
SEPARATE_OUTPUT, SEPARATE_OUTPUT,
SHADOW, SHADOW,
SINGLE_QUOTED, SINGLE_QUOTED,
SLEEP, SLEEP,
STDERR, STDERR,
STDOUT, STDOUT,
SWITCH_BUTTONS,
TAB_LEN, TAB_LEN,
THEME, THEME,
TIME_FORMAT, TIME_FORMAT,
@ -136,15 +143,16 @@ static char *date_fmt_opt, *time_fmt_opt;
static int unsigned max_input_form_opt; static int unsigned max_input_form_opt;
/* General options */ /* General options */
static int output_fd_opt; static int output_fd_opt;
bool bikeshed_opt;
/* Functions */
static void sigint_handler(int sig);
static void static void
custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
char *text, char *buf); char *text, char *buf);
static void errorexit(char *errbuf);
static void sigint_handler(int sig);
/* Dialogs */ /* Dialogs */
#define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows, \ #define BUILDER_ARGS struct bsddialog_conf *conf, char* text, int rows, \
int cols, int argc, char **argv, char *errbuf int cols, int argc, char **argv, char *errbuf
static int checklist_builder(BUILDER_ARGS); static int checklist_builder(BUILDER_ARGS);
static int datebox_builder(BUILDER_ARGS); static int datebox_builder(BUILDER_ARGS);
@ -176,23 +184,24 @@ static void usage(void)
printf("Common Options:\n"); printf("Common Options:\n");
printf("--ascii-lines, --backtitle <backtitle>, --begin-x <x>, " printf("--ascii-lines, --backtitle <backtitle>, --begin-x <x>, "
"--begin-y <y>, --cancel-label <label>, --clear, --colors, " "--begin-y <y>, --bikeshed, --cancel-label <label>, --clear, "
"--cr-wrap, --date-format <format>, --defaultno, " "--colors, --columns-per-row <columns>, --cr-wrap, "
"--default-button <label>, --default-no, --default-item <name>, " "--date-format <format>, --default-button <label>, "
"--disable-esc, --esc-cancelvalue, --exit-label <label>, " "--default-item <name>, --default-no, --disable-esc, "
"--extra-button, --extra-label <label>, " "--esc-return-cancel, --exit-label <label>, --extra-button, "
"--generic-button1 <label>, --generic-button2 <label>, --help, " "--extra-label <label>, --generic-button1 <label>, "
"--help-button, --help-label <label>, --help-status, --help-tags, " "--generic-button2 <label>, --help, --help-button, "
"--hfile <filename>, --hline <string>, --hmsg <string>, --ignore, " "--help-label <label>, --help-status, --help-tags, --hfile <file>, "
"--insecure, --item-depth, --item-help, --items-prefix, " "--hline <string>, --hmsg <string>, --ignore, --insecure, "
"--max-input <size>, --no-cancel, --nocancel, --no-collapse, " "--item-depth, --item-help, --item-prefix, --load-theme <file>, "
"--no-items, --no-label <label>, --no-lines, --no-nl-expand, " "--max-input <size>, --no-cancel, --no-collapse, --no-items, "
"--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, " "--no-label <label>, --no-lines, --no-nl-expand, --no-ok, "
"--output-fd <fd>, --output-separator <sep>, --print-maxsize, " "--no-shadow, --no-tags, --ok-label <label>, --output-fd <fd>, "
"--print-size, --print-version, --quoted, --separate-output, " "--output-separator <sep>, --print-maxsize, --print-size, "
"--separator <sep>, --shadow, --single-quoted, --sleep <secs>, " "--print-version, --quoted, --save-theme <file>, "
"--stderr, --stdout, --tab-len <spaces>, " "--separate-output, --separator <sep>, --shadow, --single-quoted, "
"--theme <blackwhite|bsddialog|flat|dialog>, " "--sleep <secs>, --stderr, --stdout, --tab-len <spaces>, "
"--switch-buttons, --theme <blackwhite|bsddialog|flat|dialog>, "
"--time-format <format>, --title <title>, --trim, --version, " "--time-format <format>, --title <title>, --trim, --version, "
"--yes-label <label>.\n"); "--yes-label <label>.\n");
printf("\n"); printf("\n");
@ -202,14 +211,14 @@ static void usage(void)
"<on|off>] ...\n"); "<on|off>] ...\n");
printf("--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n"); printf("--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n");
printf("--form <text> <rows> <cols> <formrows> [<label> <ylabel> " printf("--form <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen>] " "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters>] "
"...\n"); "...\n");
printf("--gauge <text> <rows> <cols> [<perc>]\n"); printf("--gauge <text> <rows> <cols> [<perc>]\n");
printf("--infobox <text> <rows> <cols>\n"); printf("--infobox <text> <rows> <cols>\n");
printf("--inputbox <text> <rows> <cols> [init]\n"); printf("--inputbox <text> <rows> <cols> [init]\n");
printf("--menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n"); printf("--menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
printf("--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> " printf("--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen> " "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters> "
"<0|1|2>] ...\n"); "<0|1|2>] ...\n");
printf("--mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> " printf("--mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
"<miniperc>] ...\n"); "<miniperc>] ...\n");
@ -217,7 +226,7 @@ static void usage(void)
printf("--passwordbox <text> <rows> <cols> [init]\n"); printf("--passwordbox <text> <rows> <cols> [init]\n");
printf("--passwordform <text> <rows> <cols> <formrows> [<label> " printf("--passwordform <text> <rows> <cols> <formrows> [<label> "
"<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> " "<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> "
"<maxvaluelen>] ...\n"); "<maxletters>] ...\n");
printf("--pause <text> <rows> <cols> <secs>\n"); printf("--pause <text> <rows> <cols> <secs>\n");
printf("--radiolist <text> <rows> <cols> <menurows> [<name> <desc> " printf("--radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n"); "<on|off>] ...\n");
@ -235,11 +244,12 @@ static void usage(void)
int main(int argc, char *argv[argc]) int main(int argc, char *argv[argc])
{ {
bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt; bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt;
bool esc_cancelvalue_opt, ignore_opt, print_maxsize_opt;; bool esc_return_cancel_opt, ignore_opt, print_maxsize_opt;
int input, rows, cols, output, getH, getW; bool textfromfile;
int input, rows, cols, retval, getH, getW;
int (*dialogbuilder)(BUILDER_ARGS) = NULL; int (*dialogbuilder)(BUILDER_ARGS) = NULL;
enum bsddialog_default_theme theme_opt; enum bsddialog_default_theme theme_opt;
char *text, *backtitle_opt; char *text, *backtitle_opt, *loadthemefile, *savethemefile;
char errorbuilder[1024]; char errorbuilder[1024];
struct winsize ws; struct winsize ws;
struct bsddialog_conf conf; struct bsddialog_conf conf;
@ -250,7 +260,7 @@ int main(int argc, char *argv[argc])
conf.key.enable_esc = true; conf.key.enable_esc = true;
conf.menu.on_without_ok = true; conf.menu.on_without_ok = true;
conf.form.value_without_ok = true; conf.form.value_without_ok = true;
conf.form.enable_wchar = true; conf.button.always_active = true;
backtitle_opt = NULL; backtitle_opt = NULL;
theme_opt = BSDDIALOG_THEME_FLAT; theme_opt = BSDDIALOG_THEME_FLAT;
@ -258,8 +268,12 @@ int main(int argc, char *argv[argc])
print_maxsize_opt = false; print_maxsize_opt = false;
ignore_opt = false; ignore_opt = false;
cr_wrap_opt = no_collapse_opt = no_nl_expand_opt = trim_opt = false; cr_wrap_opt = no_collapse_opt = no_nl_expand_opt = trim_opt = false;
esc_cancelvalue_opt = false; esc_return_cancel_opt = false;
textfromfile = false;
bikeshed_opt = false;
errorbuilder[0] = '\0'; errorbuilder[0] = '\0';
savethemefile = NULL;
loadthemefile = NULL;
item_output_sepnl_opt = item_singlequote_opt = false; item_output_sepnl_opt = item_singlequote_opt = false;
item_prefix_opt = item_bottomdesc_opt = item_depth_opt = false; item_prefix_opt = item_bottomdesc_opt = item_depth_opt = false;
@ -279,6 +293,7 @@ int main(int argc, char *argv[argc])
{"backtitle", required_argument, NULL, BACKTITLE}, {"backtitle", required_argument, NULL, BACKTITLE},
{"begin-x", required_argument, NULL, BEGIN_X}, {"begin-x", required_argument, NULL, BEGIN_X},
{"begin-y", required_argument, NULL, BEGIN_Y}, {"begin-y", required_argument, NULL, BEGIN_Y},
{"bikeshed", no_argument, NULL, BIKESHED},
{"cancel-label", required_argument, NULL, CANCEL_LABEL}, {"cancel-label", required_argument, NULL, CANCEL_LABEL},
{"clear", no_argument, NULL, CLEAR}, {"clear", no_argument, NULL, CLEAR},
{"colors", no_argument, NULL, COLORS}, {"colors", no_argument, NULL, COLORS},
@ -289,7 +304,7 @@ int main(int argc, char *argv[argc])
{"default-item", required_argument, NULL, DEFAULT_ITEM}, {"default-item", required_argument, NULL, DEFAULT_ITEM},
{"default-no", no_argument, NULL, DEFAULT_NO}, {"default-no", no_argument, NULL, DEFAULT_NO},
{"disable-esc", no_argument, NULL, DISABLE_ESC}, {"disable-esc", no_argument, NULL, DISABLE_ESC},
{"esc-cancelvalue", no_argument, NULL, ESC_CANCELVALUE}, {"esc-return-cancel",no_argument, NULL, ESC_RETURNCANCEL},
{"exit-label", required_argument, NULL, EXIT_LABEL}, {"exit-label", required_argument, NULL, EXIT_LABEL},
{"extra-button", no_argument, NULL, EXTRA_BUTTON}, {"extra-button", no_argument, NULL, EXTRA_BUTTON},
{"extra-label", required_argument, NULL, EXTRA_LABEL}, {"extra-label", required_argument, NULL, EXTRA_LABEL},
@ -308,6 +323,7 @@ int main(int argc, char *argv[argc])
{"item-depth", no_argument, NULL, ITEM_DEPTH}, {"item-depth", no_argument, NULL, ITEM_DEPTH},
{"item-help", no_argument, NULL, ITEM_HELP}, {"item-help", no_argument, NULL, ITEM_HELP},
{"item-prefix", no_argument, NULL, ITEM_PREFIX}, {"item-prefix", no_argument, NULL, ITEM_PREFIX},
{"load-theme", required_argument, NULL, LOAD_THEME},
{"max-input", required_argument, NULL, MAX_INPUT}, {"max-input", required_argument, NULL, MAX_INPUT},
{"no-cancel", no_argument, NULL, NO_CANCEL}, {"no-cancel", no_argument, NULL, NO_CANCEL},
{"nocancel", no_argument, NULL, NO_CANCEL}, {"nocancel", no_argument, NULL, NO_CANCEL},
@ -327,6 +343,8 @@ int main(int argc, char *argv[argc])
{"print-size", no_argument, NULL, PRINT_SIZE}, {"print-size", no_argument, NULL, PRINT_SIZE},
{"print-version", no_argument, NULL, PRINT_VERSION}, {"print-version", no_argument, NULL, PRINT_VERSION},
{"quoted", no_argument, NULL, QUOTED}, {"quoted", no_argument, NULL, QUOTED},
{"columns-per-row", required_argument, NULL, COLUMNS_PER_ROW},
{"save-theme", required_argument, NULL, SAVE_THEME},
{"separate-output", no_argument, NULL, SEPARATE_OUTPUT}, {"separate-output", no_argument, NULL, SEPARATE_OUTPUT},
{"separator", required_argument, NULL, OUTPUT_SEPARATOR}, {"separator", required_argument, NULL, OUTPUT_SEPARATOR},
{"shadow", no_argument, NULL, SHADOW}, {"shadow", no_argument, NULL, SHADOW},
@ -334,6 +352,7 @@ int main(int argc, char *argv[argc])
{"sleep", required_argument, NULL, SLEEP}, {"sleep", required_argument, NULL, SLEEP},
{"stderr", no_argument, NULL, STDERR}, {"stderr", no_argument, NULL, STDERR},
{"stdout", no_argument, NULL, STDOUT}, {"stdout", no_argument, NULL, STDOUT},
{"switch-buttons", no_argument, NULL, SWITCH_BUTTONS},
{"tab-len", required_argument, NULL, TAB_LEN}, {"tab-len", required_argument, NULL, TAB_LEN},
{"theme", required_argument, NULL, THEME}, {"theme", required_argument, NULL, THEME},
{"time-format", required_argument, NULL, TIME_FORMAT}, {"time-format", required_argument, NULL, TIME_FORMAT},
@ -373,6 +392,8 @@ int main(int argc, char *argv[argc])
break; break;
case BACKTITLE: case BACKTITLE:
backtitle_opt = optarg; backtitle_opt = optarg;
if (conf.y == BSDDIALOG_CENTER)
conf.auto_topmargin = 2;
break; break;
case BEGIN_X: case BEGIN_X:
conf.x = (int)strtol(optarg, NULL, 10); conf.x = (int)strtol(optarg, NULL, 10);
@ -389,6 +410,10 @@ int main(int argc, char *argv[argc])
conf.y, BSDDIALOG_CENTER); conf.y, BSDDIALOG_CENTER);
return (255); return (255);
} }
conf.auto_topmargin = 0;
break;
case BIKESHED:
bikeshed_opt = true;
break; break;
case CANCEL_LABEL: case CANCEL_LABEL:
conf.button.cancel_label = optarg; conf.button.cancel_label = optarg;
@ -399,6 +424,10 @@ int main(int argc, char *argv[argc])
case COLORS: case COLORS:
conf.text.highlight = true; conf.text.highlight = true;
break; break;
case COLUMNS_PER_ROW:
conf.text.cols_per_row =
(u_int)strtoul(optarg, NULL, 10);
break;
case CR_WRAP: case CR_WRAP:
cr_wrap_opt = true; cr_wrap_opt = true;
break; break;
@ -417,8 +446,8 @@ int main(int argc, char *argv[argc])
case DISABLE_ESC: case DISABLE_ESC:
conf.key.enable_esc = false; conf.key.enable_esc = false;
break; break;
case ESC_CANCELVALUE: case ESC_RETURNCANCEL:
esc_cancelvalue_opt = true; esc_return_cancel_opt = true;
break; break;
case EXIT_LABEL: case EXIT_LABEL:
conf.button.ok_label = optarg; conf.button.ok_label = optarg;
@ -454,7 +483,7 @@ int main(int argc, char *argv[argc])
conf.key.f1_file = optarg; conf.key.f1_file = optarg;
break; break;
case HLINE: case HLINE:
if (strlen(optarg) > 0) if (optarg[0] != '\0')
conf.bottomtitle = optarg; conf.bottomtitle = optarg;
break; break;
case HMSG: case HMSG:
@ -475,6 +504,9 @@ int main(int argc, char *argv[argc])
case ITEM_PREFIX: case ITEM_PREFIX:
item_prefix_opt = true; item_prefix_opt = true;
break; break;
case LOAD_THEME:
loadthemefile = optarg;
break;
case MAX_INPUT: case MAX_INPUT:
max_input_form_opt = (u_int)strtoul(optarg, NULL, 10); max_input_form_opt = (u_int)strtoul(optarg, NULL, 10);
break; break;
@ -524,6 +556,9 @@ int main(int argc, char *argv[argc])
case PRINT_VERSION: case PRINT_VERSION:
printf("bsddialog version %s\n", BSDDIALOG_VERSION); printf("bsddialog version %s\n", BSDDIALOG_VERSION);
break; break;
case SAVE_THEME:
savethemefile = optarg;
break;
case SEPARATE_OUTPUT: case SEPARATE_OUTPUT:
item_output_sepnl_opt = true; item_output_sepnl_opt = true;
break; break;
@ -542,6 +577,9 @@ int main(int argc, char *argv[argc])
case STDOUT: case STDOUT:
output_fd_opt = STDOUT_FILENO; output_fd_opt = STDOUT_FILENO;
break; break;
case SWITCH_BUTTONS:
conf.button.always_active = false;
break;
case TAB_LEN: case TAB_LEN:
conf.text.tablen = (u_int)strtoul(optarg, NULL, 10); conf.text.tablen = (u_int)strtoul(optarg, NULL, 10);
break; break;
@ -575,12 +613,14 @@ int main(int argc, char *argv[argc])
/* Dialogs */ /* Dialogs */
case CHECKLIST: case CHECKLIST:
dialogbuilder = checklist_builder; dialogbuilder = checklist_builder;
conf.auto_downmargin = 1;
break; break;
case DATEBOX: case DATEBOX:
dialogbuilder = datebox_builder; dialogbuilder = datebox_builder;
break; break;
case FORM: case FORM:
dialogbuilder = form_builder; dialogbuilder = form_builder;
conf.auto_downmargin = 1;
break; break;
case GAUGE: case GAUGE:
dialogbuilder = gauge_builder; dialogbuilder = gauge_builder;
@ -590,12 +630,15 @@ int main(int argc, char *argv[argc])
break; break;
case INPUTBOX: case INPUTBOX:
dialogbuilder = inputbox_builder; dialogbuilder = inputbox_builder;
conf.auto_downmargin = 1;
break; break;
case MENU: case MENU:
dialogbuilder = menu_builder; dialogbuilder = menu_builder;
conf.auto_downmargin = 1;
break; break;
case MIXEDFORM: case MIXEDFORM:
dialogbuilder = mixedform_builder; dialogbuilder = mixedform_builder;
conf.auto_downmargin = 1;
break; break;
case MIXEDGAUGE: case MIXEDGAUGE:
dialogbuilder = mixedgauge_builder; dialogbuilder = mixedgauge_builder;
@ -608,24 +651,29 @@ int main(int argc, char *argv[argc])
break; break;
case PASSWORDBOX: case PASSWORDBOX:
dialogbuilder = passwordbox_builder; dialogbuilder = passwordbox_builder;
conf.auto_downmargin = 1;
break; break;
case PASSWORDFORM: case PASSWORDFORM:
dialogbuilder = passwordform_builder; dialogbuilder = passwordform_builder;
conf.auto_downmargin = 1;
break; break;
case RADIOLIST: case RADIOLIST:
dialogbuilder = radiolist_builder; dialogbuilder = radiolist_builder;
conf.auto_downmargin = 1;
break; break;
case RANGEBOX: case RANGEBOX:
dialogbuilder = rangebox_builder; dialogbuilder = rangebox_builder;
break; break;
case TEXTBOX: case TEXTBOX:
dialogbuilder = textbox_builder; dialogbuilder = textbox_builder;
textfromfile = true;
break; break;
case TIMEBOX: case TIMEBOX:
dialogbuilder = timebox_builder; dialogbuilder = timebox_builder;
break; break;
case TREEVIEW: case TREEVIEW:
dialogbuilder = treeview_builder; dialogbuilder = treeview_builder;
conf.auto_downmargin = 1;
break; break;
case YESNO: case YESNO:
dialogbuilder = yesno_builder; dialogbuilder = yesno_builder;
@ -653,7 +701,7 @@ int main(int argc, char *argv[argc])
usage(); usage();
return (255); return (255);
} }
if (dialogbuilder == textbox_builder) if (textfromfile) /* textbox */
text = argv[0]; text = argv[0];
else { else {
if ((text = malloc(strlen(argv[0]) + 1)) == NULL) { if ((text = malloc(strlen(argv[0]) + 1)) == NULL) {
@ -671,45 +719,52 @@ int main(int argc, char *argv[argc])
/* bsddialog terminal mode */ /* bsddialog terminal mode */
if (bsddialog_init() != 0) { if (bsddialog_init() != 0) {
printf("Error: %s\n", bsddialog_geterror()); printf("Error: %s\n", bsddialog_geterror());
return (BSDDIALOG_ERROR); return (255);
} }
signal(SIGINT, sigint_handler); signal(SIGINT, sigint_handler);
if (theme_opt != BSDDIALOG_THEME_FLAT) if (theme_opt != BSDDIALOG_THEME_FLAT)
bsddialog_set_default_theme(theme_opt); if (bsddialog_set_default_theme(theme_opt) != BSDDIALOG_OK)
errorexit(NULL);
if (loadthemefile != NULL)
if (loadtheme(loadthemefile, errorbuilder) != BSDDIALOG_OK)
errorexit(errorbuilder);
if (bikeshed_opt)
if (bikeshed(&conf, errorbuilder) != BSDDIALOG_OK)
errorexit(errorbuilder);
if (backtitle_opt != NULL) if (backtitle_opt != NULL)
bsddialog_backtitle(&conf, backtitle_opt); if( bsddialog_backtitle(&conf, backtitle_opt))
errorexit(NULL);
errorbuilder[0] = '\0'; if (dialogbuilder != NULL) {
output = BSDDIALOG_OK; retval = dialogbuilder(&conf, text, rows, cols, argc, argv,
if (dialogbuilder != NULL)
output = dialogbuilder(conf, text, rows, cols, argc, argv,
errorbuilder); errorbuilder);
if (retval == BSDDIALOG_ERROR)
errorexit(errorbuilder);
} else
retval = BSDDIALOG_OK;
if (dialogbuilder != textbox_builder) if (savethemefile != NULL)
free(text); if (savetheme(savethemefile, errorbuilder, BSDDIALOG_VERSION) !=
BSDDIALOG_OK)
errorexit(errorbuilder);
bsddialog_end(); bsddialog_end();
/* end bsddialog terminal mode */ /* end bsddialog terminal mode */
if (output == BSDDIALOG_ERROR) { if (textfromfile == false)
if (errorbuilder[0] != '\0') free(text);
printf("Error: %s\n", errorbuilder);
else
printf("Error: %s\n", bsddialog_geterror());
return (255);
}
if (conf.get_height != NULL && conf.get_width != NULL) if (conf.get_height != NULL && conf.get_width != NULL)
dprintf(output_fd_opt, "Dialog size: (%d - %d)\n", dprintf(output_fd_opt, "Dialog size: (%d - %d)\n",
*conf.get_height, *conf.get_width); *conf.get_height, *conf.get_width);
if (output == BSDDIALOG_ESC && esc_cancelvalue_opt) if (retval == BSDDIALOG_ESC && esc_return_cancel_opt)
output = BSDDIALOG_CANCEL; retval = BSDDIALOG_CANCEL;
return (output); return (retval);
} }
void sigint_handler(int sig) void sigint_handler(int sig)
@ -719,6 +774,18 @@ void sigint_handler(int sig)
exit(255); exit(255);
} }
void errorexit(char *errbuf)
{
bsddialog_end();
if (errbuf != NULL && errbuf[0] != '\0')
printf("Error: %s\n", errbuf);
else
printf("Error: %s\n", bsddialog_geterror());
exit(255);
}
void void
custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
char *text, char *buf) char *text, char *buf)
@ -781,7 +848,7 @@ int gauge_builder(BUILDER_ARGS)
else else
perc = 0; perc = 0;
output = bsddialog_gauge(&conf, text, rows, cols, perc, STDIN_FILENO, output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO,
"XXX"); "XXX");
return (output); return (output);
@ -791,7 +858,7 @@ int infobox_builder(BUILDER_ARGS)
{ {
int output; int output;
output = bsddialog_infobox(&conf, text, rows, cols); output = bsddialog_infobox(conf, text, rows, cols);
return (output); return (output);
} }
@ -827,7 +894,7 @@ int mixedgauge_builder(BUILDER_ARGS)
minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10); minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10);
} }
output = bsddialog_mixedgauge(&conf, text, rows, cols, mainperc, output = bsddialog_mixedgauge(conf, text, rows, cols, mainperc,
nminibars, minilabels, minipercs); nminibars, minilabels, minipercs);
return (output); return (output);
@ -837,7 +904,7 @@ int msgbox_builder(BUILDER_ARGS)
{ {
int output; int output;
output = bsddialog_msgbox(&conf, text, rows, cols); output = bsddialog_msgbox(conf, text, rows, cols);
return (output); return (output);
} }
@ -853,7 +920,7 @@ int pause_builder(BUILDER_ARGS)
} }
secs = (u_int)strtoul(argv[0], NULL, 10); secs = (u_int)strtoul(argv[0], NULL, 10);
output = bsddialog_pause(&conf, text, rows, cols, secs); output = bsddialog_pause(conf, text, rows, cols, secs);
return (output); return (output);
} }
@ -879,7 +946,7 @@ int rangebox_builder(BUILDER_ARGS)
else else
value = min; value = min;
output = bsddialog_rangebox(&conf, text, rows, cols, min, max, &value); output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value);
dprintf(output_fd_opt, "%d", value); dprintf(output_fd_opt, "%d", value);
@ -890,7 +957,7 @@ int textbox_builder(BUILDER_ARGS)
{ {
int output; int output;
output = bsddialog_textbox(&conf, text, rows, cols); output = bsddialog_textbox(conf, text, rows, cols);
return (output); return (output);
} }
@ -899,7 +966,7 @@ int yesno_builder(BUILDER_ARGS)
{ {
int output; int output;
output = bsddialog_yesno(&conf, text, rows, cols); output = bsddialog_yesno(conf, text, rows, cols);
return (output); return (output);
} }
@ -925,13 +992,11 @@ int datebox_builder(BUILDER_ARGS)
dd = (u_int)strtoul(argv[2], NULL, 10); dd = (u_int)strtoul(argv[2], NULL, 10);
} }
output = bsddialog_datebox(&conf, text, rows, cols, &yy, &mm, &dd); output = bsddialog_datebox(conf, text, rows, cols, &yy, &mm, &dd);
if (output != BSDDIALOG_OK) if (output != BSDDIALOG_OK)
return (output); return (output);
if (date_fmt_opt == NULL) { if (date_fmt_opt != NULL) {
dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd);
} else {
time(&cal); time(&cal);
localtm = localtime(&cal); localtm = localtime(&cal);
localtm->tm_year = yy - 1900; localtm->tm_year = yy - 1900;
@ -939,6 +1004,10 @@ int datebox_builder(BUILDER_ARGS)
localtm->tm_mday = dd; localtm->tm_mday = dd;
strftime(stringdate, 1024, date_fmt_opt, localtm); strftime(stringdate, 1024, date_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringdate); dprintf(output_fd_opt, "%s", stringdate);
} else if (bikeshed_opt && (dd % 2 == 0)) {
dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd);
} else {
dprintf(output_fd_opt, "%u/%02u/%02u", yy, mm, dd);
} }
return (output); return (output);
@ -964,13 +1033,11 @@ int timebox_builder(BUILDER_ARGS)
ss = (u_int)strtoul(argv[2], NULL, 10); ss = (u_int)strtoul(argv[2], NULL, 10);
} }
output = bsddialog_timebox(&conf, text, rows, cols, &hh, &mm, &ss); output = bsddialog_timebox(conf, text, rows, cols, &hh, &mm, &ss);
if (output != BSDDIALOG_OK) if (output != BSDDIALOG_OK)
return (output); return (output);
if (time_fmt_opt == NULL) { if (time_fmt_opt != NULL) {
dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
} else {
time(&clock); time(&clock);
localtm = localtime(&clock); localtm = localtime(&clock);
localtm->tm_hour = hh; localtm->tm_hour = hh;
@ -978,6 +1045,10 @@ int timebox_builder(BUILDER_ARGS)
localtm->tm_sec = ss; localtm->tm_sec = ss;
strftime(stringtime, 1024, time_fmt_opt, localtm); strftime(stringtime, 1024, time_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringtime); dprintf(output_fd_opt, "%s", stringtime);
} else if (bikeshed_opt && (ss % 2 == 0)) {
dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
} else {
dprintf(output_fd_opt, "%02u:%02u:%02u", hh, mm, ss);
} }
return (output); return (output);
@ -1117,7 +1188,7 @@ int checklist_builder(BUILDER_ARGS)
if (output != 0) if (output != 0)
return (output); return (output);
output = bsddialog_checklist(&conf, text, rows, cols, menurows, nitems, output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
items, &focusitem); items, &focusitem);
print_menu_items(output, nitems, items, focusitem); print_menu_items(output, nitems, items, focusitem);
@ -1146,7 +1217,7 @@ int menu_builder(BUILDER_ARGS)
if (output != 0) if (output != 0)
return (output); return (output);
output = bsddialog_menu(&conf, text, rows, cols, menurows, nitems, output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
items, &focusitem); items, &focusitem);
print_menu_items(output, nitems, items, focusitem); print_menu_items(output, nitems, items, focusitem);
@ -1175,7 +1246,7 @@ int radiolist_builder(BUILDER_ARGS)
if (output != 0) if (output != 0)
return (output); return (output);
output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems, output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem); items, &focusitem);
print_menu_items(output, nitems, items, focusitem); print_menu_items(output, nitems, items, focusitem);
@ -1204,10 +1275,10 @@ int treeview_builder(BUILDER_ARGS)
if (output != 0) if (output != 0)
return (output); return (output);
conf.menu.no_name = true; conf->menu.no_name = true;
conf.menu.align_left = true; conf->menu.align_left = true;
output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems, output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem); items, &focusitem);
print_menu_items(output, nitems, items, focusitem); print_menu_items(output, nitems, items, focusitem);
@ -1239,7 +1310,7 @@ print_form_items(int output, int nitems, struct bsddialog_formitem *items)
return; return;
for (i = 0; i < nitems; i++) { for (i = 0; i < nitems; i++) {
dprintf(output_fd_opt, "%ls\n", (wchar_t*)items[i].value); dprintf(output_fd_opt, "%s\n", items[i].value);
free(items[i].value); free(items[i].value);
} }
} }
@ -1257,7 +1328,6 @@ int form_builder(BUILDER_ARGS)
} }
formheight = (u_int)strtoul(argv[0], NULL, 10); formheight = (u_int)strtoul(argv[0], NULL, 10);
flags = 0;
argc--; argc--;
argv++; argv++;
@ -1280,13 +1350,13 @@ int form_builder(BUILDER_ARGS)
valuelen = (int)strtol(argv[j++], NULL, 10); valuelen = (int)strtol(argv[j++], NULL, 10);
items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen; items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0); flags = (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
items[i].flags = flags; items[i].flags = flags;
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
} }
output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items); items);
print_form_items(output, nitems, items); print_form_items(output, nitems, items);
free(items); free(items);
@ -1303,14 +1373,16 @@ int inputbox_builder(BUILDER_ARGS)
item.ylabel = 0; item.ylabel = 0;
item.xlabel = 0; item.xlabel = 0;
item.init = argc > 0 ? argv[0] : ""; item.init = argc > 0 ? argv[0] : "";
item.yfield = 1; item.yfield = 0;
item.xfield = 1; item.xfield = 0;
item.fieldlen = cols > 4 ? cols-4 : 25; item.fieldlen = 1;
item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048;
item.flags = 0; item.flags = BSDDIALOG_FIELDNOCOLOR;
item.flags |= BSDDIALOG_FIELDCURSOREND;
item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = ""; item.bottomdesc = "";
output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item); output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item); print_form_items(output, 1, &item);
return (output); return (output);
@ -1350,7 +1422,7 @@ int mixedform_builder(BUILDER_ARGS)
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
} }
output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items); items);
print_form_items(output, nitems, items); print_form_items(output, nitems, items);
free(items); free(items);
@ -1367,14 +1439,17 @@ int passwordbox_builder(BUILDER_ARGS)
item.ylabel = 0; item.ylabel = 0;
item.xlabel = 0; item.xlabel = 0;
item.init = argc > 0 ? argv[0] : ""; item.init = argc > 0 ? argv[0] : "";
item.yfield = 1; item.yfield = 0;
item.xfield = 1; item.xfield = 0;
item.fieldlen = cols > 4 ? cols-4 : 25; item.fieldlen = 1;
item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048;
item.flags = BSDDIALOG_FIELDHIDDEN; item.flags = BSDDIALOG_FIELDHIDDEN;
item.flags |= BSDDIALOG_FIELDNOCOLOR;
item.flags |= BSDDIALOG_FIELDCURSOREND;
item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = ""; item.bottomdesc = "";
output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item); output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item); print_form_items(output, 1, &item);
return (output); return (output);
@ -1422,7 +1497,7 @@ int passwordform_builder(BUILDER_ARGS)
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
} }
output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items); items);
print_form_items(output, nitems, items); print_form_items(output, nitems, items);
free(items); free(items);

View File

@ -10,7 +10,9 @@
libpath=../lib libpath=../lib
examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \ examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \
datebox form formw timebox rangebox pause" datebox form timebox rangebox pause"
rm -f $examples
for e in $examples for e in $examples
do do

View File

@ -34,9 +34,7 @@ int main()
bsddialog_initconf(&conf); bsddialog_initconf(&conf);
conf.title = "datebox"; conf.title = "datebox";
output = bsddialog_datebox(&conf, output = bsddialog_datebox(&conf, "Example", 9, 35, &yy, &mm, &dd);
"TAB / RIGHT / LEFT to move,\nUP / DOWN to select time", 10, 35,
&yy, &mm, &dd);
bsddialog_end(); bsddialog_end();

View File

@ -9,6 +9,7 @@
*/ */
#include <bsddialog.h> #include <bsddialog.h>
#include <locale.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -21,21 +22,22 @@ int main()
int i, output; int i, output;
struct bsddialog_conf conf; struct bsddialog_conf conf;
struct bsddialog_formitem items[3] = { struct bsddialog_formitem items[3] = {
{"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"}, {"Input:", 0, 0, "value", 0, 10, 30, 50, NULL, 0, "desc 1"},
{"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"}, {"Input:", 1, 0, "read only", 1, 10, 30, 50, NULL, RO, "desc 2"},
{"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"} {"Password:", 2, 0, "", 2, 10, 30, 50, NULL, H, "desc 3"}
}; };
/* Optional, unless for unicode/multicolum charachters */
setlocale(LC_ALL, "");
if (bsddialog_init() == BSDDIALOG_ERROR) { if (bsddialog_init() == BSDDIALOG_ERROR) {
printf("Error: %s\n", bsddialog_geterror()); printf("Error: %s\n", bsddialog_geterror());
return (1); return (1);
} }
bsddialog_initconf(&conf); bsddialog_initconf(&conf);
conf.title = "form"; conf.title = "form";
conf.form.securech = '*'; conf.form.securech = '*';
output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items); output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
bsddialog_end(); bsddialog_end();
if (output == BSDDIALOG_ERROR) { if (output == BSDDIALOG_ERROR) {

View File

@ -1,61 +0,0 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2022 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <bsddialog.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define H BSDDIALOG_FIELDHIDDEN
#define RO BSDDIALOG_FIELDREADONLY
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"}
};
setlocale(LC_ALL, "");
if (bsddialog_init() == BSDDIALOG_ERROR) {
printf("Error: %s\n", bsddialog_geterror());
return (1);
}
bsddialog_initconf(&conf);
conf.title = "form";
conf.form.securech = '*';
conf.form.enable_wchar = true;
output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
bsddialog_end();
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++) {
printf("%s \"%ls\"\n", items[i].label, (wchar_t*)items[i].value);
free(items[i].value);
}
return (output);
}

View File

@ -34,9 +34,7 @@ int main()
bsddialog_initconf(&conf); bsddialog_initconf(&conf);
conf.title = "timebox"; conf.title = "timebox";
output = bsddialog_timebox(&conf, output = bsddialog_timebox(&conf, "Example", 9, 35, &hh, &mm, &ss);
"TAB / RIGHT / LEFT to move,\nUP / DOWN to select time", 10, 35,
&hh, &mm, &ss);
bsddialog_end(); bsddialog_end();

View File

@ -15,11 +15,11 @@
: ${BSDDIALOG_ESC=5} : ${BSDDIALOG_ESC=5}
FORMS=$(./bsddialog --title " form " --form "Hello World!" 12 40 5 \ FORMS=$(./bsddialog --title " form " --form "Hello World!" 12 40 5 \
Label1: 1 1 Value1 1 9 18 25 \ Label1: 0 0 Value1 0 8 18 25 \
Label2: 2 1 Value2 2 9 18 25 \ Label2: 1 0 Value2 1 8 18 25 \
Label3: 3 1 Value3 3 9 18 25 \ Label3: 2 0 Value3 2 8 18 25 \
Label4: 4 1 Value4 4 9 18 25 \ Label4: 3 0 Value4 3 8 18 25 \
Label5: 5 1 Value5 5 9 18 25 \ Label5: 4 0 Value5 4 8 18 25 \
3>&1 1>&2 2>&3 3>&-) 3>&1 1>&2 2>&3 3>&-)
case $? in case $? in

View File

@ -16,9 +16,9 @@
FORMS=$(./bsddialog --insecure --title " mixedform " \ FORMS=$(./bsddialog --insecure --title " mixedform " \
--mixedform "Hello World!" 12 40 3 \ --mixedform "Hello World!" 12 40 3 \
Label: 1 1 Entry 1 11 18 25 0 \ Label: 0 0 Entry 0 10 18 25 0 \
Label: 2 1 Read-Only 2 11 18 25 2 \ Label: 1 0 Read-Only 1 10 18 25 2 \
Password: 3 1 "" 3 11 18 25 1 \ Password: 2 0 "" 2 10 18 25 1 \
3>&1 1>&2 2>&3 3>&-) 3>&1 1>&2 2>&3 3>&-)
case $? in case $? in

View File

@ -16,11 +16,11 @@
FORMS=$(./bsddialog --insecure --title " passwordform " \ FORMS=$(./bsddialog --insecure --title " passwordform " \
--passwordform "Example" 12 40 5 \ --passwordform "Example" 12 40 5 \
Password1: 1 1 "" 1 12 18 25 \ Password1: 0 0 "" 0 11 18 25 \
Password2: 2 1 "" 2 12 18 25 \ Password2: 1 0 "" 1 11 18 25 \
Password3: 3 1 "" 3 12 18 25 \ Password3: 2 0 "" 2 11 18 25 \
Password4: 4 1 "" 4 12 18 25 \ Password4: 3 0 "" 3 11 18 25 \
Password5: 5 1 "" 5 12 18 25 \ Password5: 4 0 "" 4 11 18 25 \
3>&1 1>&2 2>&3 3>&-) 3>&1 1>&2 2>&3 3>&-)
case $? in case $? in

View File

@ -3,16 +3,16 @@
# #
# Written in 2021 by Alfonso Sabato Siciliano # Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.2 VERSION = 0.3
LIBRARY = bsddialog LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so} LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \ SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
messagebox.c textbox.c theme.c timebox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -D_XOPEN_SOURCE_EXTENDED -Wall -Wextra -Wno-implicit-fallthrough \ CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra -Wno-implicit-fallthrough \
-Werror -fpic -Werror -fpic
LDFLAGS = -lformw -lncursesw -ltinfo LDFLAGS = -lncursesw -ltinfo
LIBFLAG = -shared LIBFLAG = -shared
RM = rm -f RM = rm -f

View File

@ -3,7 +3,7 @@
# #
# Written in 2021 by Alfonso Sabato Siciliano # Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.2 VERSION = 0.3
LIBRARY = bsddialog LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so} LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a} LIBRARY_A = lib${LIBRARY:=.a}
@ -14,7 +14,7 @@ OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \ LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \ -Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \
-L/usr/lib -lformw -lncursesw -ltinfow -L/usr/lib -lncursesw -ltinfow
.if defined(DEBUG) .if defined(DEBUG)
# `make -DDEBUG` # `make -DDEBUG`

View File

@ -70,7 +70,7 @@ draw_bar(WINDOW *win, int y, int x, int barlen, int perc, bool withlabel,
sprintf(labelstr, "%d", label); sprintf(labelstr, "%d", label);
else else
sprintf(labelstr, "%3d%%", perc); sprintf(labelstr, "%3d%%", perc);
stringlen = (int)strlen(labelstr); stringlen = (int)strlen(labelstr); /* number, always 1-byte-ch string */
wmove(win, y, x + barlen/2 - stringlen/2); wmove(win, y, x + barlen/2 - stringlen/2);
for (i = 0; i < stringlen; i++) { for (i = 0; i < stringlen; i++) {
color = (blue_x + 1 <= barlen/2 - stringlen/2 + i ) ? color = (blue_x + 1 <= barlen/2 - stringlen/2 + i ) ?
@ -109,7 +109,7 @@ bar_checksize(int rows, int cols, struct buttons *bs)
minwidth = 0; minwidth = 0;
if (bs != NULL) /* gauge has not buttons */ if (bs != NULL) /* gauge has not buttons */
minwidth = buttons_width(*bs); minwidth = buttons_min_width(*bs);
minwidth = MAX(minwidth, MINBARWIDTH); minwidth = MAX(minwidth, MINBARWIDTH);
minwidth += VBORDERS; minwidth += VBORDERS;
@ -151,16 +151,14 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED); bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
mainloop = (fd < 0) ? false : true; input = NULL;
if (fd >= 0) {
if (mainloop) {
fd2 = dup(fd); fd2 = dup(fd);
input = fdopen(fd2, "r"); if ((input = fdopen(fd2, "r")) == NULL)
if (input == NULL)
RETURN_ERROR("Cannot build FILE* from fd"); RETURN_ERROR("Cannot build FILE* from fd");
} else }
input = NULL;
mainloop = true;
while (mainloop) { while (mainloop) {
wrefresh(widget); wrefresh(widget);
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4, prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4,
@ -168,6 +166,8 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
draw_borders(conf, bar, 3, w-6, RAISED); draw_borders(conf, bar, 3, w-6, RAISED);
draw_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/); draw_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
wrefresh(bar); wrefresh(bar);
if (input == NULL) /* that is fd < 0 */
break;
while (true) { while (true) {
fscanf(input, "%s", inputbuf); fscanf(input, "%s", inputbuf);
@ -193,10 +193,11 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
if (strcmp(inputbuf, sep) == 0) if (strcmp(inputbuf, sep) == 0)
break; break;
strcpy(pntext, inputbuf); strcpy(pntext, inputbuf);
pntext += strlen(inputbuf); pntext += strlen(inputbuf); /* end string, no strlen */
pntext[0] = ' '; pntext[0] = ' ';
pntext++; pntext++;
} }
pntext[0] = '\0';
if (update_dialog(conf, shadow, widget, y, x, h, w, textpad, if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
ntext, NULL, false) != 0) ntext, NULL, false) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
@ -216,7 +217,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int mainperc, unsigned int nminibars, const char **minilabels, unsigned int mainperc, unsigned int nminibars, const char **minilabels,
int *minipercs, bool color) int *minipercs, bool color)
{ {
int i, output, miniperc, y, x, h, w, ypad, max_minbarlen; int i, retval, miniperc, y, x, h, w, ypad, max_minbarlen;
int htextpad, htext, wtext; int htextpad, htext, wtext;
int colorperc, red, green; int colorperc, red, green;
WINDOW *widget, *textpad, *bar, *shadow; WINDOW *widget, *textpad, *bar, *shadow;
@ -240,7 +241,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
max_minbarlen = 0; 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 = MAX(max_minbarlen, (int)strcols(minilabels[i]));
max_minbarlen += 3 + 16; /* seps + [...] */ max_minbarlen += 3 + 16; /* seps + [...] */
max_minbarlen = MAX(max_minbarlen, MINMGBARWIDTH); /* mainbar */ max_minbarlen = MAX(max_minbarlen, MINMGBARWIDTH); /* mainbar */
@ -267,10 +268,10 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (set_widget_position(conf, &y, &x, h, w) != 0) if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
output = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, retval = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
NULL, false); NULL, false);
if (output == BSDDIALOG_ERROR) if (retval == BSDDIALOG_ERROR)
return (output); return (retval);
/* mini bars */ /* mini bars */
for (i = 0; i < (int)nminibars; i++) { for (i = 0; i < (int)nminibars; i++) {
@ -281,6 +282,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (color && (miniperc >= 0)) if (color && (miniperc >= 0))
wattron(widget, A_BOLD); wattron(widget, A_BOLD);
mvwaddstr(widget, i+1, 2, minilabels[i]); mvwaddstr(widget, i+1, 2, minilabels[i]);
if (color && (miniperc >= 0))
wattroff(widget, A_BOLD); wattroff(widget, A_BOLD);
/* perc */ /* perc */
if (miniperc < -11) if (miniperc < -11)
@ -338,12 +340,12 @@ bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int mainperc, unsigned int nminibars, int cols, unsigned int mainperc, unsigned int nminibars,
const char **minilabels, int *minipercs) const char **minilabels, int *minipercs)
{ {
int output; int retval;
output = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars, retval = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
minilabels, minipercs, false); minilabels, minipercs, false);
return (output); return (retval);
} }
int int
@ -352,7 +354,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
struct bsddialog_fileminibar *minibar) struct bsddialog_fileminibar *minibar)
{ {
bool update; bool update;
int perc, output, *minipercs; int perc, retval, *minipercs;
unsigned int i, mainperc, totaltodo; unsigned int i, mainperc, totaltodo;
float readforsec; float readforsec;
const char **minilabels; const char **minilabels;
@ -371,7 +373,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
} }
refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1; refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
output = BSDDIALOG_OK; retval = BSDDIALOG_OK;
i = 0; i = 0;
update = true; update = true;
time(&told); time(&told);
@ -384,9 +386,9 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
time(&tnew); time(&tnew);
if (update || tnew > told + refresh) { if (update || tnew > told + refresh) {
output = do_mixedgauge(conf, text, rows, cols, mainperc, retval = do_mixedgauge(conf, text, rows, cols, mainperc,
nminibar, minilabels, minipercs, true); nminibar, minilabels, minipercs, true);
if (output == BSDDIALOG_ERROR) if (retval == BSDDIALOG_ERROR)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
move(SCREENLINES - 1, 2); move(SCREENLINES - 1, 2);
@ -421,7 +423,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
free(minilabels); free(minilabels);
free(minipercs); free(minipercs);
return (output); return (retval);
} }
int int
@ -430,7 +432,8 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
{ {
bool loop, buttupdate, barupdate; bool loop, buttupdate, barupdate;
int y, x, h, w; int y, x, h, w;
int input, currvalue, output, sizebar, bigchange, positions; int currvalue, retval, sizebar, bigchange, positions;
wint_t input;
float perc; float perc;
WINDOW *widget, *textpad, *bar, *shadow; WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs; struct buttons bs;
@ -483,17 +486,18 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(bar); wrefresh(bar);
} }
input = getch(); if (get_wch(&input) == ERR)
continue;
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
*value = currvalue; *value = currvalue;
loop = false; loop = false;
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -587,7 +591,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
@ -596,7 +600,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar); delwin(bar);
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
return (output); return (retval);
} }
int int
@ -604,7 +608,8 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int sec) int cols, unsigned int sec)
{ {
bool loop, buttupdate, barupdate; bool loop, buttupdate, barupdate;
int output, y, x, h, w, input, tout, sizebar; int retval, y, x, h, w, tout, sizebar;
wint_t input;
float perc; float perc;
WINDOW *widget, *textpad, *bar, *shadow; WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs; struct buttons bs;
@ -650,11 +655,10 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
buttupdate = false; buttupdate = false;
} }
input = getch(); if (get_wch(&input) == ERR) { /* timeout */
if (input < 0) { /* timeout */
tout--; tout--;
if (tout < 0) { if (tout < 0) {
output = BSDDIALOG_TIMEOUT; retval = BSDDIALOG_TIMEOUT;
break; break;
} }
else { else {
@ -665,12 +669,12 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -731,7 +735,7 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
@ -742,5 +746,5 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar); delwin(bar);
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
return (output); return (retval);
} }

View File

@ -22,13 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd February 9, 2022 .Dd August 29, 2022
.Dt BSDDIALOG 3 .Dt BSDDIALOG 3
.Os .Os
.Sh NAME .Sh NAME
.Nm bsddialog_backtitle , .Nm bsddialog_backtitle ,
.Nm bsddialog_clearterminal , .Nm bsddialog_clearterminal ,
.Nm bsddialog_color , .Nm bsddialog_color ,
.Nm bsddialog_color_attrs ,
.Nm bsddialog_checklist , .Nm bsddialog_checklist ,
.Nm bsddialog_datebox , .Nm bsddialog_datebox ,
.Nm bsddialog_end , .Nm bsddialog_end ,
@ -36,8 +37,10 @@
.Nm bsddialog_gauge , .Nm bsddialog_gauge ,
.Nm bsddialog_geterror , .Nm bsddialog_geterror ,
.Nm bsddialog_get_theme , .Nm bsddialog_get_theme ,
.Nm bsddialog_hascolors ,
.Nm bsddialog_infobox , .Nm bsddialog_infobox ,
.Nm bsddialog_init , .Nm bsddialog_init ,
.Nm bsddialog_init_notheme ,
.Nm bsddialog_initconf , .Nm bsddialog_initconf ,
.Nm bsddialog_menu , .Nm bsddialog_menu ,
.Nm bsddialog_mixedgauge , .Nm bsddialog_mixedgauge ,
@ -115,6 +118,8 @@
.Ft int .Ft int
.Fn bsddialog_init "void" .Fn bsddialog_init "void"
.Ft int .Ft int
.Fn bsddialog_init_notheme "void"
.Ft int
.Fn bsddialog_initconf "struct bsddialog_conf *conf" .Fn bsddialog_initconf "struct bsddialog_conf *conf"
.Ft int .Ft int
.Fo bsddialog_menu .Fo bsddialog_menu
@ -218,7 +223,16 @@
.Fa "unsigned int flags" .Fa "unsigned int flags"
.Fc .Fc
.Ft int .Ft int
.Fo bsddialog_color_attrs
.Fa "int color"
.Fa "enum bsddialog_color *foreground"
.Fa "enum bsddialog_color *background"
.Fa "unsigned int *flags"
.Fc
.Ft int
.Fn bsddialog_get_theme "struct bsddialog_theme *theme" .Fn bsddialog_get_theme "struct bsddialog_theme *theme"
.Ft bool
.Fn bsddialog_hascolors "void"
.Ft int .Ft int
.Fn bsddialog_set_default_theme "enum bsddialog_default_theme theme" .Fn bsddialog_set_default_theme "enum bsddialog_default_theme theme"
.Ft int .Ft int
@ -239,6 +253,12 @@ API.
restores the screen like before restores the screen like before
.Fn bsddialog_init , .Fn bsddialog_init ,
then it is not possible to use the library functions. then it is not possible to use the library functions.
.Fn bsddialog_init_notheme
is equivalent to
.Fn bsddialog_init
except it does not set the default graphical theme; see
.Sx Theme
subsection to set a theme explicitly.
.Pp .Pp
.Fn bsddialog_error .Fn bsddialog_error
returns a string to describe the last error, it should be called after a returns a string to describe the last error, it should be called after a
@ -258,10 +278,9 @@ is described later.
.Pp .Pp
Each Each
.Fa char* .Fa char*
argument has to be a well terminated string, can be empty argument has to be a well terminated string, it can be a multibyte character
.Pq Dq string depending on current locale, see
but not .Xr setlocale 3 .
.Dv NULL .
.Ss Dialogs .Ss Dialogs
The dialogs have common arguments. The dialogs have common arguments.
.Fa text .Fa text
@ -282,6 +301,8 @@ struct bsddialog_conf {
bool ascii_lines; bool ascii_lines;
unsigned int auto_minheight; unsigned int auto_minheight;
unsigned int auto_minwidth; unsigned int auto_minwidth;
unsigned int auto_topmargin;
unsigned int auto_downmargin;
const char *bottomtitle; const char *bottomtitle;
bool clear; bool clear;
int *get_height; int *get_height;
@ -298,6 +319,7 @@ struct bsddialog_conf {
const char *f1_message; const char *f1_message;
} key; } key;
struct { struct {
unsigned int cols_per_row;
bool highlight; bool highlight;
unsigned int tablen; unsigned int tablen;
} text; } text;
@ -309,11 +331,13 @@ struct bsddialog_conf {
bool shortcut_buttons; bool shortcut_buttons;
} menu; } menu;
struct { struct {
bool enable_wchar; char securech;
int securech; char *securembch;
bool value_wchar;
bool value_without_ok; bool value_without_ok;
} form; } form;
struct { struct {
bool always_active;
bool without_ok; bool without_ok;
const char *ok_label; const char *ok_label;
bool with_extra; bool with_extra;
@ -343,6 +367,23 @@ minimum width if
.Fa cols .Fa cols
is is
.Dv BSDDIALOG_AUTOSIZE . .Dv BSDDIALOG_AUTOSIZE .
.It Fa conf.auto_topmargin
top margin if
.Fa rows
is
.Dv BSDDIALOG_AUTOSIZE
or
.Dv BSDDIALOG_FULLSCREEN ,
.Fa conf.y
has to be
.Dv BSDDIALOG_CENTER .
.It Fa conf.auto_downmargin
down margin if
.Fa rows
is
.Dv BSDDIALOG_AUTOSIZE
or
.Dv BSDDIALOG_FULLSCREEN .
.It Fa conf.bottomtitle .It Fa conf.bottomtitle
subtitle at the dialog bottom side. subtitle at the dialog bottom side.
.It Fa conf.clear .It Fa conf.clear
@ -382,11 +423,16 @@ file to open if F1 is pressed.
message to display if F1 is pressed. message to display if F1 is pressed.
.El .El
.Pp .Pp
.Fa conf.text.highlight .Bl -column -compact
.It Fa conf.text.cols_per_row
Try to set the number of columns for a row of
.Fa text
with autosizing; default
.Dv 10 .
.It Fa conf.text.highlight
enables highlights for enables highlights for
.Fa text , .Fa text ,
properly the following sequences are considered escapes: properly the following sequences are considered escapes:
.Bl -column -compact
.It Dq \eZ0 .It Dq \eZ0
black. black.
.It Dq \eZ1 .It Dq \eZ1
@ -404,7 +450,7 @@ cyan.
.It Dq \eZ7 .It Dq \eZ7
white. white.
.It Dq \eZr .It Dq \eZr
reverse colors between foreground and background. reverse foreground and background.
.It Dq \eZR .It Dq \eZR
disable reverse. disable reverse.
.It Dq \eZb .It Dq \eZb
@ -417,11 +463,22 @@ underline.
disable underline. disable underline.
.It Dq \eZn .It Dq \eZn
disable each customization. disable each customization.
.It Fa conf.text.tablen
tab length for
.Fa text
argument and
.Fn bsddialog_textbox
function.
.El .El
.Fa conf.text.tablen
tab length.
.Pp .Pp
.Bl -column -compact .Bl -column -compact
.It Fa conf.button.always_active
buttons always active, avoidind focus switch between buttons and input fields or
input boxes in
.Fn bsddialog_form ,
.Fn bsddialog_datebox
and
.Fn bsddialog_timebox .
.It Fa conf.button.without_ok .It Fa conf.button.without_ok
disable OK button. disable OK button.
.It Fa conf.button.ok_label .It Fa conf.button.ok_label
@ -598,8 +655,16 @@ enable shortcut keys on buttons, default on items.
.El .El
.Pp .Pp
.Fn bsddialog_form .Fn bsddialog_form
builds a dialog to display a list of items to get strings in input, an item is builds a dialog to display an array of
defined like: .Fa items
of
.Fa nitems
elements to get strings in input.
.Fa formrows
specifies the graphical height for the box around the items,
.Dv 0
for autosizing.
An item is defined like:
.Pp .Pp
.Bd -literal -offset indent -compact .Bd -literal -offset indent -compact
struct bsddialog_formitem { struct bsddialog_formitem {
@ -621,7 +686,7 @@ struct bsddialog_formitem {
.Ed .Ed
.Pp .Pp
.Fa label .Fa label
describes the request, it is printed at the position is a string to describe the request, it is printed at the position
.Fa ylabel .Fa ylabel
and and
.Fa xlabel . .Fa xlabel .
@ -632,45 +697,43 @@ and
.Fa fieldlen .Fa fieldlen
is its graphical width, while is its graphical width, while
.Fa maxvalelen .Fa maxvalelen
is the maximum length of the input string, is the maximum number of characters of the input string.
.Fa init .Fa init
is the default value. is the default field value.
If the OK button is pressed If the OK button is pressed
.Fa value .Fa value
is the allocated memory with the current field string. is the allocated memory with the current field string, its size depends on
the current locale.
.Fa flags .Fa flags
is an OR value to set the is an OR value to set the
.Dv BSDDIALOG_FIELDHIDDEN .Dv BSDDIALOG_FIELDHIDDEN ,
.Dv BSDDIALOG_FIELDREADONLY ,
.Dv BSDDIALOG_FIELDNOCOLOR ,
.Dv BSDDIALOG_FIELDCURSOREND ,
.Dv BSDDIALOG_FIELDEXTEND
and and
.Dv BSDDIALOG_FIELDREADONLY .Dv BSDDIALOG_FIELDSINGLEBYTE .
flags for the field. flags for the field.
.Fa bottomdesc .Fa bottomdesc
is printed on the bottom side of the screen if the item is focused. 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 .Pp
.Fn bsddialog_form .Fn bsddialog_form
can be customized by: can be customized by:
.Bl -column -compact .Bl -column -compact
.It Fa conf.form.enable_wchar
enables characters greater than 127 in the field,
.Fa value
is a pointer to allocated memory for a
.Em wchar_t
string.
.It Fa conf.form.securech .It Fa conf.form.securech
charachter to hide the input charachter to hide the input with
with
.Dv BSDDIALOG_FIELDHIDDEN . .Dv BSDDIALOG_FIELDHIDDEN .
.It Fa conf.form.securembch
multibyte charachter to hide the input with
.Dv BSDDIALOG_FIELDHIDDEN ,
.Fa conf.form.securech
is ignored.
.It Fa conf.form.value_wchar
the allocated
.Fa value
is a
.Em wchar_t*
string.
.It Fa conf.form.value_without_ok .It Fa conf.form.value_without_ok
allocate memory and set allocate memory and set
.Fa value .Fa value
@ -747,8 +810,8 @@ struct bsddialog_theme {
} screen; } screen;
struct { struct {
int color; int color;
unsigned int h; unsigned int y;
unsigned int w; unsigned int x;
} shadow; } shadow;
struct { struct {
int color; int color;
@ -770,20 +833,23 @@ struct bsddialog_theme {
int descsepcolor; int descsepcolor;
int f_shortcutcolor; int f_shortcutcolor;
int shortcutcolor; int shortcutcolor;
int bottomdesccolor;
} menu; } menu;
struct { struct {
int f_fieldcolor; int f_fieldcolor;
int fieldcolor; int fieldcolor;
int readonlycolor; int readonlycolor;
int bottomdesccolor;
} form; } form;
struct { struct {
int f_color; int f_color;
int color; int color;
} bar; } bar;
struct { struct {
unsigned int hmargin; unsigned int minmargin;
int leftdelim; unsigned int maxmargin;
int rightdelim; char leftdelim;
char rightdelim;
int delimcolor; int delimcolor;
int f_delimcolor; int f_delimcolor;
int color; int color;
@ -825,6 +891,8 @@ specifies OR-flags, possible values:
.Dv BSDDIALOG_REVERSE .Dv BSDDIALOG_REVERSE
and and
.Dv BSDDIALOG_UNDERLINE . .Dv BSDDIALOG_UNDERLINE .
.Fn bsddialog_color_attrs
gets the properties of a color.
.Pp .Pp
.Fn bsddialog_set_theme .Fn bsddialog_set_theme
sets sets
@ -840,6 +908,13 @@ and
.Dv BSDDIALOG_THEME_DIALOG , .Dv BSDDIALOG_THEME_DIALOG ,
they can be set via they can be set via
.Fn bsddialog_set_default_theme . .Fn bsddialog_set_default_theme .
.Pp
.Fn bsddialog_hascolors
returns
.Dv true
if the terminal provides colors,
.Dv false
otherwise.
.Sh RETURN VALUES .Sh RETURN VALUES
The functions return the value The functions return the value
.Dv BSDDIALOG_ERROR .Dv BSDDIALOG_ERROR
@ -975,8 +1050,7 @@ for (i = 0; i < 3; i++) {
.Ed .Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr bsddialog 1 , .Xr bsddialog 1 ,
.Xr curses 3 , .Xr curses 3
.Xr ncurses 3
.Sh HISTORY .Sh HISTORY
The The
.Nm bsddialog .Nm bsddialog
@ -985,8 +1059,4 @@ library first appeared in
.Sh AUTHORS .Sh AUTHORS
.Nm bsddialog .Nm bsddialog
was written by was written by
.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com . .An Alfonso Sabato Siciliano Aq Mt asiciliano@FreeBSD.org .
.Sh BUGS
.Fn bsddialog_form
does not resize the dialog after a terminal resize and does not provide
scrolling for items.

View File

@ -30,7 +30,7 @@
#include <stdbool.h> #include <stdbool.h>
#define LIBBSDDIALOG_VERSION "0.2" #define LIBBSDDIALOG_VERSION "0.3"
/* Exit status */ /* Exit status */
#define BSDDIALOG_ERROR -1 #define BSDDIALOG_ERROR -1
@ -64,13 +64,19 @@
#define BSDDIALOG_MG_PENDING -11 #define BSDDIALOG_MG_PENDING -11
/* Form */ /* Form */
#define BSDDIALOG_FIELDHIDDEN 1U #define BSDDIALOG_FIELDHIDDEN 1U
#define BSDDIALOG_FIELDREADONLY 2U #define BSDDIALOG_FIELDREADONLY 2U
#define BSDDIALOG_FIELDNOCOLOR 4U
#define BSDDIALOG_FIELDCURSOREND 8U
#define BSDDIALOG_FIELDEXTEND 16U
#define BSDDIALOG_FIELDSINGLEBYTE 32U
struct bsddialog_conf { struct bsddialog_conf {
bool ascii_lines; bool ascii_lines;
unsigned int auto_minheight; unsigned int auto_minheight;
unsigned int auto_minwidth; unsigned int auto_minwidth;
unsigned int auto_topmargin;
unsigned int auto_downmargin;
const char *bottomtitle; const char *bottomtitle;
bool clear; bool clear;
int *get_height; int *get_height;
@ -87,6 +93,7 @@ struct bsddialog_conf {
const char *f1_message; const char *f1_message;
} key; } key;
struct { struct {
unsigned int cols_per_row;
bool highlight; bool highlight;
unsigned int tablen; unsigned int tablen;
} text; } text;
@ -98,11 +105,13 @@ struct bsddialog_conf {
bool shortcut_buttons; bool shortcut_buttons;
} menu; } menu;
struct { struct {
bool enable_wchar; char securech;
int securech; char *securembch;
bool value_wchar;
bool value_without_ok; bool value_without_ok;
} form; } form;
struct { struct {
bool always_active;
bool without_ok; bool without_ok;
const char *ok_label; const char *ok_label;
bool with_extra; bool with_extra;
@ -156,6 +165,7 @@ struct bsddialog_formitem {
}; };
int bsddialog_init(void); int bsddialog_init(void);
int bsddialog_init_notheme(void);
int bsddialog_end(void); int bsddialog_end(void);
int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle); int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle);
int bsddialog_initconf(struct bsddialog_conf *conf); int bsddialog_initconf(struct bsddialog_conf *conf);

View File

@ -39,8 +39,8 @@ struct bsddialog_theme {
} screen; } screen;
struct { struct {
int color; int color;
unsigned int h; unsigned int y;
unsigned int w; unsigned int x;
} shadow; } shadow;
struct { struct {
int color; int color;
@ -62,20 +62,23 @@ struct bsddialog_theme {
int descsepcolor; int descsepcolor;
int f_shortcutcolor; int f_shortcutcolor;
int shortcutcolor; int shortcutcolor;
int bottomdesccolor;
} menu; } menu;
struct { struct {
int f_fieldcolor; int f_fieldcolor;
int fieldcolor; int fieldcolor;
int readonlycolor; int readonlycolor;
int bottomdesccolor;
} form; } form;
struct { struct {
int f_color; int f_color;
int color; int color;
} bar; } bar;
struct { struct {
unsigned int hmargin; unsigned int minmargin;
int leftdelim; unsigned int maxmargin;
int rightdelim; char leftdelim;
char rightdelim;
int delimcolor; int delimcolor;
int f_delimcolor; int f_delimcolor;
int color; int color;
@ -106,7 +109,11 @@ enum bsddialog_color {
int int
bsddialog_color(enum bsddialog_color foreground, bsddialog_color(enum bsddialog_color foreground,
enum bsddialog_color background, unsigned int flags); enum bsddialog_color background, unsigned int flags);
int
bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
enum bsddialog_color *background, unsigned int *flags);
int bsddialog_get_theme(struct bsddialog_theme *theme); int bsddialog_get_theme(struct bsddialog_theme *theme);
bool bsddialog_hascolors(void);
int bsddialog_set_default_theme(enum bsddialog_default_theme theme); int bsddialog_set_default_theme(enum bsddialog_default_theme theme);
int bsddialog_set_theme(struct bsddialog_theme *theme); int bsddialog_set_theme(struct bsddialog_theme *theme);

File diff suppressed because it is too large Load Diff

View File

@ -39,13 +39,13 @@ infobox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int htext, wtext; int htext, wtext;
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, NULL, 0, SCREENCOLS/2, if (text_size(conf, rows, cols, text, NULL, 0, 1, &htext,
&htext, &wtext) != 0) &wtext) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
} }
if (cols == BSDDIALOG_AUTOSIZE) if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, 0, NULL); *w = widget_min_width(conf, wtext, TEXTHMARGINS + 1, NULL);
if (rows == BSDDIALOG_AUTOSIZE) if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, 0, false); *h = widget_min_height(conf, htext, 0, false);

View File

@ -32,13 +32,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#include "bsddialog.h" #include "bsddialog.h"
#include "bsddialog_theme.h" #include "bsddialog_theme.h"
#include "lib_util.h" #include "lib_util.h"
#define TABLEN 4 /* Default tab len */ #define ERRBUFLEN 1024 /* Error buffer len */
#define ERRBUFLEN 1024 /* Error buffer */
/* Error */ /* Error */
static char errorbuffer[ERRBUFLEN]; static char errorbuffer[ERRBUFLEN];
@ -53,12 +54,101 @@ void set_error_string(const char *str)
strncpy(errorbuffer, str, ERRBUFLEN-1); strncpy(errorbuffer, str, ERRBUFLEN-1);
} }
/* Unicode */
wchar_t* alloc_mbstows(const char *mbstring)
{
size_t charlen, nchar;
mbstate_t mbs;
const char *pmbstring;
wchar_t *wstring;
nchar = 1;
pmbstring = mbstring;
memset(&mbs, 0, sizeof(mbs));
while ((charlen = mbrlen(pmbstring, MB_CUR_MAX, &mbs)) != 0 &&
charlen != (size_t)-1 && charlen != (size_t)-2) {
pmbstring += charlen;
nchar++;
}
if ((wstring = calloc(nchar, sizeof(wchar_t))) == NULL)
return (NULL);
mbstowcs(wstring, mbstring, nchar);
return (wstring);
}
void mvwaddwch(WINDOW *w, int y, int x, wchar_t wch)
{
wchar_t ws[2];
ws[0] = wch;
ws[1] = L'\0';
mvwaddwstr(w, y, x, ws);
}
int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col)
{
bool multicol;
int w;
unsigned int ncol;
size_t charlen, mb_cur_max;
wchar_t wch;
mbstate_t mbs;
multicol = false;
mb_cur_max = MB_CUR_MAX;
ncol = 0;
memset(&mbs, 0, sizeof(mbs));
while ((charlen = mbrlen(mbstring, mb_cur_max, &mbs)) != 0 &&
charlen != (size_t)-1 && charlen != (size_t)-2) {
if (mbtowc(&wch, mbstring, mb_cur_max) < 0)
return (-1);
w = (wch == L'\t') ? TABSIZE : wcwidth(wch);
ncol += (w < 0) ? 0 : w;
if (w > 1 && wch != L'\t')
multicol = true;
mbstring += charlen;
}
if (cols != NULL)
*cols = ncol;
if (has_multi_col != NULL)
*has_multi_col = multicol;
return (0);
}
unsigned int strcols(const char *mbstring)
{
int w;
unsigned int ncol;
size_t charlen, mb_cur_max;
wchar_t wch;
mbstate_t mbs;
mb_cur_max = MB_CUR_MAX;
ncol = 0;
memset(&mbs, 0, sizeof(mbs));
while ((charlen = mbrlen(mbstring, mb_cur_max, &mbs)) != 0 &&
charlen != (size_t)-1 && charlen != (size_t)-2) {
if (mbtowc(&wch, mbstring, mb_cur_max) < 0)
return (0);
w = (wch == L'\t') ? TABSIZE : wcwidth(wch);
ncol += (w < 0) ? 0 : w;
mbstring += charlen;
}
return (ncol);
}
/* Clear */ /* Clear */
int hide_widget(int y, int x, int h, int w, bool withshadow) int hide_widget(int y, int x, int h, int w, bool withshadow)
{ {
WINDOW *clear; WINDOW *clear;
if ((clear = newwin(h, w, y + t.shadow.h, x + t.shadow.w)) == NULL) if ((clear = newwin(h, w, y + t.shadow.y, x + t.shadow.x)) == NULL)
RETURN_ERROR("Cannot hide the widget"); RETURN_ERROR("Cannot hide the widget");
wbkgd(clear, t.screen.color); wbkgd(clear, t.screen.color);
@ -101,7 +191,7 @@ int f1help(struct bsddialog_conf *conf)
/* Buttons */ /* Buttons */
static void static void
draw_button(WINDOW *window, int y, int x, int size, const char *text, draw_button(WINDOW *window, int y, int x, int size, const char *text,
bool selected, bool shortcut) wchar_t first, bool selected, bool shortcut)
{ {
int i, color_arrows, color_shortkey, color_button; int i, color_arrows, color_shortkey, color_button;
@ -126,14 +216,14 @@ draw_button(WINDOW *window, int y, int x, int size, const char *text,
mvwaddch(window, y, x + i, t.button.rightdelim); mvwaddch(window, y, x + i, t.button.rightdelim);
wattroff(window, color_arrows); wattroff(window, color_arrows);
x = x + 1 + ((size - 2 - strlen(text))/2); x = x + 1 + ((size - 2 - strcols(text))/2);
wattron(window, color_button); wattron(window, color_button);
mvwaddstr(window, y, x, text); mvwaddstr(window, y, x, text);
wattroff(window, color_button); wattroff(window, color_button);
if (shortcut) { if (shortcut) {
wattron(window, color_shortkey); wattron(window, color_shortkey);
mvwaddch(window, y, x, text[0]); mvwaddwch(window, y, x, first);
wattroff(window, color_shortkey); wattroff(window, color_shortkey);
} }
} }
@ -142,16 +232,28 @@ void
draw_buttons(WINDOW *window, struct buttons bs, bool shortcut) draw_buttons(WINDOW *window, struct buttons bs, bool shortcut)
{ {
int i, x, startx, y, rows, cols; int i, x, startx, y, rows, cols;
unsigned int newmargin, margin, wbuttons;
getmaxyx(window, rows, cols); getmaxyx(window, rows, cols);
y = rows - 2; y = rows - 2;
startx = cols/2 - buttons_width(bs)/2; newmargin = cols - VBORDERS - (bs.nbuttons * bs.sizebutton);
newmargin /= (bs.nbuttons + 1);
newmargin = MIN(newmargin, t.button.maxmargin);
if (newmargin == 0) {
margin = t.button.minmargin;
wbuttons = buttons_min_width(bs);
} else {
margin = newmargin;
wbuttons = bs.nbuttons * bs.sizebutton;
wbuttons += (bs.nbuttons + 1) * margin;
}
startx = (cols)/2 - wbuttons/2 + newmargin;
for (i = 0; i < (int)bs.nbuttons; i++) { for (i = 0; i < (int)bs.nbuttons; i++) {
x = i * (bs.sizebutton + t.button.hmargin); x = i * (bs.sizebutton + margin);
draw_button(window, y, startx + x, bs.sizebutton, bs.label[i], draw_button(window, y, startx + x, bs.sizebutton, bs.label[i],
i == bs.curr, shortcut); bs.first[i], i == bs.curr, shortcut);
} }
} }
@ -163,6 +265,7 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
#define SIZEBUTTON 8 #define SIZEBUTTON 8
#define DEFAULT_BUTTON_LABEL BUTTON_OK_LABEL #define DEFAULT_BUTTON_LABEL BUTTON_OK_LABEL
#define DEFAULT_BUTTON_VALUE BSDDIALOG_OK #define DEFAULT_BUTTON_VALUE BSDDIALOG_OK
wchar_t first;
bs->nbuttons = 0; bs->nbuttons = 0;
bs->curr = 0; bs->curr = 0;
@ -216,6 +319,11 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
bs->nbuttons = 1; bs->nbuttons = 1;
} }
for (i = 0; i < (int)bs->nbuttons; i++) {
mbtowc(&first, bs->label[i], MB_CUR_MAX);
bs->first[i] = first;
}
if (conf->button.default_label != NULL) { if (conf->button.default_label != NULL) {
for (i = 0; i < (int)bs->nbuttons; i++) { for (i = 0; i < (int)bs->nbuttons; i++) {
if (strcmp(conf->button.default_label, if (strcmp(conf->button.default_label,
@ -224,31 +332,31 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
} }
} }
bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0])); bs->sizebutton = MAX(SIZEBUTTON - 2, strcols(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 = MAX(bs->sizebutton, strcols(bs->label[i]));
bs->sizebutton += 2; bs->sizebutton += 2;
} }
int buttons_width(struct buttons bs) int buttons_min_width(struct buttons bs)
{ {
unsigned int width; unsigned int width;
width = bs.nbuttons * bs.sizebutton; width = bs.nbuttons * bs.sizebutton;
if (bs.nbuttons > 0) if (bs.nbuttons > 0)
width += (bs.nbuttons - 1) * t.button.hmargin; width += (bs.nbuttons - 1) * t.button.minmargin;
return (width); return (width);
} }
bool shortcut_buttons(int key, struct buttons *bs) bool shortcut_buttons(wint_t key, struct buttons *bs)
{ {
bool match; bool match;
unsigned int i; unsigned int i;
match = false; match = false;
for (i = 0; i < bs->nbuttons; i++) { for (i = 0; i < bs->nbuttons; i++) {
if (tolower(key) == tolower(bs->label[i][0])) { if (towlower(key) == towlower(bs->first[i])) {
bs->curr = i; bs->curr = i;
match = true; match = true;
break; break;
@ -259,48 +367,51 @@ bool shortcut_buttons(int key, struct buttons *bs)
} }
/* Text */ /* Text */
static bool is_text_attr(const char *text) static bool is_wtext_attr(const wchar_t *wtext)
{ {
if (strnlen(text, 3) < 3) if (wcsnlen(wtext, 3) < 3)
return (false); return (false);
if (text[0] != '\\' || text[1] != 'Z') if (wtext[0] != L'\\' || wtext[1] != L'Z')
return (false); return (false);
return (strchr("nbBrRuU01234567", text[2]) == NULL ? false : true); return (wcschr(L"nbBrRuU01234567", wtext[2]) == NULL ? false : true);
} }
static bool check_set_text_attr(WINDOW *win, char *text) static bool check_set_wtext_attr(WINDOW *win, wchar_t *wtext)
{ {
if (is_text_attr(text) == false) enum bsddialog_color bg;
if (is_wtext_attr(wtext) == false)
return (false); return (false);
if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) { if ((wtext[2] - L'0') >= 0 && (wtext[2] - L'0') < 8) {
wattron(win, bsddialog_color(text[2] - '0', COLOR_WHITE, 0)); bsddialog_color_attrs(t.dialog.color, NULL, &bg, NULL);
wattron(win, bsddialog_color(wtext[2] - L'0', bg, 0));
return (true); return (true);
} }
switch (text[2]) { switch (wtext[2]) {
case 'n': case L'n':
wattron(win, t.dialog.color); wattron(win, t.dialog.color);
wattrset(win, A_NORMAL); wattrset(win, A_NORMAL);
break; break;
case 'b': case L'b':
wattron(win, A_BOLD); wattron(win, A_BOLD);
break; break;
case 'B': case L'B':
wattroff(win, A_BOLD); wattroff(win, A_BOLD);
break; break;
case 'r': case L'r':
wattron(win, A_REVERSE); wattron(win, A_REVERSE);
break; break;
case 'R': case L'R':
wattroff(win, A_REVERSE); wattroff(win, A_REVERSE);
break; break;
case 'u': case L'u':
wattron(win, A_UNDERLINE); wattron(win, A_UNDERLINE);
break; break;
case 'U': case L'U':
wattroff(win, A_UNDERLINE); wattroff(win, A_UNDERLINE);
break; break;
} }
@ -308,21 +419,27 @@ static bool check_set_text_attr(WINDOW *win, char *text)
return (true); return (true);
} }
/* Word Wrapping */
static void static void
print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str, print_string(WINDOW *win, int *rows, int cols, int *y, int *x, wchar_t *str,
bool color) bool color)
{ {
int i, j, len, reallen; int i, j, len, reallen, wc;
wchar_t ws[2];
len = reallen = strlen(str); ws[1] = L'\0';
len = wcslen(str);
if (color) { if (color) {
reallen = 0;
i=0; i=0;
while (i < len) { while (i < len) {
if (is_text_attr(str+i)) if (is_wtext_attr(str+i) == false)
reallen -= 3; reallen += wcwidth(str[i]);
i++; i++;
} }
} } else
reallen = wcswidth(str, len);
i = 0; i = 0;
while (i < len) { while (i < len) {
@ -336,13 +453,18 @@ print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str,
} }
j = *x; j = *x;
while (j < cols && i < len) { while (j < cols && i < len) {
if (color && check_set_text_attr(win, str+i)) { if (color && check_set_wtext_attr(win, str+i)) {
i += 3; i += 3;
} else if (j + wcwidth(str[i]) > cols) {
break;
} else { } else {
mvwaddch(win, *y, j, str[i]); /* inline mvwaddwch() for efficiency */
ws[0] = str[i];
mvwaddwstr(win, *y, j, ws);
wc = wcwidth(str[i]);;
reallen -= wc;
j += wc;
i++; i++;
reallen--;
j++;
*x = j; *x = j;
} }
} }
@ -354,35 +476,38 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
{ {
bool loop; bool loop;
int i, j, z, rows, cols, x, y, tablen; int i, j, z, rows, cols, x, y, tablen;
char *string; wchar_t *wtext, *string;
if ((string = malloc(strlen(text) + 1)) == NULL) if ((wtext = alloc_mbstows(text)) == NULL)
RETURN_ERROR("Cannot allocate/print text in wchar_t*");
if ((string = calloc(wcslen(wtext) + 1, sizeof(wchar_t))) == NULL)
RETURN_ERROR("Cannot build (analyze) text"); RETURN_ERROR("Cannot build (analyze) text");
getmaxyx(pad, rows, cols); getmaxyx(pad, rows, cols);
tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen; tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
i = j = x = y = 0; i = j = x = y = 0;
loop = true; loop = true;
while (loop) { while (loop) {
string[j] = text[i]; string[j] = wtext[i];
if (strchr("\n\t ", string[j]) != NULL || string[j] == '\0') { if (wcschr(L"\n\t ", string[j]) != NULL || string[j] == L'\0') {
string[j] = '\0'; string[j] = L'\0';
print_string(pad, &rows, cols, &y, &x, string, print_string(pad, &rows, cols, &y, &x, string,
conf->text.highlight); conf->text.highlight);
} }
switch (text[i]) { switch (wtext[i]) {
case '\0': case L'\0':
loop = false; loop = false;
break; break;
case '\n': case L'\n':
x = 0; x = 0;
y++; y++;
j = -1; j = -1;
break; break;
case '\t': case L'\t':
for (z = 0; z < tablen; z++) { for (z = 0; z < tablen; z++) {
if (x >= cols) { if (x >= cols) {
x = 0; x = 0;
@ -392,7 +517,7 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
} }
j = -1; j = -1;
break; break;
case ' ': case L' ':
x++; x++;
if (x >= cols) { if (x >= cols) {
x = 0; x = 0;
@ -410,79 +535,133 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
i++; i++;
} }
free(wtext);
free(string); free(string);
return (0); return (0);
} }
/* Autosize */ /* Text Autosize */
static int #define NL -1
text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows, #define WS -2
int mincols, bool increasecols, int *h, int *w) #define TB -3
{
int i, j, z, x, y; struct textproperties {
int tablen, wordlen, maxwordlen, nword, maxwords, line, maxwidth; int nword;
int *words; int *words;
#define NL -1 uint8_t *wletters;
#define WS -2 int maxwordcols;
int maxline;
bool hasnewline;
};
static int
text_properties(struct bsddialog_conf *conf, const char *text,
struct textproperties *tp)
{
int i, l, currlinecols, maxwords, wtextlen, tablen, wordcols;
wchar_t *wtext;
tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
maxwords = 1024; maxwords = 1024;
if ((words = calloc(maxwords, sizeof(int))) == NULL) if ((tp->words = calloc(maxwords, sizeof(int))) == NULL)
RETURN_ERROR("Cannot alloc memory for text autosize"); RETURN_ERROR("Cannot alloc memory for text autosize");
tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen; if ((wtext = alloc_mbstows(text)) == NULL)
maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS; RETURN_ERROR("Cannot allocate/autosize text in wchar_t*");
wtextlen = wcslen(wtext);
if ((tp->wletters = calloc(wtextlen, sizeof(uint8_t))) == NULL)
RETURN_ERROR("Cannot allocate wletters for text autosizing");
nword = 0; tp->nword = 0;
wordlen = 0; tp->maxline = 0;
maxwordlen = 0; tp->maxwordcols = 0;
i=0; tp->hasnewline = false;
while (true) { currlinecols = 0;
if (conf->text.highlight && is_text_attr(text + i)) { wordcols = 0;
i += 3; l = 0;
for (i = 0; i < wtextlen; i++) {
if (conf->text.highlight && is_wtext_attr(wtext + i)) {
i += 2; /* +1 for update statement */
continue; continue;
} }
if (nword + tablen + 1 >= maxwords) { if (tp->nword + 1 >= maxwords) {
maxwords += 1024; maxwords += 1024;
words = realloc(words, maxwords * sizeof(int)); tp->words = realloc(tp->words, maxwords * sizeof(int));
if (words == NULL) if (tp->words == NULL)
RETURN_ERROR("Cannot realloc memory for text " RETURN_ERROR("Cannot realloc memory for text "
"autosize"); "autosize");
} }
if (text[i] == '\0') { if (wcschr(L"\t\n ", wtext[i]) != NULL) {
words[nword] = wordlen; tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
maxwordlen = MAX(wordlen, maxwordlen);
break;
}
if (strchr("\t\n ", text[i]) != NULL) { if (wordcols != 0) {
maxwordlen = MAX(wordlen, maxwordlen); /* line */
currlinecols += wordcols;
if (wordlen != 0) { /* word */
words[nword] = wordlen; tp->words[tp->nword] = wordcols;
nword++; tp->nword += 1;
wordlen = 0; wordcols = 0;
} }
if (text[i] == '\t') { switch (wtext[i]) {
for (j = 0; j < tablen; j++) case L'\t':
words[nword + j] = 1; /* line */
nword += tablen; currlinecols += tablen;
} else { /* word */
words[nword] = text[i] == '\n' ? NL : WS; tp->words[tp->nword] = TB;
nword++; break;
case L'\n':
/* line */
tp->hasnewline = true;
tp->maxline = MAX(tp->maxline, currlinecols);
currlinecols = 0;
/* word */
tp->words[tp->nword] = NL;
break;
case L' ':
/* line */
currlinecols += 1;
/* word */
tp->words[tp->nword] = WS;
break;
} }
tp->nword += 1;
} else {
tp->wletters[l] = wcwidth(wtext[i]);
wordcols += tp->wletters[l];
l++;
} }
else
wordlen++;
i++;
} }
/* word */
if (wordcols != 0) {
tp->words[tp->nword] = wordcols;
tp->nword += 1;
tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
}
/* line */
tp->maxline = MAX(tp->maxline, currlinecols);
free(wtext);
return (0);
}
static int
text_autosize(struct bsddialog_conf *conf, struct textproperties *tp,
int maxrows, int mincols, bool increasecols, int *h, int *w)
{
int i, j, x, y, z, l, line, maxwidth, tablen;
maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS;
tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
if (increasecols) { if (increasecols) {
mincols = MAX(mincols, maxwordlen); mincols = MAX(mincols, tp->maxwordcols);
mincols = MAX(mincols, mincols = MAX(mincols,
(int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS); (int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS);
mincols = MIN(mincols, maxwidth); mincols = MIN(mincols, maxwidth);
@ -492,26 +671,50 @@ text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
x = 0; x = 0;
y = 1; y = 1;
line=0; line=0;
for (i = 0; i <= nword; i++) { l = 0;
if (words[i] == NL) { for (i = 0; i < tp->nword; i++) {
switch (tp->words[i]) {
case TB:
for (j = 0; j < tablen; j++) {
if (x >= mincols) {
x = 0;
y++;
}
x++;
}
break;
case NL:
y++; y++;
x = 0; x = 0;
} break;
else if (words[i] == WS) { case WS:
x++; x++;
if (x >= mincols) { if (x >= mincols) {
x = 0; x = 0;
y++; y++;
} }
} break;
else { default:
if (words[i] + x <= mincols) if (tp->words[i] + x <= mincols) {
x += words[i]; x += tp->words[i];
else { for (z = 0 ; z != tp->words[i]; l++ )
for (z = words[i]; z > 0; ) { z += tp->wletters[l];
y++; } else if (tp->words[i] <= mincols) {
x = MIN(mincols, z); y++;
z -= x; x = tp->words[i];
for (z = 0 ; z != tp->words[i]; l++ )
z += tp->wletters[l];
} else {
for (j = tp->words[i]; j > 0; ) {
y = (x == 0) ? y : y + 1;
z = 0;
while (z != j && z < mincols) {
z += tp->wletters[l];
l++;
}
x = z;
line = MAX(line, x);
j -= z;
} }
} }
} }
@ -520,16 +723,16 @@ text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
if (increasecols == false) if (increasecols == false)
break; break;
if (y <= maxrows || mincols >= maxwidth) if (mincols >= maxwidth)
break;
if (line >= y * (int)conf->text.cols_per_row && y <= maxrows)
break; break;
mincols++; mincols++;
} }
*h = (nword == 0 && words[0] == 0) ? 0 : y; *h = (tp->nword == 0) ? 0 : y;
*w = MIN(mincols, line); /* wtext can be less than mincols */ *w = MIN(mincols, line); /* wtext can be less than mincols */
free(words);
return (0); return (0);
} }
@ -537,13 +740,26 @@ int
text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text, text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext) struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext)
{ {
int wbuttons, maxhtext;
bool changewtext; bool changewtext;
int wbuttons, maxhtext;
struct textproperties tp;
wbuttons = 0; wbuttons = 0;
if (bs != NULL) if (bs != NULL)
wbuttons = buttons_width(*bs); wbuttons = buttons_min_width(*bs);
/* Rows */
if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) {
maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext;
} else { /* fixed */
maxhtext = rows - VBORDERS - rowsnotext;
}
if (bs != NULL)
maxhtext -= 2;
if (maxhtext <= 0)
maxhtext = 1; /* text_autosize() computes always htext */
/* Cols */
if (cols == BSDDIALOG_AUTOSIZE) { if (cols == BSDDIALOG_AUTOSIZE) {
startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS); startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS);
changewtext = true; changewtext = true;
@ -555,45 +771,52 @@ text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
changewtext = false; 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) if (startwtext <= 0 && changewtext)
startwtext = 1; startwtext = 1;
if (maxhtext <= 0 || startwtext <= 0) { if (startwtext <= 0)
*htext = *wtext = 0; RETURN_ERROR("Fullscreen or fixed cols to print text <=0");
return (0);
}
if (text_autosize(conf, text, maxhtext, startwtext, changewtext, /* Sizing calculation */
htext, wtext) != 0) if (text_properties(conf, text, &tp) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (text_autosize(conf, &tp, maxhtext, startwtext, changewtext, htext,
wtext) != 0)
return (BSDDIALOG_ERROR);
free(tp.words);
free(tp.wletters);
return (0); return (0);
} }
/* Widget size and position */
int widget_max_height(struct bsddialog_conf *conf) int widget_max_height(struct bsddialog_conf *conf)
{ {
int maxheight; int maxheight;
maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.h : SCREENLINES; maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.y : SCREENLINES;
if (maxheight <= 0) if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - shadow <= 0"); RETURN_ERROR("Terminal too small, screen lines - shadow <= 0");
if (conf->y > 0) { if (conf->y != BSDDIALOG_CENTER && conf->auto_topmargin > 0)
RETURN_ERROR("conf.y > 0 and conf->auto_topmargin > 0");
else if (conf->y == BSDDIALOG_CENTER) {
maxheight -= conf->auto_topmargin;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - top "
"margins <= 0");
} else if (conf->y > 0) {
maxheight -= conf->y; maxheight -= conf->y;
if (maxheight <= 0) if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - " RETURN_ERROR("Terminal too small, screen lines - "
"shadow - y <= 0"); "shadow - y <= 0");
} }
maxheight -= conf->auto_downmargin;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - Down margins "
"<= 0");
return (maxheight); return (maxheight);
} }
@ -601,7 +824,7 @@ int widget_max_width(struct bsddialog_conf *conf)
{ {
int maxwidth; int maxwidth;
maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.w : SCREENCOLS; maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.x : SCREENCOLS;
if (maxwidth <= 0) if (maxwidth <= 0)
RETURN_ERROR("Terminal too small, screen cols - shadow <= 0"); RETURN_ERROR("Terminal too small, screen cols - shadow <= 0");
@ -648,13 +871,13 @@ widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
struct buttons *bs) struct buttons *bs)
{ {
int min, delimtitle; int min, delimtitle, wbottomtitle, wtitle;
min = 0; min = 0;
/* buttons */ /* buttons */
if (bs != NULL) if (bs != NULL)
min += buttons_width(*bs); min += buttons_min_width(*bs);
/* text */ /* text */
if (wtext > 0) if (wtext > 0)
@ -666,12 +889,15 @@ widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
/* title */ /* title */
if (conf->title != NULL) { if (conf->title != NULL) {
delimtitle = t.dialog.delimtitle ? 2 : 0; delimtitle = t.dialog.delimtitle ? 2 : 0;
min = MAX(min, (int)strlen(conf->title) + 2 + delimtitle); wtitle = strcols(conf->title);
min = MAX(min, wtitle + 2 + delimtitle);
} }
/* bottom title */ /* bottom title */
if (conf->bottomtitle != NULL) if (conf->bottomtitle != NULL) {
min = MAX(min, (int)strlen(conf->bottomtitle) + 4); wbottomtitle = strcols(conf->bottomtitle);
min = MAX(min, wbottomtitle + 4);
}
/* dialog borders */ /* dialog borders */
min += VBORDERS; min += VBORDERS;
@ -722,8 +948,16 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
int int
set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w) set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
{ {
if (conf->y == BSDDIALOG_CENTER) int hshadow = conf->shadow ? (int)t.shadow.y : 0;
*y = SCREENLINES/2 - (h + t.shadow.h)/2; int wshadow = conf->shadow ? (int)t.shadow.x : 0;
if (conf->y == BSDDIALOG_CENTER) {
*y = SCREENLINES/2 - (h + hshadow)/2;
if (*y < (int)conf->auto_topmargin)
*y = conf->auto_topmargin;
if (*y + h + hshadow > SCREENLINES - (int)conf->auto_downmargin)
*y = SCREENLINES - h - hshadow - conf->auto_downmargin;
}
else if (conf->y < BSDDIALOG_CENTER) else if (conf->y < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin y (less than -1)"); RETURN_ERROR("Negative begin y (less than -1)");
else if (conf->y >= SCREENLINES) else if (conf->y >= SCREENLINES)
@ -731,13 +965,13 @@ set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
else else
*y = conf->y; *y = conf->y;
if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > SCREENLINES) if (*y + h + hshadow > SCREENLINES)
RETURN_ERROR("The lower of the box under the terminal " RETURN_ERROR("The lower of the box under the terminal "
"(begin Y + height (+ shadow) > terminal lines)"); "(begin Y + height (+ shadow) > terminal lines)");
if (conf->x == BSDDIALOG_CENTER) if (conf->x == BSDDIALOG_CENTER)
*x = SCREENCOLS/2 - (w + t.shadow.w)/2; *x = SCREENCOLS/2 - (w + wshadow)/2;
else if (conf->x < BSDDIALOG_CENTER) else if (conf->x < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin x (less than -1)"); RETURN_ERROR("Negative begin x (less than -1)");
else if (conf->x >= SCREENCOLS) else if (conf->x >= SCREENCOLS)
@ -745,14 +979,14 @@ set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
else else
*x = conf->x; *x = conf->x;
if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > SCREENCOLS) if ((*x + w + wshadow) > SCREENCOLS)
RETURN_ERROR("The right of the box over the terminal " RETURN_ERROR("The right of the box over the terminal "
"(begin X + width (+ shadow) > terminal cols)"); "(begin X + width (+ shadow) > terminal cols)");
return (0); return (0);
} }
/* Widgets builders */ /* Widgets build, update, destroy */
void void
draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols, draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
enum elevation elev) enum elevation elev)
@ -816,7 +1050,7 @@ static int
draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
WINDOW *textpad, const char *text, struct buttons *bs, bool shortcutbuttons) WINDOW *textpad, const char *text, struct buttons *bs, bool shortcutbuttons)
{ {
int h, w, ts, ltee, rtee; int h, w, wtitle, wbottomtitle, ts, ltee, rtee;
ts = conf->ascii_lines ? '-' : ACS_HLINE; ts = conf->ascii_lines ? '-' : ACS_HLINE;
ltee = conf->ascii_lines ? '+' : ACS_LTEE; ltee = conf->ascii_lines ? '+' : ACS_LTEE;
@ -830,13 +1064,15 @@ draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
draw_borders(conf, widget, h, w, RAISED); draw_borders(conf, widget, h, w, RAISED);
if (conf->title != NULL) { if (conf->title != NULL) {
if ((wtitle = strcols(conf->title)) < 0)
return (BSDDIALOG_ERROR);
if (t.dialog.delimtitle && conf->no_lines == false) { if (t.dialog.delimtitle && conf->no_lines == false) {
wattron(widget, t.dialog.lineraisecolor); wattron(widget, t.dialog.lineraisecolor);
mvwaddch(widget, 0, w/2-strlen(conf->title)/2-1, rtee); mvwaddch(widget, 0, w/2 - wtitle/2 -1, rtee);
wattroff(widget, t.dialog.lineraisecolor); wattroff(widget, t.dialog.lineraisecolor);
} }
wattron(widget, t.dialog.titlecolor); wattron(widget, t.dialog.titlecolor);
mvwaddstr(widget, 0, w/2 - strlen(conf->title)/2, conf->title); mvwaddstr(widget, 0, w/2 - wtitle/2, conf->title);
wattroff(widget, t.dialog.titlecolor); wattroff(widget, t.dialog.titlecolor);
if (t.dialog.delimtitle && conf->no_lines == false) { if (t.dialog.delimtitle && conf->no_lines == false) {
wattron(widget, t.dialog.lineraisecolor); wattron(widget, t.dialog.lineraisecolor);
@ -860,8 +1096,10 @@ draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
} }
if (conf->bottomtitle != NULL) { if (conf->bottomtitle != NULL) {
if ((wbottomtitle = strcols(conf->bottomtitle)) < 0)
return (BSDDIALOG_ERROR);
wattron(widget, t.dialog.bottomtitlecolor); wattron(widget, t.dialog.bottomtitlecolor);
wmove(widget, h - 1, w/2 - strlen(conf->bottomtitle)/2 - 1); wmove(widget, h - 1, w/2 - wbottomtitle/2 - 1);
waddch(widget, ' '); waddch(widget, ' ');
waddstr(widget, conf->bottomtitle); waddstr(widget, conf->bottomtitle);
waddch(widget, ' '); waddch(widget, ' ');
@ -886,7 +1124,7 @@ update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
if (conf->shadow) { if (conf->shadow) {
wclear(shadow); wclear(shadow);
mvwin(shadow, y + t.shadow.h, x + t.shadow.w); mvwin(shadow, y + t.shadow.y, x + t.shadow.x);
wresize(shadow, h, w); wresize(shadow, h, w);
} }
@ -913,7 +1151,7 @@ new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y,
int error; int error;
if (conf->shadow) { if (conf->shadow) {
*shadow = newwin(h, w, y + t.shadow.h, x + t.shadow.w); *shadow = newwin(h, w, y + t.shadow.y, x + t.shadow.x);
if (*shadow == NULL) if (*shadow == NULL)
RETURN_ERROR("Cannot build shadow"); RETURN_ERROR("Cannot build shadow");
wbkgd(*shadow, t.shadow.color); wbkgd(*shadow, t.shadow.color);

View File

@ -33,8 +33,9 @@
#define TEXTHMARGIN 1 #define TEXTHMARGIN 1
#define TEXTHMARGINS (TEXTHMARGIN + TEXTHMARGIN) #define TEXTHMARGINS (TEXTHMARGIN + TEXTHMARGIN)
/* current theme */ /* theme utils */
extern struct bsddialog_theme t; extern struct bsddialog_theme t;
extern bool hastermcolors;
/* debug */ /* debug */
#define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \ #define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \
@ -42,6 +43,12 @@ extern struct bsddialog_theme t;
refresh(); \ refresh(); \
} while (0) } while (0)
/* unicode */
unsigned int strcols(const char *mbstring);
int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col);
void mvwaddwch(WINDOW *w, int y, int x, wchar_t wch);
wchar_t* alloc_mbstows(const char *mbstring);
/* error buffer */ /* error buffer */
const char *get_error_string(void); const char *get_error_string(void);
void set_error_string(const char *string); void set_error_string(const char *string);
@ -56,6 +63,7 @@ struct buttons {
unsigned int nbuttons; unsigned int nbuttons;
#define MAXBUTTONS 6 /* ok + extra + cancel + help + 2 generics */ #define MAXBUTTONS 6 /* ok + extra + cancel + help + 2 generics */
const char *label[MAXBUTTONS]; const char *label[MAXBUTTONS];
wchar_t first[MAXBUTTONS];
int value[MAXBUTTONS]; int value[MAXBUTTONS];
int curr; int curr;
unsigned int sizebutton; /* including left and right delimiters */ unsigned int sizebutton; /* including left and right delimiters */
@ -70,8 +78,8 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
void void
draw_buttons(WINDOW *window, struct buttons bs, bool shortcut); draw_buttons(WINDOW *window, struct buttons bs, bool shortcut);
int buttons_width(struct buttons bs); int buttons_min_width(struct buttons bs);
bool shortcut_buttons(int key, struct buttons *bs); bool shortcut_buttons(wint_t key, struct buttons *bs);
/* help window with F1 key */ /* help window with F1 key */
int f1help(struct bsddialog_conf *conf); int f1help(struct bsddialog_conf *conf);
@ -130,4 +138,4 @@ void
end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
WINDOW *textpad); WINDOW *textpad);
#endif #endif

View File

@ -34,10 +34,11 @@
#include "bsddialog_theme.h" #include "bsddialog_theme.h"
#include "lib_util.h" #include "lib_util.h"
int bsddialog_init(void) #define COLSPERROW 10 /* Default conf.text.columns_per_row */
int bsddialog_init_notheme(void)
{ {
int i, j, c, error; int i, j, c, error;
enum bsddialog_default_theme theme;
set_error_string(""); set_error_string("");
@ -64,7 +65,18 @@ int bsddialog_init(void)
} }
} }
if (error == OK && has_colors()) hastermcolors = (error == OK && has_colors()) ? true : false;
return (BSDDIALOG_OK);
}
int bsddialog_init(void)
{
enum bsddialog_default_theme theme;
bsddialog_init_notheme();
if (bsddialog_hascolors())
theme = BSDDIALOG_THEME_FLAT; theme = BSDDIALOG_THEME_FLAT;
else else
theme = BSDDIALOG_THEME_BLACKWHITE; theme = BSDDIALOG_THEME_BLACKWHITE;
@ -113,6 +125,7 @@ int bsddialog_initconf(struct bsddialog_conf *conf)
conf->y = BSDDIALOG_CENTER; conf->y = BSDDIALOG_CENTER;
conf->x = BSDDIALOG_CENTER; conf->x = BSDDIALOG_CENTER;
conf->shadow = true; conf->shadow = true;
conf->text.cols_per_row = COLSPERROW;
return (BSDDIALOG_OK); return (BSDDIALOG_OK);
} }

View File

@ -177,9 +177,10 @@ getfastprev(int menurows, struct privateitem *pritems, int abs)
static int static int
getnextshortcut(struct bsddialog_conf *conf, int npritems, getnextshortcut(struct bsddialog_conf *conf, int npritems,
struct privateitem *pritems, int abs, int key) struct privateitem *pritems, int abs, wint_t key)
{ {
int i, ch, next; int i, next;
wchar_t wch;
next = -1; next = -1;
for (i = 0; i < npritems; i++) { for (i = 0; i < npritems; i++) {
@ -187,11 +188,11 @@ getnextshortcut(struct bsddialog_conf *conf, int npritems,
continue; continue;
if (conf->menu.no_name) if (conf->menu.no_name)
ch = pritems[i].item->desc[0]; mbtowc(&wch, pritems[i].item->desc, MB_CUR_MAX);
else else
ch = pritems[i].item->name[0]; mbtowc(&wch, pritems[i].item->name, MB_CUR_MAX);
if (ch == key) { if (wch == (wchar_t)key) {
if (i > abs) if (i > abs)
return (i); return (i);
@ -236,12 +237,12 @@ drawseparators(struct bsddialog_conf *conf, WINDOW *pad, int linelen,
} }
name = pritems[i].item->name; name = pritems[i].item->name;
desc = pritems[i].item->desc; desc = pritems[i].item->desc;
labellen = strlen(name) + strlen(desc) + 1; labellen = strcols(name) + strcols(desc) + 1;
wmove(pad, i, labellen < linelen ? linelen/2 - labellen/2 : 0); wmove(pad, i, labellen < linelen ? linelen/2 - labellen/2 : 0);
wattron(pad, t.menu.namesepcolor); wattron(pad, t.menu.namesepcolor);
waddstr(pad, name); waddstr(pad, name);
wattroff(pad, t.menu.namesepcolor); wattroff(pad, t.menu.namesepcolor);
if (strlen(name) > 0 && strlen(desc) > 0) if (strcols(name) > 0 && strcols(desc) > 0)
waddch(pad, ' '); waddch(pad, ' ');
wattron(pad, t.menu.descsepcolor); wattron(pad, t.menu.descsepcolor);
waddstr(pad, desc); waddstr(pad, desc);
@ -254,7 +255,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
struct lineposition pos, struct privateitem *pritem, bool focus) struct lineposition pos, struct privateitem *pritem, bool focus)
{ {
int colordesc, colorname, colorshortcut; int colordesc, colorname, colorshortcut;
const char *shortcut; wchar_t shortcut;
struct bsddialog_menuitem *item; struct bsddialog_menuitem *item;
item = pritem->item; item = pritem->item;
@ -303,24 +304,47 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
wattron(pad, colorshortcut); wattron(pad, colorshortcut);
if (conf->menu.no_name) if (conf->menu.no_name)
shortcut = item->desc; mbtowc(&shortcut, item->desc, MB_CUR_MAX);
else else
shortcut = item->name; mbtowc(&shortcut, item->name, MB_CUR_MAX);
wmove(pad, y, pos.xname + item->depth * DEPTH); mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut);
if (shortcut != NULL && shortcut[0] != '\0') wattroff(pad, colorshortcut);
waddch(pad, shortcut[0]);
wattroff(pad, colorshortcut);
} }
/* bottom description */ /* bottom description */
move(SCREENLINES - 1, 2); move(SCREENLINES - 1, 2);
clrtoeol(); clrtoeol();
if (item->bottomdesc != NULL && focus) { if (item->bottomdesc != NULL && focus) {
attron(t.menu.bottomdesccolor);
addstr(item->bottomdesc); addstr(item->bottomdesc);
attroff(t.menu.bottomdesccolor);
refresh(); refresh();
} }
} }
/* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
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) {
wattron(menuwin, t.dialog.arrowcolor);
if (ymenupad > 0)
mvwhline(menuwin, 0, 2,
conf->ascii_lines ? '^' : ACS_UARROW, 3);
if ((ymenupad + (int)menurows) < totnitems)
mvwhline(menuwin, h-1, 2,
conf->ascii_lines ? 'v' : ACS_DARROW, 3);
mvwprintw(menuwin, h-1, w-6, "%3d%%",
100 * (ymenupad + menurows) / totnitems);
wattroff(menuwin, t.dialog.arrowcolor);
}
}
static int static int
menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
const char *text, int linelen, unsigned int *menurows, int nitems, const char *text, int linelen, unsigned int *menurows, int nitems,
@ -365,8 +389,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
*/ */
*menurows = MIN(*h - 6 - htext, (int)*menurows); *menurows = MIN(*h - 6 - htext, (int)*menurows);
} else { } else {
if (*menurows == 0) if (*menurows == 0) {
*menurows = MIN(*h-6-htext, nitems); if (*h - 6 - htext <= 0)
*menurows = 0; /* menu_checksize() will check */
else
*menurows = MIN(*h-6-htext, nitems);
}
} }
return (0); return (0);
@ -380,8 +408,7 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
mincols = VBORDERS; mincols = VBORDERS;
/* buttons */ /* buttons */
mincols += buttons_width(bs); mincols += buttons_min_width(bs);
/* /*
* linelen check, comment to allow some hidden col otherwise portconfig * linelen check, comment to allow some hidden col otherwise portconfig
* could not show big menus like www/apache24 * could not show big menus like www/apache24
@ -392,11 +419,11 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
RETURN_ERROR("Few cols, width < size buttons or " RETURN_ERROR("Few cols, width < size buttons or "
"name + descripion of the items"); "name + descripion of the items");
textrow = text != NULL && strlen(text) > 0 ? 1 : 0; textrow = text != NULL && text[0] != '\0' ? 1 : 0;
if (nitems > 0 && menurows == 0) if (nitems > 0 && menurows == 0)
RETURN_ERROR("items > 0 but menurows == 0, probably terminal " RETURN_ERROR("items > 0 but menurows == 0, if menurows = 0 "
"too small"); "terminal too small");
menusize = nitems > 0 ? 3 : 0; menusize = nitems > 0 ? 3 : 0;
if (rows < 2 + 2 + menusize + textrow) if (rows < 2 + 2 + menusize + textrow)
@ -405,37 +432,15 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
return (0); return (0);
} }
/* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
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) {
wattron(menuwin, t.dialog.arrowcolor);
if (ymenupad > 0)
mvwprintw(menuwin, 0, 2, "^^^");
if ((ymenupad + (int)menurows) < totnitems)
mvwprintw(menuwin, h-1, 2, "vvv");
wattroff(menuwin, t.dialog.arrowcolor);
mvwprintw(menuwin, h-1, w-10, "%3d%%",
100 * (ymenupad + menurows) / totnitems);
}
}
static int static int
do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols, do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int menurows, enum menumode mode, unsigned int ngroups, unsigned int menurows, enum menumode mode, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{ {
bool loop, onetrue, movefocus, automenurows, shortcut_butts; bool loop, onetrue, movefocus, automenurows, shortcut_butts;
int i, j, y, x, h, w, output, input; int i, j, y, x, h, w, retval;
int ymenupad, ys, ye, xs, xe, abs, next, totnitems; int ymenupad, ys, ye, xs, xe, abs, next, totnitems;
wint_t input;
WINDOW *shadow, *widget, *textpad, *menuwin, *menupad; WINDOW *shadow, *widget, *textpad, *menuwin, *menupad;
struct buttons bs; struct buttons bs;
struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@ -458,14 +463,14 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (groups[i].type == BSDDIALOG_SEPARATOR) { if (groups[i].type == BSDDIALOG_SEPARATOR) {
pos.maxsepstr = MAX(pos.maxsepstr, pos.maxsepstr = MAX(pos.maxsepstr,
strlen(item->name) + strlen(item->desc)); strcols(item->name) + strcols(item->desc));
continue; continue;
} }
pos.maxprefix = MAX(pos.maxprefix,strlen(item->prefix)); pos.maxprefix = MAX(pos.maxprefix,strcols(item->prefix));
pos.maxdepth = MAX(pos.maxdepth, item->depth); pos.maxdepth = MAX(pos.maxdepth, item->depth);
pos.maxname = MAX(pos.maxname, strlen(item->name)); pos.maxname = MAX(pos.maxname, strcols(item->name));
pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc)); pos.maxdesc = MAX(pos.maxdesc, strcols(item->desc));
} }
} }
pos.maxname = conf->menu.no_name ? 0 : pos.maxname; pos.maxname = conf->menu.no_name ? 0 : pos.maxname;
@ -479,7 +484,6 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
pos.xdesc += (pos.maxname != 0 ? 1 : 0); pos.xdesc += (pos.maxname != 0 ? 1 : 0);
pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc); pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc);
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
if (set_widget_size(conf, rows, cols, &h, &w) != 0) if (set_widget_size(conf, rows, cols, &h, &w) != 0)
@ -498,11 +502,11 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
doupdate(); doupdate();
prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, y + h - menurows,
y + h - menurows, x + 1 + w - TEXTHMARGIN); x + 1 + w - TEXTHMARGIN);
menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2, menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2,
menurows+2, w-4, LOWERED); menurows + 2, w - 4, LOWERED);
menupad = newpad(totnitems, pos.line); menupad = newpad(totnitems, pos.line);
wbkgd(menupad, t.dialog.color); wbkgd(menupad, t.dialog.color);
@ -562,22 +566,23 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
movefocus = false; movefocus = false;
loop = true; loop = true;
while (loop) { while (loop) {
input = getch(); if (get_wch(&input) == ERR)
continue;
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
if (abs >= 0 && pritems[abs].type == MENUMODE) if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true; pritems[abs].on = true;
set_on_output(conf, output, ngroups, groups, pritems); set_on_output(conf, retval, ngroups, groups, pritems);
loop = false; loop = false;
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
if (abs >= 0 && pritems[abs].type == MENUMODE) if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true; pritems[abs].on = true;
set_on_output(conf, output, ngroups, groups, set_on_output(conf, retval, ngroups, groups,
pritems); pritems);
loop = false; loop = false;
} }
@ -714,10 +719,10 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
default: default:
if (shortcut_butts) { if (shortcut_butts) {
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
if (pritems[abs].type == MENUMODE) if (pritems[abs].type == MENUMODE)
pritems[abs].on = true; pritems[abs].on = true;
set_on_output(conf, output, ngroups, set_on_output(conf, retval, ngroups,
groups, pritems); groups, pritems);
loop = false; loop = false;
} }
@ -728,7 +733,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
next = getnextshortcut(conf, totnitems, pritems, abs, next = getnextshortcut(conf, totnitems, pritems, abs,
input); input);
movefocus = next != abs; movefocus = next != abs;
} } /* end switch handler */
if (movefocus) { if (movefocus) {
drawitem(conf, menupad, abs, pos, &pritems[abs], false); drawitem(conf, menupad, abs, pos, &pritems[abs], false);
@ -744,7 +749,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
movefocus = false; movefocus = false;
} }
} } /* end while handler */
if (focuslist != NULL) if (focuslist != NULL)
*focuslist = abs < 0 ? -1 : pritems[abs].group; *focuslist = abs < 0 ? -1 : pritems[abs].group;
@ -756,7 +761,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
free(pritems); free(pritems);
return (output); return (retval);
} }
/* API */ /* API */
@ -765,12 +770,12 @@ bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int ngroups, int cols, unsigned int menurows, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{ {
int output; int retval;
output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE, retval = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
ngroups, groups, focuslist, focusitem); ngroups, groups, focuslist, focusitem);
return (output); return (retval);
} }
int int
@ -778,14 +783,14 @@ bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems, int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem) struct bsddialog_menuitem *items, int *focusitem)
{ {
int output, focuslist = 0; int retval, focuslist = 0;
struct bsddialog_menugroup group = { struct bsddialog_menugroup group = {
BSDDIALOG_CHECKLIST /* unused */, nitems, items}; BSDDIALOG_CHECKLIST /* unused */, nitems, items};
output = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE, retval = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE,
1, &group, &focuslist, focusitem); 1, &group, &focuslist, focusitem);
return (output); return (retval);
} }
int int
@ -793,14 +798,14 @@ bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems, int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem) struct bsddialog_menuitem *items, int *focusitem)
{ {
int output, focuslist = 0; int retval, focuslist = 0;
struct bsddialog_menugroup group = { struct bsddialog_menugroup group = {
BSDDIALOG_CHECKLIST /* unused */, nitems, items}; BSDDIALOG_CHECKLIST /* unused */, nitems, items};
output = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1, retval = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1,
&group, &focuslist, focusitem); &group, &focuslist, focusitem);
return (output); return (retval);
} }
int int
@ -808,12 +813,12 @@ bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems, int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem) struct bsddialog_menuitem *items, int *focusitem)
{ {
int output, focuslist = 0; int retval, focuslist = 0;
struct bsddialog_menugroup group = { struct bsddialog_menugroup group = {
BSDDIALOG_RADIOLIST /* unused */, nitems, items}; BSDDIALOG_RADIOLIST /* unused */, nitems, items};
output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE, retval = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
1, &group, &focuslist, focusitem); 1, &group, &focuslist, focusitem);
return (output); return (retval);
} }

View File

@ -31,18 +31,22 @@
#include <string.h> #include <string.h>
#include "bsddialog.h" #include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h" #include "lib_util.h"
static int static int
message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int *w, const char *text, struct buttons bs) int *w, const char *text, bool *hastext, struct buttons bs)
{ {
int htext, wtext; int htext, wtext;
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE ||
if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2, hastext != NULL) {
&htext, &wtext) != 0) if (text_size(conf, rows, cols, text, &bs, 0, 1, &htext,
&wtext) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (hastext != NULL)
*hastext = htext > 0 ? true : false;
} }
if (cols == BSDDIALOG_AUTOSIZE) if (cols == BSDDIALOG_AUTOSIZE)
@ -54,34 +58,40 @@ message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
return (0); return (0);
} }
static int message_checksize(int rows, int cols, struct buttons bs) static int
message_checksize(int rows, int cols, bool hastext, struct buttons bs)
{ {
int mincols; int mincols;
mincols = VBORDERS; mincols = VBORDERS;
mincols += buttons_width(bs); mincols += buttons_min_width(bs);
if (cols < mincols) 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"); "for borders, buttons and spaces between buttons");
if (rows < HBORDERS + 2 /*buttons*/) if (rows < HBORDERS + 2 /* buttons */)
RETURN_ERROR("Msgbox and Yesno need at least height 4"); RETURN_ERROR("Msgbox and Yesno need at least 4 rows");
if (hastext && rows < HBORDERS + 2 /*buttons*/ + 1 /* text row */)
RETURN_ERROR("Msgbox and Yesno with text need at least 5 rows");
return (0); return (0);
} }
static void static void
textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad) textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad,
bool hastext)
{ {
int y, x, h, w; int y, x, h, w;
getbegyx(widget, y, x); getbegyx(widget, y, x);
getmaxyx(widget, h, w); getmaxyx(widget, h, w);
if (htextpad > h - 4) { if (hastext && htextpad > h - 4) {
wattron(widget, t.dialog.arrowcolor);
mvwprintw(widget, h-3, w-6, "%3d%%", mvwprintw(widget, h-3, w-6, "%3d%%",
100 * (ytextpad+h-4)/ htextpad); 100 * (ytextpad+h-4)/ htextpad);
wattroff(widget, t.dialog.arrowcolor);
wnoutrefresh(widget); wnoutrefresh(widget);
} }
@ -92,15 +102,16 @@ static int
do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
struct buttons bs) struct buttons bs)
{ {
bool loop; bool hastext, loop;
int y, x, h, w, input, output, ytextpad, htextpad, unused; int y, x, h, w, retval, ytextpad, htextpad, unused;
WINDOW *widget, *textpad, *shadow; WINDOW *widget, *textpad, *shadow;
wint_t input;
if (set_widget_size(conf, rows, cols, &h, &w) != 0) 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) if (message_autosize(conf, rows, cols, &h, &w, text, &hastext, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (message_checksize(h, w, bs) != 0) if (message_checksize(h, w, hastext, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0) if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
@ -112,20 +123,21 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
ytextpad = 0; ytextpad = 0;
getmaxyx(textpad, htextpad, unused); getmaxyx(textpad, htextpad, unused);
unused++; /* fix unused error */ unused++; /* fix unused error */
textupdate(widget, textpad, htextpad, ytextpad); textupdate(widget, textpad, htextpad, ytextpad, hastext);
loop = true; loop = true;
while (loop) { while (loop) {
doupdate(); doupdate();
input = getch(); if (get_wch(&input) == ERR)
continue;
switch (input) { switch (input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -163,9 +175,9 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (set_widget_size(conf, rows, cols, &h, &w) != 0) 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, if (message_autosize(conf, rows, cols, &h, &w, text,
bs) != 0) NULL, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (message_checksize(h, w, bs) != 0) if (message_checksize(h, w, hastext, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0) if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
@ -175,7 +187,8 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
getmaxyx(textpad, htextpad, unused); getmaxyx(textpad, htextpad, unused);
textupdate(widget, textpad, htextpad, ytextpad); ytextpad = 0;
textupdate(widget, textpad, htextpad, ytextpad, hastext);
/* Important to fix grey lines expanding screen */ /* Important to fix grey lines expanding screen */
refresh(); refresh();
@ -184,17 +197,17 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (ytextpad == 0) if (ytextpad == 0)
break; break;
ytextpad--; ytextpad--;
textupdate(widget, textpad, htextpad, ytextpad); textupdate(widget, textpad, htextpad, ytextpad, hastext);
break; break;
case KEY_DOWN: case KEY_DOWN:
if (ytextpad + h - 4 >= htextpad) if (ytextpad + h - 4 >= htextpad)
break; break;
ytextpad++; ytextpad++;
textupdate(widget, textpad, htextpad, ytextpad); textupdate(widget, textpad, htextpad, ytextpad, hastext);
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
@ -202,7 +215,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
return (output); return (retval);
} }
/* API */ /* API */

View File

@ -28,18 +28,61 @@
#include <sys/param.h> #include <sys/param.h>
#include <curses.h> #include <curses.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <wchar.h>
#include "bsddialog.h" #include "bsddialog.h"
#include "bsddialog_theme.h" #include "bsddialog_theme.h"
#include "lib_util.h" #include "lib_util.h"
static void
updateborders(struct bsddialog_conf *conf, WINDOW *widget, int padmargin,
int hpad, int wpad, int ypad, int xpad)
{
int h, w;
chtype arrowch, borderch;
getmaxyx(widget, h, w);
if (conf->no_lines)
borderch = ' ';
else if (conf->ascii_lines)
borderch = '|';
else
borderch = ACS_VLINE;
if (xpad > 0) {
arrowch = conf->ascii_lines ? '<' : ACS_LARROW;
arrowch |= A_ATTRIBUTES & t.dialog.arrowcolor;
} else {
arrowch = borderch;
arrowch |= A_ATTRIBUTES & t.dialog.lineraisecolor;
}
mvwvline(widget, (h / 2) - 2, 0, arrowch, 4);
if (xpad + w-2-padmargin < wpad) {
arrowch = conf->ascii_lines ? '>' : ACS_RARROW;
arrowch |= A_ATTRIBUTES & t.dialog.arrowcolor;
} else {
arrowch = borderch;
arrowch |= A_ATTRIBUTES & t.dialog.linelowercolor;
}
mvwvline(widget, (h / 2) - 2, w - 1, arrowch, 4);
if (hpad > h - 4) {
wattron(widget, t.dialog.arrowcolor);
mvwprintw(widget, h-3, w-6, "%3d%%", 100 * (ypad+h-4)/ hpad);
wattroff(widget, t.dialog.arrowcolor);
}
}
static void static void
textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int *w, int hpad, int wpad, struct buttons bs) int *w, int hpad, int wpad, int padmargin, struct buttons bs)
{ {
if (cols == BSDDIALOG_AUTOSIZE) if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, 0, wpad, &bs); *w = widget_min_width(conf, 0, wpad + padmargin, &bs);
if (rows == BSDDIALOG_AUTOSIZE) if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, 0, hpad, true); *h = widget_min_height(conf, 0, hpad, true);
@ -50,7 +93,8 @@ textbox_checksize(int rows, int cols, int hpad, struct buttons bs)
{ {
int mincols; int mincols;
mincols = VBORDERS + bs.sizebutton; mincols = VBORDERS;
mincols += buttons_min_width(bs);
if (cols < mincols) if (cols < mincols)
RETURN_ERROR("Few cols for the textbox"); RETURN_ERROR("Few cols for the textbox");
@ -66,9 +110,11 @@ int
bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows, bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
int cols) int cols)
{ {
bool loop; bool loop, has_multi_col;
int i, output, input; int i, retval, y, x, h, w;
int y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows; int hpad, wpad, ypad, xpad, ys, ye, xs, xe, padmargin, printrows;
unsigned int defaulttablen, linecols;
wint_t input;
char buf[BUFSIZ]; char buf[BUFSIZ];
FILE *fp; FILE *fp;
struct buttons bs; struct buttons bs;
@ -77,14 +123,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
if ((fp = fopen(file, "r")) == NULL) if ((fp = fopen(file, "r")) == NULL)
RETURN_ERROR("Cannot open file"); RETURN_ERROR("Cannot open file");
defaulttablen = TABSIZE;
set_tabsize((conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen);
hpad = 1; hpad = 1;
wpad = 1; wpad = 1;
pad = newpad(hpad, wpad); pad = newpad(hpad, wpad);
wbkgd(pad, t.dialog.color); wbkgd(pad, t.dialog.color);
padmargin = 0;
i = 0; i = 0;
while (fgets(buf, BUFSIZ, fp) != NULL) { while (fgets(buf, BUFSIZ, fp) != NULL) {
if ((int) strlen(buf) > wpad) { if (str_props(buf, &linecols, &has_multi_col) != 0)
wpad = strlen(buf); continue;
if ((int)linecols > wpad) {
wpad = linecols;
wresize(pad, hpad, wpad); wresize(pad, hpad, wpad);
} }
if (i > hpad-1) { if (i > hpad-1) {
@ -93,20 +144,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
} }
mvwaddstr(pad, i, 0, buf); mvwaddstr(pad, i, 0, buf);
i++; i++;
if (has_multi_col)
padmargin = 2;
} }
fclose(fp); fclose(fp);
set_tabsize(defaulttablen);
bs.nbuttons = 1; get_buttons(conf, &bs, "EXIT", NULL);
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.curr = 0;
bs.sizebutton = strlen(bs.label[0]) + 2; bs.nbuttons = 1;
if (set_widget_size(conf, rows, cols, &h, &w) != 0) if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, bs); textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, padmargin, bs);
if (textbox_checksize(h, w, hpad, bs) != 0) if (textbox_checksize(h, w, hpad, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0) if (set_widget_position(conf, &y, &x, h, w) != 0)
@ -117,26 +167,33 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
ys = y + 1; ys = y + 1;
xs = x + 1; xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5; ye = ys + h - 5;
xe = xs + w - 3; xe = xs + w - 3 - padmargin;
ypad = xpad = 0; ypad = xpad = 0;
printrows = h-4; printrows = h-4;
loop = true; loop = true;
while (loop) { while (loop) {
wnoutrefresh(widget); updateborders(conf, widget, padmargin, hpad, wpad, ypad, xpad);
pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe); /*
doupdate(); * Overflow multicolumn charchter right border:
input = getch(); * wnoutrefresh(widget);
* pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe);
* doupdate();
*/
wrefresh(widget);
prefresh(pad, ypad, xpad, ys, xs, ye, xe);
if (get_wch(&input) == ERR)
continue;
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
output = BSDDIALOG_OK; retval = BSDDIALOG_OK;
loop = false; loop = false;
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -164,7 +221,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break; break;
case KEY_RIGHT: case KEY_RIGHT:
case 'l': case 'l':
xpad = (xpad + w-2) < wpad-1 ? xpad + 1 : xpad; xpad = (xpad + w-2-padmargin) < wpad ? xpad + 1 : xpad;
break; break;
case KEY_UP: case KEY_UP:
case 'k': case 'k':
@ -189,16 +246,16 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
if (set_widget_size(conf, rows, cols, &h, &w) != 0) if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad,
bs); padmargin, bs);
if (textbox_checksize(h, w, hpad, bs) != 0) if (textbox_checksize(h, w, hpad, bs) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0) if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
ys = y + 1; ys = y + 1;
xs = x + 1; xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5; ye = ys + h - 5;
xe = xs + w - 3; xe = xs + w - 3 - padmargin;
ypad = xpad = 0; ypad = xpad = 0;
printrows = h - 4; printrows = h - 4;
@ -211,7 +268,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
@ -219,5 +276,5 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
end_dialog(conf, shadow, widget, pad); end_dialog(conf, shadow, widget, pad);
return (output); return (retval);
} }

View File

@ -34,51 +34,53 @@
#define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1)) #define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1))
struct bsddialog_theme t; struct bsddialog_theme t;
bool hastermcolors;
static struct bsddialog_theme bsddialogtheme = { static struct bsddialog_theme bsddialogtheme = {
#define bgwidget COLOR_WHITE
#define bgcurr COLOR_YELLOW
.screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN), .screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadow.h = 1, .shadow.y = 1,
.shadow.w = 2, .shadow.x = 2,
.dialog.delimtitle = true, .dialog.delimtitle = true,
.dialog.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget), .dialog.titlecolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget), .dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget), .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.color = GET_COLOR(COLOR_BLACK, bgwidget), .dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget), .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget), .dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, bgcurr), .menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget), .menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr), .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_YELLOW),
.menu.desccolor = GET_COLOR(COLOR_BLACK, bgwidget), .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_namecolor = GET_COLOR(COLOR_BLACK, bgcurr), .menu.f_namecolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.menu.namecolor = GET_COLOR(COLOR_BLACK, bgwidget), .menu.namecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget), .menu.namesepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget), .menu.descsepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr), .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
.menu.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget), .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN), .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.form.readonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE), .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE),
.form.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE), .bar.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE), .bar.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.hmargin = 3, .button.minmargin = 1,
.button.leftdelim = '[', .button.maxmargin = 5,
.button.rightdelim = ']', .button.leftdelim = '[',
.button.f_delimcolor = GET_COLOR(COLOR_BLACK, bgwidget), .button.rightdelim = ']',
.button.delimcolor = GET_COLOR(COLOR_BLACK, bgwidget), .button.f_delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.f_color = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE, .button.delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.color = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE, .button.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.button.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr) | A_UNDERLINE, .button.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget) | A_UNDERLINE .button.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
.button.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE)
}; };
static struct bsddialog_theme blackwhite = { static struct bsddialog_theme blackwhite = {
@ -87,8 +89,8 @@ static struct bsddialog_theme blackwhite = {
.screen.color = GET_COLOR(fg, bk), .screen.color = GET_COLOR(fg, bk),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadow.h = 1, .shadow.y = 1,
.shadow.w = 2, .shadow.x = 2,
.dialog.delimtitle = true, .dialog.delimtitle = true,
.dialog.titlecolor = GET_COLOR(fg, bk), .dialog.titlecolor = GET_COLOR(fg, bk),
@ -108,15 +110,18 @@ static struct bsddialog_theme blackwhite = {
.menu.descsepcolor = GET_COLOR(fg, bk), .menu.descsepcolor = GET_COLOR(fg, bk),
.menu.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE, .menu.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
.menu.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE, .menu.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE,
.menu.bottomdesccolor = GET_COLOR(fg, bk),
.form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE, .form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
.form.fieldcolor = GET_COLOR(fg, bk), .form.fieldcolor = GET_COLOR(fg, bk),
.form.readonlycolor = GET_COLOR(fg, bk), .form.readonlycolor = GET_COLOR(fg, bk),
.form.bottomdesccolor = GET_COLOR(fg, bk),
.bar.f_color = GET_COLOR(fg, bk) | A_REVERSE, .bar.f_color = GET_COLOR(fg, bk) | A_REVERSE,
.bar.color = GET_COLOR(fg, bk), .bar.color = GET_COLOR(fg, bk),
.button.hmargin = 3, .button.minmargin = 1,
.button.maxmargin = 5,
.button.leftdelim = '[', .button.leftdelim = '[',
.button.rightdelim = ']', .button.rightdelim = ']',
.button.f_delimcolor = GET_COLOR(fg, bk), .button.f_delimcolor = GET_COLOR(fg, bk),
@ -128,11 +133,11 @@ static struct bsddialog_theme blackwhite = {
}; };
static struct bsddialog_theme dialogtheme = { static struct bsddialog_theme dialogtheme = {
.screen.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.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadow.h = 1, .shadow.y = 1,
.shadow.w = 2, .shadow.x = 2,
.dialog.delimtitle = false, .dialog.delimtitle = false,
.dialog.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD, .dialog.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
@ -140,27 +145,30 @@ static struct bsddialog_theme dialogtheme = {
.dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
.dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE), .dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
.dialog.arrowcolor = GET_COLOR(COLOR_GREEN, COLOR_WHITE), .dialog.arrowcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), .menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget), .menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE), .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), .menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE), .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE), .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE),
.menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD, .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
.form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD, .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD,
.form.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD, .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.button.hmargin = 3, .button.minmargin = 1,
.button.maxmargin = 5,
.button.leftdelim = '<', .button.leftdelim = '<',
.button.rightdelim = '>', .button.rightdelim = '>',
.button.f_delimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, .button.f_delimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
@ -177,8 +185,8 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src)
dst->screen.color = src->screen.color; dst->screen.color = src->screen.color;
dst->shadow.color = src->shadow.color; dst->shadow.color = src->shadow.color;
dst->shadow.h = src->shadow.h; dst->shadow.y = src->shadow.y;
dst->shadow.w = src->shadow.w; dst->shadow.x = src->shadow.x;
dst->dialog.delimtitle = src->dialog.delimtitle; dst->dialog.delimtitle = src->dialog.delimtitle;
dst->dialog.titlecolor = src->dialog.titlecolor; dst->dialog.titlecolor = src->dialog.titlecolor;
@ -198,15 +206,18 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src)
dst->menu.descsepcolor = src->menu.descsepcolor; dst->menu.descsepcolor = src->menu.descsepcolor;
dst->menu.f_shortcutcolor = src->menu.f_shortcutcolor; dst->menu.f_shortcutcolor = src->menu.f_shortcutcolor;
dst->menu.shortcutcolor = src->menu.shortcutcolor; dst->menu.shortcutcolor = src->menu.shortcutcolor;
dst->menu.bottomdesccolor = src->menu.bottomdesccolor;
dst->form.f_fieldcolor = src->form.f_fieldcolor; dst->form.f_fieldcolor = src->form.f_fieldcolor;
dst->form.fieldcolor = src->form.fieldcolor; dst->form.fieldcolor = src->form.fieldcolor;
dst->form.readonlycolor = src->form.readonlycolor; dst->form.readonlycolor = src->form.readonlycolor;
dst->form.bottomdesccolor = src->form.bottomdesccolor;
dst->bar.f_color = src->bar.f_color; dst->bar.f_color = src->bar.f_color;
dst->bar.color = src->bar.color; dst->bar.color = src->bar.color;
dst->button.hmargin = src->button.hmargin; dst->button.minmargin = src->button.minmargin;
dst->button.maxmargin = src->button.maxmargin;
dst->button.leftdelim = src->button.leftdelim; dst->button.leftdelim = src->button.leftdelim;
dst->button.rightdelim = src->button.rightdelim; dst->button.rightdelim = src->button.rightdelim;
dst->button.f_delimcolor = src->button.f_delimcolor; dst->button.f_delimcolor = src->button.f_delimcolor;
@ -230,7 +241,7 @@ int bsddialog_get_theme(struct bsddialog_theme *theme)
set_theme(theme, &t); set_theme(theme, &t);
return (0); return (BSDDIALOG_OK);
} }
int bsddialog_set_theme(struct bsddialog_theme *theme) int bsddialog_set_theme(struct bsddialog_theme *theme)
@ -242,7 +253,7 @@ int bsddialog_set_theme(struct bsddialog_theme *theme)
set_theme(&t, theme); set_theme(&t, theme);
return (0); return (BSDDIALOG_OK);
} }
int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme) int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
@ -254,6 +265,7 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
t.dialog.delimtitle = true; t.dialog.delimtitle = true;
t.button.leftdelim = '['; t.button.leftdelim = '[';
t.button.rightdelim = ']'; t.button.rightdelim = ']';
t.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE);
} }
else if (newtheme == BSDDIALOG_THEME_BSDDIALOG) else if (newtheme == BSDDIALOG_THEME_BSDDIALOG)
bsddialog_set_theme(&bsddialogtheme); bsddialog_set_theme(&bsddialogtheme);
@ -264,7 +276,7 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
else else
RETURN_ERROR("Unknow default theme"); RETURN_ERROR("Unknow default theme");
return (0); return (BSDDIALOG_OK);
} }
int int
@ -282,3 +294,32 @@ bsddialog_color(enum bsddialog_color foreground,
return (GET_COLOR(foreground, background) | cursesflags); return (GET_COLOR(foreground, background) | cursesflags);
} }
int
bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
enum bsddialog_color *background, unsigned int *flags)
{
unsigned int flag;
short f, b;
flag = 0U;
flag |= (color & A_BOLD) ? BSDDIALOG_BOLD : 0U;
flag |= (color & A_REVERSE) ? BSDDIALOG_REVERSE : 0U;
flag |= (color & A_UNDERLINE) ? BSDDIALOG_UNDERLINE : 0U;
if (flags != NULL)
*flags = flag;
if (pair_content(PAIR_NUMBER(color), &f, &b) != OK)
RETURN_ERROR("Cannot get color attributes");
if (foreground != NULL)
*foreground = f;
if (background != NULL)
*background = b;
return (BSDDIALOG_OK);
}
bool bsddialog_hascolors(void)
{
return hastermcolors;
}

View File

@ -32,11 +32,42 @@
#include <string.h> #include <string.h>
#include "bsddialog.h" #include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h" #include "lib_util.h"
#define MINWDATE 23 /* 3 windows and their borders */ #define MINWDATE 23 /* 3 windows and their borders */
#define MINWTIME 14 /* 3 windows and their borders */ #define MINWTIME 14 /* 3 windows and their borders */
static void
drawquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
const void *value, bool focus)
{
int h, l, w;
getmaxyx(win, h, w);
draw_borders(conf, win, h, w, LOWERED);
if (focus) {
l = 2 + w%2;
wattron(win, t.dialog.arrowcolor);
mvwhline(win, 0, w/2 - l/2,
conf->ascii_lines ? '^' : ACS_UARROW, l);
mvwhline(win, h-1, w/2 - l/2,
conf->ascii_lines ? 'v' : ACS_DARROW, l);
wattroff(win, t.dialog.arrowcolor);
}
if (focus)
wattron(win, t.menu.f_namecolor);
if (strchr(fmt, 's') != NULL)
mvwprintw(win, 1, 1, fmt, (const char*)value);
else
mvwprintw(win, 1, 1, fmt, *((const int*)value));
if (focus)
wattroff(win, t.menu.f_namecolor);
wrefresh(win);
}
static int static int
datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int *w, int minw, const char *text, struct buttons bs) int *w, int minw, const char *text, struct buttons bs)
@ -50,7 +81,7 @@ datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
} }
if (cols == BSDDIALOG_AUTOSIZE) if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, htext,minw, &bs); *w = widget_min_width(conf, wtext, minw, &bs);
if (rows == BSDDIALOG_AUTOSIZE) if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, 3 /* windows */, true); *h = widget_min_height(conf, htext, 3 /* windows */, true);
@ -64,7 +95,7 @@ datetime_checksize(int rows, int cols, int minw, struct buttons bs)
int mincols; int mincols;
mincols = VBORDERS; mincols = VBORDERS;
mincols += buttons_width(bs); mincols += buttons_min_width(bs);
mincols = MAX(minw, mincols); mincols = MAX(minw, mincols);
if (cols < mincols) if (cols < mincols)
@ -81,7 +112,8 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss) int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss)
{ {
bool loop, focusbuttons; bool loop, focusbuttons;
int i, input, output, y, x, h, w, sel; int i, retval, y, x, h, w, sel;
wint_t input;
WINDOW *widget, *textpad, *shadow; WINDOW *widget, *textpad, *shadow;
struct buttons bs; struct buttons bs;
struct myclockstruct { struct myclockstruct {
@ -131,30 +163,26 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wrefresh(widget); wrefresh(widget);
sel = -1;
loop = focusbuttons = true; loop = focusbuttons = true;
while (loop) { while (loop) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++)
mvwprintw(c[i].win, 1, 1, "%2d", c[i].value); drawquare(conf, c[i].win, "%02d", &c[i].value,
wrefresh(c[i].win); sel == i);
}
if (focusbuttons == false) { if (get_wch(&input) == ERR)
wmove(c[sel].win, 1, 2); continue;
wrefresh(c[sel].win);
}
input = getch();
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
if (focusbuttons == false) if (focusbuttons || conf->button.always_active) {
break; retval = bs.value[bs.curr];
output = bs.value[bs.curr]; loop = false;
loop = false; }
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -165,14 +193,13 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ? focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false; true : false;
if (focusbuttons == false) { if (focusbuttons == false) {
curs_set(1);
sel = 0; sel = 0;
bs.curr = conf->button.always_active ? 0 : -1;
} }
} else { } else {
sel++; sel++;
focusbuttons = sel > 2 ? true : false; focusbuttons = sel > 2 ? true : false;
if (focusbuttons) { if (focusbuttons) {
curs_set(0);
bs.curr = 0; bs.curr = 0;
} }
} }
@ -184,25 +211,28 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
bs.curr--; bs.curr--;
focusbuttons = bs.curr < 0 ? false : true; focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) { if (focusbuttons == false) {
curs_set(1);
sel = 2; sel = 2;
bs.curr = conf->button.always_active ? 0 : -1;
} }
} else { } else {
sel--; sel--;
focusbuttons = sel < 0 ? true : false; focusbuttons = sel < 0 ? true : false;
if (focusbuttons) { if (focusbuttons)
curs_set(0);
bs.curr = (int)bs.nbuttons - 1; bs.curr = (int)bs.nbuttons - 1;
}
} }
draw_buttons(widget, bs, true); draw_buttons(widget, bs, true);
wrefresh(widget); wrefresh(widget);
break; break;
case KEY_UP: case KEY_UP:
if (focusbuttons) if (focusbuttons) {
break; sel = 0;
c[sel].value = c[sel].value > 0 ? focusbuttons = false;
bs.curr = conf->button.always_active ? 0 : -1;
draw_buttons(widget, bs, true);
wrefresh(widget);
} else { c[sel].value = c[sel].value > 0 ?
c[sel].value - 1 : c[sel].max; c[sel].value - 1 : c[sel].max;
}
break; break;
case KEY_DOWN: case KEY_DOWN:
if (focusbuttons) if (focusbuttons)
@ -214,10 +244,8 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
if (conf->key.f1_file == NULL && if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL) conf->key.f1_message == NULL)
break; break;
curs_set(0);
if (f1help(conf) != 0) if (f1help(conf) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
curs_set(1);
/* No break, screen size can change */ /* No break, screen size can change */
case KEY_RESIZE: case KEY_RESIZE:
/* Important for decreasing screen */ /* Important for decreasing screen */
@ -248,43 +276,33 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wclear(c[0].win); wclear(c[0].win);
mvwin(c[0].win, y + h - 6, x + w/2 - 7); mvwin(c[0].win, y + h - 6, x + w/2 - 7);
draw_borders(conf, c[0].win, 3, 4, LOWERED);
wrefresh(c[0].win);
wclear(c[1].win); wclear(c[1].win);
mvwin(c[1].win, y + h - 6, x + w/2 - 2); mvwin(c[1].win, y + h - 6, x + w/2 - 2);
draw_borders(conf, c[1].win, 3, 4, LOWERED);
wrefresh(c[1].win);
wclear(c[2].win); wclear(c[2].win);
mvwin(c[2].win, y + h - 6, x + w/2 + 3); mvwin(c[2].win, y + h - 6, x + w/2 + 3);
draw_borders(conf, c[2].win, 3, 4, LOWERED);
wrefresh(c[2].win);
/* Important to avoid grey lines expanding screen */ /* Important to avoid grey lines expanding screen */
refresh(); refresh();
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
} }
if (output == BSDDIALOG_OK) { if (retval == BSDDIALOG_OK) {
*hh = c[0].value; *hh = c[0].value;
*mm = c[1].value; *mm = c[1].value;
*ss = c[2].value; *ss = c[2].value;
} }
curs_set(0);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
delwin(c[i].win); delwin(c[i].win);
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
return (output); return (retval);
} }
int int
@ -292,7 +310,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd) int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
{ {
bool loop, focusbuttons; bool loop, focusbuttons;
int i, input, output, y, x, h, w, sel; int i, retval, y, x, h, w, sel;
wint_t input;
WINDOW *widget, *textpad, *shadow; WINDOW *widget, *textpad, *shadow;
struct buttons bs; struct buttons bs;
struct calendar { struct calendar {
@ -363,31 +382,27 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(widget); wrefresh(widget);
sel = -1;
loop = focusbuttons = true; loop = focusbuttons = true;
while (loop) { while (loop) {
mvwprintw(c[0].win, 1, 1, "%4d", c[0].value); drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name); drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
mvwprintw(c[2].win, 1, 1, "%2d", c[2].value); sel == 1);
for (i = 0; i < 3; i++) { drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
wrefresh(c[i].win);
}
if (focusbuttons == false) {
wmove(c[sel].win, 1, c[sel].x);
wrefresh(c[sel].win);
}
input = getch(); if (get_wch(&input) == ERR)
continue;
switch(input) { switch(input) {
case KEY_ENTER: case KEY_ENTER:
case 10: /* Enter */ case 10: /* Enter */
if (focusbuttons == false) if (focusbuttons || conf->button.always_active) {
break; retval = bs.value[bs.curr];
output = bs.value[bs.curr]; loop = false;
loop = false; }
break; break;
case 27: /* Esc */ case 27: /* Esc */
if (conf->key.enable_esc) { if (conf->key.enable_esc) {
output = BSDDIALOG_ESC; retval = BSDDIALOG_ESC;
loop = false; loop = false;
} }
break; break;
@ -398,14 +413,13 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ? focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false; true : false;
if (focusbuttons == false) { if (focusbuttons == false) {
curs_set(1);
sel = 0; sel = 0;
bs.curr = conf->button.always_active ? 0 : -1;
} }
} else { } else {
sel++; sel++;
focusbuttons = sel > 2 ? true : false; focusbuttons = sel > 2 ? true : false;
if (focusbuttons) { if (focusbuttons) {
curs_set(0);
bs.curr = 0; bs.curr = 0;
} }
} }
@ -417,33 +431,37 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
bs.curr--; bs.curr--;
focusbuttons = bs.curr < 0 ? false : true; focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) { if (focusbuttons == false) {
curs_set(1);
sel = 2; sel = 2;
bs.curr = conf->button.always_active ? 0 : -1;
} }
} else { } else {
sel--; sel--;
focusbuttons = sel < 0 ? true : false; focusbuttons = sel < 0 ? true : false;
if (focusbuttons) { if (focusbuttons)
curs_set(0);
bs.curr = (int)bs.nbuttons - 1; bs.curr = (int)bs.nbuttons - 1;
}
} }
draw_buttons(widget, bs, true); draw_buttons(widget, bs, true);
wrefresh(widget); wrefresh(widget);
break; break;
case KEY_UP: case KEY_UP:
if (focusbuttons) if (focusbuttons) {
break; sel = 0;
c[sel].value = c[sel].value > 1 ? focusbuttons = false;
c[sel].value - 1 : c[sel].max ; bs.curr = conf->button.always_active ? 0 : -1;
/* if mount change */ draw_buttons(widget, bs, true);
c[2].max = m[c[1].value -1].days; wrefresh(widget);
/* if year change */ } else {
if (c[1].value == 2 && ISLEAF(c[0].value)) c[sel].value = c[sel].value > 1 ?
c[2].max = 29; c[sel].value - 1 : c[sel].max ;
/* set new day */ /* if mount change */
if (c[2].value > c[2].max) c[2].max = m[c[1].value -1].days;
c[2].value = c[2].max; /* if year change */
if (c[1].value == 2 && ISLEAF(c[0].value))
c[2].max = 29;
/* set new day */
if (c[2].value > c[2].max)
c[2].value = c[2].max;
}
break; break;
case KEY_DOWN: case KEY_DOWN:
if (focusbuttons) if (focusbuttons)
@ -463,10 +481,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
if (conf->key.f1_file == NULL && if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL) conf->key.f1_message == NULL)
break; break;
curs_set(0);
if (f1help(conf) != 0) if (f1help(conf) != 0)
return (BSDDIALOG_ERROR); return (BSDDIALOG_ERROR);
curs_set(1);
/* No break, screen size can change */ /* No break, screen size can change */
case KEY_RESIZE: case KEY_RESIZE:
/* Important for decreasing screen */ /* Important for decreasing screen */
@ -496,41 +512,31 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wclear(c[0].win); wclear(c[0].win);
mvwin(c[0].win, y + h - 6, x + w/2 - 11); mvwin(c[0].win, y + h - 6, x + w/2 - 11);
draw_borders(conf, c[0].win, 3, 6, LOWERED);
wrefresh(c[0].win);
wclear(c[1].win); wclear(c[1].win);
mvwin(c[1].win, y + h - 6, x + w/2 - 4); mvwin(c[1].win, y + h - 6, x + w/2 - 4);
draw_borders(conf, c[1].win, 3, 11, LOWERED);
wrefresh(c[1].win);
wclear(c[2].win); wclear(c[2].win);
mvwin(c[2].win, y + h - 6, x + w/2 + 8); mvwin(c[2].win, y + h - 6, x + w/2 + 8);
draw_borders(conf, c[2].win, 3, 4, LOWERED);
wrefresh(c[2].win);
/* Important to avoid grey lines expanding screen */ /* Important to avoid grey lines expanding screen */
refresh(); refresh();
break; break;
default: default:
if (shortcut_buttons(input, &bs)) { if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr]; retval = bs.value[bs.curr];
loop = false; loop = false;
} }
} }
} }
if (output == BSDDIALOG_OK) { if (retval == BSDDIALOG_OK) {
*yy = c[0].value; *yy = c[0].value;
*mm = c[1].value; *mm = c[1].value;
*dd = c[2].value; *dd = c[2].value;
} }
curs_set(0);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
delwin(c[i].win); delwin(c[i].win);
end_dialog(conf, shadow, widget, textpad); end_dialog(conf, shadow, widget, textpad);
return (output); return (retval);
} }

View File

@ -0,0 +1,356 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Alfonso Sabato Siciliano
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <bsddialog.h>
#include <bsddialog_theme.h>
#include "util_theme.h"
static struct bsddialog_theme t;
static char title[1024];
enum typeprop {
BOOL,
CHAR,
INT,
UINT,
COLOR
};
struct property {
const char* name;
enum typeprop type;
void *value;
};
#define NPROPERTY 38
static struct property p[NPROPERTY] = {
{ "theme.screen.color", COLOR, &t.screen.color },
{ "theme.shadow.color", COLOR, &t.shadow.color },
{ "theme.shadow.y", UINT, &t.shadow.y },
{ "theme.shadow.x", UINT, &t.shadow.x },
{ "theme.dialog.color", COLOR, &t.dialog.color },
{ "theme.dialog.delimtitle", BOOL, &t.dialog.delimtitle },
{ "theme.dialog.titlecolor", COLOR, &t.dialog.titlecolor },
{ "theme.dialog.lineraisecolor", COLOR, &t.dialog.lineraisecolor },
{ "theme.dialog.linelowercolor", COLOR, &t.dialog.linelowercolor },
{ "theme.dialog.bottomtitlecolor", COLOR, &t.dialog.bottomtitlecolor },
{ "theme.dialog.arrowcolor", COLOR, &t.dialog.arrowcolor },
{ "theme.menu.f_selectorcolor", COLOR, &t.menu.f_selectorcolor},
{ "theme.menu.selectorcolor", COLOR, &t.menu.selectorcolor},
{ "theme.menu.f_namecolor", COLOR, &t.menu.f_namecolor},
{ "theme.menu.namecolor", COLOR, &t.menu.namecolor},
{ "theme.menu.f_desccolor", COLOR, &t.menu.f_desccolor},
{ "theme.menu.desccolor", COLOR, &t.menu.desccolor},
{ "theme.menu.namesepcolor", COLOR, &t.menu.namesepcolor},
{ "theme.menu.descsepcolor", COLOR, &t.menu.descsepcolor},
{ "theme.menu.f_shortcutcolor", COLOR, &t.menu.f_shortcutcolor},
{ "theme.menu.shortcutcolor", COLOR, &t.menu.shortcutcolor},
{ "theme.menu.bottomdesccolor", COLOR, &t.menu.bottomdesccolor},
{ "theme.form.f_fieldcolor", COLOR, &t.form.f_fieldcolor},
{ "theme.form.fieldcolor", COLOR, &t.form.fieldcolor},
{ "theme.form.readonlycolor", COLOR, &t.form.readonlycolor},
{ "theme.form.bottomdesccolor", COLOR, &t.form.bottomdesccolor},
{ "theme.bar.f_color", COLOR, &t.bar.f_color},
{ "theme.bar.color", COLOR, &t.bar.color},
{ "theme.button.minmargin", UINT, &t.button.minmargin},
{ "theme.button.maxmargin", UINT, &t.button.maxmargin},
{ "theme.button.leftdelim", CHAR, &t.button.leftdelim},
{ "theme.button.rightdelim", CHAR, &t.button.rightdelim},
{ "theme.button.delimcolor", COLOR, &t.button.delimcolor},
{ "theme.button.f_delimcolor", COLOR, &t.button.f_delimcolor},
{ "theme.button.color", COLOR, &t.button.color},
{ "theme.button.f_color", COLOR, &t.button.f_color},
{ "theme.button.shortcutcolor", COLOR, &t.button.shortcutcolor},
{ "theme.button.f_shortcutcolor", COLOR, &t.button.f_shortcutcolor}
};
static char *color[8] = {
"black",
"red",
"green",
"yellow",
"blue",
"magenta",
"cyan",
"white"
};
int savetheme(const char *file, char *errbuf, const char *version)
{
int i;
unsigned int flags;
enum bsddialog_color bg, fg;
time_t clock;
FILE *fp;
if (bsddialog_get_theme(&t) != BSDDIALOG_OK) {
sprintf(errbuf, "Cannot save theme: %s", bsddialog_geterror());
return (BSDDIALOG_ERROR);
}
if(time(&clock) < 0) {
sprintf(errbuf, "Cannot save profile (getting current time)");
return (BSDDIALOG_ERROR);
}
if ((fp = fopen(file, "w")) == NULL) {
sprintf(errbuf, "Cannot open %s to save profile", file);
return (BSDDIALOG_ERROR);
}
fprintf(fp, "### bsddialog theme - %s", ctime(&clock));
fputs("# Refer to bsddialog(3) manual for theme.* properties\n", fp);
fprintf(fp, "version %s\n", version);
for (i = 0; i < NPROPERTY; i++) {
switch (p[i].type) {
case CHAR:
fprintf(fp, "%s %c\n", p[i].name, *((char*)p[i].value));
break;
case INT:
fprintf(fp, "%s %d\n", p[i].name, *((int*)p[i].value));
break;
case UINT:
fprintf(fp, "%s %u\n", p[i].name,
*((unsigned int*)p[i].value));
break;
case BOOL:
fprintf(fp, "%s %s\n", p[i].name,
*((bool*)p[i].value) ? "true" : "false");
break;
case COLOR:
bsddialog_color_attrs(*(int*)p[i].value, &fg, &bg,
&flags);
fprintf(fp, "%s %s %s%s%s%s\n",
p[i].name, color[fg], color[bg],
flags & BSDDIALOG_BOLD ? " bold" : "",
flags & BSDDIALOG_REVERSE ? " reverse" : "",
flags & BSDDIALOG_UNDERLINE ? " underline" : "");
break;
}
}
fclose(fp);
return (BSDDIALOG_OK);
}
int loadtheme(const char *file, char *errbuf)
{
bool boolvalue;
char charvalue, *value;
char line[BUFSIZ], name[BUFSIZ], c1[BUFSIZ], c2[BUFSIZ];
int i, j, intvalue, flags;
unsigned int uintvalue;
enum bsddialog_color bg, fg;
FILE *fp;
if (bsddialog_get_theme(&t) != BSDDIALOG_OK) {
sprintf(errbuf, "Cannot get current theme: %s",
bsddialog_geterror());
return (BSDDIALOG_ERROR);
}
if((fp = fopen(file, "r")) == NULL) {
sprintf(errbuf, "Cannot open theme \"%s\"", file);
return (BSDDIALOG_ERROR);
}
#define RETURN_ERROR(name, error) do { \
sprintf(errbuf, "%s for \"%s\"", error, name); \
fclose(fp); \
return (BSDDIALOG_ERROR); \
} while (0)
while(fgets(line, BUFSIZ, fp) != NULL) {
if(line[0] == '#' || line[0] == '\n')
continue; /* superfluous, only for efficiency */
sscanf(line, "%s", name);
for (i = 0; i < NPROPERTY; i++) {
if (strcmp(name, p[i].name) == 0) {
value = &line[strlen(name)];
break;
}
}
if (i >= NPROPERTY) {
if (strcmp(name, "version") == 0)
continue;
RETURN_ERROR(name, "Unknown theme property name");
}
switch (p[i].type) {
case CHAR:
while (value[0] == ' ' || value[0] == '\n' ||
value[0] == '\0')
value++;
if (sscanf(value, "%c", &charvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a char");
*((int*)p[i].value) = charvalue;
break;
case INT:
if (sscanf(value, "%d", &intvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a int");
*((int*)p[i].value) = intvalue;
break;
case UINT:
if (sscanf(value, "%u", &uintvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a uint");
*((unsigned int*)p[i].value) = uintvalue;
break;
case BOOL:
boolvalue = (strstr(value, "true") != NULL) ?
true :false;
*((bool*)p[i].value) = boolvalue;
break;
case COLOR:
if (sscanf(value, "%s %s", c1, c2) != 2)
RETURN_ERROR(p[i].name, "Cannot get 2 colors");
/* Foreground */
for (j = 0; j < 8 ; j++)
if ((strstr(c1, color[j])) != NULL)
break;
if ((fg = j) > 7)
RETURN_ERROR(p[i].name, "Bad foreground");
/* Background */
for (j = 0; j < 8 ; j++)
if ((value = strstr(c2, color[j])) != NULL)
break;
if ((bg = j) > 7)
RETURN_ERROR(p[i].name, "Bad background");
/* Flags */
flags = 0;
if (strstr(value, "bold") != NULL)
flags |= BSDDIALOG_BOLD;
if (strstr(value, "reverse") != NULL)
flags |= BSDDIALOG_REVERSE;
if (strstr(value, "underline") != NULL)
flags |= BSDDIALOG_UNDERLINE;
*((int*)p[i].value) = bsddialog_color(fg, bg, flags);
break;
}
}
fclose(fp);
bsddialog_set_theme(&t);
return (BSDDIALOG_OK);
}
int bikeshed(struct bsddialog_conf *conf, char *errbuf)
{
int margin, i;
int colors[8] = {0, 0, 0, 0 ,0 ,0 , 0, 0};
enum bsddialog_color col[6];
time_t clock;
time(&clock);
srand(clock);
/* theme */
if (bsddialog_get_theme(&t) != BSDDIALOG_OK)
return (BSDDIALOG_ERROR);
for (i = 0; i < 6; i++) {
do {
col[i] = rand() % 8;
} while (colors[col[i]] == 1);
colors[col[i]] = 1;
}
t.screen.color = bsddialog_color(col[4], col[3], 0);
t.shadow.color = bsddialog_color(col[0], col[0], 0);
t.shadow.y = 1,
t.shadow.x = 2,
t.dialog.delimtitle = (rand() % 2 == 0) ? true : false;
t.dialog.titlecolor = bsddialog_color(col[3], col[5], 0);
t.dialog.lineraisecolor = bsddialog_color(col[0], col[5], 0);
t.dialog.linelowercolor = bsddialog_color(col[0], col[5], 0);
t.dialog.color = bsddialog_color(col[0], col[5], 0);
t.dialog.bottomtitlecolor = bsddialog_color(col[0], col[5], 0);
t.dialog.arrowcolor = bsddialog_color(col[3], col[5], 0);
t.menu.f_selectorcolor = bsddialog_color(col[5], col[3], 0);
t.menu.selectorcolor = bsddialog_color(col[0], col[5], 0);
t.menu.f_desccolor = bsddialog_color(col[5], col[3], 0);
t.menu.desccolor = bsddialog_color(col[0], col[5], 0);
t.menu.f_namecolor = bsddialog_color(col[5], col[3], 0);
t.menu.namecolor = bsddialog_color(col[3], col[5], 0);
t.menu.namesepcolor = bsddialog_color(col[1], col[5], 0);
t.menu.descsepcolor = bsddialog_color(col[1], col[5], 0);
t.menu.f_shortcutcolor = bsddialog_color(col[1], col[3], 0);
t.menu.shortcutcolor = bsddialog_color(col[1], col[5], 0);
t.menu.bottomdesccolor = bsddialog_color(col[4], col[3], 0);
t.form.f_fieldcolor = bsddialog_color(col[5], col[3], 0);
t.form.fieldcolor = bsddialog_color(col[5], col[4], 0);
t.form.readonlycolor = bsddialog_color(col[4], col[5], 0);
t.form.bottomdesccolor = bsddialog_color(col[4], col[3], 0);
t.bar.f_color = bsddialog_color(col[5], col[3], 0);
t.bar.color = bsddialog_color(col[3], col[5], 0);
t.button.minmargin = 1,
t.button.maxmargin = 5,
t.button.leftdelim = '[',
t.button.rightdelim = ']',
t.button.f_delimcolor = bsddialog_color(col[5], col[3], 0);
t.button.delimcolor = bsddialog_color(col[0], col[5], 0);
t.button.f_color = bsddialog_color(col[2], col[3], 0);
t.button.color = bsddialog_color(col[0], col[5], 0);
t.button.f_shortcutcolor = bsddialog_color(col[5], col[3], 0);
t.button.shortcutcolor = bsddialog_color(col[1], col[5], 0);
if (bsddialog_set_theme(&t))
return (BSDDIALOG_ERROR);
/* conf */
conf->button.always_active = (rand() % 2 == 0) ? true : false;
if (conf->title != NULL) {
memset(title, 0, 1024);
margin = rand() % 5;
memset(title, ' ', margin);
strcpy(title + margin, conf->title);
memset(title + strlen(title), ' ', margin);
conf->title = title;
}
return (BSDDIALOG_OK);
}

View File

@ -0,0 +1,35 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Alfonso Sabato Siciliano
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BSDDIALOG_UTILITY_THEME_H_
#define _BSDDIALOG_UTILITY_THEME_H_
int savetheme(const char *file, char *errbuf, const char *version);
int loadtheme(const char *file, char *errbuf);
int bikeshed(struct bsddialog_conf *conf, char *errbuf);
#endif

View File

@ -3,7 +3,7 @@ BSDDIALOG= ${SRCTOP}/contrib/bsddialog
PROG= bsddialog PROG= bsddialog
SRCS= bsddialog.c SRCS= bsddialog.c
MAN= bsddialog.1 MAN= bsddialog.1 util_theme.c
CFLAGS+= -I${BSDDIALOG}/lib CFLAGS+= -I${BSDDIALOG}/lib
LIBADD= bsddialog LIBADD= bsddialog