contrib/bsddialog: Import version 0.4

Improvements and changes to integrate bsddialog(1) with scripts in BASE.
Overview:

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

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

Merge commit '9f24fda5a8e7ab8243e71473c7e2dc98b4877e64'
This commit is contained in:
Alfonso S. Siciliano 2022-09-25 15:07:29 +02:00
commit 84823cc708
No known key found for this signature in database
GPG Key ID: 3F9EEFACFD371E37
30 changed files with 1734 additions and 847 deletions

View File

@ -1,29 +1,24 @@
bsddialog
.depend*
*.o
*~
*.so*
*.a
examples_library/buildlist
*.gz
*.core
*~
BSDDIALOG.geany
BSDDIALOG.tags
examples_library/calendar
examples_library/checklist
examples_library/datebox
examples_library/form
examples_library/formw
examples_library/margin
examples_library/infobox
examples_library/menu
examples_library/mixedlist
examples_library/radiolist
examples_library/theme
examples_library/treeview
examples_library/infobox
examples_library/msgbox
examples_library/pause
examples_library/radiolist
examples_library/rangebox
examples_library/sade
examples_library/theme
examples_library/timebox
examples_library/yesno
examples_library/u_msgbox
*.gz
lib/libbsddialog.so*
BSDDIALOG.geany
BSDDIALOG.tags
*.core
freebsd-lab/

View File

@ -1,17 +1,68 @@
2022-09-24 Version 0.4
Utility:
* add: --normal-screen to set normal mode.
* add: --alternate-screen to set alternate mode.
* add: --keep-tite as --alternate-screen alias.
* add: --and-dialog to build other dialogs.
* add: --and-widget as --and-dialog alias.
* add: --no-names (--no-tags becames its alias).
* add: --no-descriptions (--no-items becames its alias).
* add: --help-print-name (--help-tags becames its alias).
* add: --item-bottom-desc (--item-help becames its alias).
* add: --cr-wrap (was partially implemented) to keep '\n' with "\n".
* add: --text-unchanged to avoid default modification.
* add: --tab-escape enables "\t" in text.
* add: --clear-screen to clear the screen.
* add: --clear-dialog to clear the dialog (was --clear).
* add: --calendar dialog to select a date.
* add: DIAGNOSTICS messages for bad arguments number.
* add: DIAGNOSTICS messages for missing and unexpected options.
* change: --clear becames alias for --clear-screen.
* change: --print-maxsize format output.
* change: --menu, --radiolist, --checklist and --treeview output.
- no printed items with Cancel or ESC.
- --separator prints <sepstr> before each item except HELP.
- --separator and --separate-output print <sepstr> after each item.
- quoted item name/desc only when needed.
- --menu avoids to print selected item after focused HELP item.
* change: text default modification.
- without a "\n": '\t' -> space, '\n' -> '\n', trim spaces.
- with a "\n": '\t' -> space, '\n' -> space, "\n" -> '\n', no trim.
- delete '\n' after "\n" (also with --cr-wrap).
* change: --datebox input and output format yy/mm/dd -> dd/mm/yy.
* delete: --no-collapse (partially implemented).
* delete: --no-nl-expand (partially implemented).
* delete: --trim (partially implemented).
Library:
* add: bsddialog_msgbox() HOME, END, PPAGE and NPAGE keys.
* add: bsddialog_yesno() HOME, END, PPAGE and NPAGE keys.
* add: bsddialog_menu() SPACE key (equivalent to ENTER).
* add: bsddialog_calendar() to select a date.
* change: rename enum bsddialog_grouptype -> enum bsddialog_menutype.
* change: fixed-menurows becames at most menurows (depending on text).
* change: fixed-rows becames at most rows, min(rows, screenH - shadow).
* change: fixed-cols becames at most cols, min(cols, screenW - shadow).
* delete: undocumented internal bsddialog_menuitem.depth factor (was 2).
2022-08-29 Version 0.3
Utility:
* add: --textbox accepts options for the first button.
* add: --columns-per-row option for text autosizing.
* add: --load-theme option to read and set a custom theme at runtime.
* add: --save-theme option to save current theme.
* add: --bikeshed option for random settings.
* add: --columns-per-row for text autosizing.
* add: --load-theme to read and set a custom theme at runtime.
* add: --save-theme to save current theme.
* add: --bikeshed for random settings.
* add: --switch-buttons enables focus switching: buttons / input
components. Available for: --form, --inputbox, --mixedform,
--passwordform, --passwordbox, --timebox and --datebox.
* change: rename --esc-cancelvalue to --esc-return-cancel.
* change: form field value is printed like multibyte charachter string,
previously widechar string.
* change: --timebox output with zero padding.
* change: --datebox output mm and dd with zero padding.
* fix: --hline with empty string.
* fix: avoid to overlay the backtitle by setting a top margin.
* fix: avoid to overlay down shadow with menus and forms bottomdesc
@ -25,8 +76,8 @@
* add: conf.text.cols_per_row to set a ratio for text autosizing.
* add: timebox and datebox arrows and focus background for boxes.
* add: timebox and datebox UP key to switch focus.
* add: bsddialog_init_notheme() in bsddialo_theme.h.
* add: bsddialog_hascolors() in bsddialo_theme.h.
* add: bsddialog_init_notheme() in bsddialog.h.
* add: bsddialog_hascolors() in bsddialog_theme.h.
* add: theme.form.bottomdesccolor and theme.menu.bottomdesccolor.
* add: conf.button.always_active to disable buttons/input-boxes switch.
* add: dynamic buttons margin.
@ -60,8 +111,8 @@
- add: formheight autosizing.
- add: dynamic item position.
* fix: bsddialog_gauge() with fd < 0.
* fix: internal segmentation fault with disabled shadow.
* fix: bsddialog_gauge() refresh new text.
* fix: internal segmentation fault with disabled shadow.
* fix: center position without shadow.
* fix: bsddialog_infobox() with zero text length.
* fix: text wrapping with more than 1024 words.
@ -92,7 +143,7 @@
* change: theme.button.[left|right]ch -> theme.button.[left|right]delim.
* change: theme.button.space -> theme.button.hmargin.
* change: theme.menu.arrowcolor -> theme.dialog.arrowcolor.
* change: default menu item depth 4 -> 2.
* change: internal bsddialog_menuitem.depth factor 4 -> 2.
* fix: disable HOME, PPAGE, END and NPAGE keys in bsddialog_form().
* fix: visible cursor for timebox.c and form.c in VM VirtualBox.
* fix: mixedlist, center position of separator with big pad.
@ -106,7 +157,7 @@
2022-01-27 Version 0.1
* Common-Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>,
* Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>,
--begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap,
--date-format <format>, --defaultno, --default-button <label>,
--default-no, --default-item <name>, --disable-esc,
@ -131,4 +182,3 @@
--passwordbox, --passwordform, --pause, --radiolist, --rangebox,
--textbox, --timebox, --treeview, --yesno.
* Manuals: bsddialog.1, bsddialog.3.

View File

@ -8,8 +8,8 @@ SOURCES= bsddialog.c util_theme.c
OBJECTS= $(SOURCES:.c=.o)
LIBPATH= ./lib
LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so
CFLAGS= -Wall -Wextra -Wno-unused-parameter -I$(LIBPATH)
LDFLAGS= -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog
CFLAGS= -Wall -Wextra -I$(LIBPATH)
LDFLAGS= -ltinfo -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog
RM = rm -f
all : $(OUTPUT)

