bsddialog: import snapshot as of 2021-11-24

This commit is contained in:
Baptiste Daroussin 2021-11-24 09:42:13 +01:00
commit 857c66bb5f
42 changed files with 7241 additions and 0 deletions

28
GNUMakefile Normal file
View File

@ -0,0 +1,28 @@
# PUBLIC DOMAIN - NO WARRANTY, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
# Written by Alfonso Sabato Siciliano
OUTPUT= bsddialog
SOURCES= bsddialog.c
OBJECTS= $(SOURCES:.c=.o)
LIBPATH= ./lib
LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so
CFLAGS= -g -Wall -I$(LIBPATH)
LDFLAGS= -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog
RM = rm -f
all : $(OUTPUT)
$(OUTPUT): $(LIBBSDDIALOG) $(OBJECTS)
$(CC) $^ -o $@ $(LDFLAGS)
${LIBBSDDIALOG}:
make -C ${LIBPATH} -f GNUMakefile
%.o: %.c $(LIBBSDDIALOG)
$(CC) $(CFLAGS) -c $<
clean:
make -C ${LIBPATH} -f GNUMakefile clean
$(RM) $(OUTPUT) *.o *~

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
BSD 2-Clause License
Copyright (c) 2021, Alfonso Sabato Siciliano
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.

49
Makefile Normal file
View File

@ -0,0 +1,49 @@
# Any copyright is dedicated to the Public Domain, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
# Written by Alfonso Sabato Siciliano
OUTPUT= bsddialog
SOURCES= bsddialog.c
OBJECTS= ${SOURCES:.c=.o}
LIBPATH= ${.CURDIR}/lib
LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so
CFLAGS= -Wall -I${LIBPATH}
LDFLAGS= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog
BINDIR= /usr/local/bin
MAN= ${OUTPUT}.1
GZIP= gzip -cn
MANDIR= /usr/local/share/man/man1
INSTALL= install
RM= rm -f
all : ${OUTPUT}
${OUTPUT}: ${LIBBSDDIALOG} ${OBJECTS}
${CC} ${LDFLAGS} ${OBJECTS} -o ${.PREFIX}
${LIBBSDDIALOG}:
.if defined(PORTNCURSES)
make -C ${LIBPATH} -DPORTNCURSES
.else
make -C ${LIBPATH}
.endif
.c.o:
${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
install:
${INSTALL} -s -m 555 ${OUTPUT} ${BINDIR}
${GZIP} ${MAN} > ${MAN}.gz
${INSTALL} -m 444 ${MAN}.gz ${MANDIR}
unistall:
${RM} ${BINDIR}/${OUTPUT}
${RM} ${MANDIR}/${MAN}.gz
clean:
make -C ${LIBPATH} clean
${RM} ${OUTPUT} *.o *~ *.core ${MAN}.gz

160
README.md Normal file
View File

@ -0,0 +1,160 @@
# BSDDialog
**Work In Progress!**
This project provides **bsddialog** and **libbsddialog**, an utility and a
library to build scripts and tools with *TUI Widgets*.
Description:
<https://www.freebsd.org/status/report-2021-04-2021-06/#_bsddialog_tui_widgets>
## Getting Started
FreeBSD:
```
% git clone https://gitlab.com/alfix/bsddialog.git
% cd bsddialog
% make
% ./bsddialog --msgbox "Hello World!" 8 20
```
If you are using XFCE install
[devel/ncurses](https://www.freshports.org/devel/ncurses/)
```
% sudo pkg install ncurses
% git clone https://gitlab.com/alfix/bsddialog.git
% cd bsddialog
% make -DPORTNCURSES
% ./bsddialog --msgbox "Hello World!" 8 20
```
Linux:
```
% git clone https://gitlab.com/alfix/bsddialog.git
% cd bsddialog
% make -GNUMakefile
% ./bsddialog --msgbox "Hello World!" 8 20
```
Output:
![screenshot](screenshot.png)
Examples utility:
```
% ./bsddialog --title msgbox --msgbox "Hello World!" 5 30
% ./bsddialog --theme default --title msgbox --msgbox "Hello World!" 5 30
% ./bsddialog --begin-y 2 --title yesno --yesno "Hello World!" 5 30
% ./bsddialog --ascii-lines --pause "Hello World!" 8 50 5
% ./bsddialog --checklist "Space to select" 0 0 0 Name1 Desc1 off Name2 Desc2 on Name3 Desc3 off
% ./bsddialog --backtitle "TITLE" --title yesno --hline "bsddialog" --yesno "Hello World!" 5 25
% ./bsddialog --extra-button --help-button --defaultno --yesno "Hello World!" 0 0
```
Examples library:
```
% cd library_examples
% sh compile
% ./buildlist
% ./infobox
% ./menu
% ./mixedlist
% ./msgbox
% ./ports
% ./radiolist
% ./theme
% ./treeview
% ./yesno
```
Use Cases:
- [portconfig](https://gitlab.com/alfix/portconfig)
## Features
**Common Options:**
--ascii-lines, --aspect *ratio* (for infobox, msgbox and yesno),
--backtitle *backtitle*, --begin-x *x* (--begin *y y*),
(--begin *y x*), --cancel-label *string*, -clear (test with multiple widgets),
--colors, --date-format *format*, --default-button *string*, --defaultno,
--default-item *string*,
--exit-label *string*, --extra-button, --extra-label *string*,
--hfile *filename* (for completed widgets), n--help-button,
--help-label *string*, --help-status, --help-tags, --hline *string*, --ignore,
--item-help, --no-cancel, --nocancel, --no-label *string*, --no-items,
--no-lines, --no-ok,
--nook, --no-shadow, --no-tags, --ok-label *string*, --output-fd *fd*,
--output-separator *string*, --print-version,
--print-size (todo move lib -> utility), --quoted (quotes all != dialog),
--print-maxsize, --shadow, --single-quoted (add --quote-with *ch*?),
--separator *string* (alias --output-separator *string*),
--separate-output (rename --separate-output-withnl?), --sleep *secs*, --stderr,
--stdout, --theme *string* ("bsddialog", "dialog", "blackwhite" and "magenta"),
--time-format *format*, --title *title*, --version, --yes-label *string*.
**Widgets:**
infobox (do not clear the screen), msgbox,
yesno (dialog renames "yes/no" -> "ok/cancel" with --extra-button --help-button).
checklist, radiolist, menu, mixedlist, treeview and textbox.
## TODO
**Common Options:**
| Option | Status | Note |
| ---------------------------- | ----------- | ------------------------------- |
| --cr-wrap | Coding | |
| --help | In progress | |
| --input-fd *fd* | | |
| --insecure | | |
| --keep-tite | | |
| --keep-window | | |
| --last-key | | |
| --max-input *size* | | |
| --no-collapse | Coding | |
| --no-kill | | |
| --no-nl-expand | Coding | |
| --tab-correct | | |
| --tab-len *n* | | |
| --trim | Coding | |
To evaluate / Not planned in the short term: --column-separator *string*,
--create-rc *file*, --iso-week, --no-mouse, --print-text-only *str h w*,
--print-text-size *str h w*, --reorder, -scrollbar, --separate-widget *string*,
--size-err, --timeout *secs*,--trace *filename*, --visit-items,
--week-start *day*.
**Widgets:**
| Widget | Status | Note |
|--------------- | ----------- | ----------------------------------------------|
| --buildlist | In progress | todo autosize, resize, F1 |
| --calendar | In progress | todo autosize, resize, F1, leap year, year <=0, month days |
| --editbox | | |
| --form | In progress | implemented via --mixedform |
| --gauge | In progress | |
| --inputbox | In progress | implemented via --mixedform, todo \<init\> |
| --mixedform | In progress | todo autosize, resize, F1 |
| --mixedgauge | In progress | todo autosize, resize, F1 |
| --passwordbox | In progress | implemented via --mixedform, todo \<init\> |
| --passwordform | In progress | implemented via --mixedform |
| --pause | In progress | todo autosize, resize, F1 |
| --prgbox | In progress | add command opts |
| --programbox | Coding | |
| --progressbox | | |
| --rangebox | In progress | todo autosize, resize, F1, PAGE-UP/PAGE-DOWN/HOME/END keys |
| --timebox | In progress | todo autosize, resize, F1 |
To evaluate / Not planned in the short term: tailbox (textbox/fseek), tailboxbg,
dselect, fselect, inputmenu.

1263
bsddialog.c Normal file

File diff suppressed because it is too large Load Diff

31
lib/GNUMakefile Normal file
View File

@ -0,0 +1,31 @@
# PUBLIC DOMAIN - NO WARRANTY, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
# Written by Alfonso Sabato Siciliano
VERSION = 0.1
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h
SOURCES = barbox.c editorbox.c formbox.c lib_util.c menubox.c textbox.c \
timebox.c commandbox.c filebox.c infobox.c libbsddialog.c messagebox.c \
theme.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -g -Wall -Werror -fpic
LDFLAGS = -lform -lncurses -ltinfo
LIBFLAG = -shared
RM = rm -f
LN = ln -s -f
all : $(LIBRARY)
$(LIBRARY): $(OBJECTS)
$(CC) $(LIBFLAG) $^ -o $(LIBRARY_SO).$(VERSION) $(LDFLAGS)
${LN} ${LIBRARY_SO}.${VERSION} ${LIBRARY_SO}
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $<
clean:
$(RM) $(LIBRARY_SO)* *.o *~

73
lib/Makefile Normal file
View File

@ -0,0 +1,73 @@
# Any copyright is dedicated to the Public Domain, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
# Written by Alfonso Sabato Siciliano
VERSION = 0.1
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h
SOURCES = barbox.c editorbox.c formbox.c lib_util.c menubox.c textbox.c \
timebox.c commandbox.c filebox.c infobox.c libbsddialog.c messagebox.c \
theme.c
OBJECTS= ${SOURCES:.c=.o}
FBSDFLAGS= -O2 -pipe -std=gnu99 -Wno-format-zero-length \
-fstack-protector-strong -Qunused-arguments
CFLAGS = -I/usr/local/include -fPIC -Wall -Wextra ${FBSDFLAGS}
LDFLAGS = -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION}
INSTALL_PREFIX=/usr/local
LN = ln -s -f
RM = rm -f
CP = cp
GZIP = gzip -cn
LDCONFIG = /sbin/ldconfig -m
.if defined(PORTNCURSES)
# PORT ncurses `make -DPORTNCURSES` or `make -D PORTNCURSES`
CFLAGS += -DPORTNCURSES -I/usr/local/include
LDFLAGS += -L/usr/local/lib -lform -lncurses -ltinfo
.else
# BASE ncurses
LDFLAGS += -L/usr/lib -lform -lncurses -ltinfo
.endif
MAN= ${OUTPUT}.3
GZIP= gzip -cn
MANDIR= /usr/local/share/man/man3
INSTALL= install
RM= rm -f
#all : man ${LIBRARY}
all : ${LIBRARY}
${LIBRARY}: ${OBJECTS}
${CC} ${LDFLAGS} ${.ALLSRC} -o ${LIBRARY_SO}.${VERSION}
# LN for devel
${LN} ${LIBRARY_SO}.${VERSION} ${LIBRARY_SO}
.c.o:
${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
man:
${GZIP} ${LIBRARY}.3 > ${LIBRARY}.3.gz
clean:
${RM} ${LIBRARY_SO}* *.o *~ *.gz
install:
${CP} ${LIBRARY}.h ${INSTALL_PREFIX}/include
${CP} ${LIBRARY_SO}.${VERSION} ${INSTALL_PREFIX}/lib/
${LN} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}.${VERSION} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}
${LDCONFIG} ${INSTALL_PREFIX}/lib
${CP} ${LIBRARY}.3.gz ${INSTALL_PREFIX}/man/man3/
unistall:
${RM} ${INSTALL_PREFIX}/include/${LIBRARY}.h
${RM} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}
${RM} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}.${VERSION}
${LDCONFIG} ${INSTALL_PREFIX}/lib
${RM} ${INSTALL_PREFIX}/man/man3/${LIBRARY}.3.gz

369
lib/barbox.c Normal file
View File

