summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlfonso S. Siciliano <asiciliano@FreeBSD.org>2022-09-03 14:36:16 +0000
committerAlfonso S. Siciliano <asiciliano@FreeBSD.org>2022-09-03 14:36:16 +0000
commit2c9fd7655ba54e7239f528e1af9fe09662de9b03 (patch)
treefe1ff8f189880e6177658fee195a574d5ae6ebe7 /lib
parent2f8d4418415511460bd7b3b3e532f6b328cf993f (diff)
Diffstat (limited to 'lib')
-rw-r--r--lib/GNUMakefile6
-rw-r--r--lib/Makefile4
-rw-r--r--lib/barbox.c78
-rw-r--r--lib/bsddialog.3172
-rw-r--r--lib/bsddialog.h20
-rw-r--r--lib/bsddialog_theme.h17
-rw-r--r--lib/formbox.c1135
-rw-r--r--lib/infobox.c6
-rw-r--r--lib/lib_util.c549
-rw-r--r--lib/lib_util.h16
-rw-r--r--lib/libbsddialog.c19
-rw-r--r--lib/menubox.c155
-rw-r--r--lib/messagebox.c63
-rw-r--r--lib/textbox.c117
-rw-r--r--lib/theme.c175
-rw-r--r--lib/timebox.c190
16 files changed, 1801 insertions, 921 deletions
diff --git a/lib/GNUMakefile b/lib/GNUMakefile
index 0d724b803be3..1d55d6edd60d 100644
--- a/lib/GNUMakefile
+++ b/lib/GNUMakefile
@@ -3,16 +3,16 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.2
+VERSION = 0.3
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o)
-CFLAGS = -D_XOPEN_SOURCE_EXTENDED -Wall -Wextra -Wno-implicit-fallthrough \
+CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra -Wno-implicit-fallthrough \
-Werror -fpic
-LDFLAGS = -lformw -lncursesw -ltinfo
+LDFLAGS = -lncursesw -ltinfo
LIBFLAG = -shared
RM = rm -f
diff --git a/lib/Makefile b/lib/Makefile
index 962b059b3e03..5c535c5483f1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -3,7 +3,7 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.2
+VERSION = 0.3
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a}
@@ -14,7 +14,7 @@ OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \
- -L/usr/lib -lformw -lncursesw -ltinfow
+ -L/usr/lib -lncursesw -ltinfow
.if defined(DEBUG)
# `make -DDEBUG`
diff --git a/lib/barbox.c b/lib/barbox.c
index 49aa105c1de3..b6bfe32fc0aa 100644
--- a/lib/barbox.c
+++ b/lib/barbox.c
@@ -70,7 +70,7 @@ draw_bar(WINDOW *win, int y, int x, int barlen, int perc, bool withlabel,
sprintf(labelstr, "%d", label);
else
sprintf(labelstr, "%3d%%", perc);
- stringlen = (int)strlen(labelstr);
+ stringlen = (int)strlen(labelstr); /* number, always 1-byte-ch string */
wmove(win, y, x + barlen/2 - stringlen/2);
for (i = 0; i < stringlen; i++) {
color = (blue_x + 1 <= barlen/2 - stringlen/2 + i ) ?
@@ -109,7 +109,7 @@ bar_checksize(int rows, int cols, struct buttons *bs)
minwidth = 0;
if (bs != NULL) /* gauge has not buttons */
- minwidth = buttons_width(*bs);
+ minwidth = buttons_min_width(*bs);
minwidth = MAX(minwidth, MINBARWIDTH);
minwidth += VBORDERS;
@@ -151,16 +151,14 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
- mainloop = (fd < 0) ? false : true;
-
- if (mainloop) {
+ input = NULL;
+ if (fd >= 0) {
fd2 = dup(fd);
- input = fdopen(fd2, "r");
- if (input == NULL)
+ if ((input = fdopen(fd2, "r")) == NULL)
RETURN_ERROR("Cannot build FILE* from fd");
- } else
- input = NULL;
+ }
+ mainloop = true;
while (mainloop) {
wrefresh(widget);
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4,
@@ -168,6 +166,8 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
draw_borders(conf, bar, 3, w-6, RAISED);
draw_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
wrefresh(bar);
+ if (input == NULL) /* that is fd < 0 */
+ break;
while (true) {
fscanf(input, "%s", inputbuf);
@@ -193,10 +193,11 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
if (strcmp(inputbuf, sep) == 0)
break;
strcpy(pntext, inputbuf);
- pntext += strlen(inputbuf);
+ pntext += strlen(inputbuf); /* end string, no strlen */
pntext[0] = ' ';
pntext++;
}
+ pntext[0] = '\0';
if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
ntext, NULL, false) != 0)
return (BSDDIALOG_ERROR);
@@ -216,7 +217,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int mainperc, unsigned int nminibars, const char **minilabels,
int *minipercs, bool color)
{
- int i, output, miniperc, y, x, h, w, ypad, max_minbarlen;
+ int i, retval, miniperc, y, x, h, w, ypad, max_minbarlen;
int htextpad, htext, wtext;
int colorperc, red, green;
WINDOW *widget, *textpad, *bar, *shadow;
@@ -240,7 +241,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
max_minbarlen = 0;
for (i = 0; i < (int)nminibars; i++)
- max_minbarlen = MAX(max_minbarlen, (int)strlen(minilabels[i]));
+ max_minbarlen = MAX(max_minbarlen, (int)strcols(minilabels[i]));
max_minbarlen += 3 + 16; /* seps + [...] */
max_minbarlen = MAX(max_minbarlen, MINMGBARWIDTH); /* mainbar */
@@ -267,10 +268,10 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
- output = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
+ retval = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
NULL, false);
- if (output == BSDDIALOG_ERROR)
- return (output);
+ if (retval == BSDDIALOG_ERROR)
+ return (retval);
/* mini bars */
for (i = 0; i < (int)nminibars; i++) {
@@ -281,6 +282,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (color && (miniperc >= 0))
wattron(widget, A_BOLD);
mvwaddstr(widget, i+1, 2, minilabels[i]);
+ if (color && (miniperc >= 0))
wattroff(widget, A_BOLD);
/* perc */
if (miniperc < -11)
@@ -338,12 +340,12 @@ bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int mainperc, unsigned int nminibars,
const char **minilabels, int *minipercs)
{
- int output;
+ int retval;
- output = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
minilabels, minipercs, false);
- return (output);
+ return (retval);
}
int
@@ -352,7 +354,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
struct bsddialog_fileminibar *minibar)
{
bool update;
- int perc, output, *minipercs;
+ int perc, retval, *minipercs;
unsigned int i, mainperc, totaltodo;
float readforsec;
const char **minilabels;
@@ -371,7 +373,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
}
refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
- output = BSDDIALOG_OK;
+ retval = BSDDIALOG_OK;
i = 0;
update = true;
time(&told);
@@ -384,9 +386,9 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
time(&tnew);
if (update || tnew > told + refresh) {
- output = do_mixedgauge(conf, text, rows, cols, mainperc,
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc,
nminibar, minilabels, minipercs, true);
- if (output == BSDDIALOG_ERROR)
+ if (retval == BSDDIALOG_ERROR)
return (BSDDIALOG_ERROR);
move(SCREENLINES - 1, 2);
@@ -421,7 +423,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
free(minilabels);
free(minipercs);
- return (output);
+ return (retval);
}
int
@@ -430,7 +432,8 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
{
bool loop, buttupdate, barupdate;
int y, x, h, w;
- int input, currvalue, output, sizebar, bigchange, positions;
+ int currvalue, retval, sizebar, bigchange, positions;
+ wint_t input;
float perc;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@@ -483,17 +486,18 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(bar);
}
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
*value = currvalue;
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -587,7 +591,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -596,7 +600,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}
int
@@ -604,7 +608,8 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int sec)
{
bool loop, buttupdate, barupdate;
- int output, y, x, h, w, input, tout, sizebar;
+ int retval, y, x, h, w, tout, sizebar;
+ wint_t input;
float perc;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@@ -650,11 +655,10 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
buttupdate = false;
}
- input = getch();
- if (input < 0) { /* timeout */
+ if (get_wch(&input) == ERR) { /* timeout */
tout--;
if (tout < 0) {
- output = BSDDIALOG_TIMEOUT;
+ retval = BSDDIALOG_TIMEOUT;
break;
}
else {
@@ -665,12 +669,12 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -731,7 +735,7 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -742,5 +746,5 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
} \ No newline at end of file
diff --git a/lib/bsddialog.3 b/lib/bsddialog.3
index 38500b4da6ca..12db1f039d59 100644
--- a/lib/bsddialog.3
+++ b/lib/bsddialog.3
@@ -22,13 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 9, 2022
+.Dd August 29, 2022
.Dt BSDDIALOG 3
.Os
.Sh NAME
.Nm bsddialog_backtitle ,
.Nm bsddialog_clearterminal ,
.Nm bsddialog_color ,
+.Nm bsddialog_color_attrs ,
.Nm bsddialog_checklist ,
.Nm bsddialog_datebox ,
.Nm bsddialog_end ,
@@ -36,8 +37,10 @@
.Nm bsddialog_gauge ,
.Nm bsddialog_geterror ,
.Nm bsddialog_get_theme ,
+.Nm bsddialog_hascolors ,
.Nm bsddialog_infobox ,
.Nm bsddialog_init ,
+.Nm bsddialog_init_notheme ,
.Nm bsddialog_initconf ,
.Nm bsddialog_menu ,
.Nm bsddialog_mixedgauge ,
@@ -115,6 +118,8 @@
.Ft int
.Fn bsddialog_init "void"
.Ft int
+.Fn bsddialog_init_notheme "void"
+.Ft int
.Fn bsddialog_initconf "struct bsddialog_conf *conf"
.Ft int
.Fo bsddialog_menu
@@ -218,7 +223,16 @@
.Fa "unsigned int flags"
.Fc
.Ft int
+.Fo bsddialog_color_attrs
+.Fa "int color"
+.Fa "enum bsddialog_color *foreground"
+.Fa "enum bsddialog_color *background"
+.Fa "unsigned int *flags"
+.Fc
+.Ft int
.Fn bsddialog_get_theme "struct bsddialog_theme *theme"
+.Ft bool
+.Fn bsddialog_hascolors "void"
.Ft int
.Fn bsddialog_set_default_theme "enum bsddialog_default_theme theme"
.Ft int
@@ -239,6 +253,12 @@ API.
restores the screen like before
.Fn bsddialog_init ,
then it is not possible to use the library functions.
+.Fn bsddialog_init_notheme
+is equivalent to
+.Fn bsddialog_init
+except it does not set the default graphical theme; see
+.Sx Theme
+subsection to set a theme explicitly.
.Pp
.Fn bsddialog_error
returns a string to describe the last error, it should be called after a
@@ -258,10 +278,9 @@ is described later.
.Pp
Each
.Fa char*
-argument has to be a well terminated string, can be empty
-.Pq Dq
-but not
-.Dv NULL .
+argument has to be a well terminated string, it can be a multibyte character
+string depending on current locale, see
+.Xr setlocale 3 .
.Ss Dialogs
The dialogs have common arguments.
.Fa text
@@ -282,6 +301,8 @@ struct bsddialog_conf {
bool ascii_lines;
unsigned int auto_minheight;
unsigned int auto_minwidth;
+ unsigned int auto_topmargin;
+ unsigned int auto_downmargin;
const char *bottomtitle;
bool clear;
int *get_height;
@@ -298,6 +319,7 @@ struct bsddialog_conf {
const char *f1_message;
} key;
struct {
+ unsigned int cols_per_row;
bool highlight;
unsigned int tablen;
} text;
@@ -309,11 +331,13 @@ struct bsddialog_conf {
bool shortcut_buttons;
} menu;
struct {
- bool enable_wchar;
- int securech;
+ char securech;
+ char *securembch;
+ bool value_wchar;
bool value_without_ok;
} form;
struct {
+ bool always_active;
bool without_ok;
const char *ok_label;
bool with_extra;
@@ -343,6 +367,23 @@ minimum width if
.Fa cols
is
.Dv BSDDIALOG_AUTOSIZE .
+.It Fa conf.auto_topmargin
+top margin if
+.Fa rows
+is
+.Dv BSDDIALOG_AUTOSIZE
+or
+.Dv BSDDIALOG_FULLSCREEN ,
+.Fa conf.y
+has to be
+.Dv BSDDIALOG_CENTER .
+.It Fa conf.auto_downmargin
+down margin if
+.Fa rows
+is
+.Dv BSDDIALOG_AUTOSIZE
+or
+.Dv BSDDIALOG_FULLSCREEN .
.It Fa conf.bottomtitle
subtitle at the dialog bottom side.
.It Fa conf.clear
@@ -382,11 +423,16 @@ file to open if F1 is pressed.
message to display if F1 is pressed.
.El
.Pp
-.Fa conf.text.highlight
+.Bl -column -compact
+.It Fa conf.text.cols_per_row
+Try to set the number of columns for a row of
+.Fa text
+with autosizing; default
+.Dv 10 .
+.It Fa conf.text.highlight
enables highlights for
.Fa text ,
properly the following sequences are considered escapes:
-.Bl -column -compact
.It Dq \eZ0
black.
.It Dq \eZ1
@@ -404,7 +450,7 @@ cyan.
.It Dq \eZ7
white.
.It Dq \eZr
-reverse colors between foreground and background.
+reverse foreground and background.
.It Dq \eZR
disable reverse.
.It Dq \eZb
@@ -417,11 +463,22 @@ underline.
disable underline.
.It Dq \eZn
disable each customization.
+.It Fa conf.text.tablen
+tab length for
+.Fa text
+argument and
+.Fn bsddialog_textbox
+function.
.El
-.Fa conf.text.tablen
-tab length.
.Pp
.Bl -column -compact
+.It Fa conf.button.always_active
+buttons always active, avoidind focus switch between buttons and input fields or
+input boxes in
+.Fn bsddialog_form ,
+.Fn bsddialog_datebox
+and
+.Fn bsddialog_timebox .
.It Fa conf.button.without_ok
disable OK button.
.It Fa conf.button.ok_label
@@ -598,8 +655,16 @@ enable shortcut keys on buttons, default on items.
.El
.Pp
.Fn bsddialog_form
-builds a dialog to display a list of items to get strings in input, an item is
-defined like:
+builds a dialog to display an array of
+.Fa items
+of
+.Fa nitems
+elements to get strings in input.
+.Fa formrows
+specifies the graphical height for the box around the items,
+.Dv 0
+for autosizing.
+An item is defined like:
.Pp
.Bd -literal -offset indent -compact
struct bsddialog_formitem {
@@ -621,7 +686,7 @@ struct bsddialog_formitem {
.Ed
.Pp
.Fa label
-describes the request, it is printed at the position
+is a string to describe the request, it is printed at the position
.Fa ylabel
and
.Fa xlabel .
@@ -632,45 +697,43 @@ and
.Fa fieldlen
is its graphical width, while
.Fa maxvalelen
-is the maximum length of the input string,
+is the maximum number of characters of the input string.
.Fa init
-is the default value.
+is the default field value.
If the OK button is pressed
.Fa value
-is the allocated memory with the current field string.
+is the allocated memory with the current field string, its size depends on
+the current locale.
.Fa flags
is an OR value to set the
-.Dv BSDDIALOG_FIELDHIDDEN
+.Dv BSDDIALOG_FIELDHIDDEN ,
+.Dv BSDDIALOG_FIELDREADONLY ,
+.Dv BSDDIALOG_FIELDNOCOLOR ,
+.Dv BSDDIALOG_FIELDCURSOREND ,
+.Dv BSDDIALOG_FIELDEXTEND
and
-.Dv BSDDIALOG_FIELDREADONLY
+.Dv BSDDIALOG_FIELDSINGLEBYTE .
flags for the field.
.Fa bottomdesc
is printed on the bottom side of the screen if the item is focused.
-.Fa items
-is an array of items of
-.Fa nitems
-elements,
-.Fa formrows
-specifies the graphical fixed height for the items list;
-.Fa ylabel
-and
-.Fa yfield
-have to be between 1 and
-.Fa formrows .
.Pp
.Fn bsddialog_form
can be customized by:
.Bl -column -compact
-.It Fa conf.form.enable_wchar
-enables characters greater than 127 in the field,
-.Fa value
-is a pointer to allocated memory for a
-.Em wchar_t
-string.
.It Fa conf.form.securech
-charachter to hide the input
-with
+charachter to hide the input with
.Dv BSDDIALOG_FIELDHIDDEN .
+.It Fa conf.form.securembch
+multibyte charachter to hide the input with
+.Dv BSDDIALOG_FIELDHIDDEN ,
+.Fa conf.form.securech
+is ignored.
+.It Fa conf.form.value_wchar
+the allocated
+.Fa value
+is a
+.Em wchar_t*
+string.
.It Fa conf.form.value_without_ok
allocate memory and set
.Fa value
@@ -747,8 +810,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
- unsigned int h;
- unsigned int w;
+ unsigned int y;
+ unsigned int x;
} shadow;
struct {
int color;
@@ -770,20 +833,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
+ int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
+ int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
- unsigned int hmargin;
- int leftdelim;
- int rightdelim;
+ unsigned int minmargin;
+ unsigned int maxmargin;
+ char leftdelim;
+ char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@@ -825,6 +891,8 @@ specifies OR-flags, possible values:
.Dv BSDDIALOG_REVERSE
and
.Dv BSDDIALOG_UNDERLINE .
+.Fn bsddialog_color_attrs
+gets the properties of a color.
.Pp
.Fn bsddialog_set_theme
sets
@@ -840,6 +908,13 @@ and
.Dv BSDDIALOG_THEME_DIALOG ,
they can be set via
.Fn bsddialog_set_default_theme .
+.Pp
+.Fn bsddialog_hascolors
+returns
+.Dv true
+if the terminal provides colors,
+.Dv false
+otherwise.
.Sh RETURN VALUES
The functions return the value
.Dv BSDDIALOG_ERROR
@@ -975,8 +1050,7 @@ for (i = 0; i < 3; i++) {
.Ed
.Sh SEE ALSO
.Xr bsddialog 1 ,
-.Xr curses 3 ,
-.Xr ncurses 3
+.Xr curses 3
.Sh HISTORY
The
.Nm bsddialog
@@ -985,8 +1059,4 @@ library first appeared in
.Sh AUTHORS
.Nm bsddialog
was written by
-.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com .
-.Sh BUGS
-.Fn bsddialog_form
-does not resize the dialog after a terminal resize and does not provide
-scrolling for items. \ No newline at end of file
+.An Alfonso Sabato Siciliano Aq Mt asiciliano@FreeBSD.org .
diff --git a/lib/bsddialog.h b/lib/bsddialog.h
index 37f9899141c0..6f13da3fa667 100644
--- a/lib/bsddialog.h
+++ b/lib/bsddialog.h
@@ -30,7 +30,7 @@
#include <stdbool.h>
-#define LIBBSDDIALOG_VERSION "0.2"
+#define LIBBSDDIALOG_VERSION "0.3"
/* Exit status */
#define BSDDIALOG_ERROR -1
@@ -64,13 +64,19 @@
#define BSDDIALOG_MG_PENDING -11
/* Form */
-#define BSDDIALOG_FIELDHIDDEN 1U
-#define BSDDIALOG_FIELDREADONLY 2U
+#define BSDDIALOG_FIELDHIDDEN 1U
+#define BSDDIALOG_FIELDREADONLY 2U
+#define BSDDIALOG_FIELDNOCOLOR 4U
+#define BSDDIALOG_FIELDCURSOREND 8U
+#define BSDDIALOG_FIELDEXTEND 16U
+#define BSDDIALOG_FIELDSINGLEBYTE 32U
struct bsddialog_conf {
bool ascii_lines;
unsigned int auto_minheight;
unsigned int auto_minwidth;
+ unsigned int auto_topmargin;
+ unsigned int auto_downmargin;
const char *bottomtitle;
bool clear;
int *get_height;
@@ -87,6 +93,7 @@ struct bsddialog_conf {
const char *f1_message;
} key;
struct {
+ unsigned int cols_per_row;
bool highlight;
unsigned int tablen;
} text;
@@ -98,11 +105,13 @@ struct bsddialog_conf {
bool shortcut_buttons;
} menu;
struct {
- bool enable_wchar;
- int securech;
+ char securech;
+ char *securembch;
+ bool value_wchar;
bool value_without_ok;
} form;
struct {
+ bool always_active;
bool without_ok;
const char *ok_label;
bool with_extra;
@@ -156,6 +165,7 @@ struct bsddialog_formitem {
};
int bsddialog_init(void);
+int bsddialog_init_notheme(void);
int bsddialog_end(void);
int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle);
int bsddialog_initconf(struct bsddialog_conf *conf);
diff --git a/lib/bsddialog_theme.h b/lib/bsddialog_theme.h
index 89381cfe28d5..2f20d7b5a79c 100644
--- a/lib/bsddialog_theme.h
+++ b/lib/bsddialog_theme.h
@@ -39,8 +39,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
- unsigned int h;
- unsigned int w;
+ unsigned int y;
+ unsigned int x;
} shadow;
struct {
int color;
@@ -62,20 +62,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
+ int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
+ int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
- unsigned int hmargin;
- int leftdelim;
- int rightdelim;
+ unsigned int minmargin;
+ unsigned int maxmargin;
+ char leftdelim;
+ char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@@ -106,7 +109,11 @@ enum bsddialog_color {
int
bsddialog_color(enum bsddialog_color foreground,
enum bsddialog_color background, unsigned int flags);
+int
+bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
+ enum bsddialog_color *background, unsigned int *flags);
int bsddialog_get_theme(struct bsddialog_theme *theme);
+bool bsddialog_hascolors(void);
int bsddialog_set_default_theme(enum bsddialog_default_theme theme);
int bsddialog_set_theme(struct bsddialog_theme *theme);
diff --git a/lib/formbox.c b/lib/formbox.c
index 564fa99d69a8..cd29919417be 100644
--- a/lib/formbox.c
+++ b/lib/formbox.c
@@ -27,454 +27,608 @@
#include <sys/param.h>
-#include <ctype.h>
-#include <form.h>
+#include <curses.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
-#define ISFIELDHIDDEN(item) (item.flags & BSDDIALOG_FIELDHIDDEN)
-#define ISFIELDREADONLY(item) (item.flags & BSDDIALOG_FIELDREADONLY)
-#define REDRAWFORM 19860214 /* magic number */
+struct privateitem {
+ const char *label; /* formitem.label */
+ unsigned int ylabel; /* formitem.ylabel */
+ unsigned int xlabel; /* formitem.xlabel */
+ unsigned int yfield; /* formitem.yfield */
+ unsigned int xfield; /* formitem.xfield */
+ bool secure; /* formitem.flags & BSDDIALOG_FIELDHIDDEN */
+ bool readonly; /* formitem.flags & BSDDIALOG_FIELDREADONLY */
+ bool fieldnocolor; /* formitem.flags & BSDDIALOG_FIELDNOCOLOR */
+ bool extendfield; /* formitem.flags & BSDDIALOG_FIELDEXTEND */
+ bool fieldonebyte; /* formitem.flags & BSDDIALOG_FIELDSINGLEBYTE */
+ bool cursorend; /* formitem.flags & BSDDIALOG_FIELDCURSOREND */
+ bool cursor; /* field cursor visibility */
+ const char *bottomdesc; /* formitem.bottomdesc */
-/* field_userptr for private buffer and view options */
-struct myfield {
- int buflen;
- wchar_t *buf;
- int pos;
- int maxpos;
- bool secure;
- int securech;
- const char *bottomdesc;
+ wchar_t *privwbuf; /* formitem.value */
+ wchar_t *pubwbuf; /* string for drawitem() */
+ unsigned int maxletters; /* formitem.maxvaluelen, [priv|pub]wbuf size */
+ unsigned int nletters; /* letters in privwbuf and pubwbuf */
+ unsigned int pos; /* pos in privwbuf and pubwbuf */
+ unsigned int fieldcols; /* formitem.fieldlen */
+ unsigned int xcursor; /* position in fieldcols [0 - fieldcols-1] */
+ unsigned int xposdraw; /* first pubwbuf index to draw */
};
-#define GETMYFIELD(field) ((struct myfield*)field_userptr(field))
-#define GETMYFIELD2(form) ((struct myfield*)field_userptr(current_field(form)))
-static void insertch(struct myfield *mf, int ch)
-{
- int i;
+struct privateform {
+ WINDOW *border;
- if (mf->buflen > mf->maxpos)
- return;
+ WINDOW *pad;
+ unsigned int h; /* only to create pad */
+ unsigned int w; /* only to create pad */
+ unsigned int wmin; /* to refresh, w can change for FIELDEXTEND */
+ unsigned int ys; /* to refresh */
+ unsigned int ye; /* to refresh */
+ unsigned int xs; /* to refresh */
+ unsigned int xe; /* to refresh */
+ unsigned int y; /* changes moving focus around items */
+ unsigned int viewrows; /* visible rows, real formheight */
+ unsigned int minviewrows; /* min viewrows, ylabel != yfield */
- for (i = mf->buflen; i >= mf->pos; i--) {
- mf->buf[i+1] = mf->buf[i];
- }
+ wchar_t securewch; /* wide char of conf.form.secure[mb]ch */
+};
- mf->buf[mf->pos] = ch;
- mf->pos += 1;
- if (mf->pos > mf->maxpos)
- mf->pos = mf->maxpos;
- mf->buflen += 1;
- mf->buf[mf->buflen] = '\0';
-}
+enum operation {
+ MOVE_CURSOR_BEGIN,
+ MOVE_CURSOR_END,
+ MOVE_CURSOR_RIGHT,
+ MOVE_CURSOR_LEFT,
+ DEL_LETTER
+};
-static void shiftleft(struct myfield *mf)
+static bool fieldctl(struct privateitem *item, enum operation op)
{
- int i, last;
+ bool change;
+ int width, oldwidth, nextwidth, cols;
+ unsigned int i;
+
+ change = false;
+ switch (op){
+ case MOVE_CURSOR_BEGIN:
+ if (item->pos == 0 && item->xcursor == 0)
+ break;
+ /* here the cursor is changed */
+ change = true;
+ item->pos = 0;
+ item->xcursor = 0;
+ item->xposdraw = 0;
+ break;
+ case MOVE_CURSOR_END:
+ while (fieldctl(item, MOVE_CURSOR_RIGHT))
+ change = true;
+ break;
+ case MOVE_CURSOR_LEFT:
+ if (item->pos == 0)
+ break;
+ /* check redundant by item->pos == 0 because of 'while' below */
+ if (item->xcursor == 0 && item->xposdraw == 0)
+ break;
+ /* here some letter to left */
+ change = true;
+ item->pos -= 1;
+ width = wcwidth(item->pubwbuf[item->pos]);
+ if (((int)item->xcursor) - width < 0) {
+ item->xcursor = 0;
+ item->xposdraw -= 1;
+ } else
+ item->xcursor -= width;
+
+ while (true) {
+ if (item->xposdraw == 0)
+ break;
+ if (item->xcursor >= item->fieldcols / 2)
+ break;
+ if (wcwidth(item->pubwbuf[item->xposdraw - 1]) +
+ item->xcursor + width > item->fieldcols)
+ break;
- for (i = mf->pos; i < mf->buflen -1; i++) {
- mf->buf[i] = mf->buf[i+1];
+ item->xposdraw -= 1;
+ item->xcursor +=
+ wcwidth(item->pubwbuf[item->xposdraw]);
+ }
+ break;
+ case DEL_LETTER:
+ if (item->nletters == 0)
+ break;
+ if (item->pos == item->nletters)
+ break;
+ /* here a letter under the cursor */
+ change = true;
+ for (i = item->pos; i < item->nletters; i++) {
+ item->privwbuf[i] = item->privwbuf[i+1];
+ item->pubwbuf[i] = item->pubwbuf[i+1];
+ }
+ item->nletters -= 1;
+ item->privwbuf[i] = L'\0';
+ item->pubwbuf[i] = L'\0';
+ break;
+ case MOVE_CURSOR_RIGHT: /* used also by "insert", see handler loop */
+ if (item->pos + 1 == item->maxletters)
+ break;
+ if (item->pos == item->nletters)
+ break;
+ /* here a change to right */
+ change = true;
+ oldwidth = wcwidth(item->pubwbuf[item->pos]);
+ item->pos += 1;
+ if (item->pos == item->nletters) { /* empty column */
+ nextwidth = 1;
+ } else { /* a letter to right */
+ nextwidth = wcwidth(item->pubwbuf[item->pos]);
+ }
+ if (item->xcursor + oldwidth + nextwidth - 1 >= item->fieldcols) {
+ cols = nextwidth;
+ item->xposdraw = item->pos;
+ while (item->xposdraw != 0) {
+ cols += wcwidth(item->pubwbuf[item->xposdraw - 1]);
+ if (cols > (int)item->fieldcols)
+ break;
+ item->xposdraw -= 1;
+ }
+ item->xcursor = 0;
+ for (i = item->xposdraw; i < item->pos ; i++)
+ item->xcursor += wcwidth(item->pubwbuf[i]);
+ }
+ else {
+ item->xcursor += oldwidth;
+ }
+
+ break;
}
- last = mf->buflen > 0 ? mf->buflen -1 : 0;
- mf->buf[last] = '\0';
- mf->buflen = last;
+ return (change);
}
-static void print_bottomdesc(struct myfield *mf)
+static void
+drawitem(struct privateform *form, struct privateitem *item, bool focus)
{
+ int color;
+ unsigned int n, cols;
+
+ /* Label */
+ wattron(form->pad, t.dialog.color);
+ mvwaddstr(form->pad, item->ylabel, item->xlabel, item->label);
+ wattroff(form->pad, t.dialog.color);
+
+ /* Field */
+ if (item->readonly)
+ color = t.form.readonlycolor;
+ else if (item->fieldnocolor)
+ color = t.dialog.color;
+ else
+ color = focus ? t.form.f_fieldcolor : t.form.fieldcolor;
+ wattron(form->pad, color);
+ mvwhline(form->pad, item->yfield, item->xfield, ' ', item->fieldcols);
+ n = 0;
+ cols = wcwidth(item->pubwbuf[item->xposdraw]);
+ while (cols <= item->fieldcols && item->xposdraw + n <
+ wcslen(item->pubwbuf)) {
+ n++;
+ cols += wcwidth(item->pubwbuf[item->xposdraw + n]);
+
+ }
+ mvwaddnwstr(form->pad, item->yfield, item->xfield,
+ &item->pubwbuf[item->xposdraw], n);
+ wattroff(form->pad, color);
+
+ /* Bottom Desc */
move(SCREENLINES - 1, 2);
clrtoeol();
- if (mf->bottomdesc != NULL) {
- addstr(mf->bottomdesc);
+ if (item->bottomdesc != NULL && focus) {
+ attron(t.form.bottomdesccolor);
+ addstr(item->bottomdesc);
+ attroff(t.form.bottomdesccolor);
refresh();
}
+
+ /* Cursor */
+ curs_set((focus && item->cursor) ? 1 : 0);
+ wmove(form->pad, item->yfield, item->xfield + item->xcursor);
+
+ prefresh(form->pad, form->y, 0, form->ys, form->xs, form->ye, form->xe);
}
-static char *w2c(wchar_t *string)
+/*
+ * Trick: draw 2 times an item switching focus.
+ * Problem: curses tries to optimize the rendering but sometimes it misses some
+ * updates or draws old stuff. libformw has a similar problem fixed by the
+ * same trick.
+ * Case 1: KEY_DC and KEY_BACKSPACE, deleted multicolumn letters are drawn
+ * again. It seems fixed by new items pad and prefresh(), previously WINDOW.
+ * Case2: some terminal, tmux and ssh does not show the cursor.
+ */
+#define DRAWITEM_TRICK(form,item,focus) do { \
+ drawitem(form, item, !focus); \
+ drawitem(form, item, focus); \
+} while (0)
+
+static bool
+insertch(struct privateform *form, struct privateitem *item, wchar_t wch)
{
- int i, len;
- char *value;
+ int i;
+
+ if (item->nletters >= item->maxletters)
+ return (false);
- len = wcslen(string);
- if ((value = calloc(len + 1, sizeof(char))) == NULL)
- return NULL;
+ for (i = (int)item->nletters - 1; i >= (int)item->pos; i--) {
+ item->privwbuf[i+1] = item->privwbuf[i];
+ item->pubwbuf[i+1] = item->pubwbuf[i];
+ }
- for (i = 0; i < len; i++)
- value[i] = string[i];
- value[i] = '\0';
+ item->privwbuf[item->pos] = wch;
+ item->pubwbuf[item->pos] = item->secure ? form->securewch : wch;
+ item->nletters += 1;
+ item->privwbuf[item->nletters] = L'\0';
+ item->pubwbuf[item->nletters] = L'\0';
- return value;
+ return (true);
+}
+
+static char* alloc_wstomb(wchar_t *wstr)
+{
+ int len, nbytes, i;
+ char mbch[MB_LEN_MAX], *mbstr;
+
+ nbytes = MB_LEN_MAX; /* to ensure a null terminated string */
+ len = wcslen(wstr);
+ for (i = 0; i < len; i++) {
+ wctomb(mbch, wstr[i]);
+ nbytes += mblen(mbch, MB_LEN_MAX);
+ }
+ if((mbstr = malloc(nbytes)) == NULL)
+ return (NULL);
+
+ wcstombs(mbstr, wstr, nbytes);
+
+ return (mbstr);
}
static int
return_values(struct bsddialog_conf *conf, int output, int nitems,
- struct bsddialog_formitem *items, FORM *form, FIELD **cfield)
+ struct bsddialog_formitem *apiitems, struct privateitem *items)
{
int i;
- struct myfield *mf;
if (output != BSDDIALOG_OK && conf->form.value_without_ok == false)
return (output);
- form_driver_w(form, KEY_CODE_YES, REQ_NEXT_FIELD);
- form_driver_w(form, KEY_CODE_YES, REQ_PREV_FIELD);
for (i = 0; i < nitems; i++) {
- mf = GETMYFIELD(cfield[i]);
- if (conf->form.enable_wchar) {
- items[i].value = (char*)wcsdup(mf->buf);
+ if (conf->form.value_wchar) {
+ apiitems[i].value = (char*)wcsdup(items[i].privwbuf);
} else {
- items[i].value = w2c(mf->buf);
+ apiitems[i].value = alloc_wstomb(items[i].privwbuf);
}
- if (items[i].value == NULL)
+ if (apiitems[i].value == NULL)
RETURN_ERROR("Cannot allocate memory for form value");
}
return (output);
}
-static int
-form_handler(struct bsddialog_conf *conf, WINDOW *widget, struct buttons bs,
- WINDOW *formwin, FORM *form, FIELD **cfield, int nitems,
- struct bsddialog_formitem *items)
+static unsigned int firstitem(unsigned int nitems, struct privateitem *items)
{
- bool loop, buttupdate, informwin;
- int i, chtype, output;
- wint_t input;
- struct myfield *mf;
+ int i;
- mf = GETMYFIELD2(form);
- print_bottomdesc(mf);
- pos_form_cursor(form);
- form_driver_w(form, KEY_CODE_YES, REQ_END_LINE);
- mf->pos = MIN(mf->buflen, mf->maxpos);
- curs_set(1);
- informwin = true;
+ for (i = 0; i < (int)nitems; i++)
+ if (items[i].readonly == false)
+ break;
- bs.curr = -1;
- buttupdate = true;
+ return (i);
+}
- loop = true;
- while (loop) {
- if (buttupdate) {
- draw_buttons(widget, bs, !informwin);
- wrefresh(widget);
- buttupdate = false;
- }
- wrefresh(formwin);
- chtype = get_wch(&input);
- if (chtype != KEY_CODE_YES && input > 127 &&
- conf->form.enable_wchar == false)
- continue;
- switch(input) {
- case KEY_HOME:
- case KEY_PPAGE:
- case KEY_END:
- case KEY_NPAGE:
- /* disabled keys */
- break;
- case KEY_ENTER:
- case 10: /* Enter */
- if (informwin)
- break;
- output = return_values(conf, bs.value[bs.curr], nitems,
- items, form, cfield);
- loop = false;
- break;
- case 27: /* Esc */
- if (conf->key.enable_esc) {
- output = return_values(conf, BSDDIALOG_ESC,
- nitems, items, form, cfield);
- loop = false;
- }
- break;
- case '\t': /* TAB */
- if (informwin) {
- bs.curr = 0;
- informwin = false;
- curs_set(0);
- } else {
- bs.curr++;
- informwin = bs.curr >= (int)bs.nbuttons ?
- true : false;
- if (informwin) {
- curs_set(1);
- pos_form_cursor(form);
- }
- }
- buttupdate = true;
- break;
- case KEY_LEFT:
- if (informwin) {
- form_driver_w(form, KEY_CODE_YES, REQ_PREV_CHAR);
- mf = GETMYFIELD2(form);
- if (mf->pos > 0)
- mf->pos -= 1;
- } else {
- if (bs.curr > 0) {
- bs.curr--;
- buttupdate = true;
- }
- }
- break;
- case KEY_RIGHT:
- if (informwin) {
- mf = GETMYFIELD2(form);
- if (mf->pos >= mf->buflen)
- break;
- mf->pos += 1;
- form_driver_w(form, KEY_CODE_YES, 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.form.fieldcolor);
- set_field_back(current_field(form), t.form.fieldcolor);
- form_driver_w(form, KEY_CODE_YES, REQ_PREV_FIELD);
- form_driver_w(form, KEY_CODE_YES, REQ_END_LINE);
- mf = GETMYFIELD2(form);
- print_bottomdesc(mf);
- mf->pos = MIN(mf->buflen, mf->maxpos);
- set_field_fore(current_field(form), t.form.f_fieldcolor);
- set_field_back(current_field(form), t.form.f_fieldcolor);
- break;
- case KEY_DOWN:
- if (nitems < 2)
- break;
- set_field_fore(current_field(form), t.form.fieldcolor);
- set_field_back(current_field(form), t.form.fieldcolor);
- form_driver_w(form, KEY_CODE_YES, REQ_NEXT_FIELD);
- form_driver_w(form, KEY_CODE_YES, REQ_END_LINE);
- mf = GETMYFIELD2(form);
- print_bottomdesc(mf);
- mf->pos = MIN(mf->buflen, mf->maxpos);
- set_field_fore(current_field(form), t.form.f_fieldcolor);
- set_field_back(current_field(form), t.form.f_fieldcolor);
- break;
- case KEY_BACKSPACE:
- case 127: /* Backspace */
- mf = GETMYFIELD2(form);
- if (mf->pos <= 0)
- break;
- form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV);
- form_driver_w(form, KEY_CODE_YES, REQ_BEG_LINE);
- mf->pos = mf->pos - 1;
- for (i = 0; i < mf->pos; i++)
- form_driver_w(form, KEY_CODE_YES, REQ_NEXT_CHAR);
- shiftleft(mf);
- break;
- case KEY_DC:
- form_driver_w(form, KEY_CODE_YES, REQ_DEL_CHAR);
- mf = GETMYFIELD2(form);
- if (mf->pos < mf->buflen)
- shiftleft(mf);
- break;
- case KEY_F(1):
- if (conf->key.f1_file == NULL &&
- conf->key.f1_message == NULL)
- break;
- if (f1help(conf) != 0)
- return (BSDDIALOG_ERROR);
- /* No Break */
- case KEY_RESIZE:
- output = REDRAWFORM;
- loop = false;
- break;
- default:
- if (informwin) {
- if (chtype == KEY_CODE_YES)
- break;
- mf = GETMYFIELD2(form);
- if (mf->secure)
- form_driver_w(form, chtype, mf->securech);
- else
- form_driver_w(form, chtype, input);
- insertch(mf, input);
- }
- else {
- if (shortcut_buttons(input, &bs)) {
- output = return_values(conf,
- bs.value[bs.curr], nitems, items,
- form, cfield);
- loop = false;
- }
- }
+static unsigned int lastitem(unsigned int nitems, struct privateitem *items)
+{
+ int i;
+
+ for (i = nitems - 1; i >= 0 ; i--)
+ if (items[i].readonly == false)
break;
- }
- }
- curs_set(0);
+ return (i);
+}
- return (output);
+static unsigned int
+previtem(unsigned int nitems, struct privateitem *items, int curritem)
+{
+ int i;
+
+ for (i = curritem - 1; i >= 0; i--)
+ if (items[i].readonly == false)
+ return(i);
+
+ for (i = nitems - 1; i > curritem - 1; i--)
+ if (items[i].readonly == false)
+ return(i);
+
+ return (curritem);
+}
+
+static unsigned int
+nextitem(unsigned int nitems, struct privateitem *items, int curritem)
+{
+ int i;
+
+ for (i = curritem + 1; i < (int)nitems; i++)
+ if (items[i].readonly == false)
+ return(i);
+
+ for (i = 0; i < curritem; i++)
+ if (items[i].readonly == false)
+ return(i);
+
+ return (curritem);
+}
+
+static void
+redrawbuttons(WINDOW *window, struct buttons *bs, bool focus, bool shortcut)
+{
+ int selected;
+
+ selected = bs->curr;
+ if (focus == false)
+ bs->curr = -1;
+ draw_buttons(window, *bs, shortcut);
+ wrefresh(window);
+ bs->curr = selected;
+}
+
+static void
+update_formborders(struct bsddialog_conf *conf, struct privateform *form)
+{
+ int h, w;
+
+ getmaxyx(form->border, h, w);
+ draw_borders(conf, form->border, h, w, LOWERED);
+
+ if (form->viewrows < form->h) {
+ wattron(form->border, t.dialog.arrowcolor);
+ if (form->y > 0)
+ mvwhline(form->border, 0, (w / 2) - 2,
+ conf->ascii_lines ? '^' : ACS_UARROW, 5);
+
+ if (form->y + form->viewrows < form->h)
+ mvwhline(form->border, h-1, (w / 2) - 2,
+ conf->ascii_lines ? 'v' : ACS_DARROW, 5);
+ wattroff(form->border, t.dialog.arrowcolor);
+ wrefresh(form->border);
+ }
}
+/* use menu autosizing, linelen = form.w, nitems = form.h */
static int
-form_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
- const char *text, int linelen, unsigned int *formheight, int nitems,
+menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
+ const char *text, int linelen, unsigned int *menurows, int nitems,
struct buttons bs)
{
- int htext, wtext, menusize;
+ int htext, wtext, menusize, notext;
- if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
- if (text_size(conf, rows, cols, text, &bs, *formheight + 2,
- linelen + 2, &htext, &wtext) != 0)
+ notext = 2;
+ if (*menurows == BSDDIALOG_AUTOSIZE) {
+ /* algo 1): grows vertically */
+ /* notext = 1; */
+ /* algo 2): grows horizontally, better with little screens */
+ notext += nitems;
+ notext = MIN(notext, widget_max_height(conf) - HBORDERS - 3);
+ } else
+ notext += *menurows;
+
+ /* cols autosize, rows autosize, rows fullscreen, menu particularity */
+ if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) {
+ if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4,
+ &htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
}
if (cols == BSDDIALOG_AUTOSIZE)
- *w = widget_min_width(conf, wtext, linelen + 2, &bs);
+ *w = widget_min_width(conf, wtext, linelen + 4, &bs);
if (rows == BSDDIALOG_AUTOSIZE) {
- if (*formheight == 0) {
+ if (*menurows == 0) {
menusize = widget_max_height(conf) - HBORDERS -
2 /*buttons*/ - htext;
menusize = MIN(menusize, nitems + 2);
- *formheight = menusize - 2 < 0 ? 0 : menusize - 2;
+ *menurows = menusize - 2 < 0 ? 0 : menusize - 2;
}
- else /* h autosize with fixed formheight */
- menusize = *formheight + 2;
+ else /* h autosize with fixed menurows */
+ menusize = *menurows + 2;
*h = widget_min_height(conf, htext, menusize, true);
+ /*
+ * avoid menurows overflow and
+ * with rows=AUTOSIZE menurows!=0 becomes max-menurows
+ */
+ *menurows = MIN(*h - 6 - htext, (int)*menurows);
} else {
- if (*formheight == 0)
- *formheight = MIN(rows-6-htext, nitems);
+ if (*menurows == 0) {
+ if (*h - 6 - htext <= 0)
+ *menurows = 0; /* form_checksize() will check */
+ else
+ *menurows = MIN(*h-6-htext, nitems);
+ }
}
return (0);
}
static int
-form_checksize(int rows, int cols, const char *text, int formheight, int nitems,
- unsigned int linelen, struct buttons bs)
+form_checksize(int rows, int cols, const char *text, struct privateform *form,
+ int nitems, struct buttons bs)
{
- int mincols, textrow, formrows;
+ int mincols, textrow, menusize;
+ /* cols */
mincols = VBORDERS;
- /* buttons */
- mincols += buttons_width(bs);
- mincols = MAX(mincols, (int)linelen + 4);
+ mincols += buttons_min_width(bs);
+ mincols = MAX(mincols, (int)form->w + 6);
if (cols < mincols)
- RETURN_ERROR("Few cols, width < size buttons or "
- "forms (label + field)");
-
- textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
+ RETURN_ERROR("Form width, cols < buttons or xlabels/xfields");
- if (nitems > 0 && formheight == 0)
- RETURN_ERROR("fields > 0 but formheight == 0, probably "
+ /* rows */
+ if (nitems > 0 && form->viewrows == 0)
+ RETURN_ERROR("items > 0 but viewrows == 0, if formheight = 0 "
"terminal too small");
- formrows = nitems > 0 ? 3 : 0;
- if (rows < 2 + 2 + formrows + textrow)
- RETURN_ERROR("Few lines for this menus");
+ if (form->viewrows < form->minviewrows)
+ RETURN_ERROR("Few formheight rows, if formheight = 0 terminal "
+ "too small");
+
+ textrow = text != NULL && text[0] != '\0' ? 1 : 0;
+ menusize = nitems > 0 ? 3 : 0;
+ if (rows < 2 + 2 + menusize + textrow)
+ RETURN_ERROR("Few lines for this form");
return (0);
}
+static void curriteminview(struct privateform *form, struct privateitem *item)
+{
+ unsigned int yup, ydown;
+
+ yup = MIN(item->ylabel, item->yfield);
+ ydown = MAX(item->ylabel, item->yfield);
+
+ if (form->y > yup && form->y > 0)
+ form->y = yup;
+ if ((int)(form->y + form->viewrows) - 1 < (int)ydown)
+ form->y = ydown - form->viewrows + 1;
+}
+
+/* API */
int
bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int formheight, unsigned int nitems,
- struct bsddialog_formitem *items)
+ struct bsddialog_formitem *apiitems)
{
- int i, output, color, y, x, h, w;
- unsigned long j, maxline, mybufsize;
+ bool switchfocus, changeitem, focusinform, insecurecursor, loop;
+ int curritem, mbchsize, next, retval, y, x, h, w, wchtype;
+ unsigned int i, j, itemybeg, itemxbeg, tmp;
+ wchar_t *winit;
+ wint_t input;
+ WINDOW *widget, *textpad, *shadow;
+ struct privateitem *items, *item;
struct buttons bs;
- struct myfield *myfields;
- FIELD **cfield;
- FORM *form;
- WINDOW *widget, *formwin, *textpad, *shadow;
-
- /* disable form scrolling */
- if (formheight < nitems)
- formheight = nitems;
+ struct privateform form;
- for (i = 0; i < (int)nitems; i++) {
- if (items[i].maxvaluelen == 0)
+ for (i = 0; i < nitems; i++) {
+ if (apiitems[i].maxvaluelen == 0)
RETURN_ERROR("maxvaluelen cannot be zero");
- if (items[i].fieldlen == 0)
+ if (apiitems[i].fieldlen == 0)
RETURN_ERROR("fieldlen cannot be zero");
- if (items[i].fieldlen > items[i].maxvaluelen)
- RETURN_ERROR("fieldlen cannot be > maxvaluelen");
}
- maxline = 0;
- myfields = malloc(nitems * sizeof(struct myfield));
- cfield = calloc(nitems + 1, sizeof(FIELD*));
- for (i = 0; i < (int)nitems; i++) {
- cfield[i] = new_field(1, items[i].fieldlen, items[i].yfield-1,
- items[i].xfield-1, 0, 0);
- field_opts_off(cfield[i], O_STATIC);
- set_max_field(cfield[i], items[i].maxvaluelen);
- /* setlocale() should handle set_field_buffer() */
- set_field_buffer(cfield[i], 0, items[i].init);
-
- mybufsize = (items[i].maxvaluelen + 1) * sizeof(wchar_t);
- myfields[i].buf = malloc(mybufsize);
- memset(myfields[i].buf, 0, mybufsize);
- for (j = 0; j < items[i].maxvaluelen && j < strlen(items[i].init);
- j++)
- myfields[i].buf[j] = items[i].init[j];
-
- myfields[i].buflen = wcslen(myfields[i].buf);
-
- myfields[i].maxpos = items[i].maxvaluelen -1;
- myfields[i].pos = MIN(myfields[i].buflen, myfields[i].maxpos);
+ insecurecursor = false;
+ if (conf->form.securembch != NULL) {
+ mbchsize = mblen(conf->form.securembch, MB_LEN_MAX);
+ if(mbtowc(&form.securewch, conf->form.securembch, mbchsize) < 0)
+ RETURN_ERROR("Cannot convert securembch to wchar_t");
+ insecurecursor = true;
+ } else if (conf->form.securech != '\0') {
+ form.securewch = btowc(conf->form.securech);
+ insecurecursor = true;
+ } else {
+ form.securewch = L' ';
+ }
- myfields[i].bottomdesc = items[i].bottomdesc;
- set_field_userptr(cfield[i], &myfields[i]);
+ if ((items = malloc(nitems * sizeof(struct privateitem))) == NULL)
+ RETURN_ERROR("Cannot allocate internal items");
+ form.h = form.w = form.minviewrows = 0;
+ for (i = 0; i < nitems; i++) {
+ item = &items[i];
+ item->label = apiitems[i].label;
+ item->ylabel = apiitems[i].ylabel;
+ item->xlabel = apiitems[i].xlabel;
+ item->yfield = apiitems[i].yfield;
+ item->xfield = apiitems[i].xfield;
+ item->secure = apiitems[i].flags & BSDDIALOG_FIELDHIDDEN;
+ item->readonly = apiitems[i].flags & BSDDIALOG_FIELDREADONLY;
+ item->fieldnocolor = apiitems[i].flags & BSDDIALOG_FIELDNOCOLOR;
+ item->extendfield = apiitems[i].flags & BSDDIALOG_FIELDEXTEND;
+ item->fieldonebyte = apiitems[i].flags &
+ BSDDIALOG_FIELDSINGLEBYTE;
+ item->cursorend = apiitems[i].flags & BSDDIALOG_FIELDCURSOREND;
+ item->bottomdesc = apiitems[i].bottomdesc;
+ if (item->readonly || (item->secure && !insecurecursor))
+ item->cursor = false;
+ else
+ item->cursor = true;
- field_opts_off(cfield[i], O_AUTOSKIP);
- field_opts_off(cfield[i], O_BLANK);
+ item->maxletters = apiitems[i].maxvaluelen;
+ item->privwbuf = calloc(item->maxletters + 1, sizeof(wchar_t));
+ if (item->privwbuf == NULL)
+ RETURN_ERROR("Cannot allocate item private buffer");
+ memset(item->privwbuf, 0, item->maxletters + 1);
+ item->pubwbuf = calloc(item->maxletters + 1, sizeof(wchar_t));
+ if (item->pubwbuf == NULL)
+ RETURN_ERROR("Cannot allocate item private buffer");
+ memset(item->pubwbuf, 0, item->maxletters + 1);
- if (ISFIELDHIDDEN(items[i])) {
- myfields[i].secure = true;
- myfields[i].securech = ' ';
- if (conf->form.securech != '\0')
- myfields[i].securech = conf->form.securech;
+ if ((winit = alloc_mbstows(apiitems[i].init)) == NULL)
+ RETURN_ERROR("Cannot allocate item.init in wchar_t*");
+ wcsncpy(item->privwbuf, winit, item->maxletters);
+ wcsncpy(item->pubwbuf, winit, item->maxletters);
+ free(winit);
+ item->nletters = wcslen(item->pubwbuf);
+ if (item->secure) {
+ for (j = 0; j < item->nletters; j++)
+ item->pubwbuf[j] = form.securewch;
}
- else
- myfields[i].secure = false;
- if (ISFIELDREADONLY(items[i])) {
- field_opts_off(cfield[i], O_EDIT);
- field_opts_off(cfield[i], O_ACTIVE);
- color = t.form.readonlycolor;
+ item->fieldcols = apiitems[i].fieldlen;
+ item->xposdraw = 0;
+ item->xcursor = 0;
+ item->pos = 0;
+
+ form.h = MAX(form.h, items[i].ylabel);
+ form.h = MAX(form.h, items[i].yfield);
+ form.w = MAX(form.w, items[i].xlabel + strcols(items[i].label));
+ form.w = MAX(form.w, items[i].xfield + items[i].fieldcols);
+ if (i == 0) {
+ itemybeg = MIN(items[i].ylabel, items[i].yfield);
+ itemxbeg = MIN(items[i].xlabel, items[i].xfield);
} else {
- color = i == 0 ? t.form.f_fieldcolor : t.form.fieldcolor;
+ tmp = MIN(items[i].ylabel, items[i].yfield);
+ itemybeg = MIN(itemybeg, tmp);
+ tmp = MIN(items[i].xlabel, items[i].xfield);
+ itemxbeg = MIN(itemxbeg, tmp);
}
- set_field_fore(cfield[i], color);
- set_field_back(cfield[i], color);
-
- maxline = MAX(maxline, items[i].xlabel + strlen(items[i].label));
- maxline = MAX(maxline, items[i].xfield + items[i].fieldlen - 1);
+ tmp = abs((int)items[i].ylabel - (int)items[i].yfield);
+ form.minviewrows = MAX(form.minviewrows, tmp);
}
- cfield[i] = NULL;
-
- /* disable focus with 1 item (inputbox or passwordbox) */
- if (formheight == 1 && nitems == 1 && strlen(items[0].label) == 0 &&
- items[0].xfield == 1 ) {
- set_field_fore(cfield[0], t.dialog.color);
- set_field_back(cfield[0], t.dialog.color);
+ if (nitems > 0) {
+ form.h = form.h + 1 - itemybeg;
+ form.w -= itemxbeg;
+ form.minviewrows += 1;
+ }
+ form.wmin = form.w;
+ for (i = 0; i < nitems; i++) {
+ items[i].ylabel -= itemybeg;
+ items[i].yfield -= itemybeg;
+ items[i].xlabel -= itemxbeg;
+ items[i].xfield -= itemxbeg;
}
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
+ form.viewrows = formheight;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
- if (form_autosize(conf, rows, cols, &h, &w, text, maxline, &formheight,
- nitems, bs) != 0)
+ if (menu_autosize(conf, rows, cols, &h, &w, text, form.w,
+ &form.viewrows, form.h, bs) != 0)
return (BSDDIALOG_ERROR);
- if (form_checksize(h, w, text, formheight, nitems, maxline, bs) != 0)
+ if (form_checksize(h, w, text, &form, nitems, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
@@ -483,55 +637,308 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
true) != 0)
return (BSDDIALOG_ERROR);
+ doupdate();
+
prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN,
- y + h - formheight, x + 1 + w - TEXTHMARGIN);
+ y + h - form.viewrows, x + 1 + w - TEXTHMARGIN);
- formwin = new_boxed_window(conf, y + h - 3 - formheight -2, x +1,
- formheight+2, w-2, LOWERED);
+ form.border = new_boxed_window(conf, y + h - 5 - form.viewrows, x + 2,
+ form.viewrows + 2, w - 4, LOWERED);
- form = new_form(cfield);
- set_form_win(form, formwin);
- /* should be formheight */
- set_form_sub(form, derwin(formwin, nitems, w-4, 1, 1));
- post_form(form);
+ for (i = 0; i < nitems; i++) {
+ if (items[i].extendfield) {
+ form.w = w - 6;
+ items[i].fieldcols = form.w - items[i].xfield;
+ }
+ if (items[i].cursorend)
+ fieldctl(item, MOVE_CURSOR_END);
+ }
- for (i = 0; i < (int)nitems; i++)
- mvwaddstr(formwin, items[i].ylabel, items[i].xlabel,
- items[i].label);
+ form.pad = newpad(form.h, form.w);
+ wbkgd(form.pad, t.dialog.color);
- wrefresh(formwin);
+ form.ys = y + h - 5 - form.viewrows + 1;
+ form.ye = y + h - 5 ;
+ if ((int)form.w >= w - 6) { /* left */
+ form.xs = x + 3;
+ form.xe = form.xs + w - 7;
+ } else { /* center */
+ form.xs = x + 3 + (w-6)/2 - form.w/2;
+ form.xe = form.xs + w - 5;
+ }
+
+ curritem = -1;
+ for (i=0 ; i < nitems; i++) {
+ DRAWITEM_TRICK(&form, &items[i], false);
+ if (curritem == -1 && items[i].readonly == false)
+ curritem = i;
+ }
+ if (curritem != -1) {
+ focusinform = true;
+ redrawbuttons(widget, &bs, conf->button.always_active, false);
+ form.y = 0;
+ item = &items[curritem];
+ curriteminview(&form, item);
+ update_formborders(conf, &form);
+ wrefresh(form.border);
+ DRAWITEM_TRICK(&form, item, true);
+ } else {
+ item = NULL;
+ focusinform = false;
+ wrefresh(form.border);
+ }
+
+ changeitem = switchfocus = false;
+ loop = true;
+ while (loop) {
+ if ((wchtype = get_wch(&input)) == ERR)
+ continue;
+ switch(input) {
+ case KEY_ENTER:
+ case 10: /* Enter */
+ if (focusinform && conf->button.always_active == false)
+ break;
+ retval = return_values(conf, bs.value[bs.curr],
+ nitems, apiitems, items);
+ loop = false;
+ break;
+ case 27: /* Esc */
+ if (conf->key.enable_esc) {
+ retval = return_values(conf, BSDDIALOG_ESC,
+ nitems, apiitems, items);
+ loop = false;
+ }
+ break;
+ case '\t': /* TAB */
+ if (focusinform) {
+ switchfocus = true;
+ } else {
+ if (bs.curr + 1 < (int)bs.nbuttons) {
+ bs.curr++;
+ } else {
+ bs.curr = 0;
+ if (curritem != -1) {
+ switchfocus = true;
+ }
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ }
+ break;
+ case KEY_LEFT:
+ if (focusinform) {
+ if(fieldctl(item, MOVE_CURSOR_LEFT))
+ DRAWITEM_TRICK(&form, item, true);
+ } else if (bs.curr > 0) {
+ bs.curr--;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else if (curritem != -1) {
+ switchfocus = true;
+ }
+ break;
+ case KEY_RIGHT:
+ if (focusinform) {
+ if(fieldctl(item, MOVE_CURSOR_RIGHT))
+ DRAWITEM_TRICK(&form, item, true);
+ } else if (bs.curr < (int) bs.nbuttons - 1) {
+ bs.curr++;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else if (curritem != -1) {
+ switchfocus = true;
+ }
+ break;
+ case KEY_UP:
+ if (focusinform) {
+ next = previtem(nitems, items, curritem);
+ changeitem = curritem != next;
+ } else if (curritem != -1) {
+ switchfocus = true;
+ }
+ break;
+ case KEY_DOWN:
+ if (focusinform == false)
+ break;
+ if (nitems == 1) {
+ switchfocus = true;
+ } else {
+ next = nextitem(nitems, items, curritem);
+ changeitem = curritem != next;
+ }
+ break;
+ case KEY_PPAGE:
+ if (focusinform) {
+ next = firstitem(nitems, items);
+ changeitem = curritem != next;
+ }
+ break;
+ case KEY_NPAGE:
+ if (focusinform) {
+ next = lastitem(nitems, items);
+ changeitem = curritem != next;
+ }
+ break;
+ case KEY_BACKSPACE:
+ case 127: /* Backspace */
+ if (focusinform == false)
+ break;
+ if(fieldctl(item, MOVE_CURSOR_LEFT))
+ if(fieldctl(item, DEL_LETTER))
+ DRAWITEM_TRICK(&form, item, true);
+ break;
+ case KEY_DC:
+ if (focusinform == false)
+ break;
+ if(fieldctl(item, DEL_LETTER))
+ DRAWITEM_TRICK(&form, item, true);
+ break;
+ case KEY_HOME:
+ if (focusinform == false)
+ break;
+ if(fieldctl(item, MOVE_CURSOR_BEGIN))
+ DRAWITEM_TRICK(&form, item, true);
+ break;
+ case KEY_END:
+ if (focusinform == false)
+ break;
+ if (fieldctl(item, MOVE_CURSOR_END))
+ DRAWITEM_TRICK(&form, item, true);
+ break;
+ case KEY_F(1):
+ if (conf->key.f1_file == NULL &&
+ conf->key.f1_message == NULL)
+ break;
+ curs_set(0);
+ if (f1help(conf) != 0) {
+ retval = BSDDIALOG_ERROR;
+ loop = false;
+ }
+ /* No break, screen size can change */
+ case KEY_RESIZE:
+ /* Important for decreasing screen */
+ hide_widget(y, x, h, w, conf->shadow);
+ refresh();
- do {
- output = form_handler(conf, widget, bs, formwin, form, cfield,
- nitems, items);
+ form.viewrows = formheight;
+ form.w = form.wmin;
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return (BSDDIALOG_ERROR);
+ if (menu_autosize(conf, rows, cols, &h, &w, text, form.w,
+ &form.viewrows, form.h, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (form_checksize(h, w, text, &form, nitems, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return (BSDDIALOG_ERROR);
- if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
- text, &bs, true) != 0)
+ if (update_dialog(conf, shadow, widget, y, x, h, w,
+ textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
- doupdate();
- wrefresh(widget);
+ doupdate();
- prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN,
- y + h - formheight, x + 1 + w - TEXTHMARGIN);
+ prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN,
+ y + h - form.viewrows, x + 1 + w - TEXTHMARGIN);
- draw_borders(conf, formwin, formheight+2, w-2, LOWERED);
- wrefresh(formwin);
+ wclear(form.border);
+ mvwin(form.border, y + h - 5 - form.viewrows, x + 2);
+ wresize(form.border, form.viewrows + 2, w - 4);
- refresh();
- } while (output == REDRAWFORM);
+ for (i = 0; i < nitems; i++) {
+ fieldctl(&items[i], MOVE_CURSOR_BEGIN);
+ if (items[i].extendfield) {
+ form.w = w - 6;
+ items[i].fieldcols =
+ form.w - items[i].xfield;
+ }
+ if (items[i].cursorend)
+ fieldctl(&items[i], MOVE_CURSOR_END);
+ }
- unpost_form(form);
- free_form(form);
- for (i = 0; i < (int)nitems; i++) {
- free_field(cfield[i]);
- free(myfields[i].buf);
- }
- free(cfield);
- free(myfields);
+ form.ys = y + h - 5 - form.viewrows + 1;
+ form.ye = y + h - 5 ;
+ if ((int)form.w >= w - 6) { /* left */
+ form.xs = x + 3;
+ form.xe = form.xs + w - 7;
+ } else { /* center */
+ form.xs = x + 3 + (w-6)/2 - form.w/2;
+ form.xe = form.xs + w - 5;
+ }
+
+ if (curritem != -1) {
+ redrawbuttons(widget, &bs,
+ conf->button.always_active || !focusinform,
+ !focusinform);
+ curriteminview(&form, item);
+ update_formborders(conf, &form);
+ wrefresh(form.border);
+ /* drawitem just to prefresh() pad */
+ DRAWITEM_TRICK(&form, item, focusinform);
+ } else {
+ wrefresh(form.border);
+ }
+ break;
+ default:
+ if (wchtype == KEY_CODE_YES)
+ break;
+ if (focusinform) {
+ if (item->fieldonebyte && wctob(input) == EOF)
+ break;
+ /*
+ * MOVE_CURSOR_RIGHT manages new positions
+ * because the cursor remains on the new letter,
+ * "if" and "while" update the positions.
+ */
+ if(insertch(&form, item, input)) {
+ fieldctl(item, MOVE_CURSOR_RIGHT);
+ /*
+ * no if(fieldctl), update always
+ * because it fails with maxletters.
+ */
+ DRAWITEM_TRICK(&form, item, true);
+ }
+ } else {
+ if (shortcut_buttons(input, &bs)) {
+ retval = return_values(conf,
+ bs.value[bs.curr], nitems, apiitems,
+ items);
+ loop = false;
+ }
+ }
+ break;
+ } /* end switch handler */
- delwin(formwin);
+ if (switchfocus) {
+ focusinform = !focusinform;
+ bs.curr = 0;
+ redrawbuttons(widget, &bs,
+ conf->button.always_active || !focusinform,
+ !focusinform);
+ DRAWITEM_TRICK(&form, item, focusinform);
+ switchfocus = false;
+ }
+
+ if (changeitem) {
+ DRAWITEM_TRICK(&form, item, false);
+ curritem = next;
+ item = &items[curritem];
+ curriteminview(&form, item);
+ update_formborders(conf, &form);
+ DRAWITEM_TRICK(&form, item, true);
+ changeitem = false;
+ }
+ } /* end while handler */
+
+ curs_set(0);
+
+ delwin(form.pad);
+ delwin(form.border);
+ for (i = 0; i < nitems; i++) {
+ free(items[i].privwbuf);
+ free(items[i].pubwbuf);
+ }
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}
diff --git a/lib/infobox.c b/lib/infobox.c
index 5a6b7c2fd692..c8a0b6e90c8e 100644
--- a/lib/infobox.c
+++ b/lib/infobox.c
@@ -39,13 +39,13 @@ infobox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int htext, wtext;
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
- if (text_size(conf, rows, cols, text, NULL, 0, SCREENCOLS/2,
- &htext, &wtext) != 0)
+ if (text_size(conf, rows, cols, text, NULL, 0, 1, &htext,
+ &wtext) != 0)
return (BSDDIALOG_ERROR);
}
if (cols == BSDDIALOG_AUTOSIZE)
- *w = widget_min_width(conf, wtext, 0, NULL);
+ *w = widget_min_width(conf, wtext, TEXTHMARGINS + 1, NULL);
if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, 0, false);
diff --git a/lib/lib_util.c b/lib/lib_util.c
index 4c2ab76bc592..fcdf4c3d8769 100644
--- a/lib/lib_util.c
+++ b/lib/lib_util.c
@@ -32,13 +32,14 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
-#define TABLEN 4 /* Default tab len */
-#define ERRBUFLEN 1024 /* Error buffer */
+#define ERRBUFLEN 1024 /* Error buffer len */
/* Error */
static char errorbuffer[ERRBUFLEN];
@@ -53,12 +54,101 @@ void set_error_string(const char *str)
strncpy(errorbuffer, str, ERRBUFLEN-1);
}
+/* Unicode */
+wchar_t* alloc_mbstows(const char *mbstring)
+{
+ size_t charlen, nchar;
+ mbstate_t mbs;
+ const char *pmbstring;
+ wchar_t *wstring;
+
+ nchar = 1;
+ pmbstring = mbstring;
+ memset(&mbs, 0, sizeof(mbs));
+ while ((charlen = mbrlen(pmbstring, MB_CUR_MAX, &mbs)) != 0 &&
+ charlen != (size_t)-1 && charlen != (size_t)-2) {
+ pmbstring += charlen;
+ nchar++;
+ }
+
+ if ((wstring = calloc(nchar, sizeof(wchar_t))) == NULL)
+ return (NULL);
+ mbstowcs(wstring, mbstring, nchar);
+
+ return (wstring);
+}
+
+void mvwaddwch(WINDOW *w, int y, int x, wchar_t wch)
+{
+ wchar_t ws[2];
+
+ ws[0] = wch;
+ ws[1] = L'\0';
+ mvwaddwstr(w, y, x, ws);
+
+}
+
+int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col)
+{
+ bool multicol;
+ int w;
+ unsigned int ncol;
+ size_t charlen, mb_cur_max;
+ wchar_t wch;
+ mbstate_t mbs;
+
+ multicol = false;
+ mb_cur_max = MB_CUR_MAX;
+ ncol = 0;
+ memset(&mbs, 0, sizeof(mbs));
+ while ((charlen = mbrlen(mbstring, mb_cur_max, &mbs)) != 0 &&
+ charlen != (size_t)-1 && charlen != (size_t)-2) {
+ if (mbtowc(&wch, mbstring, mb_cur_max) < 0)
+ return (-1);
+ w = (wch == L'\t') ? TABSIZE : wcwidth(wch);
+ ncol += (w < 0) ? 0 : w;
+ if (w > 1 && wch != L'\t')
+ multicol = true;
+ mbstring += charlen;
+ }
+
+ if (cols != NULL)
+ *cols = ncol;
+ if (has_multi_col != NULL)
+ *has_multi_col = multicol;
+
+ return (0);
+}
+
+unsigned int strcols(const char *mbstring)
+{
+ int w;
+ unsigned int ncol;
+ size_t charlen, mb_cur_max;
+ wchar_t wch;
+ mbstate_t mbs;
+
+ mb_cur_max = MB_CUR_MAX;
+ ncol = 0;
+ memset(&mbs, 0, sizeof(mbs));
+ while ((charlen = mbrlen(mbstring, mb_cur_max, &mbs)) != 0 &&
+ charlen != (size_t)-1 && charlen != (size_t)-2) {
+ if (mbtowc(&wch, mbstring, mb_cur_max) < 0)
+ return (0);
+ w = (wch == L'\t') ? TABSIZE : wcwidth(wch);
+ ncol += (w < 0) ? 0 : w;
+ mbstring += charlen;
+ }
+
+ return (ncol);
+}
+
/* Clear */
int hide_widget(int y, int x, int h, int w, bool withshadow)
{
WINDOW *clear;
- if ((clear = newwin(h, w, y + t.shadow.h, x + t.shadow.w)) == NULL)
+ if ((clear = newwin(h, w, y + t.shadow.y, x + t.shadow.x)) == NULL)
RETURN_ERROR("Cannot hide the widget");
wbkgd(clear, t.screen.color);
@@ -101,7 +191,7 @@ int f1help(struct bsddialog_conf *conf)
/* Buttons */
static void
draw_button(WINDOW *window, int y, int x, int size, const char *text,
- bool selected, bool shortcut)
+ wchar_t first, bool selected, bool shortcut)
{
int i, color_arrows, color_shortkey, color_button;
@@ -126,14 +216,14 @@ draw_button(WINDOW *window, int y, int x, int size, const char *text,
mvwaddch(window, y, x + i, t.button.rightdelim);
wattroff(window, color_arrows);
- x = x + 1 + ((size - 2 - strlen(text))/2);
+ x = x + 1 + ((size - 2 - strcols(text))/2);
wattron(window, color_button);
mvwaddstr(window, y, x, text);
wattroff(window, color_button);
if (shortcut) {
wattron(window, color_shortkey);
- mvwaddch(window, y, x, text[0]);
+ mvwaddwch(window, y, x, first);
wattroff(window, color_shortkey);
}
}
@@ -142,16 +232,28 @@ void
draw_buttons(WINDOW *window, struct buttons bs, bool shortcut)
{
int i, x, startx, y, rows, cols;
+ unsigned int newmargin, margin, wbuttons;
getmaxyx(window, rows, cols);
y = rows - 2;
- startx = cols/2 - buttons_width(bs)/2;
+ newmargin = cols - VBORDERS - (bs.nbuttons * bs.sizebutton);
+ newmargin /= (bs.nbuttons + 1);
+ newmargin = MIN(newmargin, t.button.maxmargin);
+ if (newmargin == 0) {
+ margin = t.button.minmargin;
+ wbuttons = buttons_min_width(bs);
+ } else {
+ margin = newmargin;
+ wbuttons = bs.nbuttons * bs.sizebutton;
+ wbuttons += (bs.nbuttons + 1) * margin;
+ }
+ startx = (cols)/2 - wbuttons/2 + newmargin;
for (i = 0; i < (int)bs.nbuttons; i++) {
- x = i * (bs.sizebutton + t.button.hmargin);
+ x = i * (bs.sizebutton + margin);
draw_button(window, y, startx + x, bs.sizebutton, bs.label[i],
- i == bs.curr, shortcut);
+ bs.first[i], i == bs.curr, shortcut);
}
}
@@ -163,6 +265,7 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
#define SIZEBUTTON 8
#define DEFAULT_BUTTON_LABEL BUTTON_OK_LABEL
#define DEFAULT_BUTTON_VALUE BSDDIALOG_OK
+ wchar_t first;
bs->nbuttons = 0;
bs->curr = 0;
@@ -216,6 +319,11 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
bs->nbuttons = 1;
}
+ for (i = 0; i < (int)bs->nbuttons; i++) {
+ mbtowc(&first, bs->label[i], MB_CUR_MAX);
+ bs->first[i] = first;
+ }
+
if (conf->button.default_label != NULL) {
for (i = 0; i < (int)bs->nbuttons; i++) {
if (strcmp(conf->button.default_label,
@@ -224,31 +332,31 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
}
}
- bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0]));
+ bs->sizebutton = MAX(SIZEBUTTON - 2, strcols(bs->label[0]));
for (i = 1; i < (int)bs->nbuttons; i++)
- bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i]));
+ bs->sizebutton = MAX(bs->sizebutton, strcols(bs->label[i]));
bs->sizebutton += 2;
}
-int buttons_width(struct buttons bs)
+int buttons_min_width(struct buttons bs)
{
unsigned int width;
width = bs.nbuttons * bs.sizebutton;
if (bs.nbuttons > 0)
- width += (bs.nbuttons - 1) * t.button.hmargin;
+ width += (bs.nbuttons - 1) * t.button.minmargin;
return (width);
}
-bool shortcut_buttons(int key, struct buttons *bs)
+bool shortcut_buttons(wint_t key, struct buttons *bs)
{
bool match;
unsigned int i;
match = false;
for (i = 0; i < bs->nbuttons; i++) {
- if (tolower(key) == tolower(bs->label[i][0])) {
+ if (towlower(key) == towlower(bs->first[i])) {
bs->curr = i;
match = true;
break;
@@ -259,48 +367,51 @@ bool shortcut_buttons(int key, struct buttons *bs)
}
/* Text */
-static bool is_text_attr(const char *text)
+static bool is_wtext_attr(const wchar_t *wtext)
{
- if (strnlen(text, 3) < 3)
+ if (wcsnlen(wtext, 3) < 3)
return (false);
- if (text[0] != '\\' || text[1] != 'Z')
+ if (wtext[0] != L'\\' || wtext[1] != L'Z')
return (false);
- return (strchr("nbBrRuU01234567", text[2]) == NULL ? false : true);
+ return (wcschr(L"nbBrRuU01234567", wtext[2]) == NULL ? false : true);
}
-static bool check_set_text_attr(WINDOW *win, char *text)
+static bool check_set_wtext_attr(WINDOW *win, wchar_t *wtext)
{
- if (is_text_attr(text) == false)
+ enum bsddialog_color bg;
+
+ if (is_wtext_attr(wtext) == false)
return (false);
- if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) {
- wattron(win, bsddialog_color(text[2] - '0', COLOR_WHITE, 0));
+ if ((wtext[2] - L'0') >= 0 && (wtext[2] - L'0') < 8) {
+ bsddialog_color_attrs(t.dialog.color, NULL, &bg, NULL);
+ wattron(win, bsddialog_color(wtext[2] - L'0', bg, 0));
return (true);
}
- switch (text[2]) {
- case 'n':
+ switch (wtext[2]) {
+ case L'n':
wattron(win, t.dialog.color);
wattrset(win, A_NORMAL);
break;
- case 'b':
+ case L'b':
wattron(win, A_BOLD);
break;
- case 'B':
+ case L'B':
wattroff(win, A_BOLD);
break;
- case 'r':
+ case L'r':
wattron(win, A_REVERSE);
break;
- case 'R':
+ case L'R':
wattroff(win, A_REVERSE);
break;
- case 'u':
+ case L'u':
wattron(win, A_UNDERLINE);
break;
- case 'U':
+ case L'U':
wattroff(win, A_UNDERLINE);
break;
}
@@ -308,21 +419,27 @@ static bool check_set_text_attr(WINDOW *win, char *text)
return (true);
}
+/* Word Wrapping */
static void
-print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str,
+print_string(WINDOW *win, int *rows, int cols, int *y, int *x, wchar_t *str,
bool color)
{
- int i, j, len, reallen;
+ int i, j, len, reallen, wc;
+ wchar_t ws[2];
- len = reallen = strlen(str);
+ ws[1] = L'\0';
+
+ len = wcslen(str);
if (color) {
+ reallen = 0;
i=0;
while (i < len) {
- if (is_text_attr(str+i))
- reallen -= 3;
+ if (is_wtext_attr(str+i) == false)
+ reallen += wcwidth(str[i]);
i++;
}
- }
+ } else
+ reallen = wcswidth(str, len);
i = 0;
while (i < len) {
@@ -336,13 +453,18 @@ print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str,
}
j = *x;
while (j < cols && i < len) {
- if (color && check_set_text_attr(win, str+i)) {
+ if (color && check_set_wtext_attr(win, str+i)) {
i += 3;
+ } else if (j + wcwidth(str[i]) > cols) {
+ break;
} else {
- mvwaddch(win, *y, j, str[i]);
+ /* inline mvwaddwch() for efficiency */
+ ws[0] = str[i];
+ mvwaddwstr(win, *y, j, ws);
+ wc = wcwidth(str[i]);;
+ reallen -= wc;
+ j += wc;
i++;
- reallen--;
- j++;
*x = j;
}
}
@@ -354,35 +476,38 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
{
bool loop;
int i, j, z, rows, cols, x, y, tablen;
- char *string;
+ wchar_t *wtext, *string;
+
+ if ((wtext = alloc_mbstows(text)) == NULL)
+ RETURN_ERROR("Cannot allocate/print text in wchar_t*");
- if ((string = malloc(strlen(text) + 1)) == NULL)
+ if ((string = calloc(wcslen(wtext) + 1, sizeof(wchar_t))) == NULL)
RETURN_ERROR("Cannot build (analyze) text");
getmaxyx(pad, rows, cols);
- tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen;
+ tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
i = j = x = y = 0;
loop = true;
while (loop) {
- string[j] = text[i];
+ string[j] = wtext[i];
- if (strchr("\n\t ", string[j]) != NULL || string[j] == '\0') {
- string[j] = '\0';
+ if (wcschr(L"\n\t ", string[j]) != NULL || string[j] == L'\0') {
+ string[j] = L'\0';
print_string(pad, &rows, cols, &y, &x, string,
conf->text.highlight);
}
- switch (text[i]) {
- case '\0':
+ switch (wtext[i]) {
+ case L'\0':
loop = false;
break;
- case '\n':
+ case L'\n':
x = 0;
y++;
j = -1;
break;
- case '\t':
+ case L'\t':
for (z = 0; z < tablen; z++) {
if (x >= cols) {
x = 0;
@@ -392,7 +517,7 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
}
j = -1;
break;
- case ' ':
+ case L' ':
x++;
if (x >= cols) {
x = 0;
@@ -410,78 +535,133 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
i++;
}
+ free(wtext);
free(string);
return (0);
}
-/* Autosize */
+/* Text Autosize */
+#define NL -1
+#define WS -2
+#define TB -3
+
+struct textproperties {
+ int nword;
+ int *words;
+ uint8_t *wletters;
+ int maxwordcols;
+ int maxline;
+ bool hasnewline;
+};
+
static int
-text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
- int mincols, bool increasecols, int *h, int *w)
+text_properties(struct bsddialog_conf *conf, const char *text,
+ struct textproperties *tp)
{
- int i, j, z, x, y;
- int tablen, wordlen, maxwordlen, nword, maxwords, line, maxwidth;
- int *words;
-#define NL -1
-#define WS -2
+ int i, l, currlinecols, maxwords, wtextlen, tablen, wordcols;
+ wchar_t *wtext;
+
+ tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
maxwords = 1024;
- if ((words = calloc(maxwords, sizeof(int))) == NULL)
+ if ((tp->words = calloc(maxwords, sizeof(int))) == NULL)
RETURN_ERROR("Cannot alloc memory for text autosize");
- tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen;
- maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS;
+ if ((wtext = alloc_mbstows(text)) == NULL)
+ RETURN_ERROR("Cannot allocate/autosize text in wchar_t*");
+ wtextlen = wcslen(wtext);
+ if ((tp->wletters = calloc(wtextlen, sizeof(uint8_t))) == NULL)
+ RETURN_ERROR("Cannot allocate wletters for text autosizing");
- nword = 0;
- wordlen = 0;
- maxwordlen = 0;
- i=0;
- while (true) {
- if (conf->text.highlight && is_text_attr(text + i)) {
- i += 3;
+ tp->nword = 0;
+ tp->maxline = 0;
+ tp->maxwordcols = 0;
+ tp->hasnewline = false;
+ currlinecols = 0;
+ wordcols = 0;
+ l = 0;
+ for (i = 0; i < wtextlen; i++) {
+ if (conf->text.highlight && is_wtext_attr(wtext + i)) {
+ i += 2; /* +1 for update statement */
continue;
}
- if (nword + tablen >= maxwords) {
+ if (tp->nword + 1 >= maxwords) {
maxwords += 1024;
- if (realloc(words, maxwords * sizeof(int)) == NULL)
+ tp->words = realloc(tp->words, maxwords * sizeof(int));
+ if (tp->words == NULL)
RETURN_ERROR("Cannot realloc memory for text "
"autosize");
}
- if (text[i] == '\0') {
- words[nword] = wordlen;
- maxwordlen = MAX(wordlen, maxwordlen);
- break;
- }
-
- if (strchr("\t\n ", text[i]) != NULL) {
- maxwordlen = MAX(wordlen, maxwordlen);
+ if (wcschr(L"\t\n ", wtext[i]) != NULL) {
+ tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
- if (wordlen != 0) {
- words[nword] = wordlen;
- nword++;
- wordlen = 0;
+ if (wordcols != 0) {
+ /* line */
+ currlinecols += wordcols;
+ /* word */
+ tp->words[tp->nword] = wordcols;
+ tp->nword += 1;
+ wordcols = 0;
}
- if (text[i] == '\t') {
- for (j = 0; j < tablen; j++)
- words[nword + j] = 1;
- nword += tablen;
- } else {
- words[nword] = text[i] == '\n' ? NL : WS;
- nword++;
+ switch (wtext[i]) {
+ case L'\t':
+ /* line */
+ currlinecols += tablen;
+ /* word */
+ tp->words[tp->nword] = TB;
+ break;
+ case L'\n':
+ /* line */
+ tp->hasnewline = true;
+ tp->maxline = MAX(tp->maxline, currlinecols);
+ currlinecols = 0;
+ /* word */
+ tp->words[tp->nword] = NL;
+ break;
+ case L' ':
+ /* line */
+ currlinecols += 1;
+ /* word */
+ tp->words[tp->nword] = WS;
+ break;
}
+ tp->nword += 1;
+ } else {
+ tp->wletters[l] = wcwidth(wtext[i]);
+ wordcols += tp->wletters[l];
+ l++;
}
- else
- wordlen++;
-
- i++;
}
+ /* word */
+ if (wordcols != 0) {
+ tp->words[tp->nword] = wordcols;
+ tp->nword += 1;
+ tp->maxwordcols = MAX(wordcols, tp->maxwordcols);
+ }
+ /* line */
+ tp->maxline = MAX(tp->maxline, currlinecols);
+
+ free(wtext);
+
+ return (0);
+}
+
+
+static int
+text_autosize(struct bsddialog_conf *conf, struct textproperties *tp,
+ int maxrows, int mincols, bool increasecols, int *h, int *w)
+{
+ int i, j, x, y, z, l, line, maxwidth, tablen;
+
+ maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS;
+ tablen = (conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen;
if (increasecols) {
- mincols = MAX(mincols, maxwordlen);
+ mincols = MAX(mincols, tp->maxwordcols);
mincols = MAX(mincols,
(int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS);
mincols = MIN(mincols, maxwidth);
@@ -491,26 +671,50 @@ text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
x = 0;
y = 1;
line=0;
- for (i = 0; i <= nword; i++) {
- if (words[i] == NL) {
+ l = 0;
+ for (i = 0; i < tp->nword; i++) {
+ switch (tp->words[i]) {
+ case TB:
+ for (j = 0; j < tablen; j++) {
+ if (x >= mincols) {
+ x = 0;
+ y++;
+ }
+ x++;
+ }
+ break;
+ case NL:
y++;
x = 0;
- }
- else if (words[i] == WS) {
+ break;
+ case WS:
x++;
if (x >= mincols) {
x = 0;
y++;
}
- }
- else {
- if (words[i] + x <= mincols)
- x += words[i];
- else {
- for (z = words[i]; z > 0; ) {
- y++;
- x = MIN(mincols, z);
- z -= x;
+ break;
+ default:
+ if (tp->words[i] + x <= mincols) {
+ x += tp->words[i];
+ for (z = 0 ; z != tp->words[i]; l++ )
+ z += tp->wletters[l];
+ } else if (tp->words[i] <= mincols) {
+ y++;
+ x = tp->words[i];
+ for (z = 0 ; z != tp->words[i]; l++ )
+ z += tp->wletters[l];
+ } else {
+ for (j = tp->words[i]; j > 0; ) {
+ y = (x == 0) ? y : y + 1;
+ z = 0;
+ while (z != j && z < mincols) {
+ z += tp->wletters[l];
+ l++;
+ }
+ x = z;
+ line = MAX(line, x);
+ j -= z;
}
}
}
@@ -519,16 +723,16 @@ text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
if (increasecols == false)
break;
- if (y <= maxrows || mincols >= maxwidth)
+ if (mincols >= maxwidth)
+ break;
+ if (line >= y * (int)conf->text.cols_per_row && y <= maxrows)
break;
mincols++;
}
- *h = (nword == 0 && words[0] == 0) ? 0 : y;
+ *h = (tp->nword == 0) ? 0 : y;
*w = MIN(mincols, line); /* wtext can be less than mincols */
- free(words);
-
return (0);
}
@@ -536,13 +740,26 @@ int
text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext)
{
- int wbuttons, maxhtext;
bool changewtext;
+ int wbuttons, maxhtext;
+ struct textproperties tp;
wbuttons = 0;
if (bs != NULL)
- wbuttons = buttons_width(*bs);
+ wbuttons = buttons_min_width(*bs);
+ /* Rows */
+ if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) {
+ maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext;
+ } else { /* fixed */
+ maxhtext = rows - VBORDERS - rowsnotext;
+ }
+ if (bs != NULL)
+ maxhtext -= 2;
+ if (maxhtext <= 0)
+ maxhtext = 1; /* text_autosize() computes always htext */
+
+ /* Cols */
if (cols == BSDDIALOG_AUTOSIZE) {
startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS);
changewtext = true;
@@ -554,45 +771,52 @@ text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
changewtext = false;
}
- if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) {
- maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext;
- if (bs != NULL)
- maxhtext -= 2;
- } else { /* fixed */
- maxhtext = rows - VBORDERS - rowsnotext;
- if (bs != NULL)
- maxhtext -= 2;
- }
-
if (startwtext <= 0 && changewtext)
startwtext = 1;
- if (maxhtext <= 0 || startwtext <= 0) {
- *htext = *wtext = 0;
- return (0);
- }
+ if (startwtext <= 0)
+ RETURN_ERROR("Fullscreen or fixed cols to print text <=0");
- if (text_autosize(conf, text, maxhtext, startwtext, changewtext,
- htext, wtext) != 0)
+ /* Sizing calculation */
+ if (text_properties(conf, text, &tp) != 0)
+ return (BSDDIALOG_ERROR);
+ if (text_autosize(conf, &tp, maxhtext, startwtext, changewtext, htext,
+ wtext) != 0)
return (BSDDIALOG_ERROR);
+ free(tp.words);
+ free(tp.wletters);
+
return (0);
}
+/* Widget size and position */
int widget_max_height(struct bsddialog_conf *conf)
{
int maxheight;
- maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.h : SCREENLINES;
+ maxheight = conf->shadow ? SCREENLINES - (int)t.shadow.y : SCREENLINES;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - shadow <= 0");
- if (conf->y > 0) {
+ if (conf->y != BSDDIALOG_CENTER && conf->auto_topmargin > 0)
+ RETURN_ERROR("conf.y > 0 and conf->auto_topmargin > 0");
+ else if (conf->y == BSDDIALOG_CENTER) {
+ maxheight -= conf->auto_topmargin;
+ if (maxheight <= 0)
+ RETURN_ERROR("Terminal too small, screen lines - top "
+ "margins <= 0");
+ } else if (conf->y > 0) {
maxheight -= conf->y;
if (maxheight <= 0)
RETURN_ERROR("Terminal too small, screen lines - "
"shadow - y <= 0");
}
+ maxheight -= conf->auto_downmargin;
+ if (maxheight <= 0)
+ RETURN_ERROR("Terminal too small, screen lines - Down margins "
+ "<= 0");
+
return (maxheight);
}
@@ -600,7 +824,7 @@ int widget_max_width(struct bsddialog_conf *conf)
{
int maxwidth;
- maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.w : SCREENCOLS;
+ maxwidth = conf->shadow ? SCREENCOLS - (int)t.shadow.x : SCREENCOLS;
if (maxwidth <= 0)
RETURN_ERROR("Terminal too small, screen cols - shadow <= 0");
@@ -647,13 +871,13 @@ widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
struct buttons *bs)
{
- int min, delimtitle;
+ int min, delimtitle, wbottomtitle, wtitle;
min = 0;
/* buttons */
if (bs != NULL)
- min += buttons_width(*bs);
+ min += buttons_min_width(*bs);
/* text */
if (wtext > 0)
@@ -665,12 +889,15 @@ widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
/* title */
if (conf->title != NULL) {
delimtitle = t.dialog.delimtitle ? 2 : 0;
- min = MAX(min, (int)strlen(conf->title) + 2 + delimtitle);
+ wtitle = strcols(conf->title);
+ min = MAX(min, wtitle + 2 + delimtitle);
}
/* bottom title */
- if (conf->bottomtitle != NULL)
- min = MAX(min, (int)strlen(conf->bottomtitle) + 4);
+ if (conf->bottomtitle != NULL) {
+ wbottomtitle = strcols(conf->bottomtitle);
+ min = MAX(min, wbottomtitle + 4);
+ }
/* dialog borders */
min += VBORDERS;
@@ -721,8 +948,16 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
int
set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
{
- if (conf->y == BSDDIALOG_CENTER)
- *y = SCREENLINES/2 - (h + t.shadow.h)/2;
+ int hshadow = conf->shadow ? (int)t.shadow.y : 0;
+ int wshadow = conf->shadow ? (int)t.shadow.x : 0;
+
+ if (conf->y == BSDDIALOG_CENTER) {
+ *y = SCREENLINES/2 - (h + hshadow)/2;
+ if (*y < (int)conf->auto_topmargin)
+ *y = conf->auto_topmargin;
+ if (*y + h + hshadow > SCREENLINES - (int)conf->auto_downmargin)
+ *y = SCREENLINES - h - hshadow - conf->auto_downmargin;
+ }
else if (conf->y < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin y (less than -1)");
else if (conf->y >= SCREENLINES)
@@ -730,13 +965,13 @@ set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
else
*y = conf->y;
- if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > SCREENLINES)
+ if (*y + h + hshadow > SCREENLINES)
RETURN_ERROR("The lower of the box under the terminal "
"(begin Y + height (+ shadow) > terminal lines)");
if (conf->x == BSDDIALOG_CENTER)
- *x = SCREENCOLS/2 - (w + t.shadow.w)/2;
+ *x = SCREENCOLS/2 - (w + wshadow)/2;
else if (conf->x < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin x (less than -1)");
else if (conf->x >= SCREENCOLS)
@@ -744,14 +979,14 @@ set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
else
*x = conf->x;
- if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > SCREENCOLS)
+ if ((*x + w + wshadow) > SCREENCOLS)
RETURN_ERROR("The right of the box over the terminal "
"(begin X + width (+ shadow) > terminal cols)");
return (0);
}
-/* Widgets builders */
+/* Widgets build, update, destroy */
void
draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
enum elevation elev)
@@ -815,7 +1050,7 @@ static int
draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
WINDOW *textpad, const char *text, struct buttons *bs, bool shortcutbuttons)
{
- int h, w, ts, ltee, rtee;
+ int h, w, wtitle, wbottomtitle, ts, ltee, rtee;
ts = conf->ascii_lines ? '-' : ACS_HLINE;
ltee = conf->ascii_lines ? '+' : ACS_LTEE;
@@ -823,19 +1058,21 @@ draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
getmaxyx(widget, h, w);
- if (shadow != NULL)
+ if (conf->shadow)
wnoutrefresh(shadow);
draw_borders(conf, widget, h, w, RAISED);
if (conf->title != NULL) {
+ if ((wtitle = strcols(conf->title)) < 0)
+ return (BSDDIALOG_ERROR);
if (t.dialog.delimtitle && conf->no_lines == false) {
wattron(widget, t.dialog.lineraisecolor);
- mvwaddch(widget, 0, w/2-strlen(conf->title)/2-1, rtee);
+ mvwaddch(widget, 0, w/2 - wtitle/2 -1, rtee);
wattroff(widget, t.dialog.lineraisecolor);
}
wattron(widget, t.dialog.titlecolor);
- mvwaddstr(widget, 0, w/2 - strlen(conf->title)/2, conf->title);
+ mvwaddstr(widget, 0, w/2 - wtitle/2, conf->title);
wattroff(widget, t.dialog.titlecolor);
if (t.dialog.delimtitle && conf->no_lines == false) {
wattron(widget, t.dialog.lineraisecolor);
@@ -859,8 +1096,10 @@ draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
}
if (conf->bottomtitle != NULL) {
+ if ((wbottomtitle = strcols(conf->bottomtitle)) < 0)
+ return (BSDDIALOG_ERROR);
wattron(widget, t.dialog.bottomtitlecolor);
- wmove(widget, h - 1, w/2 - strlen(conf->bottomtitle)/2 - 1);
+ wmove(widget, h - 1, w/2 - wbottomtitle/2 - 1);
waddch(widget, ' ');
waddstr(widget, conf->bottomtitle);
waddch(widget, ' ');
@@ -883,9 +1122,9 @@ update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
{
int error;
- if (shadow != NULL) {
+ if (conf->shadow) {
wclear(shadow);
- mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
+ mvwin(shadow, y + t.shadow.y, x + t.shadow.x);
wresize(shadow, h, w);
}
@@ -912,7 +1151,7 @@ new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y,
int error;
if (conf->shadow) {
- *shadow = newwin(h, w, y + t.shadow.h, x + t.shadow.w);
+ *shadow = newwin(h, w, y + t.shadow.y, x + t.shadow.x);
if (*shadow == NULL)
RETURN_ERROR("Cannot build shadow");
wbkgd(*shadow, t.shadow.color);
@@ -962,10 +1201,10 @@ end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
delwin(shadow);
if (conf->clear)
- hide_widget(y, x, h, w, shadow != NULL);
+ hide_widget(y, x, h, w, conf->shadow);
if (conf->get_height != NULL)
*conf->get_height = h;
if (conf->get_width != NULL)
*conf->get_width = w;
-} \ No newline at end of file
+}
diff --git a/lib/lib_util.h b/lib/lib_util.h
index 6ebc73cf1055..238d3fda4675 100644
--- a/lib/lib_util.h
+++ b/lib/lib_util.h
@@ -33,8 +33,9 @@
#define TEXTHMARGIN 1
#define TEXTHMARGINS (TEXTHMARGIN + TEXTHMARGIN)
-/* current theme */
+/* theme utils */
extern struct bsddialog_theme t;
+extern bool hastermcolors;
/* debug */
#define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \
@@ -42,6 +43,12 @@ extern struct bsddialog_theme t;
refresh(); \
} while (0)
+/* unicode */
+unsigned int strcols(const char *mbstring);
+int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col);
+void mvwaddwch(WINDOW *w, int y, int x, wchar_t wch);
+wchar_t* alloc_mbstows(const char *mbstring);
+
/* error buffer */
const char *get_error_string(void);
void set_error_string(const char *string);
@@ -56,6 +63,7 @@ struct buttons {
unsigned int nbuttons;
#define MAXBUTTONS 6 /* ok + extra + cancel + help + 2 generics */
const char *label[MAXBUTTONS];
+ wchar_t first[MAXBUTTONS];
int value[MAXBUTTONS];
int curr;
unsigned int sizebutton; /* including left and right delimiters */
@@ -70,8 +78,8 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs,
void
draw_buttons(WINDOW *window, struct buttons bs, bool shortcut);
-int buttons_width(struct buttons bs);
-bool shortcut_buttons(int key, struct buttons *bs);
+int buttons_min_width(struct buttons bs);
+bool shortcut_buttons(wint_t key, struct buttons *bs);
/* help window with F1 key */
int f1help(struct bsddialog_conf *conf);
@@ -130,4 +138,4 @@ void
end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
WINDOW *textpad);
-#endif \ No newline at end of file
+#endif
diff --git a/lib/libbsddialog.c b/lib/libbsddialog.c
index 761bdc3efa77..1a8188b0e7d3 100644
--- a/lib/libbsddialog.c
+++ b/lib/libbsddialog.c
@@ -34,10 +34,11 @@
#include "bsddialog_theme.h"
#include "lib_util.h"
-int bsddialog_init(void)
+#define COLSPERROW 10 /* Default conf.text.columns_per_row */
+
+int bsddialog_init_notheme(void)
{
int i, j, c, error;
- enum bsddialog_default_theme theme;
set_error_string("");
@@ -64,7 +65,18 @@ int bsddialog_init(void)
}
}
- if (error == OK && has_colors())
+ hastermcolors = (error == OK && has_colors()) ? true : false;
+
+ return (BSDDIALOG_OK);
+}
+
+int bsddialog_init(void)
+{
+ enum bsddialog_default_theme theme;
+
+ bsddialog_init_notheme();
+
+ if (bsddialog_hascolors())
theme = BSDDIALOG_THEME_FLAT;
else
theme = BSDDIALOG_THEME_BLACKWHITE;
@@ -113,6 +125,7 @@ int bsddialog_initconf(struct bsddialog_conf *conf)
conf->y = BSDDIALOG_CENTER;
conf->x = BSDDIALOG_CENTER;
conf->shadow = true;
+ conf->text.cols_per_row = COLSPERROW;
return (BSDDIALOG_OK);
}
diff --git a/lib/menubox.c b/lib/menubox.c
index 22ed15e6e7a0..28b9c8a0923b 100644
--- a/lib/menubox.c
+++ b/lib/menubox.c
@@ -177,9 +177,10 @@ getfastprev(int menurows, struct privateitem *pritems, int abs)
static int
getnextshortcut(struct bsddialog_conf *conf, int npritems,
- struct privateitem *pritems, int abs, int key)
+ struct privateitem *pritems, int abs, wint_t key)
{
- int i, ch, next;
+ int i, next;
+ wchar_t wch;
next = -1;
for (i = 0; i < npritems; i++) {
@@ -187,11 +188,11 @@ getnextshortcut(struct bsddialog_conf *conf, int npritems,
continue;
if (conf->menu.no_name)
- ch = pritems[i].item->desc[0];
+ mbtowc(&wch, pritems[i].item->desc, MB_CUR_MAX);
else
- ch = pritems[i].item->name[0];
+ mbtowc(&wch, pritems[i].item->name, MB_CUR_MAX);
- if (ch == key) {
+ if (wch == (wchar_t)key) {
if (i > abs)
return (i);
@@ -236,12 +237,12 @@ drawseparators(struct bsddialog_conf *conf, WINDOW *pad, int linelen,
}
name = pritems[i].item->name;
desc = pritems[i].item->desc;
- labellen = strlen(name) + strlen(desc) + 1;
+ labellen = strcols(name) + strcols(desc) + 1;
wmove(pad, i, labellen < linelen ? linelen/2 - labellen/2 : 0);
wattron(pad, t.menu.namesepcolor);
waddstr(pad, name);
wattroff(pad, t.menu.namesepcolor);
- if (strlen(name) > 0 && strlen(desc) > 0)
+ if (strcols(name) > 0 && strcols(desc) > 0)
waddch(pad, ' ');
wattron(pad, t.menu.descsepcolor);
waddstr(pad, desc);
@@ -254,7 +255,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
struct lineposition pos, struct privateitem *pritem, bool focus)
{
int colordesc, colorname, colorshortcut;
- const char *shortcut;
+ wchar_t shortcut;
struct bsddialog_menuitem *item;
item = pritem->item;
@@ -303,24 +304,47 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
wattron(pad, colorshortcut);
if (conf->menu.no_name)
- shortcut = item->desc;
+ mbtowc(&shortcut, item->desc, MB_CUR_MAX);
else
- shortcut = item->name;
- wmove(pad, y, pos.xname + item->depth * DEPTH);
- if (shortcut != NULL && shortcut[0] != '\0')
- waddch(pad, shortcut[0]);
- wattroff(pad, colorshortcut);
+ mbtowc(&shortcut, item->name, MB_CUR_MAX);
+ mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut);
+ wattroff(pad, colorshortcut);
}
/* bottom description */
move(SCREENLINES - 1, 2);
clrtoeol();
if (item->bottomdesc != NULL && focus) {
+ attron(t.menu.bottomdesccolor);
addstr(item->bottomdesc);
+ attroff(t.menu.bottomdesccolor);
refresh();
}
}
+/* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
+static void
+update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w,
+ int totnitems, unsigned int menurows, int ymenupad)
+{
+ draw_borders(conf, menuwin, h, w, LOWERED);
+
+ if (totnitems > (int)menurows) {
+ wattron(menuwin, t.dialog.arrowcolor);
+ if (ymenupad > 0)
+ mvwhline(menuwin, 0, 2,
+ conf->ascii_lines ? '^' : ACS_UARROW, 3);
+
+ if ((ymenupad + (int)menurows) < totnitems)
+ mvwhline(menuwin, h-1, 2,
+ conf->ascii_lines ? 'v' : ACS_DARROW, 3);
+
+ mvwprintw(menuwin, h-1, w-6, "%3d%%",
+ 100 * (ymenupad + menurows) / totnitems);
+ wattroff(menuwin, t.dialog.arrowcolor);
+ }
+}
+
static int
menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
const char *text, int linelen, unsigned int *menurows, int nitems,
@@ -365,8 +389,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
*/
*menurows = MIN(*h - 6 - htext, (int)*menurows);
} else {
- if (*menurows == 0)
- *menurows = MIN(*h-6-htext, nitems);
+ if (*menurows == 0) {
+ if (*h - 6 - htext <= 0)
+ *menurows = 0; /* menu_checksize() will check */
+ else
+ *menurows = MIN(*h-6-htext, nitems);
+ }
}
return (0);
@@ -380,8 +408,7 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
mincols = VBORDERS;
/* buttons */
- mincols += buttons_width(bs);
-
+ mincols += buttons_min_width(bs);
/*
* linelen check, comment to allow some hidden col otherwise portconfig
* could not show big menus like www/apache24
@@ -392,11 +419,11 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
RETURN_ERROR("Few cols, width < size buttons or "
"name + descripion of the items");
- textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
+ textrow = text != NULL && text[0] != '\0' ? 1 : 0;
if (nitems > 0 && menurows == 0)
- RETURN_ERROR("items > 0 but menurows == 0, probably terminal "
- "too small");
+ RETURN_ERROR("items > 0 but menurows == 0, if menurows = 0 "
+ "terminal too small");
menusize = nitems > 0 ? 3 : 0;
if (rows < 2 + 2 + menusize + textrow)
@@ -405,37 +432,15 @@ menu_checksize(int rows, int cols, const char *text, int menurows, int nitems,
return (0);
}
-/* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
-static void
-update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w,
- int totnitems, unsigned int menurows, int ymenupad)
-{
- draw_borders(conf, menuwin, h, w, LOWERED);
-
- if (totnitems > (int)menurows) {
- wattron(menuwin, t.dialog.arrowcolor);
-
- if (ymenupad > 0)
- mvwprintw(menuwin, 0, 2, "^^^");
-
- if ((ymenupad + (int)menurows) < totnitems)
- mvwprintw(menuwin, h-1, 2, "vvv");
-
- wattroff(menuwin, t.dialog.arrowcolor);
-
- mvwprintw(menuwin, h-1, w-10, "%3d%%",
- 100 * (ymenupad + menurows) / totnitems);
- }
-}
-
static int
do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int menurows, enum menumode mode, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{
bool loop, onetrue, movefocus, automenurows, shortcut_butts;
- int i, j, y, x, h, w, output, input;
+ int i, j, y, x, h, w, retval;
int ymenupad, ys, ye, xs, xe, abs, next, totnitems;
+ wint_t input;
WINDOW *shadow, *widget, *textpad, *menuwin, *menupad;
struct buttons bs;
struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -458,14 +463,14 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (groups[i].type == BSDDIALOG_SEPARATOR) {
pos.maxsepstr = MAX(pos.maxsepstr,
- strlen(item->name) + strlen(item->desc));
+ strcols(item->name) + strcols(item->desc));
continue;
}
- pos.maxprefix = MAX(pos.maxprefix,strlen(item->prefix));
+ pos.maxprefix = MAX(pos.maxprefix,strcols(item->prefix));
pos.maxdepth = MAX(pos.maxdepth, item->depth);
- pos.maxname = MAX(pos.maxname, strlen(item->name));
- pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc));
+ pos.maxname = MAX(pos.maxname, strcols(item->name));
+ pos.maxdesc = MAX(pos.maxdesc, strcols(item->desc));
}
}
pos.maxname = conf->menu.no_name ? 0 : pos.maxname;
@@ -479,7 +484,6 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
pos.xdesc += (pos.maxname != 0 ? 1 : 0);
pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc);
-
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
@@ -498,11 +502,11 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
doupdate();
- prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN,
- y + h - menurows, x + 1 + w - TEXTHMARGIN);
+ prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, y + h - menurows,
+ x + 1 + w - TEXTHMARGIN);
menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2,
- menurows+2, w-4, LOWERED);
+ menurows + 2, w - 4, LOWERED);
menupad = newpad(totnitems, pos.line);
wbkgd(menupad, t.dialog.color);
@@ -562,22 +566,23 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
movefocus = false;
loop = true;
while (loop) {
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true;
- set_on_output(conf, output, ngroups, groups, pritems);
+ set_on_output(conf, retval, ngroups, groups, pritems);
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
if (abs >= 0 && pritems[abs].type == MENUMODE)
pritems[abs].on = true;
- set_on_output(conf, output, ngroups, groups,
+ set_on_output(conf, retval, ngroups, groups,
pritems);
loop = false;
}
@@ -714,10 +719,10 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
default:
if (shortcut_butts) {
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
if (pritems[abs].type == MENUMODE)
pritems[abs].on = true;
- set_on_output(conf, output, ngroups,
+ set_on_output(conf, retval, ngroups,
groups, pritems);
loop = false;
}
@@ -728,7 +733,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
next = getnextshortcut(conf, totnitems, pritems, abs,
input);
movefocus = next != abs;
- }
+ } /* end switch handler */
if (movefocus) {
drawitem(conf, menupad, abs, pos, &pritems[abs], false);
@@ -744,7 +749,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
movefocus = false;
}
- }
+ } /* end while handler */
if (focuslist != NULL)
*focuslist = abs < 0 ? -1 : pritems[abs].group;
@@ -756,7 +761,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
end_dialog(conf, shadow, widget, textpad);
free(pritems);
- return (output);
+ return (retval);
}
/* API */
@@ -765,12 +770,12 @@ bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{
- int output;
+ int retval;
- output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
+ retval = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
ngroups, groups, focuslist, focusitem);
- return (output);
+ return (retval);
}
int
@@ -778,14 +783,14 @@ bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
- int output, focuslist = 0;
+ int retval, focuslist = 0;
struct bsddialog_menugroup group = {
BSDDIALOG_CHECKLIST /* unused */, nitems, items};
- output = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE,
+ retval = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE,
1, &group, &focuslist, focusitem);
- return (output);
+ return (retval);
}
int
@@ -793,14 +798,14 @@ bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
- int output, focuslist = 0;
+ int retval, focuslist = 0;
struct bsddialog_menugroup group = {
BSDDIALOG_CHECKLIST /* unused */, nitems, items};
- output = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1,
+ retval = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1,
&group, &focuslist, focusitem);
- return (output);
+ return (retval);
}
int
@@ -808,12 +813,12 @@ bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem)
{
- int output, focuslist = 0;
+ int retval, focuslist = 0;
struct bsddialog_menugroup group = {
BSDDIALOG_RADIOLIST /* unused */, nitems, items};
- output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
+ retval = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
1, &group, &focuslist, focusitem);
- return (output);
+ return (retval);
}
diff --git a/lib/messagebox.c b/lib/messagebox.c
index 24b34ccbce97..06753be20c3d 100644
--- a/lib/messagebox.c
+++ b/lib/messagebox.c
@@ -31,18 +31,22 @@
#include <string.h>
#include "bsddialog.h"
+#include "bsddialog_theme.h"
#include "lib_util.h"
static int
message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
- int *w, const char *text, struct buttons bs)
+ int *w, const char *text, bool *hastext, struct buttons bs)
{
int htext, wtext;
- if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
- if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2,
- &htext, &wtext) != 0)
+ if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE ||
+ hastext != NULL) {
+ if (text_size(conf, rows, cols, text, &bs, 0, 1, &htext,
+ &wtext) != 0)
return (BSDDIALOG_ERROR);
+ if (hastext != NULL)
+ *hastext = htext > 0 ? true : false;
}
if (cols == BSDDIALOG_AUTOSIZE)
@@ -54,34 +58,40 @@ message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
return (0);
}
-static int message_checksize(int rows, int cols, struct buttons bs)
+static int
+message_checksize(int rows, int cols, bool hastext, struct buttons bs)
{
int mincols;
mincols = VBORDERS;
- mincols += buttons_width(bs);
+ mincols += buttons_min_width(bs);
if (cols < mincols)
RETURN_ERROR("Few cols, Msgbox and Yesno need at least width "
"for borders, buttons and spaces between buttons");
- if (rows < HBORDERS + 2 /*buttons*/)
- RETURN_ERROR("Msgbox and Yesno need at least height 4");
+ if (rows < HBORDERS + 2 /* buttons */)
+ RETURN_ERROR("Msgbox and Yesno need at least 4 rows");
+ if (hastext && rows < HBORDERS + 2 /*buttons*/ + 1 /* text row */)
+ RETURN_ERROR("Msgbox and Yesno with text need at least 5 rows");
return (0);
}
static void
-textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad)
+textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad,
+ bool hastext)
{
int y, x, h, w;
getbegyx(widget, y, x);
getmaxyx(widget, h, w);
- if (htextpad > h - 4) {
+ if (hastext && htextpad > h - 4) {
+ wattron(widget, t.dialog.arrowcolor);
mvwprintw(widget, h-3, w-6, "%3d%%",
100 * (ytextpad+h-4)/ htextpad);
+ wattroff(widget, t.dialog.arrowcolor);
wnoutrefresh(widget);
}
@@ -92,15 +102,16 @@ static int
do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
struct buttons bs)
{
- bool loop;
- int y, x, h, w, input, output, ytextpad, htextpad, unused;
+ bool hastext, loop;
+ int y, x, h, w, retval, ytextpad, htextpad, unused;
WINDOW *widget, *textpad, *shadow;
+ wint_t input;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
- if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
+ if (message_autosize(conf, rows, cols, &h, &w, text, &hastext, bs) != 0)
return (BSDDIALOG_ERROR);
- if (message_checksize(h, w, bs) != 0)
+ if (message_checksize(h, w, hastext, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
@@ -112,20 +123,21 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
ytextpad = 0;
getmaxyx(textpad, htextpad, unused);
unused++; /* fix unused error */
- textupdate(widget, textpad, htextpad, ytextpad);
+ textupdate(widget, textpad, htextpad, ytextpad, hastext);
loop = true;
while (loop) {
doupdate();
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch (input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -163,9 +175,9 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
if (message_autosize(conf, rows, cols, &h, &w, text,
- bs) != 0)
+ NULL, bs) != 0)
return (BSDDIALOG_ERROR);
- if (message_checksize(h, w, bs) != 0)
+ if (message_checksize(h, w, hastext, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
@@ -175,7 +187,8 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
return (BSDDIALOG_ERROR);
getmaxyx(textpad, htextpad, unused);
- textupdate(widget, textpad, htextpad, ytextpad);
+ ytextpad = 0;
+ textupdate(widget, textpad, htextpad, ytextpad, hastext);
/* Important to fix grey lines expanding screen */
refresh();
@@ -184,17 +197,17 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (ytextpad == 0)
break;
ytextpad--;
- textupdate(widget, textpad, htextpad, ytextpad);
+ textupdate(widget, textpad, htextpad, ytextpad, hastext);
break;
case KEY_DOWN:
if (ytextpad + h - 4 >= htextpad)
break;
ytextpad++;
- textupdate(widget, textpad, htextpad, ytextpad);
+ textupdate(widget, textpad, htextpad, ytextpad, hastext);
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -202,7 +215,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}
/* API */
diff --git a/lib/textbox.c b/lib/textbox.c
index 69eff7c0bc2e..0c6d53a8cad0 100644
--- a/lib/textbox.c
+++ b/lib/textbox.c
@@ -28,18 +28,61 @@
#include <sys/param.h>
#include <curses.h>
+#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
static void
+updateborders(struct bsddialog_conf *conf, WINDOW *widget, int padmargin,
+ int hpad, int wpad, int ypad, int xpad)
+{
+ int h, w;
+ chtype arrowch, borderch;
+
+ getmaxyx(widget, h, w);
+
+ if (conf->no_lines)
+ borderch = ' ';
+ else if (conf->ascii_lines)
+ borderch = '|';
+ else
+ borderch = ACS_VLINE;
+
+ if (xpad > 0) {
+ arrowch = conf->ascii_lines ? '<' : ACS_LARROW;
+ arrowch |= A_ATTRIBUTES & t.dialog.arrowcolor;
+ } else {
+ arrowch = borderch;
+ arrowch |= A_ATTRIBUTES & t.dialog.lineraisecolor;
+ }
+ mvwvline(widget, (h / 2) - 2, 0, arrowch, 4);
+
+ if (xpad + w-2-padmargin < wpad) {
+ arrowch = conf->ascii_lines ? '>' : ACS_RARROW;
+ arrowch |= A_ATTRIBUTES & t.dialog.arrowcolor;
+ } else {
+ arrowch = borderch;
+ arrowch |= A_ATTRIBUTES & t.dialog.linelowercolor;
+ }
+ mvwvline(widget, (h / 2) - 2, w - 1, arrowch, 4);
+
+ if (hpad > h - 4) {
+ wattron(widget, t.dialog.arrowcolor);
+ mvwprintw(widget, h-3, w-6, "%3d%%", 100 * (ypad+h-4)/ hpad);
+ wattroff(widget, t.dialog.arrowcolor);
+ }
+}
+
+static void
textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
- int *w, int hpad, int wpad, struct buttons bs)
+ int *w, int hpad, int wpad, int padmargin, struct buttons bs)
{
if (cols == BSDDIALOG_AUTOSIZE)
- *w = widget_min_width(conf, 0, wpad, &bs);
+ *w = widget_min_width(conf, 0, wpad + padmargin, &bs);
if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, 0, hpad, true);
@@ -50,7 +93,8 @@ textbox_checksize(int rows, int cols, int hpad, struct buttons bs)
{
int mincols;
- mincols = VBORDERS + bs.sizebutton;
+ mincols = VBORDERS;
+ mincols += buttons_min_width(bs);
if (cols < mincols)
RETURN_ERROR("Few cols for the textbox");
@@ -66,9 +110,11 @@ int
bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
int cols)
{
- bool loop;
- int i, output, input;
- int y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows;
+ bool loop, has_multi_col;
+ int i, retval, y, x, h, w;
+ int hpad, wpad, ypad, xpad, ys, ye, xs, xe, padmargin, printrows;
+ unsigned int defaulttablen, linecols;
+ wint_t input;
char buf[BUFSIZ];
FILE *fp;
struct buttons bs;
@@ -77,14 +123,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
if ((fp = fopen(file, "r")) == NULL)
RETURN_ERROR("Cannot open file");
+ defaulttablen = TABSIZE;
+ set_tabsize((conf->text.tablen == 0) ? TABSIZE : (int)conf->text.tablen);
hpad = 1;
wpad = 1;
pad = newpad(hpad, wpad);
wbkgd(pad, t.dialog.color);
+ padmargin = 0;
i = 0;
while (fgets(buf, BUFSIZ, fp) != NULL) {
- if ((int) strlen(buf) > wpad) {
- wpad = strlen(buf);
+ if (str_props(buf, &linecols, &has_multi_col) != 0)
+ continue;
+ if ((int)linecols > wpad) {
+ wpad = linecols;
wresize(pad, hpad, wpad);
}
if (i > hpad-1) {
@@ -93,20 +144,19 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
}
mvwaddstr(pad, i, 0, buf);
i++;
+ if (has_multi_col)
+ padmargin = 2;
}
fclose(fp);
+ set_tabsize(defaulttablen);
- bs.nbuttons = 1;
- bs.label[0] = "EXIT";
- if (conf->button.ok_label != NULL)
- bs.label[0] = conf->button.ok_label;
- bs.value[0] = BSDDIALOG_OK;
+ get_buttons(conf, &bs, "EXIT", NULL);
bs.curr = 0;
- bs.sizebutton = strlen(bs.label[0]) + 2;
+ bs.nbuttons = 1;
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
- textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, bs);
+ textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, padmargin, bs);
if (textbox_checksize(h, w, hpad, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
@@ -117,26 +167,33 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
return (BSDDIALOG_ERROR);
ys = y + 1;
- xs = x + 1;
+ xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5;
- xe = xs + w - 3;
+ xe = xs + w - 3 - padmargin;
ypad = xpad = 0;
printrows = h-4;
loop = true;
while (loop) {
- wnoutrefresh(widget);
- pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe);
- doupdate();
- input = getch();
+ updateborders(conf, widget, padmargin, hpad, wpad, ypad, xpad);
+ /*
+ * Overflow multicolumn charchter right border:
+ * wnoutrefresh(widget);
+ * pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe);
+ * doupdate();
+ */
+ wrefresh(widget);
+ prefresh(pad, ypad, xpad, ys, xs, ye, xe);
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = BSDDIALOG_OK;
+ retval = BSDDIALOG_OK;
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -164,7 +221,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break;
case KEY_RIGHT:
case 'l':
- xpad = (xpad + w-2) < wpad-1 ? xpad + 1 : xpad;
+ xpad = (xpad + w-2-padmargin) < wpad ? xpad + 1 : xpad;
break;
case KEY_UP:
case 'k':
@@ -189,16 +246,16 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return (BSDDIALOG_ERROR);
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad,
- bs);
+ padmargin, bs);
if (textbox_checksize(h, w, hpad, bs) != 0)
return (BSDDIALOG_ERROR);
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
ys = y + 1;
- xs = x + 1;
+ xs = (padmargin == 0) ? x + 1 : x + 2;
ye = ys + h - 5;
- xe = xs + w - 3;
+ xe = xs + w - 3 - padmargin;
ypad = xpad = 0;
printrows = h - 4;
@@ -211,7 +268,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -219,5 +276,5 @@ bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows,
end_dialog(conf, shadow, widget, pad);
- return (output);
-} \ No newline at end of file
+ return (retval);
+}
diff --git a/lib/theme.c b/lib/theme.c
index 20b1e35428dd..40310d58cda4 100644
--- a/lib/theme.c
+++ b/lib/theme.c
@@ -34,51 +34,53 @@
#define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1))
struct bsddialog_theme t;
+bool hastermcolors;
static struct bsddialog_theme bsddialogtheme = {
-#define bgwidget COLOR_WHITE
-#define bgcurr COLOR_YELLOW
.screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadow.h = 1,
- .shadow.w = 2,
+ .shadow.y = 1,
+ .shadow.x = 2,
.dialog.delimtitle = true,
- .dialog.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .dialog.color = GET_COLOR(COLOR_BLACK, bgwidget),
- .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+ .dialog.titlecolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
+ .dialog.lineraisecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .dialog.arrowcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
- .menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, bgcurr),
- .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr),
- .menu.desccolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .menu.f_namecolor = GET_COLOR(COLOR_BLACK, bgcurr),
- .menu.namecolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .menu.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .menu.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr),
- .menu.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget),
+ .menu.f_selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
+ .menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_YELLOW),
+ .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .menu.f_namecolor = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
+ .menu.namecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .menu.namesepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
+ .menu.descsepcolor = GET_COLOR(COLOR_YELLOW, COLOR_WHITE),
+ .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
+ .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
- .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
- .form.readonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE),
+ .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
+ .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE),
+ .form.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
- .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
+ .bar.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
+ .bar.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
- .button.hmargin = 3,
- .button.leftdelim = '[',
- .button.rightdelim = ']',
- .button.f_delimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .button.delimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .button.f_color = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE,
- .button.color = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE,
- .button.f_shortcutcolor = GET_COLOR(COLOR_RED, bgcurr) | A_UNDERLINE,
- .button.shortcutcolor = GET_COLOR(COLOR_RED, bgwidget) | A_UNDERLINE
+ .button.minmargin = 1,
+ .button.maxmargin = 5,
+ .button.leftdelim = '[',
+ .button.rightdelim = ']',
+ .button.f_delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .button.delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .button.f_color = GET_COLOR(COLOR_BLACK, COLOR_YELLOW),
+ .button.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .button.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_YELLOW),
+ .button.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE)
};
static struct bsddialog_theme blackwhite = {
@@ -87,8 +89,8 @@ static struct bsddialog_theme blackwhite = {
.screen.color = GET_COLOR(fg, bk),
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadow.h = 1,
- .shadow.w = 2,
+ .shadow.y = 1,
+ .shadow.x = 2,
.dialog.delimtitle = true,
.dialog.titlecolor = GET_COLOR(fg, bk),
@@ -108,15 +110,18 @@ static struct bsddialog_theme blackwhite = {
.menu.descsepcolor = GET_COLOR(fg, bk),
.menu.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
.menu.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE,
+ .menu.bottomdesccolor = GET_COLOR(fg, bk),
- .form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
- .form.fieldcolor = GET_COLOR(fg, bk),
- .form.readonlycolor = GET_COLOR(fg, bk),
+ .form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
+ .form.fieldcolor = GET_COLOR(fg, bk),
+ .form.readonlycolor = GET_COLOR(fg, bk),
+ .form.bottomdesccolor = GET_COLOR(fg, bk),
.bar.f_color = GET_COLOR(fg, bk) | A_REVERSE,
.bar.color = GET_COLOR(fg, bk),
- .button.hmargin = 3,
+ .button.minmargin = 1,
+ .button.maxmargin = 5,
.button.leftdelim = '[',
.button.rightdelim = ']',
.button.f_delimcolor = GET_COLOR(fg, bk),
@@ -128,11 +133,11 @@ static struct bsddialog_theme blackwhite = {
};
static struct bsddialog_theme dialogtheme = {
- .screen.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
+ .screen.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
.shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadow.h = 1,
- .shadow.w = 2,
+ .shadow.y = 1,
+ .shadow.x = 2,
.dialog.delimtitle = false,
.dialog.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
@@ -140,27 +145,30 @@ static struct bsddialog_theme dialogtheme = {
.dialog.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
.dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
- .dialog.arrowcolor = GET_COLOR(COLOR_GREEN, COLOR_WHITE),
+ .dialog.arrowcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
- .menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
- .menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
- .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
- .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
- .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE),
- .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.f_selectorcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .menu.selectorcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .menu.f_namecolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
+ .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE),
+ .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
- .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD,
+ .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
+ .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD,
+ .form.bottomdesccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
.bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
.bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
- .button.hmargin = 3,
+ .button.minmargin = 1,
+ .button.maxmargin = 5,
.button.leftdelim = '<',
.button.rightdelim = '>',
.button.f_delimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
@@ -177,8 +185,8 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src)
dst->screen.color = src->screen.color;
dst->shadow.color = src->shadow.color;
- dst->shadow.h = src->shadow.h;
- dst->shadow.w = src->shadow.w;
+ dst->shadow.y = src->shadow.y;
+ dst->shadow.x = src->shadow.x;
dst->dialog.delimtitle = src->dialog.delimtitle;
dst->dialog.titlecolor = src->dialog.titlecolor;
@@ -198,15 +206,18 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src)
dst->menu.descsepcolor = src->menu.descsepcolor;
dst->menu.f_shortcutcolor = src->menu.f_shortcutcolor;
dst->menu.shortcutcolor = src->menu.shortcutcolor;
+ dst->menu.bottomdesccolor = src->menu.bottomdesccolor;
- dst->form.f_fieldcolor = src->form.f_fieldcolor;
- dst->form.fieldcolor = src->form.fieldcolor;
- dst->form.readonlycolor = src->form.readonlycolor;
+ dst->form.f_fieldcolor = src->form.f_fieldcolor;
+ dst->form.fieldcolor = src->form.fieldcolor;
+ dst->form.readonlycolor = src->form.readonlycolor;
+ dst->form.bottomdesccolor = src->form.bottomdesccolor;
dst->bar.f_color = src->bar.f_color;
dst->bar.color = src->bar.color;
- dst->button.hmargin = src->button.hmargin;
+ dst->button.minmargin = src->button.minmargin;
+ dst->button.maxmargin = src->button.maxmargin;
dst->button.leftdelim = src->button.leftdelim;
dst->button.rightdelim = src->button.rightdelim;
dst->button.f_delimcolor = src->button.f_delimcolor;
@@ -230,7 +241,7 @@ int bsddialog_get_theme(struct bsddialog_theme *theme)
set_theme(theme, &t);
- return (0);
+ return (BSDDIALOG_OK);
}
int bsddialog_set_theme(struct bsddialog_theme *theme)
@@ -242,7 +253,7 @@ int bsddialog_set_theme(struct bsddialog_theme *theme)
set_theme(&t, theme);
- return (0);
+ return (BSDDIALOG_OK);
}
int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
@@ -254,6 +265,7 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
t.dialog.delimtitle = true;
t.button.leftdelim = '[';
t.button.rightdelim = ']';
+ t.dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE);
}
else if (newtheme == BSDDIALOG_THEME_BSDDIALOG)
bsddialog_set_theme(&bsddialogtheme);
@@ -264,7 +276,7 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
else
RETURN_ERROR("Unknow default theme");
- return (0);
+ return (BSDDIALOG_OK);
}
int
@@ -282,3 +294,32 @@ bsddialog_color(enum bsddialog_color foreground,
return (GET_COLOR(foreground, background) | cursesflags);
}
+
+int
+bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
+ enum bsddialog_color *background, unsigned int *flags)
+{
+ unsigned int flag;
+ short f, b;
+
+ flag = 0U;
+ flag |= (color & A_BOLD) ? BSDDIALOG_BOLD : 0U;
+ flag |= (color & A_REVERSE) ? BSDDIALOG_REVERSE : 0U;
+ flag |= (color & A_UNDERLINE) ? BSDDIALOG_UNDERLINE : 0U;
+ if (flags != NULL)
+ *flags = flag;
+
+ if (pair_content(PAIR_NUMBER(color), &f, &b) != OK)
+ RETURN_ERROR("Cannot get color attributes");
+ if (foreground != NULL)
+ *foreground = f;
+ if (background != NULL)
+ *background = b;
+
+ return (BSDDIALOG_OK);
+}
+
+bool bsddialog_hascolors(void)
+{
+ return hastermcolors;
+} \ No newline at end of file
diff --git a/lib/timebox.c b/lib/timebox.c
index 7d69666c32b8..529563b49bca 100644
--- a/lib/timebox.c
+++ b/lib/timebox.c
@@ -32,11 +32,42 @@
#include <string.h>
#include "bsddialog.h"
+#include "bsddialog_theme.h"
#include "lib_util.h"
#define MINWDATE 23 /* 3 windows and their borders */
#define MINWTIME 14 /* 3 windows and their borders */
+static void
+drawquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
+ const void *value, bool focus)
+{
+ int h, l, w;
+
+ getmaxyx(win, h, w);
+ draw_borders(conf, win, h, w, LOWERED);
+ if (focus) {
+ l = 2 + w%2;
+ wattron(win, t.dialog.arrowcolor);
+ mvwhline(win, 0, w/2 - l/2,
+ conf->ascii_lines ? '^' : ACS_UARROW, l);
+ mvwhline(win, h-1, w/2 - l/2,
+ conf->ascii_lines ? 'v' : ACS_DARROW, l);
+ wattroff(win, t.dialog.arrowcolor);
+ }
+
+ if (focus)
+ wattron(win, t.menu.f_namecolor);
+ if (strchr(fmt, 's') != NULL)
+ mvwprintw(win, 1, 1, fmt, (const char*)value);
+ else
+ mvwprintw(win, 1, 1, fmt, *((const int*)value));
+ if (focus)
+ wattroff(win, t.menu.f_namecolor);
+
+ wrefresh(win);
+}
+
static int
datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
int *w, int minw, const char *text, struct buttons bs)
@@ -50,7 +81,7 @@ datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
}
if (cols == BSDDIALOG_AUTOSIZE)
- *w = widget_min_width(conf, htext,minw, &bs);
+ *w = widget_min_width(conf, wtext, minw, &bs);
if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, 3 /* windows */, true);
@@ -64,7 +95,7 @@ datetime_checksize(int rows, int cols, int minw, struct buttons bs)
int mincols;
mincols = VBORDERS;
- mincols += buttons_width(bs);
+ mincols += buttons_min_width(bs);
mincols = MAX(minw, mincols);
if (cols < mincols)
@@ -81,7 +112,8 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss)
{
bool loop, focusbuttons;
- int i, input, output, y, x, h, w, sel;
+ int i, retval, y, x, h, w, sel;
+ wint_t input;
WINDOW *widget, *textpad, *shadow;
struct buttons bs;
struct myclockstruct {
@@ -131,30 +163,26 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wrefresh(widget);
+ sel = -1;
loop = focusbuttons = true;
while (loop) {
- for (i = 0; i < 3; i++) {
- mvwprintw(c[i].win, 1, 1, "%2d", c[i].value);
- wrefresh(c[i].win);
- }
-
- if (focusbuttons == false) {
- wmove(c[sel].win, 1, 2);
- wrefresh(c[sel].win);
- }
+ for (i = 0; i < 3; i++)
+ drawquare(conf, c[i].win, "%02d", &c[i].value,
+ sel == i);
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- if (focusbuttons == false)
- break;
- output = bs.value[bs.curr];
- loop = false;
+ if (focusbuttons || conf->button.always_active) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -165,14 +193,13 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false;
if (focusbuttons == false) {
- curs_set(1);
sel = 0;
+ bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel++;
focusbuttons = sel > 2 ? true : false;
if (focusbuttons) {
- curs_set(0);
bs.curr = 0;
}
}
@@ -184,25 +211,28 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
bs.curr--;
focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) {
- curs_set(1);
sel = 2;
+ bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel--;
focusbuttons = sel < 0 ? true : false;
- if (focusbuttons) {
- curs_set(0);
+ if (focusbuttons)
bs.curr = (int)bs.nbuttons - 1;
- }
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_UP:
- if (focusbuttons)
- break;
- c[sel].value = c[sel].value > 0 ?
+ if (focusbuttons) {
+ sel = 0;
+ focusbuttons = false;
+ bs.curr = conf->button.always_active ? 0 : -1;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else { c[sel].value = c[sel].value > 0 ?
c[sel].value - 1 : c[sel].max;
+ }
break;
case KEY_DOWN:
if (focusbuttons)
@@ -214,10 +244,8 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
break;
- curs_set(0);
if (f1help(conf) != 0)
return (BSDDIALOG_ERROR);
- curs_set(1);
/* No break, screen size can change */
case KEY_RESIZE:
/* Important for decreasing screen */
@@ -248,43 +276,33 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
wclear(c[0].win);
mvwin(c[0].win, y + h - 6, x + w/2 - 7);
- draw_borders(conf, c[0].win, 3, 4, LOWERED);
- wrefresh(c[0].win);
-
wclear(c[1].win);
mvwin(c[1].win, y + h - 6, x + w/2 - 2);
- draw_borders(conf, c[1].win, 3, 4, LOWERED);
- wrefresh(c[1].win);
-
wclear(c[2].win);
mvwin(c[2].win, y + h - 6, x + w/2 + 3);
- draw_borders(conf, c[2].win, 3, 4, LOWERED);
- wrefresh(c[2].win);
/* Important to avoid grey lines expanding screen */
refresh();
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
}
- if (output == BSDDIALOG_OK) {
+ if (retval == BSDDIALOG_OK) {
*hh = c[0].value;
*mm = c[1].value;
*ss = c[2].value;
}
- curs_set(0);
-
for (i = 0; i < 3; i++)
delwin(c[i].win);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}
int
@@ -292,7 +310,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
{
bool loop, focusbuttons;
- int i, input, output, y, x, h, w, sel;
+ int i, retval, y, x, h, w, sel;
+ wint_t input;
WINDOW *widget, *textpad, *shadow;
struct buttons bs;
struct calendar {
@@ -363,31 +382,27 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(widget);
+ sel = -1;
loop = focusbuttons = true;
while (loop) {
- mvwprintw(c[0].win, 1, 1, "%4d", c[0].value);
- mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name);
- mvwprintw(c[2].win, 1, 1, "%2d", c[2].value);
- for (i = 0; i < 3; i++) {
- wrefresh(c[i].win);
- }
- if (focusbuttons == false) {
- wmove(c[sel].win, 1, c[sel].x);
- wrefresh(c[sel].win);
- }
+ drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
+ drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
+ sel == 1);
+ drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- if (focusbuttons == false)
- break;
- output = bs.value[bs.curr];
- loop = false;
+ if (focusbuttons || conf->button.always_active) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -398,14 +413,13 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
focusbuttons = bs.curr < (int)bs.nbuttons ?
true : false;
if (focusbuttons == false) {
- curs_set(1);
sel = 0;
+ bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel++;
focusbuttons = sel > 2 ? true : false;
if (focusbuttons) {
- curs_set(0);
bs.curr = 0;
}
}
@@ -417,33 +431,37 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
bs.curr--;
focusbuttons = bs.curr < 0 ? false : true;
if (focusbuttons == false) {
- curs_set(1);
sel = 2;
+ bs.curr = conf->button.always_active ? 0 : -1;
}
} else {
sel--;
focusbuttons = sel < 0 ? true : false;
- if (focusbuttons) {
- curs_set(0);
+ if (focusbuttons)
bs.curr = (int)bs.nbuttons - 1;
- }
}
draw_buttons(widget, bs, true);
wrefresh(widget);
break;
case KEY_UP:
- if (focusbuttons)
- break;
- c[sel].value = c[sel].value > 1 ?
- c[sel].value - 1 : c[sel].max ;
- /* if mount change */
- c[2].max = m[c[1].value -1].days;
- /* if year change */
- if (c[1].value == 2 && ISLEAF(c[0].value))
- c[2].max = 29;
- /* set new day */
- if (c[2].value > c[2].max)
- c[2].value = c[2].max;
+ if (focusbuttons) {
+ sel = 0;
+ focusbuttons = false;
+ bs.curr = conf->button.always_active ? 0 : -1;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else {
+ c[sel].value = c[sel].value > 1 ?
+ c[sel].value - 1 : c[sel].max ;
+ /* if mount change */
+ c[2].max = m[c[1].value -1].days;
+ /* if year change */
+ if (c[1].value == 2 && ISLEAF(c[0].value))
+ c[2].max = 29;
+ /* set new day */
+ if (c[2].value > c[2].max)
+ c[2].value = c[2].max;
+ }
break;
case KEY_DOWN:
if (focusbuttons)
@@ -463,10 +481,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
break;
- curs_set(0);
if (f1help(conf) != 0)
return (BSDDIALOG_ERROR);
- curs_set(1);
/* No break, screen size can change */
case KEY_RESIZE:
/* Important for decreasing screen */
@@ -496,41 +512,31 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
wclear(c[0].win);
mvwin(c[0].win, y + h - 6, x + w/2 - 11);
- draw_borders(conf, c[0].win, 3, 6, LOWERED);
- wrefresh(c[0].win);
-
wclear(c[1].win);
mvwin(c[1].win, y + h - 6, x + w/2 - 4);
- draw_borders(conf, c[1].win, 3, 11, LOWERED);
- wrefresh(c[1].win);
-
wclear(c[2].win);
mvwin(c[2].win, y + h - 6, x + w/2 + 8);
- draw_borders(conf, c[2].win, 3, 4, LOWERED);
- wrefresh(c[2].win);
/* Important to avoid grey lines expanding screen */
refresh();
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
}
- if (output == BSDDIALOG_OK) {
+ if (retval == BSDDIALOG_OK) {
*yy = c[0].value;
*mm = c[1].value;
*dd = c[2].value;
}
- curs_set(0);
-
for (i = 0; i < 3; i++)
delwin(c[i].win);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}