View File

@ -9,13 +9,13 @@ OBJECTS= ${SOURCES:.c=.o}
LIBPATH= ${.CURDIR}/lib
LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so
CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter
CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror
# `make -DDEBUG`
.if defined(DEBUG)
CFLAGS= -g -Wall -I${LIBPATH}
LIBDEBUG= -DDEBUG
.endif
LDFLAGS+= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog
LDFLAGS+= -ltinfow -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog
BINDIR= /usr/local/bin
MAN= ${OUTPUT}.1

View File

@ -1,22 +1,8 @@
# BSDDialog 0.3
# BSDDialog 0.4
This project provides **bsddialog** and **libbsddialog**, an utility
and a library to build scripts and tools with TUI dialogs and widgets.
## Intro
Briefly:
<https://www.freebsd.org/status/report-2021-04-2021-06/bsddialog/>
Utility:
<https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html>
Library:
<https://alfonsosiciliano.gitlab.io/posts/2022-01-16-libbsddialog.html>
Screenshots:
<https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074>
[Screenshots](https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074).
## Getting Started
@ -48,9 +34,9 @@ Output:
**Dialogs:**
--checklist, --datebox, --form, --gauge, --inputbox, --menu, --mixedform,
--mixedgauge, --msgbox, --passwordbox, --passwordform, --pause, --radiolist,
--rangebox, --textbox, --timebox, --treeview, --yesno.
--calendar, --checklist, --datebox, --form, --gauge, --infobox, --inputbox,
--menu, --mixedform, --mixedgauge, --msgbox, --passwordbox, --passwordform,
--pause, --radiolist, --rangebox, --textbox, --timebox, --treeview, --yesno.
**Manual**
@ -72,6 +58,7 @@ Output:
and [Examples](https://gitlab.com/alfix/bsddialog/-/tree/main/examples_utility)
in the _Public Domain_ to build new projects:
```
% sh ./examples_utility/calendar.sh
% sh ./examples_utility/checklist.sh
% sh ./examples_utility/form.sh
% sh ./examples_utility/gauge.sh
@ -109,6 +96,7 @@ in the _Public Domain_ to build new projects:
```
% cd examples_library
% sh compile
% ./calendar
% ./checklist
% ./datebox
% ./form

View File

@ -1,4 +1,5 @@
.\"
.\"
.\" Copyright (c) 2021-2022 Alfonso Sabato Siciliano
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 29, 2022
.Dd September 23, 2022
.Dt BSDDIALOG 1
.Os
.Sh NAME
@ -34,12 +35,19 @@
.Nm
.Fl Fl version
.Nm
.Op Fl Fl common-option
.Op Fl Fl option
.Fl Fl dialog
.Ar text
.Ar rows
.Ar cols
.Op Ar dialog-parameter
.Op Ar dialog-argument
.Nm
.Fl Fl dialog1
.Ar ...
.Oo Fl Fl and-dialog
.Fl Fl dialog2
.Ar ...
.Oc ...
.Sh DESCRIPTION
The
.Nm bsddialog
@ -51,21 +59,24 @@ The options
and
.Fl Fl version
print the list of options and the version, respectively, then exit.
.Fl Fl and-dialog
builds another dialog unless the previous one returns Error, ESC or Cancel.
.Pp
The following options are available for each dialog.
.Ar text
is a message printed inside the dialog, except for
.Fl Fl textbox
described later.
is a message printed inside the dialog.
.Ar rows
and
.Ar cols
are the height and width, 0 for autosize and -1 for fullscreen.
.Pp
The possible input got from the user interface is printed to standard error.
.Ss Common options
.Ss Options
The following options can change the default behavior of the utility and are
common to some dialog.
.Bl -tag -width Ds
.It Fl Fl alternate-screen
If available set alternate screen mode, see
.Xr terminfo 5 .
.It Fl Fl ascii-lines
Ascii characters to draw lines.
.It Fl Fl backtitle Ar backtitle
@ -85,8 +96,10 @@ Zero padding with time or date output.
Label for the
.Dq Cancel
button.
.It Fl Fl clear
.It Fl Fl clear-dialog
Hide the dialog at exit.
.It Fl Fl clear-screen
Clear the screen, after the dialog exit if a dialog is built.
.It Fl Fl colors
Enable highlights for text, the following sequences are considered escapes:
.Bl -column -compact
@ -125,13 +138,19 @@ restore normal text.
Try to set the number of columns for a row of text with autosizing; default
.Dv 10 .
.It Fl Fl cr-wrap
Replace new line with a space in
.Ar text .
Keep new line in
.Ar text
also if it constains a
.Dq \en ,
see
.Fl Fl text-unchanged .
.It Fl Fl date-format Ar format
String accepted by
.Xr strftime 3
to customize the output of
.Fl Fl datebox .
.Fl Fl datebox
and
.Fl Fl calendar
.It Fl Fl default-button Ar label
Focus on the button with
.Ar label
@ -146,18 +165,12 @@ Focus on
or
.Dq \&No
button on startup.
.It Fl Fl defaultno
Equivalent to
.Fl Fl default-no .
.It Fl Fl disable-esc
Disable ESC key to quit.
.It Fl Fl esc-return-cancel
Exits with the
ESC key returns
.Dq Cancel
button value if the ESC key is pressed.
.It Fl Fl exit-label Ar label
Equivalent to
.Fl Fl ok-label .
button value.
.It Fl Fl extra-button
Add a button with
.Dq Extra
@ -184,14 +197,14 @@ Set
for
.Dq Help
button.
.It Fl Fl help-print-name
Print the name of the focused item if the Help button is pressed also
with
.Fl Fl item-bottom-desc .
.It Fl Fl help-status
Print also the selected items if the
.Dq Help
button is pressed.
.It Fl Fl help-tags
Print the name of the focused item if the Help button is pressed also
with
.Fl Fl item-help .
.It Fl Fl hfile Ar filename
Open
.Ar filename
@ -208,11 +221,11 @@ Do not exit with unknown options.
Print
.Sq *
to hide passwords while typing; whitespace otherwise.
.It Fl Fl item-bottom-desc
Set a help string for each item of a Checklist, Form, Menu, Mixedform,
Passwordform, Radiolist and Treeview to display at the bottom screen side.
.It Fl Fl item-depth
Specify a margin for items, available for Checklist, Menu and Radiolist.
.It Fl Fl item-help
Set a help string for each element of a Checklist, Form, Menu, Mixedform,
Passwordform, Radiolist and Treeview to display at the bottom screen side.
.It Fl Fl item-prefix
Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview.
.It Fl Fl load-theme Ar file
@ -228,59 +241,46 @@ default 2048.
Do not show
.Dq Cancel
button.
.It Fl Fl no-collapse
Do not replace a TAB character with a space in
.Ar text .
.It Fl Fl no-items
.It Fl Fl no-descriptions
Do not display items desciption, for Checklist, Menu, Radiolist or Treeview.
.It Fl Fl no-label Ar label
Equivalent to
.Fl Fl cancel-label .
.It Fl Fl no-lines
Do not draw borders and lines.
.It Fl Fl no-nl-expand
do not consider the sequence
.Dq \en
like new line.
.It Fl Fl no-names
Do not display items name, for Checklist, Menu and Radiolist.
.It Fl Fl no-ok
Do not draw
.Dq OK
button.
.It Fl Fl no-shadow
No not draw the shadow of the dialog.
.It Fl Fl no-tags
Do not display items name, for Checklist, Menu and Radiolist.
.It Fl Fl nocancel
Equivalent to
.Fl Fl no-cancel .
.It Fl Fl nook
Equivalent to
.Fl Fl no-ok .
.It Fl Fl ok-label Ar label
Set
.Ar label
for
.Dq OK
button.
.It Fl Fl normal-screen
If available set normal screen mode, see
.Xr terminfo 5 .
.It Fl Fl output-fd Ar fd
Print input from user interface to the specified file descriptor.
.It Fl Fl output-separator Ar sep
Set a sepator for the items in output, default whitespace.
.It Fl Fl print-maxsize
Screen size.
This option can be used without a dialog.
.It Fl Fl print-size
Print Dialog height and widget at exit.
.It Fl Fl print-version
Print version.
This option can be used without a dialog.
.It Fl Fl quoted
Quote items in output, default only when necessary.
.It Fl Fl save-theme Ar file
Save the current theme.
This option can be used without a dialog.
.It Fl Fl separate-output
Separate selected items with a new line and avoid to quote.
.It Fl Fl separator Ar sep
Equivalent to
.Fl Fl output-separator .
.It Fl Fl shadow
Show a pseudo shadow for the dialog, enabled by default.
.It Fl Fl single-quoted
@ -302,12 +302,29 @@ Suitable for:
.Fl Fl mixedform ,
.Fl Fl passwordbox ,
.Fl Fl passwordform ,
.Fl Fl timebox
.Fl Fl timebox ,
.Fl Fl calendar
and
.Fl Fl datebox .
.It Fl Fl tab-escape
Replace
.Dq \et
with a tab in
.Ar text .
.It Fl Fl tab-len Ar spaces
Number of spaces to print a TAB in
.Ar text .
.It Fl Fl text-unchanged
By default the
.Ar text
is changed before to be printed.
If it contains at least a
.Dq \en
each new line and TAB is converted to a space, subsequent spaces are merged.
Otherwise new line characters are preserved and a TAB becomes a space.
This option disable the
.Ar text
modification.
.It Fl Fl theme Ar theme
Set a graphical style: blackwhite, bsddialog, flat or dialog.
.It Fl Fl time-format Ar format
@ -317,16 +334,12 @@ to customize the output of
.Fl Fl timebox .
.It Fl Fl title Ar title
Dialog title.
.It Fl Fl trim
remove consecutive spaces in
.Ar text .
.It Fl Fl yes-label Ar label
Equivalent to
.Fl Fl ok-label .
.El
.Ss Dialogs
The following dialogs are available:
.Bl -tag -width Ds
.It Fl Fl calendar Ar text Ar rows Ar cols Op Ar day Ar month Ar year
Dialog to select a date.
.It Fl Fl checklist Ar text Ar rows Ar cols Ar menurows Oo Ar name Ar desc \
Ar status Oc ...
Checklist to select some item from a list via the SPACE key.
@ -342,7 +355,7 @@ or
The names of the selected items are printed to standard error.
.Ar menurows
is the graphical height of the list, 0 for autosize.
.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar year Ar month Ar day
.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar day Ar month Ar year
Dialog to select a date.
.It Fl Fl form Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \
Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Oc ...
@ -393,7 +406,7 @@ Dialog to get a string in input,
.Ar init
is the default value.
.It Fl Fl menu Ar text Ar rows Ar cols Ar menurows Oo Ar name desc Oc ...
Builds a menu to select an item from a list.
Builds a menu to select an item from a list, Space key is equivalent to Enter.
An item has a
.Ar name
and a
@ -461,6 +474,7 @@ a blank line,
Dialog to diplay a message without the
.Dq Cancel
button.
UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text.
.It Fl Fl passwordbox Ar text Ar rows Ar cols Op Ar init
Dialog to get a password,
.Ar init
@ -522,6 +536,7 @@ buttons are renamed
.Dq Yes
and
.Dq \&No .
UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text.
.El
.Sh EXIT STATUS
The
@ -574,6 +589,10 @@ Checklist:
Form:
.Dl bsddialog --form Form 0 0 0 L1: 0 0 X 0 4 20 25 L2: 1 0 Y 1 4 20 25
.Pp
Multi-dialog:
.Dl bsddialog --normal-screen --begin-y 1 --yesno Continue? 0 0 \e \
--and-dialog --begin-y 10 --infobox Yes 0 0
.Pp
Bikeshed:
.Dl bsddialog --bikeshed --inputbox Example 0 0
.Pp
@ -614,6 +633,27 @@ do
i=`expr $i + 1`
done | bsddialog --title Gauge --gauge "Starting..." 10 70
.Ed
.Sh COMPATIBILITY
Outdated options are retained for compatibility, properly equivalent options are
used:
.Bd -literal -offset indent -compact
Obsolete Equivalent
--and-widget --and-dialog
--calendar <text> 2 <cols> --calendar <text> 0 <cols>
--clear --clear-screen
--defaultno --default-no
--exit-label --ok-label
--help-tags --help-print-name
--item-help --item-bottom-desc
--keep-tite --alternate-screen
--no-items --no-descriptions
--no-label --cancel-label
--no-tags --no-names
--nocancel --no-cancel
--nook --no-ok
--separator --output-separator
--yes-label --ok-label
.Ed
.Sh SEE ALSO
.Xr bsddialog 3
.Sh HISTORY
@ -633,7 +673,8 @@ provides a subset of the functionality described in the
manual.
The following features were reimplemented:
.Pp
Common options:
Options:
.Fl Fl and-widget ,
.Fl Fl ascii-lines ,
.Fl Fl backtitle ,
.Fl Fl cancel-label ,
@ -658,14 +699,13 @@ Common options:
.Fl Fl ignore ,
.Fl Fl insecure ,
.Fl Fl item-help ,
.Fl Fl keep-tite ,
.Fl Fl max-input ,
.Fl Fl no-cancel ,
.Fl Fl nocancel ,
.Fl Fl no-collapse ,
.Fl Fl no-items ,
.Fl Fl no-label ,
.Fl Fl no-lines ,
.Fl Fl no-nl-expand ,
.Fl Fl no-ok ,
.Fl Fl nook ,
.Fl Fl no-shadow ,
@ -687,11 +727,11 @@ Common options:
.Fl Fl tab-len ,
.Fl Fl time-format ,
.Fl Fl title ,
.Fl Fl trim ,
.Fl Fl version ,
.Fl Fl yes-label .
.Pp
Dialogs:
.Fl Fl calendar ,
.Fl Fl checklist ,
.Fl Fl form ,
.Fl Fl gauge ,
@ -715,8 +755,10 @@ Some feature differs in input, output, or behavior.
Compatibility is not a priority for future development.
.Sh THANKS TO
.An Baptiste Daroussin
.Aq Mt bapt@FreeBSD.org
and
.Aq Mt bapt@FreeBSD.org ,
.An \&Ed Maste
.Aq Mt emaste@FreeBSD.org
and
.An Juraj Lutter
.Aq Mt otis@FreeBSD.org
for suggestions, help, and testing.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2022 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <bsddialog.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main()
{
int output;
unsigned int yy, mm, dd;
struct bsddialog_conf conf;
time_t cal;
struct tm *localtm;
time(&cal);
localtm = localtime(&cal);
yy = localtm->tm_year + 1900;
mm = localtm->tm_mon + 1;
dd = localtm->tm_mday;
if (bsddialog_init() == BSDDIALOG_ERROR) {
printf("Error: %s\n", bsddialog_geterror());
return (1);
}
bsddialog_initconf(&conf);
conf.title = "calendar";
output = bsddialog_calendar(&conf, "Example", 18, 40, &yy, &mm, &dd);
bsddialog_end();
switch (output) {
case BSDDIALOG_OK:
printf("Date: %u/%u/%u", yy, mm, dd);
break;
case BSDDIALOG_CANCEL:
printf("Cancel");
break;
case BSDDIALOG_ERROR:
printf("Error: %s", bsddialog_geterror());
break;
}
printf("\n");
return (output);
}

View File

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

View File

@ -27,7 +27,7 @@ int main()
{"Password:", 2, 0, "", 2, 10, 30, 50, NULL, H, "desc 3"}
};
/* Optional, unless for unicode/multicolum charachters */
/* Optional, unless for unicode/multi-column characters */
setlocale(LC_ALL, "");
if (bsddialog_init() == BSDDIALOG_ERROR) {
@ -56,4 +56,4 @@ int main()
}
return (output);
}
}