@ -0,0 +1,369 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <stdlib.h>
#include <string.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Bar": gauge - mixedgauge - rangebox - pause */
extern struct bsddialog_theme t;
static void
draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, int label)
{
char labelstr[128];
int i, blue_x, color;
blue_x = (int)((perc*(size))/100);
wmove(win, y, x);
for (i = 0; i < size; i++) {
color = (i <= blue_x) ? t.currbarcolor : t.barcolor;
wattron(win, color);
waddch(win, ' ');
wattroff(win, color);
}
if (withlabel)
sprintf(labelstr, "%d", label);
else
sprintf(labelstr, "%3d%%", perc);
wmove(win, y, x + size/2 - 2);
for (i=0; i < (int) strlen(labelstr); i++) {
color = ( (blue_x + 1) <= (size/2 - (int) strlen(labelstr)/2 + i) ) ?
t.barcolor : t.currbarcolor;
wattron(win, color);
waddch(win, labelstr[i]);
wattroff(win, color);
}
}
int bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols, int perc)
{
WINDOW *widget, *bar, *shadow;
char input[2048];
int i, y, x;
bool mainloop = true;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
false) <0)
return -1;
bar = new_boxed_window(conf, y+rows -4, x+3, 3, cols-6, RAISED);
wrefresh(widget);
wrefresh(bar);
while (mainloop) {
draw_perc_bar(bar, 1, 1, cols-8, perc, false, -1 /*unused*/);
wrefresh(widget);
wrefresh(bar);
while (true) {
scanf("%s", input);
if (strcmp(input,"EOF") == 0) {
mainloop = false;
break;
}
if (strcmp(input,"XXX") == 0)
break;
}
scanf("%d", &perc);
perc = perc < 0 ? 0 : perc;
perc = perc > 100 ? 100 : perc;
i = 2;
wmove(widget, 1, 1);
wclrtoeol(widget);
while (true) {
scanf("%s", input);
if (strcmp(input,"EOF") == 0) {
mainloop = false;
break;
}
if (strcmp(input,"XXX") == 0)
break;
//print_text(conf, widget, 1, 1, cols-2, input);
mvwaddstr(widget, 1, i, input);
i = i + strlen(input) + 1;
wrefresh(widget);
}
}
delwin(bar);
end_widget(conf, widget, rows, cols, shadow);
return BSDDIALOG_YESOK;
}
int bsddialog_mixedgauge(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int perc, int argc, char **argv)
{
WINDOW *widget, *bar, *shadow;
int i, miniperc, y, x;
char states[11][16] = {
"[ Succeeded ]",
"[ Failed ]",
"[ Passed ]",
"[ Completed ]",
"[ Checked ]",
"[ Done ]",
"[ Skipped ]",
"[ In Progress ]",
"!!! BLANK !!!",
"[ N/A ]",
"[ UNKNOWN ]",};
if (new_widget(conf, &widget, &y, &x, NULL, &rows, &cols, &shadow,
false) <0)
return -1;
bar = new_boxed_window(conf, y+rows -4, x+3, 3, cols-6, RAISED);
/* mini bars */
for (i=0; i < (argc/2); i++) {
miniperc = atol(argv[i*2 + 1]);
if (miniperc == 8)
continue;
mvwaddstr(widget, i+1, 2, argv[i*2]);
if (miniperc > 9)
mvwaddstr(widget, i+1, cols-2-15, states[10]);
else if (miniperc >= 0 && miniperc <= 9)
mvwaddstr(widget, i+1, cols-2-15, states[miniperc]);
else { //miniperc < 0
miniperc = abs(miniperc);
mvwaddstr(widget, i+1, cols-2-15, "[ ]");
draw_perc_bar(widget, i+1, 1+cols-2-15, 13, miniperc,
false, -1 /*unused*/);
}
}
print_text(conf, widget, rows-6, 2, cols-2, text);
/* main bar */
draw_perc_bar(bar, 1, 1, cols-8, perc, false, -1 /*unused*/);
wattron(bar, t.barcolor);
mvwaddstr(bar, 0, 2, "Overall Progress");
wattroff(bar, t.barcolor);
wrefresh(widget);
wrefresh(bar);
getch();
delwin(bar);
end_widget(conf, widget, rows, cols, shadow);
return BSDDIALOG_YESOK;
}
int
bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols, int min,
int max, int *value)
{
WINDOW *widget, *bar, *shadow;
int y, x;
bool loop, buttupdate, barupdate;
int input, currvalue, output, sizebar;
float perc;
int positions = max - min + 1;
struct buttons bs;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
bar = new_boxed_window(conf, y + rows - 6, x +7, 3, cols-14, RAISED);
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
if (value == NULL)
RETURN_ERROR("*value == NULL");
currvalue = *value;
sizebar = cols - 16;
loop = buttupdate = barupdate = true;
while(loop) {
if (barupdate) {
perc = ((float)(currvalue - min)*100) / ((float)positions-1);
draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue);
barupdate = false;
wrefresh(bar);
}
if (buttupdate) {
draw_buttons(widget, rows-2, cols, bs, true);
wrefresh(widget);
buttupdate = false;
}
input = getch();
switch(input) {
case 10: // Enter
output = bs.value[bs.curr]; // values -> outputs
*value = currvalue;
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': // TAB
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
case KEY_UP:
if (currvalue < max) {
currvalue++;
barupdate = true;
}
break;
case KEY_DOWN:
if (currvalue > min) {
currvalue--;
barupdate = true;
}
break;
}
}
delwin(bar);
end_widget(conf, widget, rows, cols, shadow);
return output;
}
int bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols, int sec)
{
WINDOW *widget, *bar, *shadow;
int output, y, x;
bool loop, buttupdate, barupdate;
int input, currvalue, sizebar;
float perc;
struct buttons bs;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
bar = new_boxed_window(conf, y + rows - 6, x +7, 3, cols-14, RAISED);
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
currvalue = sec;
sizebar = cols-16;
nodelay(stdscr, TRUE);
timeout(1000);
//wtimeout(buttwin, 2);
loop = buttupdate = barupdate = true;
while(loop) {
if (barupdate) {
perc = ((float)(currvalue*100)) / ((float)sec);
draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue);
barupdate = false;
wrefresh(bar);
}
if (buttupdate) {
draw_buttons(widget, rows-2, cols, bs, true);
wrefresh(widget);
buttupdate = false;
}
input = getch();
if(input < 0) {
currvalue--;
if (currvalue < 0) {
output = BSDDIALOG_ERROR;
break;
}
else {
barupdate = true;
continue;
}
}
switch(input) {
case 10: // Enter
output = bs.value[bs.curr]; // values -> outputs
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': // TAB
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
}
}
nodelay(stdscr, FALSE);
delwin(bar);
end_widget(conf, widget, rows, cols, shadow);
return output;
}

257
lib/bsddialog.h Normal file
View File

