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/form
examples_library/formw
examples_library/margin
examples_library/menu
examples_library/mixedlist
examples_library/radiolist
@ -19,6 +20,7 @@ examples_library/rangebox
examples_library/sade
examples_library/timebox
examples_library/yesno
examples_library/u_msgbox
*.gz
lib/libbsddialog.so*
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:
* add: (this) CHANGELOG.
@ -31,7 +104,7 @@
* 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>,
--begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap,

View File

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

View File

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

View File

@ -1,14 +1,13 @@
# BSDDialog 0.2
# BSDDialog 0.3
This project provides **bsddialog** and **libbsddialog**, an utility and a
library to build scripts and tools with TUI dialogs and widgets.
This project provides **bsddialog** and **libbsddialog**, an utility
and a library to build scripts and tools with TUI dialogs and widgets.
## Intro
Briefly:
<https://www.freebsd.org/status/report-2021-04-2021-06/#_bsddialog_tui_widgets>
<https://www.freebsd.org/status/report-2021-04-2021-06/bsddialog/>
Utility:
<https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html>
@ -31,6 +30,15 @@ FreeBSD:
% ./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:
![screenshot](screenshot.png)
@ -101,6 +109,7 @@ in the _Public Domain_ to build new projects:
```
% cd examples_library
% sh compile
% ./checklist
% ./datebox
% ./form
% ./infobox
@ -114,4 +123,10 @@ in the _Public Domain_ to build new projects:
% ./timebox
% ./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
.\" SUCH DAMAGE.
.\"
.Dd February 3, 2022
.Dd August 29, 2022
.Dt BSDDIALOG 1
.Os
.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.
.It Fl Fl begin-y Ar y
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
Label for the
.Dq Cancel
@ -100,7 +107,7 @@ cyan.
.It Dq \eZ7
white.
.It Dq \eZr
reverse foreground and background colors.
reverse foreground and background.
.It Dq \eZR
disable reverse.
.It Dq \eZb
@ -112,8 +119,11 @@ underline.
.It Dq \eZU
disable underline.
.It Dq \eZn
restore to normal text.
restore normal text.
.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
Replace new line with a space in
.Ar text .
@ -141,7 +151,7 @@ Equivalent to
.Fl Fl default-no .
.It Fl Fl disable-esc
Disable ESC key to quit.
.It Fl Fl esc-cancelvalue
.It Fl Fl esc-return-cancel
Exits with the
.Dq Cancel
button value if the ESC key is pressed.
@ -197,8 +207,7 @@ Do not exit with unknown options.
.It Fl Fl insecure
Print
.Sq *
to hide passwords while typing, default space
.Sq " " .
to hide passwords while typing; whitespace otherwise.
.It Fl Fl item-depth
Specify a margin for items, available for Checklist, Menu and Radiolist.
.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.
.It Fl Fl item-prefix
Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview.
.It Fl Fl load-theme Ar file
Load theme from
.Ar file .
.It Fl Fl max-input Ar size
Maximum length of the input for
.Fl Fl input-box
.Fl Fl inputbox
ans
.Fl Fl passwordbox ,
default 2048.
@ -262,6 +274,8 @@ Print Dialog height and widget at exit.
Print version.
.It Fl Fl quoted
Quote items in output, default only when necessary.
.It Fl Fl save-theme Ar file
Save the current theme.
.It Fl Fl separate-output
Separate selected items with a new line and avoid to quote.
.It Fl Fl separator Ar sep
@ -279,6 +293,18 @@ seconds to close the dialog.
Print input from user interface to standand error, default.
.It Fl Fl stdout
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
Number of spaces to print a TAB in
.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
Dialog to select a date.
.It Fl Fl form Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \
Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxvaluelen Oc ...
Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Oc ...
Dialog to get a list of strings via forms.
A form has a
.Ar label
@ -333,19 +359,21 @@ and
.Ar xfield
with graphical length
.Ar fieldlen ,
.Ar maxvaluelen
.Ar maxletters
is the maximum input length.
The field can be customized, if
.Ar fieldlen
is 0 its length is the absolute value of
.Ar maxvaluelen ,
if
.Ar maxvaluelen
is negative the field is read only,
is negative the field is read only and its absolute value is the field length.
If
.Ar maxletters
is 0 it is the absolute value of
.Ar fieldlen .
.Ar init
is a default value.
.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
Dialog with a bar to shows
.Ar percentage ,
@ -374,7 +402,7 @@ The name of the selected item is printed to standard error.
.Ar menurows
is the graphical height of the list, 0 for autosize.
.It Fl Fl mixedform Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \
Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxvaluelen Ar flag Oc ...
Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Ar flag Oc ...
Dialog to get a list of strings via forms.
A form has a
.Ar label
@ -388,7 +416,7 @@ at the position
.Ar yfield
and
.Ar xfield ,
.Ar maxvaluelen
.Ar maxletters
is the maximum input length,
.Ar init
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
field read only.
.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 \
Ar miniperc Oc ...
Dialog to show a main bar to represent
@ -436,7 +466,8 @@ Dialog to get a password,
.Ar init
is the default value.
.It Fl Fl passwordform Ar text Ar rows Ar cols Ar formrows Oo Ar label \
Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar valuelen Oc ...
Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters \
Oc ...
Dialog to get a list of passwords, equivalent to
.Fl Fl form
except typed characters are hidden.
@ -531,14 +562,39 @@ Backtitle, title and message:
Yes-No Question and theme:
.Dl bsddialog --theme blackwhite --yesno Question 10 30
.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:
.Dl bsddialog --checklist Checklist 0 0 3 N1 \&D1 off N2 D2 on N3 D3 off
.Pp
Mixedgauge:
.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 "\(dq" -1" L2 30
.Pp
Form:
.Dl bsddialog --form Form 0 0 2 L1: 1 1 X 1 5 20 25 L2: 2 1 X 2 5 20 25
.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
Gauge script:
.Bd -literal -offset indent -compact
@ -558,22 +614,6 @@ do
i=`expr $i + 1`
done | bsddialog --title Gauge --gauge "Starting..." 10 70
.Ed
.Pp
Mixedgauge script:
.Bd -literal -offset indent -compact
perc=0
while [ $perc -le 100 ]
do
bsddialog --sleep 1 --title Mixedgauge \e
--mixedgauge "\enExample...\en" 0 0 $perc \e
"Hidden" " -9" \e
"Label 1" " -4" \e
"Label 2" " -4" \e
"Label 3" $perc
perc=`expr $perc + 20`
done
.Ed
.Sh SEE ALSO
.Xr bsddialog 3
.Sh HISTORY
@ -584,7 +624,99 @@ utility first appeared in
.Sh AUTHORS
.Nm bsddialog
was written by
.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com .
.Sh BUGS
Forms do not resize the dialog after a terminal change and do not provide
scrolling for items.
.An Alfonso Sabato Siciliano
.Aq Mt asiciliano@FreeBSD.org .
.Pp
.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_theme.h>
#define BSDDIALOG_VERSION "0.2"
#include "util_theme.h"
#define BSDDIALOG_VERSION "0.3"
enum OPTS {
/* Common options */
@ -47,16 +49,18 @@ enum OPTS {
BACKTITLE,
BEGIN_X,
BEGIN_Y,
BIKESHED,
CANCEL_LABEL,
CLEAR,
COLORS,
COLUMNS_PER_ROW,
CR_WRAP,
DATE_FORMAT,
DEFAULT_BUTTON,
DEFAULT_ITEM,
DEFAULT_NO,
DISABLE_ESC,
ESC_CANCELVALUE,
ESC_RETURNCANCEL,
EXIT_LABEL,
EXTRA_BUTTON,
EXTRA_LABEL,
@ -75,6 +79,7 @@ enum OPTS {
ITEM_DEPTH,
ITEM_HELP,
ITEM_PREFIX,
LOAD_THEME,
MAX_INPUT,
NO_CANCEL,
NO_COLLAPSE,
@ -91,12 +96,14 @@ enum OPTS {
PRINT_SIZE,
PRINT_VERSION,
QUOTED,
SAVE_THEME,
SEPARATE_OUTPUT,
SHADOW,
SINGLE_QUOTED,
SLEEP,
STDERR,
STDOUT,
SWITCH_BUTTONS,
TAB_LEN,
THEME,
TIME_FORMAT,
@ -136,15 +143,16 @@ static char *date_fmt_opt, *time_fmt_opt;
static int unsigned max_input_form_opt;
/* General options */
static int output_fd_opt;
bool bikeshed_opt;
/* Functions */
static void sigint_handler(int sig);
static void
custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
char *text, char *buf);
static void sigint_handler(int sig);
static void errorexit(char *errbuf);
/* 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
static int checklist_builder(BUILDER_ARGS);
static int datebox_builder(BUILDER_ARGS);
@ -176,23 +184,24 @@ static void usage(void)
printf("Common Options:\n");
printf("--ascii-lines, --backtitle <backtitle>, --begin-x <x>, "
"--begin-y <y>, --cancel-label <label>, --clear, --colors, "
"--cr-wrap, --date-format <format>, --defaultno, "
"--default-button <label>, --default-no, --default-item <name>, "
"--disable-esc, --esc-cancelvalue, --exit-label <label>, "
"--extra-button, --extra-label <label>, "
"--generic-button1 <label>, --generic-button2 <label>, --help, "
"--help-button, --help-label <label>, --help-status, --help-tags, "
"--hfile <filename>, --hline <string>, --hmsg <string>, --ignore, "
"--insecure, --item-depth, --item-help, --items-prefix, "
"--max-input <size>, --no-cancel, --nocancel, --no-collapse, "
"--no-items, --no-label <label>, --no-lines, --no-nl-expand, "
"--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, "
"--output-fd <fd>, --output-separator <sep>, --print-maxsize, "
"--print-size, --print-version, --quoted, --separate-output, "
"--separator <sep>, --shadow, --single-quoted, --sleep <secs>, "
"--stderr, --stdout, --tab-len <spaces>, "
"--theme <blackwhite|bsddialog|flat|dialog>, "
"--begin-y <y>, --bikeshed, --cancel-label <label>, --clear, "
"--colors, --columns-per-row <columns>, --cr-wrap, "
"--date-format <format>, --default-button <label>, "
"--default-item <name>, --default-no, --disable-esc, "
"--esc-return-cancel, --exit-label <label>, --extra-button, "
"--extra-label <label>, --generic-button1 <label>, "
"--generic-button2 <label>, --help, --help-button, "
"--help-label <label>, --help-status, --help-tags, --hfile <file>, "
"--hline <string>, --hmsg <string>, --ignore, --insecure, "
"--item-depth, --item-help, --item-prefix, --load-theme <file>, "
"--max-input <size>, --no-cancel, --no-collapse, --no-items, "
"--no-label <label>, --no-lines, --no-nl-expand, --no-ok, "
"--no-shadow, --no-tags, --ok-label <label>, --output-fd <fd>, "
"--output-separator <sep>, --print-maxsize, --print-size, "
"--print-version, --quoted, --save-theme <file>, "
"--separate-output, --separator <sep>, --shadow, --single-quoted, "
"--sleep <secs>, --stderr, --stdout, --tab-len <spaces>, "
"--switch-buttons, --theme <blackwhite|bsddialog|flat|dialog>, "
"--time-format <format>, --title <title>, --trim, --version, "
"--yes-label <label>.\n");
printf("\n");
@ -202,14 +211,14 @@ static void usage(void)
"<on|off>] ...\n");
printf("--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n");
printf("--form <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen>] "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters>] "
"...\n");
printf("--gauge <text> <rows> <cols> [<perc>]\n");
printf("--infobox <text> <rows> <cols>\n");
printf("--inputbox <text> <rows> <cols> [init]\n");
printf("--menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
printf("--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters> "
"<0|1|2>] ...\n");
printf("--mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
"<miniperc>] ...\n");
@ -217,7 +226,7 @@ static void usage(void)
printf("--passwordbox <text> <rows> <cols> [init]\n");
printf("--passwordform <text> <rows> <cols> <formrows> [<label> "
"<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> "
"<maxvaluelen>] ...\n");
"<maxletters>] ...\n");
printf("--pause <text> <rows> <cols> <secs>\n");
printf("--radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n");
@ -235,11 +244,12 @@ static void usage(void)
int main(int argc, char *argv[argc])
{
bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt;
bool esc_cancelvalue_opt, ignore_opt, print_maxsize_opt;;
int input, rows, cols, output, getH, getW;
bool esc_return_cancel_opt, ignore_opt, print_maxsize_opt;
bool textfromfile;
int input, rows, cols, retval, getH, getW;
int (*dialogbuilder)(BUILDER_ARGS) = NULL;
enum bsddialog_default_theme theme_opt;
char *text, *backtitle_opt;
char *text, *backtitle_opt, *loadthemefile, *savethemefile;
char errorbuilder[1024];
struct winsize ws;
struct bsddialog_conf conf;
@ -250,7 +260,7 @@ int main(int argc, char *argv[argc])
conf.key.enable_esc = true;
conf.menu.on_without_ok = true;
conf.form.value_without_ok = true;
conf.form.enable_wchar = true;
conf.button.always_active = true;
backtitle_opt = NULL;
theme_opt = BSDDIALOG_THEME_FLAT;
@ -258,8 +268,12 @@ int main(int argc, char *argv[argc])
print_maxsize_opt = false;
ignore_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';
savethemefile = NULL;
loadthemefile = NULL;
item_output_sepnl_opt = item_singlequote_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},
{"begin-x", required_argument, NULL, BEGIN_X},
{"begin-y", required_argument, NULL, BEGIN_Y},
{"bikeshed", no_argument, NULL, BIKESHED},
{"cancel-label", required_argument, NULL, CANCEL_LABEL},
{"clear", no_argument, NULL, CLEAR},
{"colors", no_argument, NULL, COLORS},
@ -289,7 +304,7 @@ int main(int argc, char *argv[argc])
{"default-item", required_argument, NULL, DEFAULT_ITEM},
{"default-no", no_argument, NULL, DEFAULT_NO},
{"disable-esc", no_argument, NULL, DISABLE_ESC},
{"esc-cancelvalue", no_argument, NULL, ESC_CANCELVALUE},
{"esc-return-cancel",no_argument, NULL, ESC_RETURNCANCEL},
{"exit-label", required_argument, NULL, EXIT_LABEL},
{"extra-button", no_argument, NULL, EXTRA_BUTTON},
{"extra-label", required_argument, NULL, EXTRA_LABEL},
@ -308,6 +323,7 @@ int main(int argc, char *argv[argc])
{"item-depth", no_argument, NULL, ITEM_DEPTH},
{"item-help", no_argument, NULL, ITEM_HELP},
{"item-prefix", no_argument, NULL, ITEM_PREFIX},
{"load-theme", required_argument, NULL, LOAD_THEME},
{"max-input", required_argument, NULL, MAX_INPUT},
{"no-cancel", no_argument, NULL, NO_CANCEL},
{"nocancel", no_argument, NULL, NO_CANCEL},
@ -327,6 +343,8 @@ int main(int argc, char *argv[argc])
{"print-size", no_argument, NULL, PRINT_SIZE},
{"print-version", no_argument, NULL, PRINT_VERSION},
{"quoted", no_argument, NULL, QUOTED},
{"columns-per-row", required_argument, NULL, COLUMNS_PER_ROW},
{"save-theme", required_argument, NULL, SAVE_THEME},
{"separate-output", no_argument, NULL, SEPARATE_OUTPUT},
{"separator", required_argument, NULL, OUTPUT_SEPARATOR},
{"shadow", no_argument, NULL, SHADOW},
@ -334,6 +352,7 @@ int main(int argc, char *argv[argc])
{"sleep", required_argument, NULL, SLEEP},
{"stderr", no_argument, NULL, STDERR},
{"stdout", no_argument, NULL, STDOUT},
{"switch-buttons", no_argument, NULL, SWITCH_BUTTONS},
{"tab-len", required_argument, NULL, TAB_LEN},
{"theme", required_argument, NULL, THEME},
{"time-format", required_argument, NULL, TIME_FORMAT},
@ -373,6 +392,8 @@ int main(int argc, char *argv[argc])
break;
case BACKTITLE:
backtitle_opt = optarg;
if (conf.y == BSDDIALOG_CENTER)
conf.auto_topmargin = 2;
break;
case BEGIN_X:
conf.x = (int)strtol(optarg, NULL, 10);
@ -389,6 +410,10 @@ int main(int argc, char *argv[argc])
conf.y, BSDDIALOG_CENTER);
return (255);
}
conf.auto_topmargin = 0;
break;
case BIKESHED:
bikeshed_opt = true;
break;
case CANCEL_LABEL:
conf.button.cancel_label = optarg;
@ -399,6 +424,10 @@ int main(int argc, char *argv[argc])
case COLORS:
conf.text.highlight = true;
break;
case COLUMNS_PER_ROW:
conf.text.cols_per_row =
(u_int)strtoul(optarg, NULL, 10);
break;
case CR_WRAP:
cr_wrap_opt = true;
break;
@ -417,8 +446,8 @@ int main(int argc, char *argv[argc])
case DISABLE_ESC:
conf.key.enable_esc = false;
break;
case ESC_CANCELVALUE:
esc_cancelvalue_opt = true;
case ESC_RETURNCANCEL:
esc_return_cancel_opt = true;
break;
case EXIT_LABEL:
conf.button.ok_label = optarg;
@ -454,7 +483,7 @@ int main(int argc, char *argv[argc])
conf.key.f1_file = optarg;
break;
case HLINE:
if (strlen(optarg) > 0)
if (optarg[0] != '\0')
conf.bottomtitle = optarg;
break;
case HMSG:
@ -475,6 +504,9 @@ int main(int argc, char *argv[argc])
case ITEM_PREFIX:
item_prefix_opt = true;
break;
case LOAD_THEME:
loadthemefile = optarg;
break;
case MAX_INPUT:
max_input_form_opt = (u_int)strtoul(optarg, NULL, 10);
break;
@ -524,6 +556,9 @@ int main(int argc, char *argv[argc])
case PRINT_VERSION:
printf("bsddialog version %s\n", BSDDIALOG_VERSION);
break;
case SAVE_THEME:
savethemefile = optarg;
break;
case SEPARATE_OUTPUT:
item_output_sepnl_opt = true;
break;
@ -542,6 +577,9 @@ int main(int argc, char *argv[argc])
case STDOUT:
output_fd_opt = STDOUT_FILENO;
break;
case SWITCH_BUTTONS:
conf.button.always_active = false;
break;
case TAB_LEN:
conf.text.tablen = (u_int)strtoul(optarg, NULL, 10);
break;
@ -575,12 +613,14 @@ int main(int argc, char *argv[argc])
/* Dialogs */
case CHECKLIST:
dialogbuilder = checklist_builder;
conf.auto_downmargin = 1;
break;
case DATEBOX:
dialogbuilder = datebox_builder;
break;
case FORM:
dialogbuilder = form_builder;
conf.auto_downmargin = 1;
break;
case GAUGE:
dialogbuilder = gauge_builder;
@ -590,12 +630,15 @@ int main(int argc, char *argv[argc])
break;
case INPUTBOX:
dialogbuilder = inputbox_builder;
conf.auto_downmargin = 1;
break;
case MENU:
dialogbuilder = menu_builder;
conf.auto_downmargin = 1;
break;
case MIXEDFORM:
dialogbuilder = mixedform_builder;
conf.auto_downmargin = 1;
break;
case MIXEDGAUGE:
dialogbuilder = mixedgauge_builder;
@ -608,24 +651,29 @@ int main(int argc, char *argv[argc])
break;
case PASSWORDBOX:
dialogbuilder = passwordbox_builder;
conf.auto_downmargin = 1;
break;
case PASSWORDFORM:
dialogbuilder = passwordform_builder;
conf.auto_downmargin = 1;
break;
case RADIOLIST:
dialogbuilder = radiolist_builder;
conf.auto_downmargin = 1;
break;
case RANGEBOX:
dialogbuilder = rangebox_builder;
break;
case TEXTBOX:
dialogbuilder = textbox_builder;
textfromfile = true;
break;
case TIMEBOX:
dialogbuilder = timebox_builder;
break;
case TREEVIEW:
dialogbuilder = treeview_builder;
conf.auto_downmargin = 1;
break;
case YESNO:
dialogbuilder = yesno_builder;
@ -653,7 +701,7 @@ int main(int argc, char *argv[argc])
usage();
return (255);
}
if (dialogbuilder == textbox_builder)
if (textfromfile) /* textbox */
text = argv[0];
else {
if ((text = malloc(strlen(argv[0]) + 1)) == NULL) {
@ -671,45 +719,52 @@ int main(int argc, char *argv[argc])
/* bsddialog terminal mode */
if (bsddialog_init() != 0) {
printf("Error: %s\n", bsddialog_geterror());
return (BSDDIALOG_ERROR);
return (255);
}
signal(SIGINT, sigint_handler);
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)
bsddialog_backtitle(&conf, backtitle_opt);
if( bsddialog_backtitle(&conf, backtitle_opt))
errorexit(NULL);
errorbuilder[0] = '\0';
output = BSDDIALOG_OK;
if (dialogbuilder != NULL)
output = dialogbuilder(conf, text, rows, cols, argc, argv,
if (dialogbuilder != NULL) {
retval = dialogbuilder(&conf, text, rows, cols, argc, argv,
errorbuilder);
if (retval == BSDDIALOG_ERROR)
errorexit(errorbuilder);
} else
retval = BSDDIALOG_OK;
if (dialogbuilder != textbox_builder)
free(text);
if (savethemefile != NULL)
if (savetheme(savethemefile, errorbuilder, BSDDIALOG_VERSION) !=
BSDDIALOG_OK)
errorexit(errorbuilder);
bsddialog_end();
/* end bsddialog terminal mode */
if (output == BSDDIALOG_ERROR) {
if (errorbuilder[0] != '\0')
printf("Error: %s\n", errorbuilder);
else
printf("Error: %s\n", bsddialog_geterror());
return (255);
}
if (textfromfile == false)
free(text);
if (conf.get_height != NULL && conf.get_width != NULL)
dprintf(output_fd_opt, "Dialog size: (%d - %d)\n",
*conf.get_height, *conf.get_width);
if (output == BSDDIALOG_ESC && esc_cancelvalue_opt)
output = BSDDIALOG_CANCEL;
if (retval == BSDDIALOG_ESC && esc_return_cancel_opt)
retval = BSDDIALOG_CANCEL;
return (output);
return (retval);
}
void sigint_handler(int sig)
@ -719,6 +774,18 @@ void sigint_handler(int sig)
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
custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
char *text, char *buf)
@ -781,7 +848,7 @@ int gauge_builder(BUILDER_ARGS)
else
perc = 0;
output = bsddialog_gauge(&conf, text, rows, cols, perc, STDIN_FILENO,
output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO,
"XXX");
return (output);
@ -791,7 +858,7 @@ int infobox_builder(BUILDER_ARGS)
{
int output;
output = bsddialog_infobox(&conf, text, rows, cols);
output = bsddialog_infobox(conf, text, rows, cols);
return (output);
}
@ -827,7 +894,7 @@ int mixedgauge_builder(BUILDER_ARGS)
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);
return (output);
@ -837,7 +904,7 @@ int msgbox_builder(BUILDER_ARGS)
{
int output;
output = bsddialog_msgbox(&conf, text, rows, cols);
output = bsddialog_msgbox(conf, text, rows, cols);
return (output);
}
@ -853,7 +920,7 @@ int pause_builder(BUILDER_ARGS)
}
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);
}
@ -879,7 +946,7 @@ int rangebox_builder(BUILDER_ARGS)
else
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);
@ -890,7 +957,7 @@ int textbox_builder(BUILDER_ARGS)
{
int output;
output = bsddialog_textbox(&conf, text, rows, cols);
output = bsddialog_textbox(conf, text, rows, cols);
return (output);
}
@ -899,7 +966,7 @@ int yesno_builder(BUILDER_ARGS)
{
int output;
output = bsddialog_yesno(&conf, text, rows, cols);
output = bsddialog_yesno(conf, text, rows, cols);
return (output);
}
@ -925,13 +992,11 @@ int datebox_builder(BUILDER_ARGS)
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)
return (output);
if (date_fmt_opt == NULL) {
dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd);
} else {
if (date_fmt_opt != NULL) {
time(&cal);
localtm = localtime(&cal);
localtm->tm_year = yy - 1900;
@ -939,6 +1004,10 @@ int datebox_builder(BUILDER_ARGS)
localtm->tm_mday = dd;
strftime(stringdate, 1024, date_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringdate);
} else if (bikeshed_opt && (dd % 2 == 0)) {
dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd);
} else {
dprintf(output_fd_opt, "%u/%02u/%02u", yy, mm, dd);
}
return (output);
@ -964,13 +1033,11 @@ int timebox_builder(BUILDER_ARGS)
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)
return (output);
if (time_fmt_opt == NULL) {
dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
} else {
if (time_fmt_opt != NULL) {
time(&clock);
localtm = localtime(&clock);
localtm->tm_hour = hh;
@ -978,6 +1045,10 @@ int timebox_builder(BUILDER_ARGS)
localtm->tm_sec = ss;
strftime(stringtime, 1024, time_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringtime);
} else if (bikeshed_opt && (ss % 2 == 0)) {
dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
} else {
dprintf(output_fd_opt, "%02u:%02u:%02u", hh, mm, ss);
}
return (output);
@ -1117,7 +1188,7 @@ int checklist_builder(BUILDER_ARGS)
if (output != 0)
return (output);
output = bsddialog_checklist(&conf, text, rows, cols, menurows, nitems,
output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem);
@ -1146,7 +1217,7 @@ int menu_builder(BUILDER_ARGS)
if (output != 0)
return (output);
output = bsddialog_menu(&conf, text, rows, cols, menurows, nitems,
output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem);
@ -1175,7 +1246,7 @@ int radiolist_builder(BUILDER_ARGS)
if (output != 0)
return (output);
output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem);
@ -1204,10 +1275,10 @@ int treeview_builder(BUILDER_ARGS)
if (output != 0)
return (output);
conf.menu.no_name = true;
conf.menu.align_left = true;
conf->menu.no_name = 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);
print_menu_items(output, nitems, items, focusitem);
@ -1239,7 +1310,7 @@ print_form_items(int output, int nitems, struct bsddialog_formitem *items)
return;
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);
}
}
@ -1257,7 +1328,6 @@ int form_builder(BUILDER_ARGS)
}
formheight = (u_int)strtoul(argv[0], NULL, 10);
flags = 0;
argc--;
argv++;
@ -1280,13 +1350,13 @@ int form_builder(BUILDER_ARGS)
valuelen = (int)strtol(argv[j++], NULL, 10);
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].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);
print_form_items(output, nitems, items);
free(items);
@ -1303,14 +1373,16 @@ int inputbox_builder(BUILDER_ARGS)
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
item.yfield = 1;
item.xfield = 1;
item.fieldlen = cols > 4 ? cols-4 : 25;
item.yfield = 0;
item.xfield = 0;
item.fieldlen = 1;
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 = "";
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);
return (output);
@ -1350,7 +1422,7 @@ int mixedform_builder(BUILDER_ARGS)
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);
print_form_items(output, nitems, items);
free(items);
@ -1367,14 +1439,17 @@ int passwordbox_builder(BUILDER_ARGS)
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
item.yfield = 1;
item.xfield = 1;
item.fieldlen = cols > 4 ? cols-4 : 25;
item.yfield = 0;
item.xfield = 0;
item.fieldlen = 1;
item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048;
item.flags = BSDDIALOG_FIELDHIDDEN;
item.flags |= BSDDIALOG_FIELDNOCOLOR;
item.flags |= BSDDIALOG_FIELDCURSOREND;
item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = "";
output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item);
return (output);
@ -1422,7 +1497,7 @@ int passwordform_builder(BUILDER_ARGS)
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);
print_form_items(output, nitems, items);
free(items);

View File

@ -10,7 +10,9 @@
libpath=../lib
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
do

View File

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

View File

@ -9,6 +9,7 @@
*/
#include <bsddialog.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -21,21 +22,22 @@ int main()
int i, output;
struct bsddialog_conf conf;
struct bsddialog_formitem items[3] = {
{"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"},
{"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"},
{"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"}
{"Input:", 0, 0, "value", 0, 10, 30, 50, NULL, 0, "desc 1"},
{"Input:", 1, 0, "read only", 1, 10, 30, 50, NULL, RO, "desc 2"},
{"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) {
printf("Error: %s\n", bsddialog_geterror());
return (1);
}
bsddialog_initconf(&conf);
conf.title = "form";
conf.form.securech = '*';
output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
bsddialog_end();
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);
conf.title = "timebox";
output = bsddialog_timebox(&conf,
"TAB / RIGHT / LEFT to move,\nUP / DOWN to select time", 10, 35,
&hh, &mm, &ss);
output = bsddialog_timebox(&conf, "Example", 9, 35, &hh, &mm, &ss);
bsddialog_end();

View File

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

View File

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

View File

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

View File

@ -3,16 +3,16 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.2
VERSION = 0.3
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -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
LDFLAGS = -lformw -lncursesw -ltinfo
LDFLAGS = -lncursesw -ltinfo
LIBFLAG = -shared
RM = rm -f

View File

@ -3,7 +3,7 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.2
VERSION = 0.3
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a}
@ -14,7 +14,7 @@ OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \
-L/usr/lib -lformw -lncursesw -ltinfow
-L/usr/lib -lncursesw -ltinfow
.if defined(DEBUG)
# `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);
else
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);
for (i = 0; i < stringlen; 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;
if (bs != NULL) /* gauge has not buttons */
minwidth = buttons_width(*bs);
minwidth = buttons_min_width(*bs);
minwidth = MAX(minwidth, MINBARWIDTH);
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);
mainloop = (fd < 0) ? false : true;
if (mainloop) {
input = NULL;
if (fd >= 0) {
fd2 = dup(fd);
input = fdopen(fd2, "r");
if (input == NULL)
if ((input = fdopen(fd2, "r")) == NULL)
RETURN_ERROR("Cannot build FILE* from fd");
} else
input = NULL;
}
mainloop = true;
while (mainloop) {
wrefresh(widget);
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_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
wrefresh(bar);
if (input == NULL) /* that is fd < 0 */
break;
while (true) {
fscanf(input, "%s", inputbuf);
@ -193,10 +193,11 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
if (strcmp(inputbuf, sep) == 0)
break;
strcpy(pntext, inputbuf);
pntext += strlen(inputbuf);
pntext += strlen(inputbuf); /* end string, no strlen */
pntext[0] = ' ';
pntext++;
}
pntext[0] = '\0';
if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
ntext, NULL, false) != 0)
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,
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 colorperc, red, green;
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;
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 = 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)
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);
if (output == BSDDIALOG_ERROR)
return (output);
if (retval == BSDDIALOG_ERROR)
return (retval);
/* mini bars */
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))
wattron(widget, A_BOLD);
mvwaddstr(widget, i+1, 2, minilabels[i]);
if (color && (miniperc >= 0))
wattroff(widget, A_BOLD);
/* perc */
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,
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);
return (output);
return (retval);
}
int
@ -352,7 +354,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
struct bsddialog_fileminibar *minibar)
{
bool update;
int perc, output, *minipercs;
int perc, retval, *minipercs;
unsigned int i, mainperc, totaltodo;
float readforsec;
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;
output = BSDDIALOG_OK;
retval = BSDDIALOG_OK;
i = 0;
update = true;
time(&told);
@ -384,9 +386,9 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
time(&tnew);
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);
if (output == BSDDIALOG_ERROR)
if (retval == BSDDIALOG_ERROR)
return (BSDDIALOG_ERROR);
move(SCREENLINES - 1, 2);
@ -421,7 +423,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
free(minilabels);
free(minipercs);
return (output);
return (retval);
}
int
@ -430,7 +432,8 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
{
bool loop, buttupdate, barupdate;
int y, x, h, w;
int input, currvalue, output, sizebar, bigchange, positions;
int currvalue, retval, sizebar, bigchange, positions;
wint_t input;
float perc;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@ -483,17 +486,18 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(bar);
}
input = getch();
if (get_wch(&input) == ERR)
continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
*value = currvalue;
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
loop = false;
}
break;
@ -587,7 +591,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
}
}
@ -596,7 +600,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
return (output);
return (retval);
}
int
@ -604,7 +608,8 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int sec)
{
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;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@ -650,11 +655,10 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
buttupdate = false;
}
input = getch();
if (input < 0) { /* timeout */
if (get_wch(&input) == ERR) { /* timeout */
tout--;
if (tout < 0) {
output = BSDDIALOG_TIMEOUT;
retval = BSDDIALOG_TIMEOUT;
break;
}
else {
@ -665,12 +669,12 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
loop = false;
}
break;
@ -731,7 +735,7 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
}
}
@ -742,5 +746,5 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
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
.\" SUCH DAMAGE.
.\"
.Dd February 9, 2022
.Dd August 29, 2022
.Dt BSDDIALOG 3
.Os
.Sh NAME
.Nm bsddialog_backtitle ,
.Nm bsddialog_clearterminal ,
.Nm bsddialog_color ,
.Nm bsddialog_color_attrs ,
.Nm bsddialog_checklist ,
.Nm bsddialog_datebox ,
.Nm bsddialog_end ,
@ -36,8 +37,10 @@
.Nm bsddialog_gauge ,
.Nm bsddialog_geterror ,
.Nm bsddialog_get_theme ,
.Nm bsddialog_hascolors ,
.Nm bsddialog_infobox ,
.Nm bsddialog_init ,
.Nm bsddialog_init_notheme ,
.Nm bsddialog_initconf ,
.Nm bsddialog_menu ,
.Nm bsddialog_mixedgauge ,
@ -115,6 +118,8 @@
.Ft int
.Fn bsddialog_init "void"
.Ft int
.Fn bsddialog_init_notheme "void"
.Ft int
.Fn bsddialog_initconf "struct bsddialog_conf *conf"
.Ft int
.Fo bsddialog_menu
@ -218,7 +223,16 @@
.Fa "unsigned int flags"
.Fc
.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"
.Ft bool
.Fn bsddialog_hascolors "void"
.Ft int
.Fn bsddialog_set_default_theme "enum bsddialog_default_theme theme"
.Ft int
@ -239,6 +253,12 @@ API.
restores the screen like before
.Fn bsddialog_init ,
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
.Fn bsddialog_error
returns a string to describe the last error, it should be called after a
@ -258,10 +278,9 @@ is described later.
.Pp
Each
.Fa char*
argument has to be a well terminated string, can be empty
.Pq Dq
but not
.Dv NULL .
argument has to be a well terminated string, it can be a multibyte character
string depending on current locale, see
.Xr setlocale 3 .
.Ss Dialogs
The dialogs have common arguments.
.Fa text
@ -282,6 +301,8 @@ struct bsddialog_conf {
bool ascii_lines;
unsigned int auto_minheight;
unsigned int auto_minwidth;
unsigned int auto_topmargin;
unsigned int auto_downmargin;
const char *bottomtitle;
bool clear;
int *get_height;
@ -298,6 +319,7 @@ struct bsddialog_conf {
const char *f1_message;
} key;
struct {
unsigned int cols_per_row;
bool highlight;
unsigned int tablen;
} text;
@ -309,11 +331,13 @@ struct bsddialog_conf {
bool shortcut_buttons;
} menu;
struct {
bool enable_wchar;
int securech;
char securech;
char *securembch;
bool value_wchar;
bool value_without_ok;
} form;
struct {
bool always_active;
bool without_ok;
const char *ok_label;
bool with_extra;
@ -343,6 +367,23 @@ minimum width if
.Fa cols
is
.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
subtitle at the dialog bottom side.
.It Fa conf.clear
@ -382,11 +423,16 @@ file to open if F1 is pressed.
message to display if F1 is pressed.
.El
.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
.Fa text ,
properly the following sequences are considered escapes:
.Bl -column -compact
.It Dq \eZ0
black.
.It Dq \eZ1
@ -404,7 +450,7 @@ cyan.
.It Dq \eZ7
white.
.It Dq \eZr
reverse colors between foreground and background.
reverse foreground and background.
.It Dq \eZR
disable reverse.
.It Dq \eZb
@ -417,11 +463,22 @@ underline.
disable underline.
.It Dq \eZn
disable each customization.
.It Fa conf.text.tablen
tab length for
.Fa text
argument and
.Fn bsddialog_textbox
function.
.El
.Fa conf.text.tablen
tab length.
.Pp
.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
disable OK button.
.It Fa conf.button.ok_label
@ -598,8 +655,16 @@ enable shortcut keys on buttons, default on items.
.El
.Pp
.Fn bsddialog_form
builds a dialog to display a list of items to get strings in input, an item is
defined like:
builds a dialog to display an array of
.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
.Bd -literal -offset indent -compact
struct bsddialog_formitem {
@ -621,7 +686,7 @@ struct bsddialog_formitem {
.Ed
.Pp
.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
and
.Fa xlabel .
@ -632,45 +697,43 @@ and
.Fa fieldlen
is its graphical width, while
.Fa maxvalelen
is the maximum length of the input string,
is the maximum number of characters of the input string.
.Fa init
is the default value.
is the default field value.
If the OK button is pressed
.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
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
.Dv BSDDIALOG_FIELDREADONLY
.Dv BSDDIALOG_FIELDSINGLEBYTE .
flags for the field.
.Fa bottomdesc
is printed on the bottom side of the screen if the item is focused.
.Fa items
is an array of items of
.Fa nitems
elements,
.Fa formrows
specifies the graphical fixed height for the items list;
.Fa ylabel
and
.Fa yfield
have to be between 1 and
.Fa formrows .
.Pp
.Fn bsddialog_form
can be customized by:
.Bl -column -compact
.It Fa conf.form.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
charachter to hide the input
with
charachter to hide the input with
.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
allocate memory and set
.Fa value
@ -747,8 +810,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
unsigned int h;
unsigned int w;
unsigned int y;
unsigned int x;
} shadow;
struct {
int color;
@ -770,20 +833,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
unsigned int hmargin;
int leftdelim;
int rightdelim;
unsigned int minmargin;
unsigned int maxmargin;
char leftdelim;
char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@ -825,6 +891,8 @@ specifies OR-flags, possible values:
.Dv BSDDIALOG_REVERSE
and
.Dv BSDDIALOG_UNDERLINE .
.Fn bsddialog_color_attrs
gets the properties of a color.
.Pp
.Fn bsddialog_set_theme
sets
@ -840,6 +908,13 @@ and
.Dv BSDDIALOG_THEME_DIALOG ,
they can be set via
.Fn bsddialog_set_default_theme .
.Pp
.Fn bsddialog_hascolors
returns
.Dv true
if the terminal provides colors,
.Dv false
otherwise.
.Sh RETURN VALUES
The functions return the value
.Dv BSDDIALOG_ERROR
@ -975,8 +1050,7 @@ for (i = 0; i < 3; i++) {
.Ed
.Sh SEE ALSO
.Xr bsddialog 1 ,
.Xr curses 3 ,
.Xr ncurses 3
.Xr curses 3
.Sh HISTORY
The
.Nm bsddialog
@ -985,8 +1059,4 @@ library first appeared in
.Sh AUTHORS
.Nm bsddialog
was written by
.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com .
.Sh BUGS
.Fn bsddialog_form
does not resize the dialog after a terminal resize and does not provide
scrolling for items.
.An Alfonso Sabato Siciliano Aq Mt asiciliano@FreeBSD.org .

View File

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

View File

@ -39,8 +39,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
unsigned int h;
unsigned int w;
unsigned int y;
unsigned int x;
} shadow;
struct {
int color;
@ -62,20 +62,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
unsigned int hmargin;
int leftdelim;
int rightdelim;
unsigned int minmargin;
unsigned int maxmargin;
char leftdelim;
char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@ -106,7 +109,11 @@ enum bsddialog_color {
int
bsddialog_color(enum bsddialog_color foreground,
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);
bool bsddialog_hascolors(void);
int bsddialog_set_default_theme(enum bsddialog_default_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;
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, NULL, 0, SCREENCOLS/2,
&htext, &wtext) != 0)
if (text_size(conf, rows, cols, text, NULL, 0, 1, &htext,
&wtext) != 0)
return (BSDDIALOG_ERROR);
}
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)
*h = widget_min_height(conf, htext, 0, false);

View File

@ -32,13 +32,14 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
#define TABLEN 4 /* Default tab len */
#define ERRBUFLEN 1024 /* Error buffer */
#define ERRBUFLEN 1024 /* Error buffer len */
/* Error */
static char errorbuffer[ERRBUFLEN];
@ -53,12 +54,101 @@ void set_error_string(const char *str)
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 */
int hide_widget(int y, int x, int h, int w, bool withshadow)
{
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");
wbkgd(clear, t.screen.color);
@ -101,7 +191,7 @@ int f1help(struct bsddialog_conf *conf)
/* Buttons */
static void
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;
@ -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);
wattroff(window, color_arrows);
x = x + 1 + ((size - 2 - strlen(text))/2);
x = x + 1 + ((size - 2 - strcols(text))/2);
wattron(window, color_button);
mvwaddstr(window, y, x, text);
wattroff(window, color_button);
if (shortcut) {
wattron(window, color_shortkey);
mvwaddch(window, y, x, text[0]);
mvwaddwch(window, y, x, first);
wattroff(window, color_shortkey);
}
}
@ -142,16 +232,28 @@ void
draw_buttons(WINDOW *window, struct buttons bs, bool shortcut)
{
int i, x, startx, y, rows, cols;
unsigned int newmargin, margin, wbuttons;
getmaxyx(window, rows, cols);
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++) {
x = i * (bs.sizebutton + t.button.hmargin);
x = i * (bs.sizebutton + margin);
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 DEFAULT_BUTTON_LABEL BUTTON_OK_LABEL
#define DEFAULT_BUTTON_VALUE BSDDIALOG_OK
wchar_t first;
bs->nbuttons = 0;
bs->curr = 0;
@ -216,6 +319,11 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
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) {
for (i = 0; i < (int)bs->nbuttons; i++) {
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++)
bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i]));
bs->sizebutton = MAX(bs->sizebutton, strcols(bs->label[i]));
bs->sizebutton += 2;
}
int buttons_width(struct buttons bs)
int buttons_min_width(struct buttons bs)
{
unsigned int width;
width = bs.nbuttons * bs.sizebutton;
if (bs.nbuttons > 0)
width += (bs.nbuttons - 1) * t.button.hmargin;
width += (bs.nbuttons - 1) * t.button.minmargin;
return (width);
}
bool shortcut_buttons(int key, struct buttons *bs)
bool shortcut_buttons(wint_t key, struct buttons *bs)
{
bool match;
unsigned int i;
match = false;
for (i = 0; i < bs->nbuttons; i++) {
if (tolower(key) == tolower(bs->label[i][0])) {
if (towlower(key) == towlower(bs->first[i])) {
bs->curr = i;
match = true;
break;
@ -259,48 +367,51 @@ bool shortcut_buttons(int key, struct buttons *bs)
}
/* 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);
if (text[0] != '\\' || text[1] != 'Z')
if (wtext[0] != L'\\' || wtext[1] != L'Z')
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);
if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) {
wattron(win, bsddialog_color(text[2] - '0', COLOR_WHITE, 0));
if ((wtext[2] - L'0') >= 0 && (wtext[2] - L'0') < 8) {
bsddialog_color_attrs(t.dialog.color, NULL, &bg, NULL);
wattron(win, bsddialog_color(wtext[2] - L'0', bg, 0));
return (true);
}
switch (text[2]) {
case 'n':
switch (wtext[2]) {
case L'n':
wattron(win, t.dialog.color);
wattrset(win, A_NORMAL);
break;
case 'b':
case L'b':
wattron(win, A_BOLD);
break;
case 'B':
case L'B':
wattroff(win, A_BOLD);
break;
case 'r':
case L'r':
wattron(win, A_REVERSE);
break;
case 'R':
case L'R':
wattroff(win, A_REVERSE);
break;
case 'u':
case L'u':
wattron(win, A_UNDERLINE);
break;
case 'U':
case L'U':
wattroff(win, A_UNDERLINE);
break;
}
@ -308,21 +419,27 @@ static bool check_set_text_attr(WINDOW *win, char *text)
return (true);
}
/* Word Wrapping */
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)
{
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) {
reallen = 0;
i=0;
while (i < len) {
if (is_text_attr(str+i))
reallen -= 3;
if (is_wtext_attr(str+i) == false)
reallen += wcwidth(str[i]);
i++;
}
}
} else
reallen = wcswidth(str, len);
i = 0;
while (i < len) {
@ -336,13 +453,18 @@ print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str,
}
j = *x;
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;
} else if (j + wcwidth(str[i]) > cols) {
break;
} 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++;
reallen--;
j++;
*x = j;
}
}
@ -354,35 +476,38 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
{
bool loop;
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");
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;
loop = true;
while (loop) {
string[j] = text[i];
string[j] = wtext[i];
if (strchr("\n\t ", string[j]) != NULL || string[j] == '\0') {
string[j] = '\0';
if (wcschr(L"\n\t ", string[j]) != NULL || string[j] == L'\0') {
string[j] = L'\0';
print_string(pad, &rows, cols, &y, &x, string,
conf->text.highlight);
}
switch (text[i]) {
case '\0':
switch (wtext[i]) {
case L'\0':
loop = false;
break;
case '\n':
case L'\n':
x = 0;
y++;
j = -1;
break;
case '\t':
case L'\t':
for (z = 0; z < tablen; z++) {
if (x >= cols) {
x = 0;
@ -392,7 +517,7 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
}
j = -1;
break;
case ' ':
case L' ':
x++;
if (x >= cols) {
x = 0;
@ -410,79 +535,133 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
i++;
}
free(wtext);
free(string);
return (0);
}
/* Autosize */
static int
text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
int mincols, bool increasecols, int *h, int *w)
{
int i, j, z, x, y;
int tablen, wordlen, maxwordlen, nword, maxwords, line, maxwidth;
/* Text Autosize */
#define NL -1
#define WS -2
#define TB -3
struct textproperties {
int nword;
int *words;
#define NL -1
#define WS -2
uint8_t *wletters;
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;
if ((words = calloc(maxwords, sizeof(int))) == NULL)
if ((tp->words = calloc(maxwords, sizeof(int))) == NULL)
RETURN_ERROR("Cannot alloc memory for text autosize");
tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen;
maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS;
if ((wtext = alloc_mbstows(text)) == NULL)
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;
wordlen = 0;
maxwordlen = 0;
i=0;
while (true) {
if (conf->text.highlight && is_text_attr(text + i)) {
i += 3;
tp->nword = 0;
tp->maxline = 0;
tp->maxwordcols = 0;
tp->hasnewline = false;
currlinecols = 0;
wordcols = 0;
l = 0;
for (i = 0; i < wtextlen; i++) {
if (conf->text.highlight && is_wtext_attr(wtext + i)) {
i += 2; /* +1 for update statement */
continue;
}
if (nword + tablen + 1 >= maxwords) {
if (tp->nword + 1 >= maxwords) {
maxwords += 1024;
words = realloc(words, maxwords * sizeof(int));
if (words == NULL)
tp->words = realloc(tp->words, maxwords * sizeof(int));
if (tp->words == NULL)
RETURN_ERROR("Cannot realloc memory for text "
"autosize");
}
if (text[i] == '\0') {
words[nword] = wordlen;
maxwordlen = MAX(wordlen, maxwordlen);
break;
}
if (wcschr(L"\t\n ", wtext[i]) != NULL) {
tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
if (strchr("\t\n ", text[i]) != NULL) {
maxwordlen = MAX(wordlen, maxwordlen);
if (wordlen != 0) {
words[nword] = wordlen;
nword++;
wordlen = 0;
if (wordcols != 0) {
/* line */
currlinecols += wordcols;
/* word */
tp->words[tp->nword] = wordcols;
tp->nword += 1;
wordcols = 0;
}
if (text[i] == '\t') {
for (j = 0; j < tablen; j++)
words[nword + j] = 1;
nword += tablen;
} else {
words[nword] = text[i] == '\n' ? NL : WS;
nword++;
switch (wtext[i]) {
case L'\t':
/* line */
currlinecols += tablen;
/* word */
tp->words[tp->nword] = TB;
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) {
mincols = MAX(mincols, maxwordlen);
mincols = MAX(mincols, tp->maxwordcols);
mincols = MAX(mincols,
(int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS);
mincols = MIN(mincols, maxwidth);
@ -492,26 +671,50 @@ text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
x = 0;
y = 1;
line=0;
for (i = 0; i <= nword; i++) {
if (words[i] == NL) {
l = 0;
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++;
x = 0;
}
else if (words[i] == WS) {
break;
case WS:
x++;
if (x >= mincols) {
x = 0;
y++;
}
}
else {
if (words[i] + x <= mincols)
x += words[i];
else {
for (z = words[i]; z > 0; ) {
y++;
x = MIN(mincols, z);
z -= x;
break;
default:
if (tp->words[i] + x <= mincols) {
x += tp->words[i];
for (z = 0 ; z != tp->words[i]; l++ )
z += tp->wletters[l];
} else if (tp->words[i] <= mincols) {
y++;
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)
break;
if (y <= maxrows || mincols >= maxwidth)
if (mincols >= maxwidth)
break;
if (line >= y * (int)conf->text.cols_per_row && y <= maxrows)
break;
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 */
free(words);
return (0);
}
@ -537,13 +740,26 @@ int
text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext)
{
int wbuttons, maxhtext;
bool changewtext;
int wbuttons, maxhtext;
struct textproperties tp;
wbuttons = 0;
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) {
startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS);
changewtext = true;
@ -555,45 +771,52 @@ text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
changewtext = false;
}
if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) {
maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext;
if (bs != NULL)
maxhtext -= 2;
} else { /* fixed */
maxhtext = rows - VBORDERS - rowsnotext;
if (bs != NULL)
maxhtext -= 2;
}
if (startwtext <= 0 && changewtext)
startwtext = 1;
if (maxhtext <= 0 || startwtext <= 0) {
*htext = *wtext = 0;
return (0);
}
if (startwtext <= 0)
RETURN_ERROR("Fullscreen or fixed cols to print text <=0");
if (text_autosize(conf, text, maxhtext, startwtext, changewtext,
htext, wtext) != 0)
/* Sizing calculation */
if (text_properties(conf, text, &tp) != 0)
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);
}
/* Widget size and position */
int widget_max_height(struct bsddialog_conf *conf)
{
int maxheight;
maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.h : SCREENLINES;
maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.y : SCREENLINES;
if (maxheight <= 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;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - "
"shadow - y <= 0");
}
maxheight -= conf->auto_downmargin;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - Down margins "
"<= 0");
return (maxheight);
}
@ -601,7 +824,7 @@ int widget_max_width(struct bsddialog_conf *conf)
{
int maxwidth;
maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.w : SCREENCOLS;
maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.x : SCREENCOLS;
if (maxwidth <= 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)
{
int min, delimtitle;
int min, delimtitle, wbottomtitle, wtitle;
min = 0;
/* buttons */
if (bs != NULL)
min += buttons_width(*bs);
min += buttons_min_width(*bs);
/* text */
if (wtext > 0)
@ -666,12 +889,15 @@ widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
/* title */
if (conf->title != NULL) {
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 */
if (conf->bottomtitle != NULL)
min = MAX(min, (int)strlen(conf->bottomtitle) + 4);
if (conf->bottomtitle != NULL) {
wbottomtitle = strcols(conf->bottomtitle);
min = MAX(min, wbottomtitle + 4);
}
/* dialog borders */
min += VBORDERS;
@ -722,8 +948,16 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
int
set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
{
if (conf->y == BSDDIALOG_CENTER)
*y = SCREENLINES/2 - (h + t.shadow.h)/2;
int hshadow = conf->shadow ? (int)t.shadow.y : 0;
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)
RETURN_ERROR("Negative begin y (less than -1)");
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
*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 "
"(begin Y + height (+ shadow) > terminal lines)");
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)
RETURN_ERROR("Negative begin x (less than -1)");
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
*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 "
"(begin X + width (+ shadow) > terminal cols)");
return (0);
}
/* Widgets builders */
/* Widgets build, update, destroy */
void
draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
enum elevation elev)
@ -816,7 +1050,7 @@ static int
draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
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;
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);
if (conf->title != NULL) {
if ((wtitle = strcols(conf->title)) < 0)
return (BSDDIALOG_ERROR);
if (t.dialog.delimtitle && conf->no_lines == false) {
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);
}
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);
if (t.dialog.delimtitle && conf->no_lines == false) {
wattron(widget, t.dialog.lineraisecolor);
@ -860,8 +1096,10 @@ draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
}
if (conf->bottomtitle != NULL) {
if ((wbottomtitle = strcols(conf->bottomtitle)) < 0)
return (BSDDIALOG_ERROR);
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, ' ');
waddstr(widget, conf->bottomtitle);
waddch(widget, ' ');
@ -886,7 +1124,7 @@ update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
if (conf->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);
}
@ -913,7 +1151,7 @@ new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y,
int error;
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)
RETURN_ERROR("Cannot build shadow");
wbkgd(*shadow, t.shadow.color);

View File

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

View File

@ -34,10 +34,11 @@
#include "bsddialog_theme.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;
enum bsddialog_default_theme theme;
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;
else
theme = BSDDIALOG_THEME_BLACKWHITE;
@ -113,6 +125,7 @@ int bsddialog_initconf(struct bsddialog_conf *conf)
conf->y = BSDDIALOG_CENTER;
conf->x = BSDDIALOG_CENTER;
conf->shadow = true;
conf->text.cols_per_row = COLSPERROW;
return (BSDDIALOG_OK);
}

View File

@ -177,9 +177,10 @@ getfastprev(int menurows, struct privateitem *pritems, int abs)
static int
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;
for (i = 0; i < npritems; i++) {
@ -187,11 +188,11 @@ getnextshortcut(struct bsddialog_conf *conf, int npritems,
continue;
if (conf->menu.no_name)
ch = pritems[i].item->desc[0];
mbtowc(&wch, pritems[i].item->desc, MB_CUR_MAX);
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)
return (i);
@ -236,12 +237,12 @@ drawseparators(struct bsddialog_conf *conf, WINDOW *pad, int linelen,
}
name = pritems[i].item->name;
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);
wattron(pad, t.menu.namesepcolor);
waddstr(pad, name);
wattroff(pad, t.menu.namesepcolor);
if (strlen(name) > 0 && strlen(desc) > 0)
if (strcols(name) > 0 && strcols(desc) > 0)
waddch(pad, ' ');
wattron(pad, t.menu.descsepcolor);
waddstr(pad, desc);
@ -254,7 +255,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
struct lineposition pos, struct privateitem *pritem, bool focus)
{
int colordesc, colorname, colorshortcut;
const char *shortcut;
wchar_t shortcut;
struct bsddialog_menuitem *item;
item = pritem->item;
@ -303,24 +304,47 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
wattron(pad, colorshortcut);
if (conf->menu.no_name)
shortcut = item->desc;
mbtowc(&shortcut, item->desc, MB_CUR_MAX);
else
shortcut = item->name;
wmove(pad, y, pos.xname + item->depth * DEPTH);
if (shortcut != NULL && shortcut[0] != '\0')
waddch(pad, shortcut[0]);
wattroff(pad, colorshortcut);
mbtowc(&shortcut, item->name, MB_CUR_MAX);
mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut);
wattroff(pad, colorshortcut);
}
/* bottom description */
move(SCREENLINES - 1, 2);
clrtoeol();
if (item->bottomdesc != NULL && focus) {
attron(t.menu.bottomdesccolor);
addstr(item->bottomdesc);
attroff(t.menu.bottomdesccolor);
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
menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
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);
} else {
if (*menurows == 0)
*menurows = MIN(*h-6-htext, nitems);
if (*menurows == 0) {
if (*h - 6 - htext <= 0)
*menurows = 0; /* menu_checksize() will check */
else
*menurows = MIN(*h-6-htext, nitems);
}
}
return (0);
@ -380,8 +408,7 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
mincols = VBORDERS;
/* buttons */
mincols += buttons_width(bs);
mincols += buttons_min_width(bs);
/*
* linelen check, comment to allow some hidden col otherwise portconfig
* 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 "
"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)
RETURN_ERROR("items > 0 but menurows == 0, probably terminal "
"too small");
RETURN_ERROR("items > 0 but menurows == 0, if menurows = 0 "
"terminal too small");
menusize = nitems > 0 ? 3 : 0;
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);
}
/* 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
do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int menurows, enum menumode mode, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{
bool loop, onetrue, movefocus, automenurows, shortcut_butts;
int i, j, y, x, h, w, output, input;
int i, j, y, x, h, w, retval;
int ymenupad, ys, ye, xs, xe, abs, next, totnitems;
wint_t input;
WINDOW *shadow, *widget, *textpad, *menuwin, *menupad;
struct buttons bs;
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) {
pos.maxsepstr = MAX(pos.maxsepstr,
strlen(item->name) + strlen(item->desc));
strcols(item->name) + strcols(item->desc));
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.maxname = MAX(pos.maxname, strlen(item->name));
pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc));
pos.maxname = MAX(pos.maxname, strcols(item->name));
pos.maxdesc = MAX(pos.maxdesc, strcols(item->desc));
}
}
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.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc);
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
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();
prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN,
y + h - menurows, x + 1 + w - TEXTHMARGIN);
prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, y + h - menurows,
x + 1 + w - TEXTHMARGIN);
menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2,
menurows+2, w-4, LOWERED);
menurows + 2, w - 4, LOWERED);
menupad = newpad(totnitems, pos.line);
wbkgd(menupad, t.dialog.color);
@ -562,22 +566,23 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
movefocus = false;
loop = true;
while (loop) {
input = getch();
if (get_wch(&input) == ERR)
continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true;
set_on_output(conf, output, ngroups, groups, pritems);
set_on_output(conf, retval, ngroups, groups, pritems);
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true;
set_on_output(conf, output, ngroups, groups,
set_on_output(conf, retval, ngroups, groups,
pritems);
loop = false;
}
@ -714,10 +719,10 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
default:
if (shortcut_butts) {
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
if (pritems[abs].type == MENUMODE)
pritems[abs].on = true;
set_on_output(conf, output, ngroups,
set_on_output(conf, retval, ngroups,
groups, pritems);
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,
input);
movefocus = next != abs;
}
} /* end switch handler */
if (movefocus) {
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);
movefocus = false;
}
}
} /* end while handler */
if (focuslist != NULL)
*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);
free(pritems);
return (output);
return (retval);
}
/* API */
@ -765,12 +770,12 @@ bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{
int output;
int retval;
output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
retval = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
ngroups, groups, focuslist, focusitem);
return (output);
return (retval);
}
int
@ -778,14 +783,14 @@ bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
int output, focuslist = 0;
int retval, focuslist = 0;
struct bsddialog_menugroup group = {
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);
return (output);
return (retval);
}
int
@ -793,14 +798,14 @@ bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
int output, focuslist = 0;
int retval, focuslist = 0;
struct bsddialog_menugroup group = {
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);
return (output);
return (retval);
}
int
@ -808,12 +813,12 @@ bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
int output, focuslist = 0;
int retval, focuslist = 0;
struct bsddialog_menugroup group = {
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);
return (output);
return (retval);
}