View File

@ -0,0 +1,34 @@
#!/bin/sh
#-
# SPDX-License-Identifier: CC0-1.0
#
# Written in 2022 by Alfonso Sabato Siciliano.
#
# To the extent possible under law, the author has dedicated all copyright
# and related and neighboring rights to this software to the public domain
# worldwide. This software is distributed without any warranty, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>.
: ${BSDDIALOG_ERROR=255}
: ${BSDDIALOG_OK=0}
: ${BSDDIALOG_CANCEL=1}
: ${BSDDIALOG_ESC=5}
DATE=$(./bsddialog --title " calendar " --date-format "%x" \
--calendar "Hello World!" 20 40 \
3>&1 1>&2 2>&3 3>&-)
case $? in
$BSDDIALOG_ERROR )
exit 1
;;
$BSDDIALOG_ESC )
echo "[ESC]"
;;
$BSDDIALOG_CANCEL )
echo "[Cancel]"
;;
$BSDDIALOG_OK )
echo "[OK] $DATE"
;;
esac

View File

@ -14,8 +14,7 @@
: ${BSDDIALOG_CANCEL=1}
: ${BSDDIALOG_ESC=5}
TIME=$(./bsddialog --title " timebox " \
--timebox "Tab / Left / Right to move\nUp / Down to select" 10 40 \
TIME=$(./bsddialog --title " timebox " --timebox "Hello World!" 8 25 \
3>&1 1>&2 2>&3 3>&-)
case $? in

View File

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

View File

@ -3,13 +3,13 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.3
VERSION = 0.4
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
messagebox.c textbox.c theme.c timebox.c
SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \
lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \

View File

@ -327,7 +327,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
wrefresh(bar);
/* getch(); port ncurses shows nothing */
/* getch(); alternate mode (port devel/ncurses) shows nothing */
delwin(bar);
end_dialog(conf, shadow, widget, textpad);

View File

@ -22,11 +22,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 29, 2022
.Dd September 23, 2022
.Dt BSDDIALOG 3
.Os
.Sh NAME
.Nm bsddialog_backtitle ,
.Nm bsddialog_calendar ,
.Nm bsddialog_clearterminal ,
.Nm bsddialog_color ,
.Nm bsddialog_color_attrs ,
@ -62,6 +63,16 @@
.Ft int
.Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle"
.Ft int
.Fo bsddialog_calendar
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
.Fa "int rows"
.Fa "int cols"
.Fa "unsigned int *yy"
.Fa "unsigned int *mm"
.Fa "unsigned int *dd"
.Fc
.Ft int
.Fo bsddialog_checklist
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
@ -75,7 +86,7 @@
.Ft int
.Fn bsddialog_clearterminal "void"
.Ft int
.Fo bsddialog_datebox"
.Fo bsddialog_datebox
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
.Fa "int rows"
@ -476,7 +487,8 @@ function.
buttons always active, avoidind focus switch between buttons and input fields or
input boxes in
.Fn bsddialog_form ,
.Fn bsddialog_datebox
.Fn bsddialog_datebox ,
.Fn bsddialog_calendar
and
.Fn bsddialog_timebox .
.It Fa conf.button.without_ok
@ -515,7 +527,10 @@ to true,
and
.Fa conf.x
to
.Dv BSDDIALOG_CENTER .
.Dv BSDDIALOG_CENTER ,
.Fa conf.text.cols_per_row
to
.Dv 10 .
.Pp
.Fn bsddialog_infobox
builds a dialog without buttons and returns instantly.
@ -531,8 +546,10 @@ builds a dialog waiting until the timeout in
.Fa seconds
expires or a button is pressed.
.Pp
.Fn bsddialog_calendar
and
.Fn bsddialog_datebox
builds a dialog to select a date,
build a dialog to select a date,
.Fa yy ,
.Fa mm ,
and
@ -606,14 +623,14 @@ builds a dialog with collections of checklists, radiolists and separators.
A collection is a set defined like:
.Pp
.Bd -literal -offset indent -compact
enum bsddialog_grouptype {
enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
enum bsddialog_grouptype type;
enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@ -1013,7 +1030,7 @@ struct bsddialog_menuitem check[2] = {
struct bsddialog_menuitem sep[1] = {
{ "3", true, 0, "Radiolist", "(desc)", "" }
};
struct bsddialog_menuitem radio[5] = {
struct bsddialog_menuitem radio[2] = {
{ "4", true, 0, "Name 1", "Desc 1", "Radio Bottom Desc 1" },
{ "5", false, 0, "Name 2", "Desc 2", "Radio Bottom Desc 2" }
};

View File

@ -30,7 +30,7 @@
#include <stdbool.h>
#define LIBBSDDIALOG_VERSION "0.3"
#define LIBBSDDIALOG_VERSION "0.4"
/* Exit status */
#define BSDDIALOG_ERROR -1
@ -136,14 +136,14 @@ struct bsddialog_menuitem {
const char *bottomdesc;
};
enum bsddialog_grouptype {
enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
enum bsddialog_grouptype type;
enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@ -173,6 +173,10 @@ int bsddialog_clearterminal(void);
const char *bsddialog_geterror(void);
/* Dialogs */
int
bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd);
int
bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,

View File

@ -0,0 +1,520 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Alfonso Sabato Siciliano
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
#define MINHCAL 13
#define MINWCAL 36 /* 34 calendar, 1 + 1 margins */
#define MINYEAR 1900
#define MAXYEAR 999999999
static int month_days(int yy, int mm)
{
int days;
if (mm == 2)
days = ISLEAP(yy) ? 29 : 28;
else if (mm == 4 || mm == 6 || mm == 9 || mm == 11)
days = 30;
else
days = 31;
return (days);
}
enum operation {
UP_DAY,
DOWN_DAY,
LEFT_DAY,
RIGHT_DAY,
UP_MONTH,
DOWN_MONTH,
UP_YEAR,
DOWN_YEAR
};
static void datectl(enum operation op, int *yy, int *mm, int *dd)
{
int ndays;
ndays = month_days(*yy, *mm);
switch (op) {
case UP_DAY:
if (*dd > 7)
*dd -= 7;
else {
if (*mm == 1) {
*yy -= 1;
*mm = 12;
} else
*mm -= 1;
ndays = month_days(*yy, *mm);
*dd = ndays - abs(7 - *dd);
}
break;
case DOWN_DAY:
if (*dd + 7 < ndays)
*dd += 7;
else {
if (*mm == 12) {
*yy += 1;
*mm = 1;
} else
*mm += 1;
*dd = *dd + 7 - ndays;
}
break;
case LEFT_DAY:
if (*dd > 1)
*dd -= 1;
else {
if (*mm == 1) {
*yy -= 1;
*mm = 12;
} else
*mm -= 1;
*dd = month_days(*yy, *mm);
}
break;
case RIGHT_DAY:
if (*dd < ndays)
*dd += 1;
else {
if (*mm == 12) {
*yy += 1;
*mm = 1;
} else
*mm += 1;
*dd = 1;
}
break;
case UP_MONTH:
if (*mm == 1) {
*mm = 12;
*yy -= 1;
} else
*mm -= 1;
ndays = month_days(*yy, *mm);
if (*dd > ndays)
*dd = ndays;
break;
case DOWN_MONTH:
if (*mm == 12) {
*mm = 1;
*yy += 1;
} else
*mm += 1;
ndays = month_days(*yy, *mm);
if (*dd > ndays)
*dd = ndays;
break;
case UP_YEAR:
*yy -= 1;
ndays = month_days(*yy, *mm);
if (*dd > ndays)
*dd = ndays;
break;
case DOWN_YEAR:
*yy += 1;
ndays = month_days(*yy, *mm);
if (*dd > ndays)
*dd = ndays;
break;
}
if (*yy < MINYEAR) {
*yy = MINYEAR;
*mm = 1;
*dd = 1;
}
if (*yy > MAXYEAR) {
*yy = MAXYEAR;
*mm = 12;
*dd = 31;
}
}
static int week_day(int yy, int mm, int dd)
{
int wd;
dd += mm < 3 ? yy-- : yy - 2;
wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400;
wd %= 7;
return (wd);
}
static void
print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
bool active)
{
int ndays, i, y, x, wd, h, w;
getmaxyx(win, h, w);
wclear(win);
draw_borders(conf, win, h, w, RAISED);
if (active) {
wattron(win, t.dialog.arrowcolor);
mvwhline(win, 0, 15, conf->ascii_lines ? '^' : ACS_UARROW, 4);
mvwhline(win, h-1, 15, conf->ascii_lines ? 'v' : ACS_DARROW, 4);
mvwvline(win, 3, 0, conf->ascii_lines ? '<' : ACS_LARROW, 3);
mvwvline(win, 3, w-1, conf->ascii_lines ? '>' : ACS_RARROW, 3);
wattroff(win, t.dialog.arrowcolor);
}
mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat");
ndays = month_days(yy, mm);
y = 2;
wd = week_day(yy, mm, 1);
for (i = 1; i <= ndays; i++) {
x = 5 + (4 * wd); /* x has to be 6 with week number */
wmove(win, y, x);
mvwprintw(win, y, x, "%2d", i);
if (i == dd) {
wattron(win, t.menu.f_namecolor);
mvwprintw(win, y, x, "%2d", i);
wattroff(win, t.menu.f_namecolor);
}
wd++;
if (wd > 6) {
wd = 0;
y++;
}
}
wrefresh(win);
}
static void
drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
const void *value, bool focus)
{
int h, w;
getmaxyx(win, h, w);
draw_borders(conf, win, h, w, RAISED);
if (focus) {
wattron(win, t.dialog.arrowcolor);
mvwhline(win, 0, 7, conf->ascii_lines ? '^' : ACS_UARROW, 3);
mvwhline(win, 2, 7, conf->ascii_lines ? 'v' : ACS_DARROW, 3);
wattroff(win, t.dialog.arrowcolor);
}
if (focus)
wattron(win, t.menu.f_namecolor);
if (strchr(fmt, 's') != NULL)
mvwprintw(win, 1, 1, fmt, (const char*)value);
else
mvwprintw(win, 1, 1, fmt, *((const int*)value));
if (focus)
wattroff(win, t.menu.f_namecolor);
wrefresh(win);
}
static int
calendar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int *w, const char *text, struct buttons bs)
{
int htext, wtext;
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, &bs, MINHCAL, MINWCAL,
&htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
}
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, MINWCAL, &bs);
if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, MINHCAL, true);
return (0);
}
static int calendar_checksize(int rows, int cols, struct buttons bs)
{
int mincols;
mincols = MAX(MINWCAL, buttons_min_width(bs));
mincols += VBORDERS;
if (cols < mincols)
RETURN_ERROR("Few cols for this calendar (at least 38)");
if (rows < MINHCAL + 2 + 2) /* 2 buttons + 2 borders */
RETURN_ERROR("Few rows for calendar (at least 17)");
return (0);
}
int
bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
{
bool loop, focusbuttons;
int retval, y, x, h, w, sel, ycal, xcal, year, month, day;
wint_t input;
WINDOW *widget, *textpad, *shadow, *yearwin, *monthwin, *daywin;
struct buttons bs;
const char *m[12] = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
};
if (yy == NULL || mm == NULL || dd == NULL)
RETURN_ERROR("yy / mm / dd cannot be NULL");
year = *yy > MAXYEAR ? MAXYEAR : *yy;
if (year < MINYEAR)
year = MINYEAR;
month = *mm > 12 ? 12 : *mm;
if (month == 0)
month = 1;
day = *dd == 0 ? 1 : *dd;
if(day > month_days(year, month))
day = month_days(year, month);
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
if (calendar_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
return (BSDDIALOG_ERROR);
if (calendar_checksize(h, w, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
true) != 0)
return (BSDDIALOG_ERROR);
pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
doupdate();
ycal = y + h - 15;
xcal = x + w/2 - 17;
mvwaddstr(widget, h - 16, w/2 - 17, "Month");
monthwin = new_boxed_window(conf, ycal, xcal, 3, 17, RAISED);
mvwaddstr(widget, h - 16, w/2, "Year");
yearwin = new_boxed_window(conf, ycal, xcal + 17, 3, 17, RAISED);
daywin = new_boxed_window(conf, ycal + 3, xcal, 9, 34, RAISED);
wrefresh(widget);
sel = -1;
loop = focusbuttons = true;
while (loop) {
drawsquare(conf, monthwin, "%15s", m[month - 1], sel == 0);
drawsquare(conf, yearwin, "%15d", &year, sel == 1);
print_calendar(conf, daywin, year, month, day, sel == 2);
if (get_wch(&input) == ERR)
continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
if (focusbuttons || conf->button.always_active) {
retval = bs.value[bs.curr];
loop = false;
}
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
retval = BSDDIALOG_ESC;
loop = false;
}
break;
case '\t': /* TAB */
if (focusbuttons) {
bs.curr++;
if (bs.curr >= (int)bs.nbuttons) {
focusbuttons = false;
sel = 0;
bs.curr = conf->button.always_active ?
0 : -1;
}
} else {
sel++;
if (sel > 2) {
focusbuttons = true;
sel = -1;
bs.curr = 0;
}
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_RIGHT:
if (focusbuttons) {
bs.curr++;
if (bs.curr >= (int)bs.nbuttons) {
focusbuttons = false;
sel = 0;
bs.curr = conf->button.always_active ?
0 : -1;
}
} else if (sel == 2) {
datectl(RIGHT_DAY, &year, &month, &day);
} else { /* Month or Year*/
sel++;
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_LEFT:
if (focusbuttons) {
bs.curr--;
if (bs.curr < 0) {
focusbuttons = false;
sel = 2;
bs.curr = conf->button.always_active ?
0 : -1;
}
} else if (sel == 2) {
datectl(LEFT_DAY, &year, &month, &day);
} else if (sel == 1) {
sel = 0;
} else { /* sel = 0, Month */
focusbuttons = true;
sel = -1;
bs.curr = 0;
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_UP:
if (focusbuttons) {
sel = 2;
focusbuttons = false;
bs.curr = conf->button.always_active ? 0 : -1;
draw_buttons(widget, bs, true);
wrefresh(widget);
} else if (sel == 0) {
datectl(UP_MONTH, &year, &month, &day);
} else if (sel == 1) {
datectl(UP_YEAR, &year, &month, &day);
} else { /* sel = 2 */
datectl(UP_DAY, &year, &month, &day);
}
break;
case KEY_DOWN:
if (focusbuttons) {
break;
} else if (sel == 0) {
datectl(DOWN_MONTH, &year, &month, &day);
} else if (sel == 1) {
datectl(DOWN_YEAR, &year, &month, &day);
} else { /* sel = 2 */
datectl(DOWN_DAY, &year, &month, &day);
}
break;
case KEY_HOME:
datectl(UP_MONTH, &year, &month, &day);
break;
case KEY_END:
datectl(DOWN_MONTH, &year, &month, &day);
break;
case KEY_PPAGE:
datectl(UP_YEAR, &year, &month, &day);
break;
case KEY_NPAGE:
datectl(DOWN_YEAR, &year, &month, &day);
break;
case KEY_F(1):
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
break;
if (f1help(conf) != 0)
return (BSDDIALOG_ERROR);
/* No break, screen size can change */
case KEY_RESIZE:
/* Important for decreasing screen */
hide_widget(y, x, h, w, conf->shadow);
refresh();
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
if (calendar_autosize(conf, rows, cols, &h, &w, text,
bs) != 0)
return (BSDDIALOG_ERROR);
if (calendar_checksize(h, w, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
if (update_dialog(conf, shadow, widget, y, x, h, w,
textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
doupdate();
ycal = y + h - 15;
xcal = x + w/2 - 17;
mvwaddstr(widget, h - 16, w/2 - 17, "Month");
mvwin(monthwin, ycal, xcal);
mvwaddstr(widget, h - 16, w/2, "Year");
mvwin(yearwin, ycal, xcal + 17);
mvwin(daywin, ycal + 3, xcal);
wrefresh(widget);
/* Important to avoid grey lines expanding screen */
refresh();
break;
default:
if (shortcut_buttons(input, &bs)) {
retval = bs.value[bs.curr];
loop = false;
}
}
}
if (retval == BSDDIALOG_OK) {
*yy = year;
*mm = month;
*dd = day;
}
delwin(yearwin);
delwin(monthwin);
delwin(daywin);
end_dialog(conf, shadow, widget, textpad);
return (retval);
}

View File

@ -424,34 +424,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
} else
notext += *menurows;
/* cols autosize, rows autosize, rows fullscreen, menu particularity */
if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4,
&htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
}
if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext,
&wtext) != 0)
return (BSDDIALOG_ERROR);
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, linelen + 4, &bs);
if (rows == BSDDIALOG_AUTOSIZE) {
if (*menurows == 0) {
if (*menurows == BSDDIALOG_AUTOSIZE) {
menusize = widget_max_height(conf) - HBORDERS -
2 /*buttons*/ - htext;
menusize = MIN(menusize, nitems + 2);
*menurows = menusize - 2 < 0 ? 0 : menusize - 2;
}
else /* h autosize with fixed menurows */
} else /* h autosize with fixed menurows */
menusize = *menurows + 2;
*h = widget_min_height(conf, htext, menusize, true);
/*
* avoid menurows overflow and
* with rows=AUTOSIZE menurows!=0 becomes max-menurows
*/
*menurows = MIN(*h - 6 - htext, (int)*menurows);
} else {
if (*menurows == 0) {
} else { /* fixed rows */
if (*menurows == BSDDIALOG_AUTOSIZE) {
if (*h - 6 - htext <= 0)
*menurows = 0; /* form_checksize() will check */
else
@ -459,6 +450,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
}
}
/* avoid menurows overflow and menurows becomes at most menurows */
if (*h - 6 - htext <= 0)
*menurows = 0; /* form_checksize() will check */
else
*menurows = MIN(*h - 6 - htext, (int)*menurows);
return (0);
}