@ -0,0 +1,257 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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_H_
#define _BSDDIALOG_H_
#include <stdbool.h>
/* Exit status */
#define BSDDIALOG_ERROR -1
#define BSDDIALOG_YESOK 0
#define BSDDIALOG_NOCANCEL 1
#define BSDDIALOG_HELP 2
#define BSDDIALOG_EXTRA 3
#define BSDDIALOG_ITEM_HELP 4
#define BSDDIALOG_ESC 5
/* size and position */
#define BSDDIALOG_FULLSCREEN -1
#define BSDDIALOG_AUTOSIZE 0
#define BSDDIALOG_CENTER -1
struct bsddialog_conf {
/* conf.* */
bool ascii_lines;
int aspect_ratio;
int x;
int y;
bool clear;
int *get_height;
int *get_width;
char *hfile;
char *hline;
/*int input_fd;*/
/*bool keep_tite;*/
/*bool keep_window;*/
/*bool last_key;*/
/*int max_input;*/
/*bool no_kill;*/
bool no_lines;
/*bool no_mouse; useful?*/
/*bool scrollbar; useful?*/
/*char *separate_witget;*/
bool shadow;
/*bool size_err;*/
int sleep;
/*int timeout;*/
char *title;
/* conf.text.* */
struct {
bool colors;
bool cr_wrap;
bool no_collapse;
bool no_nl_expand;
/*bool tab_correct; textbox?*/
/*int tab_len; textbox?*/
bool trim;
} text;
/* conf.form.* */
/*struct {
bool insecure;
} form;*/
/* conf.menu.* */
struct {
bool align_left;
char *colums_separator;
char *default_item; /*delete, add int *focus to API?*/
bool no_items;
bool no_tags;
/*bool visit_items;*/
} menu;
/* conf.button.* */
struct {
char *cancel_label;
bool defaultno;
char *default_label;
char *exit_label;
bool extra_button;
char *extra_label;
bool help_button;
char *help_label;
bool no_cancel;
char *no_label;
bool no_ok;
char *ok_label;
char *yes_label;
} button;
};
struct bsddialog_menuitem {
char *prefix;
bool on;
int depth;
char *name;
char *desc;
char *bottomdesc;
};
enum bsddialog_grouptype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
enum bsddialog_grouptype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
int bsddialog_init(void);
int bsddialog_end(void);
int bsddialog_backtitle(struct bsddialog_conf conf, char *backtitle);
const char *bsddialog_geterror(void);
int bsddialog_terminalheight(void);
int bsddialog_terminalwidth(void);
void bsddialog_initconf(struct bsddialog_conf *conf);
/* widgets */
int
bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int *yy, unsigned int *mm, unsigned int *dd);
int
bsddialog_checklist(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
bsddialog_dselect(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_editbox(struct bsddialog_conf conf, char* text, int rows, int cols);
int bsddialog_form(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int argc, char **argv);
int
bsddialog_fselect(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols,
int perc);
int
bsddialog_infobox(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_inputbox(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_inputmenu(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_menu(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
bsddialog_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int argc, char **argv);
int
bsddialog_mixedgauge(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int perc, int argc, char **argv);
int
bsddialog_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups,
int *focuslist, int *focusitem);
int
bsddialog_msgbox(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_passwordbox(struct bsddialog_conf conf, char* text, int rows,
int cols);
int
bsddialog_passwordform(struct bsddialog_conf conf, char* text, int rows,
int cols, int formheight, int argc, char **argv);
int
bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols,
int sec);
int
bsddialog_prgbox(struct bsddialog_conf conf, char* text, int rows, int cols,
char *command);
int
bsddialog_programbox(struct bsddialog_conf conf, char* text, int rows,
int cols);
int
bsddialog_progressbox(struct bsddialog_conf conf, char* text, int rows,
int cols);
int
bsddialog_radiolist(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols,
int min, int max, int *value);
int
bsddialog_tailbox(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_tailboxbg(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_textbox(struct bsddialog_conf conf, char* text, int rows, int cols);
int
bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int *hh, unsigned int *mm, unsigned int *ss);
int
bsddialog_treeview(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int bsddialog_yesno(struct bsddialog_conf conf, char* text, int rows, int cols);
#endif

96
lib/bsddialog_theme.h Normal file
View File

@ -0,0 +1,96 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 _LIBBSDDIALOG_THEME_H_
#define _LIBBSDDIALOG_THEME_H_
enum bsddialog_color {
BSDDIALOG_BLACK = 0,
BSDDIALOG_RED,
BSDDIALOG_GREEN,
BSDDIALOG_YELLOW,
BSDDIALOG_BLUE,
BSDDIALOG_MAGENTA,
BSDDIALOG_CYAN,
BSDDIALOG_WHITE,
};
struct bsddialog_theme {
int shadowcolor;
unsigned int shadowrows;
unsigned int shadowcols;
int backgroundcolor;
bool surroundtitle;
int titlecolor;
int lineraisecolor;
int linelowercolor;
int widgetcolor;
unsigned int texthmargin;
int curritemcolor;
int itemcolor;
int currtagcolor;
int tagcolor;
int namesepcolor;
int descsepcolor;
int currfieldcolor;
int fieldcolor;
int fieldreadonlycolor;
int currbarcolor;
int barcolor;
unsigned int buttonspace;
int buttleftch;
int buttrightchar;
int currbuttdelimcolor;
int buttdelimcolor;
int currbuttoncolor;
int buttoncolor;
int currshortkeycolor;
int shortkeycolor;
int bottomtitlecolor;
};
enum bsddialog_default_theme {
BSDDIALOG_THEME_BLACKWHITE,
BSDDIALOG_THEME_BSDDIALOG,
BSDDIALOG_THEME_DEFAULT,
BSDDIALOG_THEME_DIALOG,
BSDDIALOG_THEME_MAGENTA,
};
int bsddialog_color(enum bsddialog_color background, enum bsddialog_color foreground);
struct bsddialog_theme bsddialog_get_theme();
void bsddialog_set_theme(struct bsddialog_theme theme);
int bsddialog_set_default_theme(enum bsddialog_default_theme theme);
#endif

211
lib/commandbox.c Normal file
View File

@ -0,0 +1,211 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <unistd.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Command": prgbox - programbox - progressbox */
#define MAXINPUT 2048 /* in bsddialoh.h? in bsddialog.c get/set static maxinput? */
extern struct bsddialog_theme t;
static int
command_handler(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey)
{
bool loop, update;
int i, input;
int output;
loop = update = true;
while(loop) {
if (update) {
draw_buttons(window, y, cols, bs, shortkey);
update = false;
}
wrefresh(window);
input = getch();
switch (input) {
case 10: /* Enter */
output = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
update = true;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
update = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
update = true;
}
break;
default:
if (shortkey) {
for (i = 0; i < (int) bs.nbuttons; i++)
if (input == (bs.label[i])[0]) {
output = bs.value[i];
loop = false;
}
}
}
}
return output;
}
int
bsddialog_prgbox(struct bsddialog_conf conf, char* text, int rows, int cols, char *command)
{
char line[MAXINPUT];
WINDOW *widget, *pad, *shadow;
int i, y, x, padrows, padcols, ys, ye, xs, xe;
int output;
int pipefd[2];
struct buttons bs;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
NULL, BUTTONLABEL(help_label));
if (text != NULL && conf.no_lines == false) {
print_text(conf, widget, 1, 1, cols-2, text);
mvwhline(widget, 2, 2, conf.ascii_lines ? '-' : ACS_HLINE, cols -4);
wrefresh(widget);
}
padrows = text == NULL ? rows - 4 : rows - 6;
padcols = cols - 2;
ys = text == NULL ? y + 1 : y + 3;
xs = x + 1;
ye = ys + padrows;
xe = xs + padcols;
pad = newpad(padrows, padcols);
wbkgd(pad, t.widgetcolor);
pipe(pipefd);
if (fork() == 0)
{
close(pipefd[0]); // close reading
dup2(pipefd[1], 1); // send stdout to the pipe
dup2(pipefd[1], 2); // send stderr to the pipe
close(pipefd[1]); // this descriptor is no longer needed
//const char *ls="/bin/ls";
execl(command, command, NULL);
return 0;
}
else
{
close(pipefd[1]); // close write
i = 0;
while (read(pipefd[0], line, MAXINPUT) != 0) {
mvwaddstr(pad, i, 0, line);
prefresh(pad, 0, 0, ys, xs, ye, xe);
i++;
}
}
output = command_handler(widget, rows-2, cols, bs, true);
return output;
}
int bsddialog_programbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
char line[MAXINPUT];
WINDOW *widget, *pad, *shadow;
int i, y, x, padrows, padcols, ys, ye, xs, xe, output;
struct buttons bs;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
if (text != NULL && conf.no_lines == false) {
mvwhline(widget, 2, 2, conf.ascii_lines ? '-' : ACS_HLINE, cols -4);
wrefresh(widget);
}
padrows = text == NULL ? rows - 4 : rows - 6;
padcols = cols - 2;
ys = text == NULL ? y + 1 : y + 3;
xs = x + 1;
ye = ys + padrows;
xe = xs + padcols;
pad = newpad(padrows, padcols);
i = 0;
//while (fgets(line, MAXINPUT, stdin) != NULL) {
while(getstr(line) != ERR){
mvwaddstr(pad, i, 0, line);
prefresh(pad, 0, 0, ys, xs, ye, xe);
i++;
}
output = command_handler(widget, rows-2, cols, bs, true);
return output;
}
int bsddialog_progressbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
text = "Progressbox unimplemented";
bsddialog_msgbox(conf, text, rows, cols);
RETURN_ERROR(text);
}

45
lib/editorbox.c Normal file
View File

@ -0,0 +1,45 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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.
*/
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
/* "Editor": editbox */
int bsddialog_editbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
text = "Editbox unimplemented";
bsddialog_msgbox(conf, text, rows, cols);
RETURN_ERROR(text);
}

52
lib/filebox.c Normal file
View File

@ -0,0 +1,52 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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.
*/
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
/* "File": dselect - fselect */
int bsddialog_dselect(struct bsddialog_conf conf, char* text, int rows, int cols)
{
text = "Dselect unimplemented";
bsddialog_msgbox(conf, text, rows, cols);
RETURN_ERROR(text);
}
int bsddialog_fselect(struct bsddialog_conf conf, char* text, int rows, int cols)
{
text = "Fselect unimplemented";
bsddialog_msgbox(conf, text, rows, cols);
RETURN_ERROR(text);
}

396
lib/formbox.c Normal file
View File

@ -0,0 +1,396 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <stdlib.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#include <ncurses/form.h>
#else
#include <curses.h>
#include <form.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Form": inputbox - passwordbox - form - passwordform - mixedform */
extern struct bsddialog_theme t;
int bsddialog_inputmenu(struct bsddialog_conf conf, char* text, int rows, int cols)
{
text = "Inputbox unimplemented";
bsddialog_msgbox(conf, text, rows, cols);
RETURN_ERROR(text);
}
#define ITEMHIDDEN 0x1
#define ISITEMHIDDEN(item) (item.itemflags & 0x1)
#define ITEMREADONLY 0x2
#define ISITEMREADONLY(item) (item.itemflags & 0x2)
struct formitem {
char *label;
unsigned int ylabel;
unsigned int xlabel;
char *item;
unsigned int yitem;
unsigned int xitem;
int itemlen;
unsigned int inputlen;
unsigned int itemflags;
};
static int
mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
bool shortkey, WINDOW *entry, FORM *form, FIELD **field, int nitems
/*struct formitem *items*/)
{
bool loop, buttupdate, inentry = true;
int input, output;
curs_set(2);
pos_form_cursor(form);
loop = buttupdate = true;
bs.curr = -1;
while(loop) {
if (buttupdate) {
draw_buttons(widget, y, cols, bs, shortkey);
wrefresh(widget);
buttupdate = false;
}
wrefresh(entry);
input = getch();
switch(input) {
case 10: // Enter
if (inentry)
break;
output = bs.value[bs.curr]; // values -> buttvalues
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
/* add a struct for forms */
/*for (i=0; i<nitems; i++) {
bufp = field_buffer(field[i], 0);
dprintf(fd, "\n+%s", bufp);
bufp = field_buffer(field[i], 1);
dprintf(fd, "-%s+", bufp);
}*/
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': // TAB
if (inentry) {
bs.curr = 0;
inentry = false;
curs_set(0);
} else {
bs.curr++;
inentry = bs.curr >= (int) bs.nbuttons ? true : false;
if (inentry) {
curs_set(2);
pos_form_cursor(form);
}
}
buttupdate = true;
break;
case KEY_LEFT:
if (inentry) {
form_driver(form, REQ_PREV_CHAR);
} else {
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
}
break;
case KEY_RIGHT:
if (inentry) {
form_driver(form, REQ_NEXT_CHAR);
} else {
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
}
break;
case KEY_UP:
if (nitems < 2)
break;
set_field_fore(current_field(form), t.fieldcolor);
set_field_back(current_field(form), t.fieldcolor);
form_driver(form, REQ_PREV_FIELD);
form_driver(form, REQ_END_LINE);
set_field_fore(current_field(form), t.currfieldcolor);
set_field_back(current_field(form), t.currfieldcolor);
break;
case KEY_DOWN:
if (nitems < 2)
break;
set_field_fore(current_field(form), t.fieldcolor);
set_field_back(current_field(form), t.fieldcolor);
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_END_LINE);
set_field_fore(current_field(form), t.currfieldcolor);
set_field_back(current_field(form), t.currfieldcolor);
break;
case KEY_BACKSPACE:
form_driver(form, REQ_DEL_PREV);
break;
case KEY_DC:
form_driver(form, REQ_DEL_CHAR);
break;
default:
if (inentry) {
form_driver(form, input);
}
break;
}
}
curs_set(0);
return output;
}
static int
do_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int nitems, struct formitem *items)
{
WINDOW *widget, *entry, *shadow;
int i, output, color, y, x;
FIELD **field;
FORM *form;
struct buttons bs;
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
entry = new_boxed_window(conf, y + rows - 3 - formheight -2, x +1,
formheight+2, cols-2, LOWERED);
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
field = calloc(nitems + 1, sizeof(FIELD*));
for (i=0; i < nitems; i++) {
field[i] = new_field(1, items[i].itemlen, items[i].yitem-1, items[i].xitem-1, 0, 1);
field_opts_off(field[i], O_STATIC);
set_max_field(field[i], items[i].inputlen);
set_field_buffer(field[i], 0, items[i].item);
set_field_buffer(field[i], 1, items[i].item);
field_opts_off(field[i], O_AUTOSKIP);
field_opts_off(field[i], O_BLANK);
//field_opts_off(field[i], O_BS_OVERLOAD);
if (ISITEMHIDDEN(items[i]))
field_opts_off(field[i], O_PUBLIC);
if (ISITEMREADONLY(items[i])) {
field_opts_off(field[i], O_EDIT);
field_opts_off(field[i], O_ACTIVE);
color = t.fieldreadonlycolor;
} else {
color = i == 0 ? t.currfieldcolor : t.fieldcolor;
}
set_field_fore(field[i], color);
set_field_back(field[i], color);
}
field[i] = NULL;
if (nitems == 1) {// inputbox or passwordbox
set_field_fore(field[0], t.widgetcolor);
set_field_back(field[0], t.widgetcolor);
}
form = new_form(field);
set_form_win(form, entry);
set_form_sub(form, derwin(entry, nitems, cols-4, 1, 1));
post_form(form);
for (i=0; i < nitems; i++)
mvwaddstr(entry, items[i].ylabel, items[i].xlabel, items[i].label);
wrefresh(entry);
output = mixedform_handler(widget, rows-2, cols, bs, true, entry, form,
field, nitems /*,items*/);
unpost_form(form);
free_form(form);
for (i=0; i < nitems; i++)
free_field(field[i]);
free(field);
delwin(entry);
end_widget(conf, widget, rows, cols, shadow);
return output;
}
int bsddialog_inputbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
int output;
struct formitem item;
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.item = ""; // TODO add argv
item.yitem = 1;
item.xitem = 1;
item.itemlen = cols-4;
item.inputlen = 2048; // todo conf.sizeinput
item.itemflags = 0;
output = do_mixedform(conf, text, rows, cols, 1, 1, &item);
return output;
}
int bsddialog_passwordbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
int output;
struct formitem item;
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.item = ""; // TODO add argv
item.yitem = 1;
item.xitem = 1;
item.itemlen = cols-4;
item.inputlen = 2048; // todo conf.sizeinput
item.itemflags = ITEMHIDDEN;
output = do_mixedform(conf, text, rows, cols, 1, 1, &item);
return output;
}
int
bsddialog_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int argc, char **argv)
{
int i, output, nitems;
struct formitem items[128];
if ((argc % 9) != 0)
return (-1);
nitems = argc / 9;
for (i=0; i<nitems; i++) {
items[i].label = argv[9*i];
items[i].ylabel = atoi(argv[9*i+1]);
items[i].xlabel = atoi(argv[9*i+2]);
items[i].item = argv[9*i+3];
items[i].yitem = atoi(argv[9*i+4]);
items[i].xitem = atoi(argv[9*i+5]);
items[i].itemlen = atoi(argv[9*i+6]);
items[i].inputlen = atoi(argv[9*i+7]);
items[i].itemflags = atoi(argv[9*i+8]);
}
output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
return output;
}
int
bsddialog_form(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int argc, char **argv)
{
int i, output, nitems, itemlen, inputlen;
unsigned int flags = 0;
struct formitem items[128];
if ((argc % 8) != 0)
return (-1);
nitems = argc / 8;
for (i=0; i<nitems; i++) {
items[i].label = argv[8*i];
items[i].ylabel = atoi(argv[8*i+1]);
items[i].xlabel = atoi(argv[8*i+2]);
items[i].item = argv[8*i+3];
items[i].yitem = atoi(argv[8*i+4]);
items[i].xitem = atoi(argv[8*i+5]);
itemlen = atoi(argv[8*i+6]);
items[i].itemlen = abs(itemlen);
inputlen = atoi(argv[8*i+7]);
items[i].inputlen = inputlen == 0 ? abs(itemlen) : inputlen;
flags = flags | (itemlen < 0 ? ITEMREADONLY : 0);
items[i].itemflags = flags;
}
output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
return output;
}
int
bsddialog_passwordform(struct bsddialog_conf conf, char* text, int rows, int cols,
int formheight, int argc, char **argv)
{
int i, output, nitems, itemlen, inputlen;
unsigned int flags = ITEMHIDDEN;
struct formitem items[128];
if ((argc % 8) != 0)
return (-1);
nitems = argc / 8;
for (i=0; i<nitems; i++) {
items[i].label = argv[8*i];
items[i].ylabel = atoi(argv[8*i+1]);
items[i].xlabel = atoi(argv[8*i+2]);
items[i].item = argv[8*i+3];
items[i].yitem = atoi(argv[8*i+4]);
items[i].xitem = atoi(argv[8*i+5]);
itemlen = atoi(argv[8*i+6]);
items[i].itemlen = abs(itemlen);
inputlen = atoi(argv[8*i+7]);
items[i].inputlen = inputlen == 0 ? abs(itemlen) : inputlen;
flags = flags | (itemlen < 0 ? ITEMREADONLY : 0);
items[i].itemflags = flags;
}
output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
return output;
}

114
lib/infobox.c Normal file
View File

@ -0,0 +1,114 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Info": infobox */
#define MIN_HEIGHT 3
extern struct bsddialog_theme t;
static int
infobox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
char *text)
{
int maxword, maxline, nlines;
if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
return BSDDIALOG_ERROR;
if (cols == BSDDIALOG_AUTOSIZE) {
/* text size */
*w = maxline + VBORDERS + t.texthmargin * 2;
/* avoid terminal overflow */
*w = MIN(*w, widget_max_width(conf));
}
if (rows == BSDDIALOG_AUTOSIZE) {
*h = MIN_HEIGHT - 1;
if (maxword > 0)
*h += MIN(nlines, (*w / GET_ASPECT_RATIO(conf)));
*h = MAX(*h, MIN_HEIGHT);
/* avoid terminal overflow */
*h = MIN(*h, widget_max_height(conf));
}
return 0;
}
static int infobox_checksize(int rows, int cols)
{
if (cols < HBORDERS + 1 + (int) t.texthmargin * 2)
RETURN_ERROR("Few cols, infobox needs at least width 3 + text "\
"margins");
if (rows < 3)
RETURN_ERROR("Infobox needs at least height 3");
return 0;
}
int
bsddialog_infobox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
WINDOW *shadow, *widget, *textpad;
int y, x, h, w, htextpad;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
if (infobox_autosize(conf, rows, cols, &h, &w, text) != 0)
return BSDDIALOG_ERROR;
if (infobox_checksize(h, w) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
&textpad, &htextpad, text, false) != 0)
return BSDDIALOG_ERROR;
pnoutrefresh(textpad, 0, 0, y+1, x+1+t.texthmargin, y+h-2, x+w-t.texthmargin);
doupdate();
end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return (BSDDIALOG_YESOK);
}

996
lib/lib_util.c Normal file
View File