View File

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

View File

@ -28,18 +28,61 @@
#include <sys/param.h>
#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "bsddialog.h"
#include "bsddialog_theme.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
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)
*w = widget_min_width(conf, 0, wpad, &bs);
*w = widget_min_width(conf, 0, wpad + padmargin, &bs);
if (rows == BSDDIALOG_AUTOSIZE)
*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;
mincols = VBORDERS + bs.sizebutton;
mincols = VBORDERS;
mincols += buttons_min_width(bs);
if (cols < mincols)
RETURN_ERROR("Few cols for the textbox");
@ -66,9 +110,11 @@ int
bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
int cols)
{
bool loop;
int i, output, input;
int y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows;
bool loop, has_multi_col;
int i, retval, y, x, h, w;
int hpad, wpad, ypad, xpad, ys, ye, xs, xe, padmargin, printrows;
unsigned int defaulttablen, linecols;
wint_t input;
char buf[BUFSIZ];
FILE *fp;
struct buttons bs;
@ -77,14 +123,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
if ((fp = fopen(file, "r")) == NULL)
RETURN_ERROR("Cannot open file");
defaulttablen = TABSIZE;
set_tabsize((conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen);
hpad = 1;
wpad = 1;
pad = newpad(hpad, wpad);
wbkgd(pad, t.dialog.color);
padmargin = 0;
i = 0;
while (fgets(buf, BUFSIZ, fp) != NULL) {
if ((int) strlen(buf) > wpad) {
wpad = strlen(buf);
if (str_props(buf, &linecols, &has_multi_col) != 0)
continue;
if ((int)linecols > wpad) {
wpad = linecols;
wresize(pad, hpad, wpad);
}
if (i > hpad-1) {
@ -93,20 +144,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
}
mvwaddstr(pad, i, 0, buf);
i++;
if (has_multi_col)
padmargin = 2;
}
fclose(fp);
set_tabsize(defaulttablen);
bs.nbuttons = 1;
bs.label[0] = "EXIT";
if (conf->button.ok_label != NULL)
bs.label[0] = conf->button.ok_label;
bs.value[0] = BSDDIALOG_OK;
get_buttons(conf, &bs, "EXIT", NULL);
bs.curr = 0;
bs.sizebutton = strlen(bs.label[0]) + 2;
bs.nbuttons = 1;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
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)
return (BSDDIALOG_ERROR);
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);
ys = y + 1;
xs = x + 1;
xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5;
xe = xs + w - 3;
xe = xs + w - 3 - padmargin;
ypad = xpad = 0;
printrows = h-4;
loop = true;
while (loop) {
wnoutrefresh(widget);
pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe);
doupdate();
input = getch();
updateborders(conf, widget, padmargin, hpad, wpad, ypad, xpad);
/*
* Overflow multicolumn charchter right border:
* 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) {
case KEY_ENTER:
case 10: /* Enter */
output = BSDDIALOG_OK;
retval = BSDDIALOG_OK;
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
loop = false;
}
break;
@ -164,7 +221,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break;
case KEY_RIGHT:
case 'l':
xpad = (xpad + w-2) < wpad-1 ? xpad + 1 : xpad;
xpad = (xpad + w-2-padmargin) < wpad ? xpad + 1 : xpad;
break;
case KEY_UP:
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)
return (BSDDIALOG_ERROR);
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad,
bs);
padmargin, bs);
if (textbox_checksize(h, w, hpad, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
ys = y + 1;
xs = x + 1;
xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5;
xe = xs + w - 3;
xe = xs + w - 3 - padmargin;
ypad = xpad = 0;
printrows = h - 4;
@ -211,7 +268,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
}
}
@ -219,5 +276,5 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
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))
struct bsddialog_theme t;
bool hastermcolors;
static struct bsddialog_theme bsddialogtheme = {
#define bgwidget COLOR_WHITE
#define bgcurr COLOR_YELLOW
.screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadow.h = 1,
.shadow.w = 2,
.shadow.y = 1,
.shadow.x = 2,
.dialog.delimtitle = true,
.dialog.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget),
.dialog.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget),
.dialog.color = GET_COLOR(COLOR_BLACK, bgwidget),
.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget),
.dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.dialog.titlecolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, bgcurr),
.menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr),
.menu.desccolor = GET_COLOR(COLOR_BLACK, bgwidget),
.menu.f_namecolor = GET_COLOR(COLOR_BLACK, bgcurr),
.menu.namecolor = GET_COLOR(COLOR_BLACK, bgwidget),
.menu.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.menu.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr),
.menu.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget),
.menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_YELLOW),
.menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_namecolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.menu.namecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.namesepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.descsepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
.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.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.form.readonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE),
.form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.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.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.bar.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.bar.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.hmargin = 3,
.button.leftdelim = '[',
.button.rightdelim = ']',
.button.f_delimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.button.delimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.button.f_color = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE,
.button.color = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE,
.button.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr) | A_UNDERLINE,
.button.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget) | A_UNDERLINE
.button.minmargin = 1,
.button.maxmargin = 5,
.button.leftdelim = '[',
.button.rightdelim = ']',
.button.f_delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
.button.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.button.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
.button.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE)
};
static struct bsddialog_theme blackwhite = {
@ -87,8 +89,8 @@ static struct bsddialog_theme blackwhite = {
.screen.color = GET_COLOR(fg, bk),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadow.h = 1,
.shadow.w = 2,
.shadow.y = 1,
.shadow.x = 2,
.dialog.delimtitle = true,
.dialog.titlecolor = GET_COLOR(fg, bk),
@ -108,15 +110,18 @@ static struct bsddialog_theme blackwhite = {
.menu.descsepcolor = GET_COLOR(fg, bk),
.menu.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
.menu.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE,
.menu.bottomdesccolor = GET_COLOR(fg, bk),
.form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
.form.fieldcolor = GET_COLOR(fg, bk),
.form.readonlycolor = GET_COLOR(fg, bk),
.form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
.form.fieldcolor = 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.color = GET_COLOR(fg, bk),
.button.hmargin = 3,
.button.minmargin = 1,
.button.maxmargin = 5,
.button.leftdelim = '[',
.button.rightdelim = ']',
.button.f_delimcolor = GET_COLOR(fg, bk),
@ -128,11 +133,11 @@ static struct bsddialog_theme blackwhite = {
};
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.h = 1,
.shadow.w = 2,
.shadow.y = 1,
.shadow.x = 2,
.dialog.delimtitle = false,
.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.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.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.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE),
.menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE),
.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.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
.form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD,
.form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | 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.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.button.hmargin = 3,
.button.minmargin = 1,
.button.maxmargin = 5,
.button.leftdelim = '<',
.button.rightdelim = '>',
.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->shadow.color = src->shadow.color;
dst->shadow.h = src->shadow.h;
dst->shadow.w = src->shadow.w;
dst->shadow.y = src->shadow.y;
dst->shadow.x = src->shadow.x;
dst->dialog.delimtitle = src->dialog.delimtitle;
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.f_shortcutcolor = src->menu.f_shortcutcolor;
dst->menu.shortcutcolor = src->menu.shortcutcolor;
dst->menu.bottomdesccolor = src->menu.bottomdesccolor;
dst->form.f_fieldcolor = src->form.f_fieldcolor;
dst->form.fieldcolor = src->form.fieldcolor;
dst->form.readonlycolor = src->form.readonlycolor;
dst->form.f_fieldcolor = src->form.f_fieldcolor;
dst->form.fieldcolor = src->form.fieldcolor;
dst->form.readonlycolor = src->form.readonlycolor;
dst->form.bottomdesccolor = src->form.bottomdesccolor;
dst->bar.f_color = src->bar.f_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.rightdelim = src->button.rightdelim;
dst->button.f_delimcolor = src->button.f_delimcolor;
@ -230,7 +241,7 @@ int bsddialog_get_theme(struct bsddialog_theme *theme)
set_theme(theme, &t);
return (0);
return (BSDDIALOG_OK);
}
int bsddialog_set_theme(struct bsddialog_theme *theme)
@ -242,7 +253,7 @@ int bsddialog_set_theme(struct bsddialog_theme *theme)
set_theme(&t, theme);
return (0);
return (BSDDIALOG_OK);
}
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.button.leftdelim = '[';
t.button.rightdelim = ']';
t.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE);
}
else if (newtheme == BSDDIALOG_THEME_BSDDIALOG)
bsddialog_set_theme(&bsddialogtheme);
@ -264,7 +276,7 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
else
RETURN_ERROR("Unknow default theme");
return (0);
return (BSDDIALOG_OK);
}
int
@ -282,3 +294,32 @@ bsddialog_color(enum bsddialog_color foreground,
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 "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
#define MINWDATE 23 /* 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
datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
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)
*w = widget_min_width(conf, htext,minw, &bs);
*w = widget_min_width(conf, wtext, minw, &bs);
if (rows == BSDDIALOG_AUTOSIZE)
*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;
mincols = VBORDERS;
mincols += buttons_width(bs);
mincols += buttons_min_width(bs);
mincols = MAX(minw, 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)
{
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;
struct buttons bs;
struct myclockstruct {
@ -131,30 +163,26 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wrefresh(widget);
sel = -1;
loop = focusbuttons = true;
while (loop) {
for (i = 0; i < 3; i++) {
mvwprintw(c[i].win, 1, 1, "%2d", c[i].value);
wrefresh(c[i].win);
}
for (i = 0; i < 3; i++)
drawquare(conf, c[i].win, "%02d", &c[i].value,
sel == i);
if (focusbuttons == false) {
wmove(c[sel].win, 1, 2);
wrefresh(c[sel].win);
}
input = getch();
if (get_wch(&input) == ERR)
continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
if (focusbuttons == false)
break;
output = bs.value[bs.curr];
loop = false;
if (focusbuttons || conf->button.always_active) {
retval = bs.value[bs.curr];
loop = false;
}
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
loop = false;
}
break;
@ -165,14 +193,13 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false;
if (focusbuttons == false) {
curs_set(1);
sel = 0;
bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel++;
focusbuttons = sel > 2 ? true : false;
if (focusbuttons) {
curs_set(0);
bs.curr = 0;
}
}
@ -184,25 +211,28 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
bs.curr--;
focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) {
curs_set(1);
sel = 2;
bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel--;
focusbuttons = sel < 0 ? true : false;
if (focusbuttons) {
curs_set(0);
if (focusbuttons)
bs.curr = (int)bs.nbuttons - 1;
}
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_UP:
if (focusbuttons)
break;
c[sel].value = c[sel].value > 0 ?
if (focusbuttons) {
sel = 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;
}
break;
case KEY_DOWN:
if (focusbuttons)
@ -214,10 +244,8 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
break;
curs_set(0);
if (f1help(conf) != 0)
return (BSDDIALOG_ERROR);
curs_set(1);
/* No break, screen size can change */
case KEY_RESIZE:
/* Important for decreasing screen */
@ -248,43 +276,33 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wclear(c[0].win);
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);
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);
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 */
refresh();
break;
default:
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
}
}
}
if (output == BSDDIALOG_OK) {
if (retval == BSDDIALOG_OK) {
*hh = c[0].value;
*mm = c[1].value;
*ss = c[2].value;
}
curs_set(0);
for (i = 0; i < 3; i++)
delwin(c[i].win);
end_dialog(conf, shadow, widget, textpad);
return (output);
return (retval);
}
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)
{
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;
struct buttons bs;
struct calendar {
@ -363,31 +382,27 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(widget);
sel = -1;
loop = focusbuttons = true;
while (loop) {
mvwprintw(c[0].win, 1, 1, "%4d", c[0].value);
mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name);
mvwprintw(c[2].win, 1, 1, "%2d", c[2].value);
for (i = 0; i < 3; i++) {
wrefresh(c[i].win);
}
if (focusbuttons == false) {
wmove(c[sel].win, 1, c[sel].x);
wrefresh(c[sel].win);
}
drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
sel == 1);
drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
input = getch();
if (get_wch(&input) == ERR)
continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
if (focusbuttons == false)
break;
output = bs.value[bs.curr];
loop = false;
if (focusbuttons || conf->button.always_active) {
retval = bs.value[bs.curr];
loop = false;
}
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
output = BSDDIALOG_ESC;
retval = BSDDIALOG_ESC;
loop = false;
}
break;
@ -398,14 +413,13 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false;
if (focusbuttons == false) {
curs_set(1);
sel = 0;
bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel++;
focusbuttons = sel > 2 ? true : false;
if (focusbuttons) {
curs_set(0);
bs.curr = 0;
}
}
@ -417,33 +431,37 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
bs.curr--;
focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) {
curs_set(1);
sel = 2;
bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel--;
focusbuttons = sel < 0 ? true : false;
if (focusbuttons) {
curs_set(0);
if (focusbuttons)
bs.curr = (int)bs.nbuttons - 1;
}
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_UP:
if (focusbuttons)
break;
c[sel].value = c[sel].value > 1 ?
c[sel].value - 1 : c[sel].max ;
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* if year change */
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;
if (focusbuttons) {
sel = 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 > 1 ?
c[sel].value - 1 : c[sel].max ;
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* 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;
case KEY_DOWN:
if (focusbuttons)
@ -463,10 +481,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
break;
curs_set(0);
if (f1help(conf) != 0)
return (BSDDIALOG_ERROR);
curs_set(1);
/* No break, screen size can change */
case KEY_RESIZE:
/* Important for decreasing screen */
@ -496,41 +512,31 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wclear(c[0].win);
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);
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);
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 */
refresh();
break;
default:
if (shortcut_buttons(input, &bs)) {
output = bs.value[bs.curr];
retval = bs.value[bs.curr];
loop = false;
}
}
}
if (output == BSDDIALOG_OK) {
if (retval == BSDDIALOG_OK) {
*yy = c[0].value;
*mm = c[1].value;
*dd = c[2].value;
}
curs_set(0);
for (i = 0; i < 3; i++)
delwin(c[i].win);
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
SRCS= bsddialog.c
MAN= bsddialog.1
MAN= bsddialog.1 util_theme.c
CFLAGS+= -I${BSDDIALOG}/lib
LIBADD= bsddialog