View File

@ -921,11 +921,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
*h = maxheight;
else if (rows < BSDDIALOG_FULLSCREEN)
RETURN_ERROR("Negative (less than -1) height");
else if (rows > BSDDIALOG_AUTOSIZE) {
if ((*h = rows) > maxheight)
RETURN_ERROR("Height too big (> terminal height - "
"shadow)");
}
else if (rows > BSDDIALOG_AUTOSIZE) /* fixed rows */
*h = MIN(rows, maxheight); /* rows is at most maxheight */
/* rows == AUTOSIZE: each widget has to set its size */
if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR)
@ -935,11 +932,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
*w = maxwidth;
else if (cols < BSDDIALOG_FULLSCREEN)
RETURN_ERROR("Negative (less than -1) width");
else if (cols > BSDDIALOG_AUTOSIZE) {
if ((*w = cols) > maxwidth)
RETURN_ERROR("Width too big (> terminal width - "
"shadow)");
}
else if (cols > BSDDIALOG_AUTOSIZE) /* fixed cols */
*w = MIN(cols, maxwidth); /* cols is at most maxwidth */
/* cols == AUTOSIZE: each widget has to set its size */
return (0);

View File

@ -43,6 +43,9 @@ extern bool hastermcolors;
refresh(); \
} while (0)
/* date */
#define ISLEAP(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
/* unicode */
unsigned int strcols(const char *mbstring);
int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col);