@ -0,0 +1,996 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
extern struct bsddialog_theme t;
/* Error buffer */
#define ERRBUFLEN 1024
static char errorbuffer[ERRBUFLEN];
const char *get_error_string(void)
{
return errorbuffer;
}
void set_error_string(char *str)
{
strncpy(errorbuffer, str, ERRBUFLEN-1);
}
/* cleaner */
int hide_widget(int y, int x, int h, int w, bool withshadow)
{
WINDOW *clear;
/* no check: y, x, h and w are checked by the builders */
if ((clear = newwin(h, w, y + t.shadowrows, x + t.shadowcols)) == NULL)
RETURN_ERROR("Cannot hide the widget");
wbkgd(clear, t.backgroundcolor);
if (withshadow)
wrefresh(clear);
mvwin(clear, y, x);
wrefresh(clear);
delwin(clear);
return 0;
}
/* F1 help */
int f1help(struct bsddialog_conf conf)
{
char *file = conf.hfile;
char *title = conf.title;
int output;
conf.hfile = NULL;
conf.clear = true;
conf.y = BSDDIALOG_CENTER;
conf.x = BSDDIALOG_CENTER;
conf.title = "HELP";
conf.sleep = 0;
output = bsddialog_textbox(conf, file, BSDDIALOG_AUTOSIZE,
BSDDIALOG_AUTOSIZE);
conf.hfile = file;
conf.title = title;
return output;
}
/* Buttons */
void
draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected,
bool shortkey)
{
int i, color_arrows, color_shortkey, color_button;
if (selected) {
color_arrows = t.currbuttdelimcolor;
color_shortkey = t.currshortkeycolor;
color_button = t.currbuttoncolor;
} else {
color_arrows = t.buttdelimcolor;
color_shortkey = t.shortkeycolor;
color_button = t.buttoncolor;
}
wattron(window, color_arrows);
mvwaddch(window, y, x, t.buttleftch);
wattroff(window, color_arrows);
wattron(window, color_button);
for(i = 1; i < size - 1; i++)
waddch(window, ' ');
wattroff(window, color_button);
wattron(window, color_arrows);
mvwaddch(window, y, x + i, t.buttrightchar);
wattroff(window, color_arrows);
x = x + 1 + ((size - 2 - strlen(text))/2);
wattron(window, color_button);
mvwaddstr(window, y, x, text);
wattroff(window, color_button);
if (shortkey) {
wattron(window, color_shortkey);
mvwaddch(window, y, x, text[0]);
wattroff(window, color_shortkey);
}
}
void
draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey)
{
int i, x, start_x;
start_x = bs.sizebutton * bs.nbuttons + (bs.nbuttons - 1) * t.buttonspace;
start_x = cols/2 - start_x/2;
for (i = 0; i < (int) bs.nbuttons; i++) {
x = i * (bs.sizebutton + t.buttonspace);
draw_button(window, y, start_x + x, bs.sizebutton, bs.label[i],
i == bs.curr, shortkey);
}
}
void
get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
char *extralabel, char *nocancellabel, char *helplabel)
{
int i;
#define SIZEBUTTON 8
#define DEFAULT_BUTTON_LABEL LABEL_ok_label
#define DEFAULT_BUTTON_VALUE BSDDIALOG_YESOK
bs->nbuttons = 0;
bs->curr = 0;
bs->sizebutton = 0;
if (yesoklabel != NULL && conf.button.no_ok == false) {
bs->label[0] = yesoklabel;
bs->value[0] = BSDDIALOG_YESOK;
bs->nbuttons += 1;
}
if (extralabel != NULL && conf.button.extra_button) {
bs->label[bs->nbuttons] = extralabel;
bs->value[bs->nbuttons] = BSDDIALOG_EXTRA;
bs->nbuttons += 1;
}
if (nocancellabel != NULL && conf.button.no_cancel == false) {
bs->label[bs->nbuttons] = nocancellabel;
bs->value[bs->nbuttons] = BSDDIALOG_NOCANCEL;
if (conf.button.defaultno)
bs->curr = bs->nbuttons;
bs->nbuttons += 1;
}
if (helplabel != NULL && conf.button.help_button) {
bs->label[bs->nbuttons] = helplabel;
bs->value[bs->nbuttons] = BSDDIALOG_HELP;
bs->nbuttons += 1;
}
if (bs->nbuttons == 0) {
bs->label[0] = DEFAULT_BUTTON_LABEL;
bs->value[0] = DEFAULT_BUTTON_VALUE;
bs->nbuttons = 1;
}
if (conf.button.default_label != NULL) {
for (i=0; i<(int)bs->nbuttons; i++) {
if (strcmp(conf.button.default_label, bs->label[i]) == 0)
bs->curr = i;
}
}
bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0]));
for (i=1; i < (int) bs->nbuttons; i++)
bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i]));
bs->sizebutton += 2;
}
/* Text */
// old text, to delete in the future
enum token { TEXT, WS, END };
static bool check_set_ncurses_attr(WINDOW *win, char *text)
{
bool isattr;
int colors[8] = {
COLOR_BLACK,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW,
COLOR_BLUE,
COLOR_MAGENTA,
COLOR_CYAN,
COLOR_WHITE
};
if (text[0] == '\0' || text[0] != '\\')
return false;
if (text[1] == '\0' || text[1] != 'Z')
return false;
if (text[2] == '\0')
return false;
if ((text[2] - 48) >= 0 && (text[2] - 48) < 8) {
// tocheck: import BSD_COLOR
// tofix color background
wattron(win, COLOR_PAIR(colors[text[2] - 48] * 8 + COLOR_WHITE + 1));
return true;
}
isattr = true;
switch (text[2]) {
case 'n':
wattrset(win, A_NORMAL);
break;
case 'b':
wattron(win, A_BOLD);
break;
case 'B':
wattroff(win, A_BOLD);
break;
case 'r':
wattron(win, A_REVERSE);
break;
case 'R':
wattroff(win, A_REVERSE);
break;
case 'u':
wattron(win, A_UNDERLINE);
break;
case 'U':
wattroff(win, A_UNDERLINE);
break;
default:
isattr = false;
}
return isattr;
}
static bool isws(int ch)
{
return (ch == ' ' || ch == '\t' || ch == '\n');
}
static int
next_token(char *text, char *valuestr)
{
int i, j;
enum token tok;
i = j = 0;
if (text[0] == '\0')
return END;
while (text[i] != '\0') {
if (isws(text[i])) {
if (i == 0) {
valuestr[0] = text[i];
valuestr[1] = '\0';
tok = WS;
}
break;
}
valuestr[j] = text[i];
j++;
valuestr[j] = '\0';
i++;
tok = TEXT;
}
return tok;
}
static void
print_string(WINDOW *win, int *y, int *x, int minx, int maxx, char *str, bool color)
{
int i, j, len, reallen;
if(strlen(str) == 0)
return;
len = reallen = strlen(str);
if (color) {
i=0;
while (i < len) {
if (check_set_ncurses_attr(win, str+i))
reallen -= 3;
i++;
}
}
i = 0;
while (i < len) {
if (*x + reallen > maxx) {
*y = (*x != minx ? *y+1 : *y);
*x = minx;
}
j = *x;
while (j < maxx && i < len) {
if (color && check_set_ncurses_attr(win, str+i)) {
i += 3;
} else {
mvwaddch(win, *y, j, str[i]);
i++;
reallen--;
j++;
*x = j;
}
}
}
}
void
print_text(struct bsddialog_conf conf, WINDOW *pad, int starty, int minx, int maxx,
char *text)
{
char *valuestr;
int x, y;
bool loop;
enum token tok;
valuestr = malloc(strlen(text) + 1);
x = minx;
y = starty;
loop = true;
while (loop) {
tok = next_token(text, valuestr);
switch (tok) {
case END:
loop = false;
break;
case WS:
text += strlen(valuestr);
print_string(pad, &y, &x, minx, maxx, valuestr, false /*useless*/);
break;
case TEXT:
text += strlen(valuestr);
print_string(pad, &y, &x, minx, maxx, valuestr, conf.text.colors);
break;
}
}
free(valuestr);
}
// new text funcs
static bool is_ncurses_attr(char *text)
{
bool isattr;
if (strnlen(text, 3) < 3)
return false;
if (text[0] != '\\' || text[1] != 'Z')
return false;
if ((text[2] - '0') >= 0 && (text[2] - '0') < 8)
return true;
isattr = text[2] == 'n' || text[2] == 'b' || text[2] == 'B' ||
text[2] == 'r' || text[2] == 'R' || text[2] == 'u' ||
text[2] == 'U';
return isattr;
}
static void
print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool color)
{
int i, j, len, reallen;
if(strlen(str) == 0)
return;
len = reallen = strlen(str);
if (color) {
i=0;
while (i < len) {
if (is_ncurses_attr(str+i))
reallen -= 3;
i++;
}
}
i = 0;
while (i < len) {
if (*x + reallen > cols) {
*y = (*x != 0 ? *y+1 : *y);
if (*y >= *rows) {
*rows = *y + 1;
wresize(win, *rows, cols);
}
*x = 0;
}
j = *x;
while (j < cols && i < len) {
if (color && check_set_ncurses_attr(win, str+i)) {
i += 3;
} else {
mvwaddch(win, *y, j, str[i]);
i++;
reallen--;
j++;
*x = j;
}
}
}
}
static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
{
int i, j;
i = j = 0;
while (text[i] != '\0') {
switch (text[i]) {
case '\\':
buf[j] = '\\';
switch (text[i+1]) {
case '\\':
i++;
break;
case 'n':
if (conf.text.no_nl_expand) {
j++;
buf[j] = 'n';
} else
buf[j] = '\n';
i++;
break;
case 't':
if (conf.text.no_collapse) {
j++;
buf[j] = 't';
} else
buf[j] = '\t';
i++;
break;
}
break;
case '\n':
buf[j] = conf.text.cr_wrap ? ' ' : '\n';
break;
case '\t':
buf[j] = conf.text.no_collapse ? '\t' : ' ';
break;
default:
buf[j] = text[i];
}
i++;
j += (buf[j] == ' ' && conf.text.trim && j > 0 && buf[j-1] == ' ') ?
0 : 1;
}
buf[j] = '\0';
}
int
get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
int *maxline, int *nlines)
{
char *buf;
int i, buflen, wordlen, linelen;
if ((buf = malloc(strlen(text) + 1)) == NULL)
RETURN_ERROR("Cannot building a buffer to find the properties "\
"of the text properties");
prepare_text(conf, text, buf);
buflen = strlen(buf) + 1;
*maxword = 0;
wordlen = 0;
for (i=0; i < buflen; i++) {
if (buf[i] == '\t' || buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\0')
if (wordlen != 0) {
*maxword = MAX(*maxword, wordlen);
wordlen = 0;
continue;
}
if (conf.text.colors && is_ncurses_attr(buf + i))
i += 3;
else
wordlen++;
}
*maxline = linelen = 0;
*nlines = 1;
for (i=0; i < buflen; i++) {
switch (buf[i]) {
case '\n':
*nlines = *nlines + 1;
case '\0':
*maxline = MAX(*maxline, linelen);
linelen = 0;
break;
default:
if (conf.text.colors && is_ncurses_attr(buf + i))
i += 3;
else
linelen++;
}
}
if (*nlines == 1 && *maxline == 0)
*nlines = 0;
free(buf);
return 0;
}
static int
print_textpad(struct bsddialog_conf conf, WINDOW *pad, int *rows, int cols, char *text)
{
char *buf, *string;
int i, j, x, y;
bool loop;
if ((buf = malloc(strlen(text) + 1)) == NULL)
RETURN_ERROR("Cannot build (analyze) text");
prepare_text(conf, text, buf);
if ((string = malloc(strlen(text) + 1)) == NULL) {
free(buf);
RETURN_ERROR("Cannot build (analyze) text");
}
i = j = x = y = 0;
loop = true;
while (loop) {
string[j] = buf[i];
if (string[j] == '\0' || string[j] == '\n' ||
string[j] == '\t' || string[j] == ' ') {
if (j != 0) {
string[j] = '\0';
print_str(pad, rows, &y, &x, cols, string, conf.text.colors);
}
}
switch (buf[i]) {
case '\0':
loop = false;
break;
case '\n':
j = -1;
x = 0;
y++;
break;
case '\t':
for (j=0; j<4 /*tablen*/; j++) {
x++;
if (x >= cols) {
x = 0;
y++;
}
}
j = -1;
break;
case ' ':
x++;
if (x >= cols) {
x = 0;
y++;
}
j = -1;
}
if (y >= *rows) { /* check for whitespaces */
*rows = y + 1;
wresize(pad, *rows, cols);
}
j++;
i++;
}
free(string);
free(buf);
return 0;
}
/* autosize */
/*
* max y, that is from 0 to LINES - 1 - t.shadowrows,
* could not be max height but avoids problems with checksize
*/
int widget_max_height(struct bsddialog_conf conf)
{
int maxheight;
if ((maxheight = conf.shadow ? LINES - 1 - t.shadowrows : LINES - 1) <= 0)
RETURN_ERROR("Terminal too small, LINES - shadow <= 0");
if (conf.y > 0)
if ((maxheight -= conf.y) <=0)
RETURN_ERROR("Terminal too small, LINES - shadow - y <= 0");
return maxheight;
}
/*
* max x, that is from 0 to COLS - 1 - t.shadowcols,
* * could not be max height but avoids problems with checksize
*/
int widget_max_width(struct bsddialog_conf conf)
{
int maxwidth;
if ((maxwidth = conf.shadow ? COLS - 1 - t.shadowcols : COLS - 1) <= 0)
RETURN_ERROR("Terminal too small, COLS - shadow <= 0");
if (conf.x > 0)
if ((maxwidth -= conf.x) <=0)
RETURN_ERROR("Terminal too small, COLS - shadow - x <= 0");
return maxwidth;
}
int
set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w)
{
int maxheight, maxwidth;
if ((maxheight = widget_max_height(conf)) == BSDDIALOG_ERROR)
return BSDDIALOG_ERROR;
if (rows == BSDDIALOG_FULLSCREEN)
*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");
}
/* rows == AUTOSIZE: each widget has to set its size */
if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR)
return BSDDIALOG_ERROR;
if (cols == BSDDIALOG_FULLSCREEN)
*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)");
}
/* cols == AUTOSIZE: each widget has to set its size */
return 0;
}
int
set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w)
{
if (conf.y == BSDDIALOG_CENTER)
*y = LINES/2 - h/2;
else if (conf.y < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin y (less than -1)");
else if (conf.y >= LINES)
RETURN_ERROR("Begin Y under the terminal");
else
*y = conf.y;
if ((*y + h + (conf.shadow ? (int) t.shadowrows : 0)) > LINES)
RETURN_ERROR("The lower of the box under the terminal "\
"(begin Y + height (+ shadow) > terminal lines)");
if (conf.x == BSDDIALOG_CENTER)
*x = COLS/2 - w/2;
else if (conf.x < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin x (less than -1)");
else if (conf.x >= COLS)
RETURN_ERROR("Begin X over the right of the terminal");
else
*x = conf.x;
if ((*x + w + (conf.shadow ? (int) t.shadowcols : 0)) > COLS)
RETURN_ERROR("The right of the box over the terminal "\
"(begin X + width (+ shadow) > terminal cols)");
return 0;
}
/* Widgets builders */
void
draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
enum elevation elev)
{
int leftcolor, rightcolor;
int ls, rs, ts, bs, tl, tr, bl, br;
int ltee, rtee;
ls = rs = ACS_VLINE;
ts = bs = ACS_HLINE;
tl = ACS_ULCORNER;
tr = ACS_URCORNER;
bl = ACS_LLCORNER;
br = ACS_LRCORNER;
ltee = ACS_LTEE;
rtee = ACS_RTEE;
if (conf.no_lines == false) {
if (conf.ascii_lines) {
ls = rs = '|';
ts = bs = '-';
tl = tr = bl = br = ltee = rtee = '+';
}
leftcolor = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
rightcolor = elev == RAISED ? t.linelowercolor : t.lineraisecolor;
wattron(win, leftcolor);
wborder(win, ls, rs, ts, bs, tl, tr, bl, br);
wattroff(win, leftcolor);
wattron(win, rightcolor);
mvwaddch(win, 0, cols-1, tr);
mvwvline(win, 1, cols-1, rs, rows-2);
mvwaddch(win, rows-1, cols-1, br);
mvwhline(win, rows-1, 1, bs, cols-2);
wattroff(win, rightcolor);
}
}
WINDOW *
new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
enum elevation elev)
{
WINDOW *win;
if ((win = newwin(rows, cols, y, x)) == NULL) {
set_error_string("Cannot build boxed window");
return NULL;
}
wbkgd(win, t.widgetcolor);
draw_borders(conf, win, rows, cols, elev);
return win;
}
/*
* `enum elevation elev` could be useless because it should be always RAISED,
* to check at the end.
*/
static int
draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev,
WINDOW *textpad, int *htextpad, char *text, bool buttons)
{
int ts, ltee, rtee;
int colorsurroundtitle;
ts = conf.ascii_lines ? '-' : ACS_HLINE;
ltee = conf.ascii_lines ? '+' : ACS_LTEE;
rtee = conf.ascii_lines ? '+' : ACS_RTEE;
colorsurroundtitle = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
if (shadow != NULL)
wnoutrefresh(shadow);
// move / resize now or the caller?
draw_borders(conf, widget, h, w, elev);
if (conf.title != NULL) {
if (t.surroundtitle && conf.no_lines == false) {
wattron(widget, colorsurroundtitle);
mvwaddch(widget, 0, w/2 - strlen(conf.title)/2 - 1, rtee);
wattroff(widget, colorsurroundtitle);
}
wattron(widget, t.titlecolor);
mvwaddstr(widget, 0, w/2 - strlen(conf.title)/2, conf.title);
wattroff(widget, t.titlecolor);
if (t.surroundtitle && conf.no_lines == false) {
wattron(widget, colorsurroundtitle);
waddch(widget, ltee);
wattroff(widget, colorsurroundtitle);
}
}
if (conf.hline != NULL) {
wattron(widget, t.bottomtitlecolor);
wmove(widget, h - 1, w/2 - strlen(conf.hline)/2 - 1);
waddch(widget, '[');
waddstr(widget, conf.hline);
waddch(widget, ']');
wattroff(widget, t.bottomtitlecolor);
}
if (textpad == NULL && text != NULL) /* no pad, text null for textbox */
print_text(conf, widget, 1, 2, w-3, text);
if (buttons && conf.no_lines == false) {
wattron(widget, t.lineraisecolor);
mvwaddch(widget, h-3, 0, ltee);
mvwhline(widget, h-3, 1, ts, w-2);
wattroff(widget, t.lineraisecolor);
wattron(widget, t.linelowercolor);
mvwaddch(widget, h-3, w-1, rtee);
wattroff(widget, t.linelowercolor);
}
wnoutrefresh(widget);
if (textpad == NULL)
return 0; /* widget_init() ends */
if (text != NULL) /* programbox etc */
if (print_textpad(conf, textpad, htextpad,
w - HBORDERS - t.texthmargin * 2, text) !=0)
return BSDDIALOG_ERROR;
return 0;
}
/*
* `enum elevation elev` could be useless because it should be always RAISED,
* to check at the end.
*/
int
update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev,
WINDOW *textpad, int *htextpad, char *text, bool buttons)
{
int error;
/* nothing for now */
error = draw_widget_withtextpad(conf, shadow, widget, h, w,
elev, textpad, htextpad, text, buttons);
return error;
}
/*
* `enum elevation elev` could be useless because it should be always RAISED,
* to check at the end.
*/
int
new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
WINDOW **widget, int y, int x, int h, int w, enum elevation elev,
WINDOW **textpad, int *htextpad, char *text, bool buttons)
{
int error;
if (conf.shadow) {
*shadow = newwin(h, w, y + t.shadowrows, x + t.shadowcols);
if (*shadow == NULL)
RETURN_ERROR("Cannot build shadow");
wbkgd(*shadow, t.shadowcolor);
}
if ((*widget = new_boxed_window(conf, y, x, h, w, elev)) == NULL) {
if (conf.shadow)
delwin(*shadow);
return BSDDIALOG_ERROR;
}
if (textpad == NULL) { /* widget_init() */
error = draw_widget_withtextpad(conf, *shadow, *widget, h, w,
elev, NULL, NULL, text, buttons);
return error;
}
if (text != NULL) { /* programbox etc */
*htextpad = 1;
*textpad = newpad(*htextpad, w - HBORDERS - t.texthmargin * 2);
if (*textpad == NULL) {
delwin(*textpad);
if (conf.shadow)
delwin(*shadow);
RETURN_ERROR("Cannot build the pad window for text");
}
wbkgd(*textpad, t.widgetcolor);
}
error = draw_widget_withtextpad(conf, *shadow, *widget, h, w, elev,
*textpad, htextpad, text, buttons);
return error;
}
int
new_widget(struct bsddialog_conf conf, WINDOW **widget, int *y, int *x,
char *text, int *h, int *w, WINDOW **shadow, bool buttons)
{
// to delete (each widget has to check its x,y,h,w)
if (*h <= 0)
; /* todo */
if (*w <= 0)
; /* todo */
*y = (conf.y < 0) ? (LINES/2 - *h/2) : conf.y;
*x = (conf.x < 0) ? (COLS/2 - *w/2) : conf.x;
if (new_widget_withtextpad(conf, shadow, widget, *y, *x, *h, *w, RAISED,
NULL, NULL, text, buttons) != 0)
return BSDDIALOG_ERROR;
if (conf.shadow)
wrefresh(*shadow);
wrefresh(*widget);
return 0;
}
void
end_widget_withtextpad(struct bsddialog_conf conf, WINDOW *window, int h, int w,
WINDOW *textpad, WINDOW *shadow)
{
int y, x;
getbegyx(window, y, x); /* for clear, add y & x to args? */
if (conf.sleep > 0)
sleep(conf.sleep);
if (textpad != NULL)
delwin(textpad);
delwin(window);
if (conf.shadow)
delwin(shadow);
if (conf.clear)
hide_widget(y, x, h, w, shadow != NULL);
if (conf.get_height != NULL)
*conf.get_height = h;
if (conf.get_width != NULL)
*conf.get_width = w;
}
void
end_widget(struct bsddialog_conf conf, WINDOW *window, int h, int w,
WINDOW *shadow)
{
end_widget_withtextpad(conf, window, h, w, NULL, shadow);
}

146
lib/lib_util.h Normal file
View File

@ -0,0 +1,146 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 _LIBBSDDIALOG_UTIL_H_
#define _LIBBSDDIALOG_UTIL_H_
/*
* Utils to implement widgets - Internal library API
*/
#define HBORDERS 2
#define VBORDERS 2
/* ncurses has not a Ctrl key macro */
#define KEY_CTRL(x) ((x) & 0x1f)
/* Set default aspect ratio to 9 */
#define GET_ASPECT_RATIO(conf) (conf.aspect_ratio > 0 ? conf.aspect_ratio : 9)
/* debug */
#define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \
mvprintw(y, x, fmt, __VA_ARGS__); \
refresh(); \
} while (0)
/* error buffer */
const char *get_error_string(void);
void set_error_string(char *string);
#define RETURN_ERROR(str) do { \
set_error_string(str); \
return BSDDIALOG_ERROR; \
} while (0)
/* Buttons */
#define LABEL_cancel_label "Cancel"
#define LABEL_exit_label "EXIT"
#define LABEL_extra_label "Extra"
#define LABEL_help_label "Help"
#define LABEL_no_label "No"
#define LABEL_ok_label "OK"
#define LABEL_yes_label "Yes"
#define BUTTONLABEL(l) (conf.button.l != NULL ? conf.button.l : LABEL_ ##l)
#define MAXBUTTONS 4 /* yes|ok - extra - no|cancel - help */
struct buttons {
unsigned int nbuttons;
char *label[MAXBUTTONS];
int value[MAXBUTTONS];
int curr;
unsigned int sizebutton; /* including left and right delimiters */
};
void
get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
char *extralabel, char *nocancellabel, char *helplabel);
void
draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected,
bool shortkey);
void
draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey);
/* help window with F1 key */
int f1help(struct bsddialog_conf conf);
/* cleaner */
int hide_widget(int y, int x, int h, int w, bool withshadow);
/* (auto) size and (auto) position */
int
get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
int *maxline, int *nlines);
int widget_max_height(struct bsddialog_conf conf);
int widget_max_width(struct bsddialog_conf conf);
int
set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w);
int
set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w);
/* widget builders */
void
print_text(struct bsddialog_conf conf, WINDOW *pad, int starty, int minx,
int maxx, char *text);
enum elevation { RAISED, LOWERED };
void
draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
enum elevation elev);
WINDOW *
new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
enum elevation elev);
int
new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
WINDOW **widget, int y, int x, int h, int w, enum elevation elev,
WINDOW **textpad, int *htextpad, char *text, bool buttons);
int
update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev, WINDOW *textpad,
int *htextpad, char *text, bool buttons);
void
end_widget_withtextpad(struct bsddialog_conf conf, WINDOW *window, int h, int w,
WINDOW *textpad, WINDOW *shadow);
int
new_widget(struct bsddialog_conf conf, WINDOW **widget, int *y, int *x,
char *text, int *h, int *w, WINDOW **shadow, bool buttons);
void
end_widget(struct bsddialog_conf conf, WINDOW *window, int h, int w,
WINDOW *shadow);
#endif

142
lib/libbsddialog.c Normal file
View File

@ -0,0 +1,142 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/*
* This file implements some public function not related to a specific widget.
* utils.h/c provides private functions to implement the library.
* theme.h/c is public API related to theme.
* Widgets implementation:
* infobox.c infobox
* messgebox.c msgbox - yesno
* menubox.c buildlist - checklist - menu - mixedlist - radiolist - treeview
* formbox.c inputbox - passwordbox - form - passwordform - mixedform
* editorbox.c editbox
* barbox.c gauge - mixedgauge - rangebox - pause
* timebox.c timebox - calendar
* commandbox.c prgbox - programbox - progressbox
* tailbox.c tailbox - tailboxbg - textbox
* filebox.c dselect - fselect
*/
extern struct bsddialog_theme t;
int bsddialog_init(void)
{
int i, j, c = 1, error = OK;
set_error_string("");
if(initscr() == NULL)
RETURN_ERROR("Cannot init ncurses (initscr)");
error += keypad(stdscr, TRUE);
nl();
error += cbreak();
error += noecho();
curs_set(0);
if(error != OK) {
bsddialog_end();
RETURN_ERROR("Cannot init ncurses (keypad and cursor)");
}
error += start_color();
for (i=0; i<8; i++)
for(j=0; j<8; j++) {
error += init_pair(c, i, j);
c++;
}
if(error != OK) {
bsddialog_end();
RETURN_ERROR("Cannot init ncurses (colors)");
}
if (bsddialog_set_default_theme(BSDDIALOG_THEME_DIALOG) != 0)
error = BSDDIALOG_ERROR;
return error;
}
int bsddialog_end(void)
{
if (endwin() != OK)
RETURN_ERROR("Cannot end ncurses (endwin)");
return 0;
}
int bsddialog_backtitle(struct bsddialog_conf conf, char *backtitle)
{
mvaddstr(0, 1, backtitle);
if (conf.no_lines != true)
mvhline(1, 1, conf.ascii_lines ? '-' : ACS_HLINE, COLS-2);
refresh();
return 0;
}
const char *bsddialog_geterror(void)
{
return get_error_string();
}
int bsddialog_terminalheight(void)
{
return LINES;
}
int bsddialog_terminalwidth(void)
{
return COLS;
}
void bsddialog_initconf(struct bsddialog_conf *conf)
{
memset(conf, 0, sizeof(struct bsddialog_conf));
conf->x = conf->y = BSDDIALOG_CENTER;
conf->shadow = true;
}