View File

@ -99,7 +99,9 @@ int bsddialog_end(void)
int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle)
{
mvaddstr(0, 1, backtitle);
move(0, 1);
clrtoeol();
addstr(backtitle);
if (conf->no_lines != true)
mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE,
SCREENCOLS - 2);

View File

@ -36,7 +36,6 @@
#include "bsddialog_theme.h"
#include "lib_util.h"
#define DEPTH 2
#define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */
enum menumode {
@ -277,7 +276,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
colorname = focus ? t.menu.f_namecolor : t.menu.namecolor;
if (conf->menu.no_name == false) {
wattron(pad, colorname);
mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, item->name);
mvwaddstr(pad, y, pos.xname + item->depth, item->name);
wattroff(pad, colorname);
}
@ -290,8 +289,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
if (conf->menu.no_desc == false) {
wattron(pad, colordesc);
if (conf->menu.no_name)
mvwaddstr(pad, y, pos.xname + item->depth * DEPTH,
item->desc);
mvwaddstr(pad, y, pos.xname + item->depth, item->desc);
else
mvwaddstr(pad, y, pos.xdesc, item->desc);
wattroff(pad, colordesc);
@ -307,7 +305,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
mbtowc(&shortcut, item->desc, MB_CUR_MAX);
else
mbtowc(&shortcut, item->name, MB_CUR_MAX);
mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut);
mvwaddwch(pad, y, pos.xname + item->depth, shortcut);
wattroff(pad, colorshortcut);
}
@ -362,34 +360,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
} else
notext += *menurows;
/* cols autosize, rows autosize, rows fullscreen, menu particularity */
if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4,
&htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
}
if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext,
&wtext) != 0)
return (BSDDIALOG_ERROR);
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, linelen + 4, &bs);
if (rows == BSDDIALOG_AUTOSIZE) {
if (*menurows == 0) {
if (*menurows == BSDDIALOG_AUTOSIZE) {
menusize = widget_max_height(conf) - HBORDERS -
2 /*buttons*/ - htext;
menusize = MIN(menusize, nitems + 2);
*menurows = menusize - 2 < 0 ? 0 : menusize - 2;
}
else /* h autosize with fixed menurows */
} else /* h autosize with fixed menurows */
menusize = *menurows + 2;
*h = widget_min_height(conf, htext, menusize, true);
/*
* avoid menurows overflow and
* with rows=AUTOSIZE menurows!=0 becomes max-menurows
*/
*menurows = MIN(*h - 6 - htext, (int)*menurows);
} else {
if (*menurows == 0) {
} else { /* fixed rows */
if (*menurows == BSDDIALOG_AUTOSIZE) {
if (*h - 6 - htext <= 0)
*menurows = 0; /* menu_checksize() will check */
else
@ -397,6 +386,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
}
}
/* avoid menurows overflow and menurows becomes at most menurows */
if (*h - 6 - htext <= 0)
*menurows = 0; /* menu_checksize() will check */
else
*menurows = MIN(*h - 6 - htext, (int)*menurows);
return (0);
}
@ -475,7 +470,6 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
}
pos.maxname = conf->menu.no_name ? 0 : pos.maxname;
pos.maxdesc = conf->menu.no_desc ? 0 : pos.maxdesc;
pos.maxdepth = DEPTH * pos.maxdepth;
pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0);
pos.xname = pos.xselector + pos.selectorlen +
@ -696,11 +690,15 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
movefocus = next != abs;
break;
case ' ': /* Space */
if (pritems[abs].type == MENUMODE)
break;
else if (pritems[abs].type == CHECKLISTMODE)
if (pritems[abs].type == MENUMODE) {
retval = bs.value[bs.curr];
pritems[abs].on = true;
set_on_output(conf, retval, ngroups, groups,
pritems);
loop = false;
} else if (pritems[abs].type == CHECKLISTMODE) {
pritems[abs].on = !pritems[abs].on;
else { /* RADIOLISTMODE */
} else { /* RADIOLISTMODE */
for (i = abs - pritems[abs].index;
i < totnitems &&
pritems[i].group == pritems[abs].group;

View File

@ -103,7 +103,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
struct buttons bs)
{
bool hastext, loop;
int y, x, h, w, retval, ytextpad, htextpad, unused;
int y, x, h, w, retval, ytextpad, htextpad, printrows, unused;
WINDOW *widget, *textpad, *shadow;
wint_t input;
@ -120,12 +120,13 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
true) != 0)
return (BSDDIALOG_ERROR);
printrows = h - 4;
ytextpad = 0;
getmaxyx(textpad, htextpad, unused);
unused++; /* fix unused error */
textupdate(widget, textpad, htextpad, ytextpad, hastext);
loop = true;
while (loop) {
textupdate(widget, textpad, htextpad, ytextpad, hastext);
doupdate();
if (get_wch(&input) == ERR)
continue;
@ -160,6 +161,30 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
wnoutrefresh(widget);
}
break;
case KEY_UP:
if (ytextpad > 0)
ytextpad--;
break;
case KEY_DOWN:
if (ytextpad + printrows < htextpad)
ytextpad++;
break;
case KEY_HOME:
ytextpad = 0;
break;
case KEY_END:
ytextpad = htextpad - printrows;
ytextpad = ytextpad < 0 ? 0 : ytextpad;
break;
case KEY_PPAGE:
ytextpad -= printrows;
ytextpad = ytextpad < 0 ? 0 : ytextpad;
break;
case KEY_NPAGE:
ytextpad += printrows;
if (ytextpad + printrows > htextpad)
ytextpad = htextpad - printrows;
break;
case KEY_F(1):
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
@ -186,6 +211,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
printrows = h - 4;
getmaxyx(textpad, htextpad, unused);
ytextpad = 0;
textupdate(widget, textpad, htextpad, ytextpad, hastext);
@ -193,18 +219,6 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
/* Important to fix grey lines expanding screen */
refresh();
break;
case KEY_UP:
if (ytextpad == 0)
break;
ytextpad--;
textupdate(widget, textpad, htextpad, ytextpad, hastext);
break;
case KEY_DOWN:
if (ytextpad + h - 4 >= htextpad)
break;
ytextpad++;
textupdate(widget, textpad, htextpad, ytextpad, hastext);
break;
default:
if (shortcut_buttons(input, &bs)) {
retval = bs.value[bs.curr];

View File

@ -258,7 +258,6 @@ int bsddialog_set_theme(struct bsddialog_theme *theme)
int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
{
if (newtheme == BSDDIALOG_THEME_FLAT) {
bsddialog_set_theme(&dialogtheme);
t.dialog.lineraisecolor = t.dialog.linelowercolor;

View File

@ -39,7 +39,7 @@
#define MINWTIME 14 /* 3 windows and their borders */
static void
drawquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
const void *value, bool focus)
{
int h, l, w;
@ -167,7 +167,7 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
loop = focusbuttons = true;
while (loop) {
for (i = 0; i < 3; i++)
drawquare(conf, c[i].win, "%02d", &c[i].value,
drawsquare(conf, c[i].win, "%02d", &c[i].value,
sel == i);
if (get_wch(&input) == ERR)
@ -341,8 +341,6 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
{ "October", 31 }, { "November", 30 }, { "December", 31 }
};
#define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
for (i = 0 ; i < 3; i++) {
if (c[i].value > c[i].max)
c[i].value = c[i].max;
@ -350,7 +348,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
c[i].value = 1;
}
c[2].max = m[c[1].value -1].days;
if (c[1].value == 2 && ISLEAF(c[0].value))
if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
if (c[2].value > c[2].max)
c[2].value = c[2].max;
@ -385,10 +383,10 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
sel = -1;
loop = focusbuttons = true;
while (loop) {
drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
drawsquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
drawsquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
sel == 1);
drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
drawsquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
if (get_wch(&input) == ERR)
continue;
@ -456,7 +454,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* if year change */
if (c[1].value == 2 && ISLEAF(c[0].value))
if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
/* set new day */
if (c[2].value > c[2].max)
@ -471,7 +469,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* if year change */
if (c[1].value == 2 && ISLEAF(c[0].value))
if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
/* set new day */
if (c[2].value > c[2].max)
@ -539,4 +537,4 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
end_dialog(conf, shadow, widget, textpad);
return (retval);
}
}

View File

@ -100,7 +100,7 @@ static struct property p[NPROPERTY] = {
{ "theme.button.f_shortcutcolor", COLOR, &t.button.f_shortcutcolor}
};
static char *color[8] = {
static const char *color[8] = {
"black",
"red",
"green",
@ -111,7 +111,15 @@ static char *color[8] = {
"white"
};
int savetheme(const char *file, char *errbuf, const char *version)
#define EXIT_FMTERROR(fmt, ...) do { \
bsddialog_end(); \
printf("Error: "); \
printf(fmt, __VA_ARGS__); \
printf(".\n"); \
exit (255); \
} while (0)
void savetheme(const char *file, const char *version)
{
int i;
unsigned int flags;
@ -119,20 +127,14 @@ int savetheme(const char *file, char *errbuf, const char *version)
time_t clock;
FILE *fp;
if (bsddialog_get_theme(&t) != BSDDIALOG_OK) {
sprintf(errbuf, "Cannot save theme: %s", bsddialog_geterror());
return (BSDDIALOG_ERROR);
}
if (bsddialog_get_theme(&t) != BSDDIALOG_OK)
EXIT_FMTERROR("cannot save theme: %s", bsddialog_geterror());
if(time(&clock) < 0) {
sprintf(errbuf, "Cannot save profile (getting current time)");
return (BSDDIALOG_ERROR);
}
if(time(&clock) < 0)
EXIT_FMTERROR("%s", "cannot save profile getting current time");
if ((fp = fopen(file, "w")) == NULL) {
sprintf(errbuf, "Cannot open %s to save profile", file);
return (BSDDIALOG_ERROR);
}
if ((fp = fopen(file, "w")) == NULL)
EXIT_FMTERROR("cannot open %s to save profile", file);
fprintf(fp, "### bsddialog theme - %s", ctime(&clock));
fputs("# Refer to bsddialog(3) manual for theme.* properties\n", fp);
@ -167,11 +169,15 @@ int savetheme(const char *file, char *errbuf, const char *version)
}
fclose(fp);
return (BSDDIALOG_OK);
}
int loadtheme(const char *file, char *errbuf)
void setdeftheme(enum bsddialog_default_theme theme)
{
if (bsddialog_set_default_theme(theme) != BSDDIALOG_OK)
EXIT_FMTERROR("%s", bsddialog_geterror());
}
void loadtheme(const char *file)
{
bool boolvalue;
char charvalue, *value;
@ -181,21 +187,16 @@ int loadtheme(const char *file, char *errbuf)
enum bsddialog_color bg, fg;
FILE *fp;
if (bsddialog_get_theme(&t) != BSDDIALOG_OK) {
sprintf(errbuf, "Cannot get current theme: %s",
if (bsddialog_get_theme(&t) != BSDDIALOG_OK)
EXIT_FMTERROR("Cannot get current theme: %s",
bsddialog_geterror());
return (BSDDIALOG_ERROR);
}
if((fp = fopen(file, "r")) == NULL) {
sprintf(errbuf, "Cannot open theme \"%s\"", file);
return (BSDDIALOG_ERROR);
}
if((fp = fopen(file, "r")) == NULL)
EXIT_FMTERROR("Cannot open theme \"%s\"", file);
#define RETURN_ERROR(name, error) do { \
sprintf(errbuf, "%s for \"%s\"", error, name); \
#define EXIT_ERROR(name, error) do { \
fclose(fp); \
return (BSDDIALOG_ERROR); \
EXIT_FMTERROR("%s for \"%s\"", error, name); \
} while (0)
while(fgets(line, BUFSIZ, fp) != NULL) {
@ -211,7 +212,7 @@ int loadtheme(const char *file, char *errbuf)
if (i >= NPROPERTY) {
if (strcmp(name, "version") == 0)
continue;
RETURN_ERROR(name, "Unknown theme property name");
EXIT_ERROR(name, "Unknown theme property name");
}
switch (p[i].type) {
case CHAR:
@ -219,17 +220,17 @@ int loadtheme(const char *file, char *errbuf)
value[0] == '\0')
value++;
if (sscanf(value, "%c", &charvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a char");
EXIT_ERROR(p[i].name, "Cannot get a char");
*((int*)p[i].value) = charvalue;
break;
case INT:
if (sscanf(value, "%d", &intvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a int");
EXIT_ERROR(p[i].name, "Cannot get a int");
*((int*)p[i].value) = intvalue;
break;
case UINT:
if (sscanf(value, "%u", &uintvalue) != 1)
RETURN_ERROR(p[i].name, "Cannot get a uint");
EXIT_ERROR(p[i].name, "Cannot get a uint");
*((unsigned int*)p[i].value) = uintvalue;
break;
case BOOL:
@ -239,19 +240,19 @@ int loadtheme(const char *file, char *errbuf)
break;
case COLOR:
if (sscanf(value, "%s %s", c1, c2) != 2)
RETURN_ERROR(p[i].name, "Cannot get 2 colors");
EXIT_ERROR(p[i].name, "Cannot get 2 colors");
/* Foreground */
for (j = 0; j < 8 ; j++)
if ((strstr(c1, color[j])) != NULL)
break;
if ((fg = j) > 7)
RETURN_ERROR(p[i].name, "Bad foreground");
EXIT_ERROR(p[i].name, "Bad foreground");
/* Background */
for (j = 0; j < 8 ; j++)
if ((value = strstr(c2, color[j])) != NULL)
break;
if ((bg = j) > 7)
RETURN_ERROR(p[i].name, "Bad background");
EXIT_ERROR(p[i].name, "Bad background");
/* Flags */
flags = 0;
if (strstr(value, "bold") != NULL)
@ -268,11 +269,9 @@ int loadtheme(const char *file, char *errbuf)
fclose(fp);
bsddialog_set_theme(&t);
return (BSDDIALOG_OK);
}
int bikeshed(struct bsddialog_conf *conf, char *errbuf)
void bikeshed(struct bsddialog_conf *conf)
{
int margin, i;
int colors[8] = {0, 0, 0, 0 ,0 ,0 , 0, 0};
@ -284,7 +283,7 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf)
/* theme */
if (bsddialog_get_theme(&t) != BSDDIALOG_OK)
return (BSDDIALOG_ERROR);
EXIT_FMTERROR("%s", bsddialog_geterror());
for (i = 0; i < 6; i++) {
do {
@ -339,7 +338,7 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf)
t.button.shortcutcolor = bsddialog_color(col[1], col[5], 0);
if (bsddialog_set_theme(&t))
return (BSDDIALOG_ERROR);
EXIT_FMTERROR("%s", bsddialog_geterror());
/* conf */
conf->button.always_active = (rand() % 2 == 0) ? true : false;
@ -351,6 +350,4 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf)
memset(title + strlen(title), ' ', margin);
conf->title = title;
}
return (BSDDIALOG_OK);
}

View File

@ -28,8 +28,9 @@
#ifndef _BSDDIALOG_UTILITY_THEME_H_
#define _BSDDIALOG_UTILITY_THEME_H_
int savetheme(const char *file, char *errbuf, const char *version);
int loadtheme(const char *file, char *errbuf);
int bikeshed(struct bsddialog_conf *conf, char *errbuf);
void savetheme(const char *file, const char *version);
void loadtheme(const char *file);
void setdeftheme(enum bsddialog_default_theme theme);
void bikeshed(struct bsddialog_conf *conf);
#endif

View File

@ -6,6 +6,7 @@ LIB= bsddialog
PRIVATELIB= yes
SHLIB_MAJOR= 0
SRCS= barbox.c \
calendarbox.c \
formbox.c \
infobox.c \
lib_util.c \

View File

@ -5,8 +5,6 @@ PROG= bsddialog
SRCS= bsddialog.c util_theme.c
MAN= bsddialog.1
CFLAGS+= -I${BSDDIALOG}/lib
LIBADD= bsddialog
WARNS= 3
LIBADD= bsddialog tinfow
.include <bsd.prog.mk>