1015
lib/menubox.c Normal file

File diff suppressed because it is too large Load Diff

278
lib/messagebox.c Normal file
View File

@ -0,0 +1,278 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <ctype.h>
#include <string.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Message": msgbox - yesno */
#define AUTO_WIDTH (COLS / 3U)
/*
* Min height = 5: 2 up & down borders + 2 label & up border buttons + 1 line
* for text, at least 1 line is important for widget_withtextpad_init() to avoid
* "Cannot build the pad window for text".
*/
#define MIN_HEIGHT 5
extern struct bsddialog_theme t;
static int
message_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
char *text, struct buttons bs)
{
int maxword, maxline, nlines, line;
if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
return BSDDIALOG_ERROR;
if (cols == BSDDIALOG_AUTOSIZE) {
*w = VBORDERS;
/* buttons size */
*w += bs.nbuttons * bs.sizebutton;
*w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
/* text size */
line = MIN(maxline + VBORDERS + t.texthmargin * 2, AUTO_WIDTH);
line = MAX(line, (int) (maxword + VBORDERS + t.texthmargin * 2));
*w = MAX(*w, line);
/* avoid terminal overflow */
*w = MIN(*w, widget_max_width(conf));
}
if (rows == BSDDIALOG_AUTOSIZE) {
*h = MIN_HEIGHT - 1;
if (maxword > 0)
*h += MAX(nlines, (*w / GET_ASPECT_RATIO(conf)));
*h = MAX(*h, MIN_HEIGHT);
/* avoid terminal overflow */
*h = MIN(*h, widget_max_height(conf));
}
return 0;
}
static int message_checksize(int rows, int cols, struct buttons bs)
{
int mincols;
mincols = VBORDERS;
mincols += bs.nbuttons * bs.sizebutton;
mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
if (cols < mincols)
RETURN_ERROR("Few cols, Msgbox and Yesno need at least width "\
"for borders, buttons and spaces between buttons");
if (rows < MIN_HEIGHT)
RETURN_ERROR("Msgbox and Yesno need at least height 5");
return 0;
}
static void
buttonsupdate(WINDOW *widget, int h, int w, struct buttons bs, bool shortkey)
{
draw_buttons(widget, h-2, w, bs, shortkey);
wnoutrefresh(widget);
}
static void
textupdate(WINDOW *widget, int y, int x, int h, int w, WINDOW *textpad,
int htextpad, int textrow)
{
if (htextpad > h - 4) {
mvwprintw(widget, h-3, w-6, "%3d%%",
100 * (textrow+h-4)/ htextpad);
wnoutrefresh(widget);
}
pnoutrefresh(textpad, textrow, 0, y+1, x+2, y+h-4, x+w-2);
}
static int
do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
struct buttons bs, bool shortkey)
{
WINDOW *widget, *textpad, *shadow;
bool loop;
int i, y, x, h, w, input, output, htextpad, textrow;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
return BSDDIALOG_ERROR;
if (message_checksize(h, w, bs) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
&textpad, &htextpad, text, true) != 0)
return BSDDIALOG_ERROR;
textrow = 0;
loop = true;
buttonsupdate(widget, h, w, bs, shortkey);
textupdate(widget, y, x, h, w, textpad, htextpad, textrow);
while(loop) {
doupdate();
input = getch();
switch (input) {
case 10: /* Enter */
output = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttonsupdate(widget, h, w, bs, shortkey);
break;
case KEY_F(1):
if (conf.hfile == NULL)
break;
if (f1help(conf) != 0)
return BSDDIALOG_ERROR;
/* No break! the terminal size can change */
case KEY_RESIZE:
hide_widget(y, x, h, w,conf.shadow);
/*
* Unnecessary, but, when the columns decrease the
* following "refresh" seem not work
*/
refresh();
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
return BSDDIALOG_ERROR;
if (message_checksize(h, w, bs) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
wclear(shadow);
mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
wresize(shadow, h, w);
wclear(widget);
mvwin(widget, y, x);
wresize(widget, h, w);
htextpad = 1;
wclear(textpad);
wresize(textpad, 1, w - HBORDERS - t.texthmargin * 2);
if(update_widget_withtextpad(conf, shadow, widget, h, w,
RAISED, textpad, &htextpad, text, true) != 0)
return BSDDIALOG_ERROR;
buttonsupdate(widget, h, w, bs, shortkey);
textupdate(widget, y, x, h, w, textpad, htextpad, textrow);
/* Important to fix grey lines expanding screen */
refresh();
break;
case KEY_UP:
if (textrow == 0)
break;
textrow--;
textupdate(widget, y, x, h, w, textpad, htextpad, textrow);
break;
case KEY_DOWN:
if (textrow + h - 4 >= htextpad)
break;
textrow++;
textupdate(widget, y, x, h, w, textpad, htextpad, textrow);
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttonsupdate(widget, h, w, bs, shortkey);
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttonsupdate(widget, h, w, bs, shortkey);
}
break;
default:
if (shortkey == false)
break;
for (i = 0; i < (int) bs.nbuttons; i++)
if (tolower(input) == tolower((bs.label[i])[0])) {
output = bs.value[i];
loop = false;
}
}
}
end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
/* API */
int
bsddialog_msgbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
struct buttons bs;
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
NULL /* nocancel */, BUTTONLABEL(help_label));
return (do_widget(conf, text, rows, cols, bs, true));
}
int
bsddialog_yesno(struct bsddialog_conf conf, char* text, int rows, int cols)
{
struct buttons bs;
get_buttons(conf, &bs, BUTTONLABEL(yes_label), BUTTONLABEL(extra_label),
BUTTONLABEL(no_label), BUTTONLABEL(help_label));
return (do_widget(conf, text, rows, cols, bs, true));
}

280
lib/textbox.c Normal file
View File

@ -0,0 +1,280 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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 <string.h>
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
/* "Text": tailbox - tailboxbg - textbox */
#define BUTTON_TEXTBOX "HELP"
extern struct bsddialog_theme t;
enum textmode { TAILMODE, TAILBGMODE, TEXTMODE};
static void
textbox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
int hpad, int wpad)
{
if (cols == BSDDIALOG_AUTOSIZE) {
*w = VBORDERS;
/* buttons size */
*w += strlen(BUTTON_TEXTBOX) + 2 /* text delims*/;
/* text size */
*w = MAX(*w, wpad + VBORDERS);
/* avoid terminal overflow */
*w = MIN(*w, widget_max_width(conf)-1); /* again -1, fix util.c */
}
if (rows == BSDDIALOG_AUTOSIZE) {
*h = hpad + 4; /* HBORDERS + button border */
/* avoid terminal overflow */
*h = MIN(*h, widget_max_height(conf));
}
}
static int textbox_checksize(int rows, int cols, int hpad, int wpad)
{
int mincols;
mincols = VBORDERS + strlen(BUTTON_TEXTBOX) + 2 /* text delims */;
if (cols < mincols)
RETURN_ERROR("Few cols for the textbox");
if (rows < 4 /* HBORDERS + button*/ + (hpad > 0 ? 1 : 0))
RETURN_ERROR("Few rows for the textbox");
return 0;
}
static int
do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows, int cols)
{
WINDOW *widget, *pad, *shadow;
int i, input, y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows;
char buf[BUFSIZ], *exitbutt;
FILE *fp;
bool loop;
int output;
if (mode == TAILMODE || mode == TAILBGMODE) {
bsddialog_msgbox(conf, "Tailbox and Tailboxbg unimplemented", rows, cols);
RETURN_ERROR("Tailbox and Tailboxbg unimplemented");
}
if ((fp = fopen(path, "r")) == NULL)
RETURN_ERROR("Cannot open file");
/*if (mode == TAILMODE) {
fseek (fp, 0, SEEK_END);
i = nlines = 0;
while (i < hpad) {
line = ;
}
for (i=hpad-1; i--; i>=0) {
}
}*/
hpad = 1;
wpad = 1;
pad = newpad(hpad, wpad);
wbkgd(pad, t.widgetcolor);
i = 0;
while(fgets(buf, BUFSIZ, fp) != NULL) {
if ((int) strlen(buf) > wpad) {
wpad = strlen(buf);
wresize(pad, hpad, wpad);
}
if (i > hpad-1) {
hpad++;
wresize(pad, hpad, wpad);
}
mvwaddstr(pad, i, 0, buf);
i++;
}
fclose(fp);
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad);
if (textbox_checksize(h, w, hpad, wpad) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
NULL, NULL, NULL, true) != 0)
return BSDDIALOG_ERROR;
exitbutt = conf.button.exit_label == NULL ? BUTTON_TEXTBOX : conf.button.exit_label;
draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, strlen(exitbutt)+2,
exitbutt, true, true);
wrefresh(widget);
ys = y + 1;
xs = x + 1;
ye = ys + h - 5;
xe = xs + w - 3;
ypad = xpad = 0;
printrows = h-4;
loop = true;
while(loop) {
prefresh(pad, ypad, xpad, ys, xs, ye, xe);
input = getch();
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
output = BSDDIALOG_YESOK;
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case KEY_HOME:
ypad = 0;
break;
case KEY_END:
ypad = hpad - printrows;
ypad = ypad < 0 ? 0 : ypad;
break;
case KEY_PPAGE:
ypad -= printrows;
ypad = ypad < 0 ? 0 : ypad;
break;
case KEY_NPAGE:
ypad += printrows;
ypad = ypad + printrows > hpad ? hpad - printrows : ypad;
break;
case '0':
xpad = 0;
case KEY_LEFT:
case 'h':
xpad = xpad > 0 ? xpad - 1 : 0;
break;
case KEY_RIGHT:
case 'l':
xpad = (xpad + w-2) < wpad-1 ? xpad + 1 : xpad;
break;
case KEY_UP:
case 'k':
ypad = ypad > 0 ? ypad - 1 : 0;
break;
case KEY_DOWN:
case'j':
ypad = ypad + printrows <= hpad -1 ? ypad + 1 : ypad;
break;
case KEY_F(1):
if (conf.hfile == NULL)
break;
if (f1help(conf) != 0)
return BSDDIALOG_ERROR;
/* No break! the terminal size can change */
case KEY_RESIZE:
hide_widget(y, x, h, w,conf.shadow);
/*
* Unnecessary, but, when the columns decrease the
* following "refresh" seem not work
*/
refresh();
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad);
if (textbox_checksize(h, w, hpad, wpad) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
wclear(shadow);
mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
wresize(shadow, h, w);
wclear(widget);
mvwin(widget, y, x);
wresize(widget, h, w);
ys = y + 1;
xs = x + 1;
ye = ys + h - 5;
xe = xs + w - 3;
ypad = xpad = 0;
printrows = h - 4;
if(update_widget_withtextpad(conf, shadow, widget, h, w,
RAISED, NULL, NULL, NULL, true) != 0)
return BSDDIALOG_ERROR;
draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2,
strlen(exitbutt)+2, exitbutt, true, true);
wrefresh(widget); /* for button */
/* Important to fix grey lines expanding screen */
refresh();
break;
}
}
end_widget_withtextpad(conf, widget, h, w, pad, shadow);
return output;
}
int bsddialog_tailbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
return (do_textbox(TAILMODE, conf, text, rows, cols));
}
int bsddialog_tailboxbg(struct bsddialog_conf conf, char* text, int rows, int cols)
{
return (do_textbox(TAILBGMODE, conf, text, rows, cols));
}
int bsddialog_textbox(struct bsddialog_conf conf, char* text, int rows, int cols)
{
return (do_textbox(TEXTMODE, conf, text, rows, cols));
}

286
lib/theme.c Normal file
View File

@ -0,0 +1,286 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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.
*/
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
#include "bsddialog_theme.h"
#define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1))
struct bsddialog_theme t;
static struct bsddialog_theme bsddialogtheme = {
#define bgwidget COLOR_WHITE
#define bgcurr COLOR_YELLOW
.shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadowrows = 1,
.shadowcols = 2,
.backgroundcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.surroundtitle = true,
.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget),
.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget),
.widgetcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.texthmargin = 1,
.curritemcolor = GET_COLOR(COLOR_WHITE, bgcurr),
.itemcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.currtagcolor = GET_COLOR(COLOR_BLACK, bgcurr),
.tagcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
.currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
.fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE),
.currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
.buttonspace = 3,
.buttleftch = '[',
.buttrightchar = ']',
.currbuttdelimcolor = GET_COLOR(COLOR_WHITE, bgcurr),
.buttdelimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
.currbuttoncolor = GET_COLOR(COLOR_WHITE, bgcurr) | A_UNDERLINE,
.buttoncolor = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE,
.currshortkeycolor = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE,
.shortkeycolor = GET_COLOR(COLOR_YELLOW, bgwidget) | A_UNDERLINE,
.bottomtitlecolor= GET_COLOR(COLOR_BLACK, bgwidget)
};
static struct bsddialog_theme blackwhite = {
#define bk COLOR_BLACK
#define fg COLOR_WHITE
.shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadowrows = 1,
.shadowcols = 2,
.backgroundcolor = GET_COLOR(fg, bk),
.surroundtitle = true,
.titlecolor = GET_COLOR(fg, bk),
.lineraisecolor = GET_COLOR(fg, bk),
.linelowercolor = GET_COLOR(fg, bk),
.widgetcolor = GET_COLOR(fg, bk),
.texthmargin = 1,
.curritemcolor = GET_COLOR(fg, bk) | A_REVERSE,
.itemcolor = GET_COLOR(fg, bk),
.currtagcolor = GET_COLOR(fg, bk) | A_REVERSE,
.tagcolor = GET_COLOR(fg, bk),
.namesepcolor = GET_COLOR(fg, bk),
.descsepcolor = GET_COLOR(fg, bk),
.currfieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
.fieldcolor = GET_COLOR(fg, bk),
.fieldreadonlycolor = GET_COLOR(fg, bk),
.currbarcolor = GET_COLOR(fg, bk) | A_REVERSE,
.barcolor = GET_COLOR(fg, bk),
.buttonspace = 3,
.buttleftch = '[',
.buttrightchar = ']',
.currbuttdelimcolor = GET_COLOR(fg, bk),
.buttdelimcolor = GET_COLOR(fg, bk),
.currbuttoncolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
.buttoncolor = GET_COLOR(fg, bk) | A_UNDERLINE,
.currshortkeycolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
.shortkeycolor = GET_COLOR(fg, bk) | A_UNDERLINE,
.bottomtitlecolor= GET_COLOR(fg, bk)
};
static struct bsddialog_theme dialogtheme = {
.shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadowrows = 1,
.shadowcols = 2,
.backgroundcolor = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
.surroundtitle = false,
.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_WHITE) | A_BOLD,
.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
.widgetcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.texthmargin = 1,
.curritemcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.itemcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
.currtagcolor = GET_COLOR(COLOR_YELLOW,COLOR_BLUE) | A_BOLD,
.tagcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
.currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
.fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE)| A_BOLD,
.currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.buttonspace = 3,
.buttleftch = '<',
.buttrightchar = '>',
.currbuttdelimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.buttdelimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.currbuttoncolor = GET_COLOR(COLOR_YELLOW, COLOR_BLUE) | A_BOLD,
.buttoncolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.currshortkeycolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.shortkeycolor = GET_COLOR(COLOR_RED, COLOR_WHITE) | A_BOLD,
.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD
};
static struct bsddialog_theme magentatheme = {
.shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
.shadowrows = 1,
.shadowcols = 2,
.backgroundcolor = GET_COLOR(COLOR_WHITE, COLOR_MAGENTA) | A_BOLD,
.surroundtitle = true,
.titlecolor = GET_COLOR(COLOR_RED, COLOR_CYAN),
.lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.widgetcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.texthmargin = 1,
.curritemcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.itemcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD,
.currtagcolor = GET_COLOR(COLOR_YELLOW,COLOR_BLUE) | A_BOLD,
.tagcolor = GET_COLOR(COLOR_BLUE, COLOR_CYAN) | A_BOLD,
.namesepcolor = GET_COLOR(COLOR_RED, COLOR_CYAN) | A_BOLD,
.descsepcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD,
.currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
.fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE)| A_BOLD,
.currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
.buttonspace = 3,
.buttleftch = '<',
.buttrightchar = '>',
.currbuttdelimcolor = GET_COLOR(COLOR_WHITE, COLOR_RED) | A_BOLD,
.buttdelimcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.currbuttoncolor = GET_COLOR(COLOR_WHITE, COLOR_RED),
.buttoncolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.currshortkeycolor = GET_COLOR(COLOR_WHITE, COLOR_RED) | A_BOLD,
.shortkeycolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.bottomtitlecolor= GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD
};
void bsddialog_set_theme(struct bsddialog_theme newtheme)
{
t.shadowcolor = newtheme.shadowcolor;
t.shadowrows = newtheme.shadowrows;
t.shadowcols = newtheme.shadowcols;
t.backgroundcolor = newtheme.backgroundcolor;
t.surroundtitle = newtheme.surroundtitle;
t.titlecolor = newtheme.titlecolor;
t.lineraisecolor = newtheme.lineraisecolor;
t.linelowercolor = newtheme.linelowercolor;
t.widgetcolor = newtheme.widgetcolor;
t.texthmargin = newtheme.texthmargin;
t.curritemcolor = newtheme.curritemcolor;
t.itemcolor = newtheme.itemcolor;
t.currtagcolor = newtheme.currtagcolor;
t.tagcolor = newtheme.tagcolor;
t.namesepcolor = newtheme.namesepcolor;
t.descsepcolor = newtheme.descsepcolor;
t.currfieldcolor = newtheme.currfieldcolor;
t.fieldcolor = newtheme.fieldcolor;
t.fieldreadonlycolor = newtheme.fieldreadonlycolor;
t.currbarcolor = newtheme.currbarcolor;
t.barcolor = newtheme.barcolor;
t.buttonspace = newtheme.buttonspace;
t.buttleftch = newtheme.buttleftch;
t.buttrightchar = newtheme.buttrightchar;
t.currbuttdelimcolor = newtheme.currbuttdelimcolor;
t.buttdelimcolor = newtheme.buttdelimcolor;
t.currbuttoncolor = newtheme.currbuttoncolor;
t.buttoncolor = newtheme.buttoncolor;
t.currshortkeycolor = newtheme.currshortkeycolor;
t.shortkeycolor = newtheme.shortkeycolor;
t.bottomtitlecolor = newtheme.bottomtitlecolor;
bkgd(t.backgroundcolor);
refresh();
}
int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
{
if (newtheme == BSDDIALOG_THEME_DEFAULT)
bsddialog_set_theme(dialogtheme);
else if (newtheme == BSDDIALOG_THEME_BSDDIALOG)
bsddialog_set_theme(bsddialogtheme);
else if (newtheme == BSDDIALOG_THEME_BLACKWHITE)
bsddialog_set_theme(blackwhite);
else if (newtheme == BSDDIALOG_THEME_DIALOG)
bsddialog_set_theme(dialogtheme);
else if (newtheme == BSDDIALOG_THEME_MAGENTA)
bsddialog_set_theme(magentatheme);
else
RETURN_ERROR("Unknow default theme");
return 0;
}
int
bsddialog_color(enum bsddialog_color background, enum bsddialog_color foreground)
{
return GET_COLOR(background, foreground);
}
struct bsddialog_theme bsddialog_get_theme()
{
return t;
}

241
lib/timebox.c Normal file
View File

@ -0,0 +1,241 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 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.
*/
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#include "bsddialog.h"
#include "lib_util.h"
/* "Time": timebox - calendar */
int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int *hh, unsigned int *mm, unsigned int *ss)
{
WINDOW *widget, *shadow;
int i, input, output, y, x, sel;
struct buttons bs;
bool loop, buttupdate;
if (hh == NULL || mm == NULL || ss == NULL)
RETURN_ERROR("hh or mm or ss == NULL");
struct myclockstruct {
unsigned int max;
unsigned int curr;
WINDOW *win;
} c[3] = { {23, *hh, NULL}, {59, *mm, NULL}, {59, *ss, NULL} };
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 7, 3, 4, LOWERED);
mvwaddch(widget, rows - 5, cols/2 - 3, ':');
c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 2, 3, 4, LOWERED);
mvwaddch(widget, rows - 5, cols/2 + 2, ':');
c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 3, 3, 4, LOWERED);
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
sel=0;
curs_set(2);
loop = buttupdate = true;
while(loop) {
if (buttupdate) {
draw_buttons(widget, rows-2, cols, bs, true);
wrefresh(widget);
buttupdate = false;
}
for (i=0; i<3; i++) {
mvwprintw(c[i].win, 1, 1, "%2d", c[i].curr);
wrefresh(c[i].win);
}
wmove(c[sel].win, 1, 2);
wrefresh(c[sel].win);
input = getch();
switch(input) {
case 10: /* Enter */
output = bs.value[bs.curr];
if (output == BSDDIALOG_YESOK) {
*hh = c[0].curr - 1900;
*mm = c[1].curr;
*ss = c[2].curr;
}
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': /* TAB */
sel = (sel + 1) % 3;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
case KEY_UP:
c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 0;
break;
case KEY_DOWN:
c[sel].curr = c[sel].curr > 0 ? c[sel].curr - 1 : c[sel].max;
break;
}
}
curs_set(0);
for (i=0; i<3; i++)
delwin(c[i].win);
end_widget(conf, widget, rows, cols, shadow);
return output;
}
int bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int cols,
unsigned int *yy, unsigned int *mm, unsigned int *dd)
{
WINDOW *widget, *shadow;
int i, input, output, y, x, sel;
struct buttons bs;
bool loop, buttupdate;
if (yy == NULL || mm == NULL || dd == NULL)
RETURN_ERROR("yy or mm or dd == NULL");
struct calendar {
unsigned int max;
unsigned int curr;
WINDOW *win;
unsigned int x;
} c[3] = {{9999, *yy, NULL, 4 }, {12, *mm, NULL, 9 }, {31, *dd, NULL, 2 }};
struct month {
char *name;
unsigned int days;
} m[12] = {
{ "January", 30 }, { "February", 30 }, { "March", 30 },
{ "April", 30 }, { "May", 30 }, { "June", 30 },
{ "July", 30 }, { "August", 30 }, { "September", 30 },
{ "October", 30 }, { "November", 30 }, { "December", 30 }
};
if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
true) <0)
return -1;
c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 12, 3, 6, LOWERED);
mvwaddch(widget, rows - 5, cols/2 - 6, '/');
c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 5, 3, 11, LOWERED);
mvwaddch(widget, rows - 5, cols/2 + 6, '/');
c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 7, 3, 4, LOWERED);
wrefresh(widget);
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
sel=2;
curs_set(2);
loop = buttupdate = true;
while(loop) {
if (buttupdate) {
draw_buttons(widget, rows-2, cols, bs, true);
wrefresh(widget);
buttupdate = false;
}
mvwprintw(c[0].win, 1, 1, "%4d", c[0].curr);
mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].curr-1].name);
mvwprintw(c[2].win, 1, 1, "%2d", c[2].curr);
for (i=0; i<3; i++) {
wrefresh(c[i].win);
}
wmove(c[sel].win, 1, c[sel].x);
wrefresh(c[sel].win);
input = getch();
switch(input) {
case 10: // Enter
output = bs.value[bs.curr]; // values -> outputs
if (output == BSDDIALOG_YESOK) {
*yy = c[0].curr - 1900;
*mm = c[1].curr;
*dd = c[2].curr;
}
loop = false;
break;
case 27: // Esc
output = BSDDIALOG_ESC;
loop = false;
break;
case '\t': // TAB
sel = (sel + 1) % 3;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
case KEY_UP:
c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 1;
break;
case KEY_DOWN:
c[sel].curr = c[sel].curr > 1 ? c[sel].curr - 1 : c[sel].max;
break;
}
}
curs_set(0);
for (i=0; i<3; i++)
delwin(c[i].win);
end_widget(conf, widget, rows, cols, shadow);
return output;
}

View File

@ -0,0 +1,44 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int i, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem items[5] = {
{"", false, 0, "Name 1", "Desc 1", "Bottom Desc 1"},
{"", true, 0, "Name 2", "Desc 2", "Bottom Desc 2"},
{"", false, 0, "Name 3", "Desc 3", "Bottom Desc 3"},
{"", true, 0, "Name 4", "Desc 4", "Bottom Desc 4"},
{"", false, 0, "Name 5", "Desc 5", "Bottom Desc 5"}
};
bsddialog_initconf(&conf);
conf.title = "radiolist";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_buildlist(conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
printf("Buildlist:\n");
for (i=0; i<5; i++)
printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name);
return output;
}

View File

@ -0,0 +1,44 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int i, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem items[5] = {
{"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"},
{"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"},
{"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"},
{"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"},
{"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"}
};
bsddialog_initconf(&conf);
conf.title = "checklist";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_checklist(conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
printf("Checklist:\n");
for (i=0; i<5; i++)
printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name);
return output;
}

10
library_examples/compile Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
libpath=../lib
examples="buildlist menu treeview checklist radiolist mixedlist theme \
infobox yesno msgbox ports"
for e in $examples
do
cc -g -Wall -I$libpath ${e}.c -o $e -L$libpath -lbsddialog -Wl,-rpath=$libpath
done

View File

@ -0,0 +1,32 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int output;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
conf.title = "infobox";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_infobox(conf, "Example", 7, 20);
bsddialog_end();
return output;
}

44
library_examples/menu.c Normal file
View File

@ -0,0 +1,44 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int i, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem items[5] = {
{"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"},
{"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"},
{"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"},
{"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"},
{"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"}
};
bsddialog_initconf(&conf);
conf.title = "menu";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_menu(conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
printf("Menu:\n");
for (i=0; i<5; i++)
printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name);
return output;
}

View File

@ -0,0 +1,71 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
/* Actually this is an example for mixedmenu to reproduce dialog4ports(1) */
int main()
{
int i, j, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem item;
struct bsddialog_menuitem check[5] = {
{ "+", true, 0, "Name 1", "Desc 1", "Bottom Desc 1" },
{ "" , false, 0, "Name 2", "Desc 2", "Bottom Desc 2" },
{ "+", true, 0, "Name 3", "Desc 3", "Bottom Desc 3" },
{ "" , false, 0, "Name 4", "Desc 4", "Bottom Desc 4" },
{ "+", true, 0, "Name 5", "Desc 5", "Bottom Desc 5" }
};
struct bsddialog_menuitem sep[1] = {
{ "", true, 0, "Radiolist", "(desc)", "" }
};
struct bsddialog_menuitem radio[5] = {
{ "", true, 0, "Name 1", "Desc 1", "Bottom Desc 1" },
{ "+", false, 0, "Name 2", "Desc 2", "Bottom Desc 2" },
{ "", false, 0, "Name 3", "Desc 3", "Bottom Desc 3" },
{ "+", false, 0, "Name 4", "Desc 4", "Bottom Desc 4" },
{ "", false, 0, "Name 5", "Desc 5", "Bottom Desc 5" }
};
struct bsddialog_menugroup group[3] = {
{ BSDDIALOG_CHECKLIST, 5, check },
{ BSDDIALOG_SEPARATOR, 1, sep },
{ BSDDIALOG_RADIOLIST, 5, radio }
};
bsddialog_initconf(&conf);
conf.title = "mixedmenu";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_mixedlist(conf, "dialog4ports", 20, 30, 11, 3, group,
NULL,NULL);
bsddialog_end();
printf("Mixedlist (dialog4ports):\n");
for (i=0; i<3; i++) {
for (j=0; j<group[i].nitems; j++) {
item = group[i].items[j];
if (group[i].type == BSDDIALOG_SEPARATOR)
printf("----- %s -----\n", item.name);
else if (group[i].type == BSDDIALOG_RADIOLIST)
printf(" (%c) %s\n", item.on ? '*' : ' ', item.name);
else /* BSDDIALOG_PORTCHECKLIST */
printf(" [%c] %s\n", item.on ? 'X' : ' ', item.name);
}
}
return output;
}

42
library_examples/msgbox.c Normal file
View File

@ -0,0 +1,42 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int input;
struct bsddialog_conf conf;
/* Configuration */
bsddialog_initconf(&conf);
conf.title = "msgbox";
/* Run BSDDialog */
if (bsddialog_init() == BSDDIALOG_ERROR) {
printf("Error: %s\n", bsddialog_geterror());
return -1;
}
input = bsddialog_msgbox(conf, "Example", 7, 20);
bsddialog_end();
/* User Input */
printf("User input: ");
switch (input) {
case BSDDIALOG_ERROR: printf("Error %s\n", bsddialog_geterror()); break;
case BSDDIALOG_YESOK: printf("OK\n"); break;
case BSDDIALOG_ESC: printf("ESC\n"); break;
}
return input;
}

97
library_examples/ports.c Normal file
View File

@ -0,0 +1,97 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
/* Actually this is an example for mixedmenu to reproduce dialog4ports(1) */
int main()
{
int i, j, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem item;
struct bsddialog_menuitem check1[5] = {
{ "+", true, 0, "CSCOPE", "cscope support", "" },
{ "+", true, 0, "DEFAULT_VIMRC", "Install bundled vimrc as default setting", "" },
{ "", false, 0, "MAKE_JOBS", "Enable parallel build", "" },
{ "", true, 0, "NLS", "Native Language Support", "" },
{ "+", false, 0, "XTERM_SAVE", "Restore xterm screen after exit", "" }
};
struct bsddialog_menuitem sep1[1] = {
{ "", true, 0, "Optional language bindings", "", "" }
};
struct bsddialog_menuitem check2[6] = {
{ "", false, 0, "LUA", "Lua scripting language support", "" },
{ "+", true, 0, "PERL", "Perl scripting language support", "" },
{ "", true, 0, "PYTHON", "Python bindings or support", "" },
{ "+", true, 0, "RUBY", "Ruby bindings or support", "" },
{ "", false, 0, "SCHEME", "MzScheme (Racket) bindings", "" },
{ "", false, 0, "TCL", "Tcl scripting language support", "" }
};
struct bsddialog_menuitem sep2[1] = {
{ "", true, 0, "CTAGS", "", "" }
};
struct bsddialog_menuitem radio1[3] = {
{ "+", false, 0, "CTAGS_BASE", "Use system ctags", "" },
{ "", true, 0, "CTAGS_EXUBERANT", "Use exctags instead of ctags", "" },
{ "", false, 0, "CTAGS_UNIVERSAL", "Use uctags instead of ctags", "" }
};
struct bsddialog_menuitem sep3[1] = {
{ "", true, 0, "User interface", "", "" }
};
struct bsddialog_menuitem radio2[7] = {
{ "", false, 0, "ATHENA", "Athena GUI toolkit", "" },
{ "", false, 0, "CONSOLE","Console/terminal mode", "" },
{ "", false, 0, "GNOME", "GNOME desktop environment support", "" },
{ "", false, 0, "GTK2", "GTK+ 2 GUI toolkit support", "" },
{ "", true, 0, "GTK3", "GTK+ 3 GUI toolkit support", "" },
{ "", false, 0, "MOTIF", "Motif widget library support", "" },
{ "", false, 0, "X11", "X11 (graphics) support", "" }
};
struct bsddialog_menugroup group[7] = {
{ BSDDIALOG_CHECKLIST, 5, check1 },
{ BSDDIALOG_SEPARATOR, 1, sep1 },
{ BSDDIALOG_CHECKLIST, 6, check2 },
{ BSDDIALOG_SEPARATOR, 1, sep2 },
{ BSDDIALOG_RADIOLIST, 3, radio1 },
{ BSDDIALOG_SEPARATOR, 1, sep3 },
{ BSDDIALOG_RADIOLIST, 7, radio2 },
};
bsddialog_initconf(&conf);
conf.title = "vim-8.2.2569";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_mixedlist(conf, "", 0, 0, 0, 7, group, NULL,NULL);
bsddialog_end();
printf("Options:\n");
for (i=0; i<7; i++) {
for (j=0; j<group[i].nitems; j++) {
item = group[i].items[j];
if (group[i].type == BSDDIALOG_SEPARATOR)
printf("----- %s -----\n", item.name);
else if (group[i].type == BSDDIALOG_RADIOLIST)
printf(" (%c) %s\n", item.on ? '*' : ' ', item.name);
else /* BSDDIALOG_PORTCHECKLIST */
printf(" [%c] %s\n", item.on ? 'X' : ' ', item.name);
}
}
return output;
}

View File

@ -0,0 +1,44 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int i, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem items[5] = {
{"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"},
{"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"},
{"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"},
{"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"},
{"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"}
};
bsddialog_initconf(&conf);
conf.title = "radiolist";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_radiolist(conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
printf("Radiolist:\n");
for (i=0; i<5; i++)
printf(" (%c) %s\n", items[i].on ? '*' : ' ', items[i].name);
return output;
}

67
library_examples/theme.c Normal file
View File

@ -0,0 +1,67 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
#include <bsddialog_theme.h>
int main()
{
int output;
struct bsddialog_conf conf;
enum bsddialog_default_theme theme;
struct bsddialog_menuitem items[5] = {
{"", false, 0, "Dialog", "Current dialog theme", "BSDDIALOG_THEME_DIALOG" },
{"", false, 0, "BSDDialog", "Future default theme", "BSDDIALOG_THEME_DEFAULT"},
{"", false, 0, "BlackWhite","Black and White theme", "BSDDIALOG_THEME_BLACKWHITE"},
{"", false, 0, "Magenta", "Testing", "BSDDIALOG_THEME_MAGENTA"},
{"", false, 0, "Quit", "Exit", "Quit or Cancel to exit" }
};
bsddialog_initconf(&conf);
conf.title = " Theme ";
if (bsddialog_init() == BSDDIALOG_ERROR)
return BSDDIALOG_ERROR;
while (true) {
bsddialog_backtitle(conf, "Theme Example");
output = bsddialog_menu(conf, "Choose theme", 15, 40, 5, 5, items, NULL);
if (output != BSDDIALOG_YESOK || items[4].on)
break;
if (items[0].on) {
theme = BSDDIALOG_THEME_DIALOG;
conf.menu.default_item = items[0].name;
}
else if (items[1].on) {
theme = BSDDIALOG_THEME_BSDDIALOG;
conf.menu.default_item = items[1].name;
}
else if (items[2].on) {
theme = BSDDIALOG_THEME_BLACKWHITE;
conf.menu.default_item = items[2].name;
}
else if (items[3].on) {
theme = BSDDIALOG_THEME_MAGENTA;
conf.menu.default_item = items[3].name;
}
bsddialog_set_default_theme(theme);
}
bsddialog_end();
return output;
}

View File

@ -0,0 +1,44 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int i, output;
struct bsddialog_conf conf;
struct bsddialog_menuitem items[5] = {
{"", false, 0, "Name 1", "Desc 1", "Bottom Desc 1"},
{"", false, 1, "Name 2", "Desc 2", "Bottom Desc 2"},
{"", false, 1, "Name 3", "Desc 3", "Bottom Desc 3"},
{"", false, 2, "Name 4", "Desc 4", "Bottom Desc 4"},
{"", false, 1, "Name 5", "Desc 5", "Bottom Desc 5"}
};
bsddialog_initconf(&conf);
conf.title = "radiolist";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_treeview(conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
printf("Treeview:\n");
for (i=0; i<5; i++)
printf(" (%c) %s\n", items[i].on ? '*' : ' ', items[i].name);
return output;
}

32
library_examples/yesno.c Normal file
View File

@ -0,0 +1,32 @@
/*-
* SPDX-License-Identifier: CC0-1.0
*
* Written in 2021 by Alfonso Sabato Siciliano.
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty, see:
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdio.h>
#include <string.h>
#include <bsddialog.h>
int main()
{
int output;
struct bsddialog_conf conf;
bsddialog_initconf(&conf);
conf.title = "yesno";
if (bsddialog_init() < 0)
return -1;
output = bsddialog_yesno(conf, "Example", 7, 25);
bsddialog_end();
return output;
}

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,20 @@
#!/bin/sh
input="A B C D E F G"
total=`echo $input | awk '{print split($0, a)}'`
curr=1
for i in $input
do
sleep 1
perc="$(expr $(expr $curr "*" 100 ) "/" $total )"
echo XXX
echo $perc
echo "[$curr/$total] Input: $i"
echo XXX
if [ $curr -eq $total ]
then
echo EOF
fi
curr=`expr $curr + 1`
done | ./bsddialog --title gauge --gauge "[0/$total] Starting..." 10 70 0

View File

@ -0,0 +1,3 @@
#!/bin/sh
./bsddialog --sleep 5 --title infobox --infobox "Hello World!\n5 seconds" 6 20

View File

@ -0,0 +1,41 @@
#!/bin/sh
./bsddialog --title menu --menu "Hello World!" 15 30 5 \
"Tag 1" "DESC 1 xyz" \
"Tag 2" "DESC 2 xyz" \
"Tag 3" "DESC 3 xyz" \
"Tag 4" "DESC 4 xyz" \
"Tag 5" "DESC 5 xyz" \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --title checklist --checklist "Hello World!" 15 30 5 \
"Tag 1" "DESC 1 xyz" on \
"Tag 2" "DESC 2 xyz" off \
"Tag 3" "DESC 3 xyz" on \
"Tag 4" "DESC 4 xyz" off \
"Tag 5" "DESC 5 xyz" on \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --title radiolist --radiolist "Hello World!" 15 30 5 \
"Tag 1" "DESC 1 xyz" off \
"Tag 2" "DESC 2 xyz" off \
"Tag 3" "DESC 3 xyz" on \
"Tag 4" "DESC 4 xyz" off \
"Tag 5" "DESC 5 xyz" off \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --title buildlist --buildlist "Hello World!" 15 40 5 \
"Tag 1" "DESC 1 xyz" off \
"Tag 2" "DESC 2 xyz" off \
"Tag 3" "DESC 3 xyz" on \
"Tag 4" "DESC 4 xyz" off \
"Tag 5" "DESC 5 xyz" off \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --title treeview --treeview "Hello World!" 15 40 5 \
0 "Tag 1" "DESC 1 xyz" off \
1 "Tag 2" "DESC 2 xyz" off \
2 "Tag 3" "DESC 3 xyz" on \
1 "Tag 4" "DESC 4 xyz" off \
1 "Tag 5" "DESC 5 xyz" off \
2>out.txt ; cat out.txt ; rm out.txt

View File

@ -0,0 +1,5 @@
#!/bin/sh
./bsddialog --title msgbox --msgbox "Hello World!" 6 20
./bsddialog --title yesno --yesno "Hello World!" 6 25

View File

@ -0,0 +1,25 @@
#!/bin/sh
./bsddialog --title mixedform --mixedform "Hello World!" 12 40 5 \
Label: 1 1 Entry 1 11 18 25 0 \
Label: 2 1 Read-Only 2 11 18 25 2 \
Password: 3 1 Value2 3 11 18 25 1 \
Password: 4 1 Value4 4 11 18 25 3 \
Label5: 5 1 Value5 5 11 18 25 4 \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --backtitle "BSD-2-Clause Licese" --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 \
2>out.txt ; cat out.txt ; rm out.txt
./bsddialog --title passwordform --passwordform "Hello World!" 12 40 5 \
Password1: 1 1 Value1 1 12 18 25 \
Password2: 2 1 Value2 2 12 18 25 \
Password3: 3 1 Value3 3 12 18 25 \
Password4: 4 1 Value4 4 12 18 25 \
Password5: 5 1 Value5 5 12 18 25 \
2>out.txt ; cat out.txt ; rm out.txt

View File

@ -0,0 +1,24 @@
#!/bin/sh
input="A B C D E F G H"
total=`echo $input | awk '{print split($0, a)}'`
curr=1
for i in $input
do
perc="$(expr $(expr $curr "*" 100 ) "/" $total )"
curr=`expr $curr + 1`
./bsddialog --title " mixedgauge " --mixedgauge "Hello World! Press <ENTER>" 20 35 $perc \
"Hidden!" 8 \
"Label 1" 0 \
"Label 2" 1 \
"Label 3" 2 \
"Label 4" 3 \
"Label 5" 4 \
"Label 6" 5 \
"Label 7" 6 \
"Label 8" 7 \
"Label 9" 9 \
"Label X" -- -$perc
#sleep 1
done