summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/GNUMakefile10
-rw-r--r--lib/Makefile6
-rw-r--r--lib/barbox.c2
-rw-r--r--lib/bsddialog.333
-rw-r--r--lib/bsddialog.h10
-rw-r--r--lib/calendarbox.c520
-rw-r--r--lib/formbox.c29
-rw-r--r--lib/lib_util.c14
-rw-r--r--lib/lib_util.h3
-rw-r--r--lib/libbsddialog.c4
-rw-r--r--lib/menubox.c50
-rw-r--r--lib/messagebox.c42
-rw-r--r--lib/theme.c1
-rw-r--r--lib/timebox.c20
14 files changed, 645 insertions, 99 deletions
diff --git a/lib/GNUMakefile b/lib/GNUMakefile
index 1d55d6edd60d..3c31c78fdf88 100644
--- a/lib/GNUMakefile
+++ b/lib/GNUMakefile
@@ -3,15 +3,15 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.3
+VERSION = 0.4
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
-SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
- messagebox.c textbox.c theme.c timebox.c
+SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \
+ lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o)
-CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra -Wno-implicit-fallthrough \
- -Werror -fpic
+CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra \
+ -Wno-implicit-fallthrough -Werror -fpic
LDFLAGS = -lncursesw -ltinfo
LIBFLAG = -shared
diff --git a/lib/Makefile b/lib/Makefile
index 5c535c5483f1..0f536fb38743 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -3,13 +3,13 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.3
+VERSION = 0.4
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
-SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
- messagebox.c textbox.c theme.c timebox.c
+SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \
+ lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
diff --git a/lib/barbox.c b/lib/barbox.c
index b6bfe32fc0aa..71759839a709 100644
--- a/lib/barbox.c
+++ b/lib/barbox.c
@@ -327,7 +327,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
wrefresh(bar);
- /* getch(); port ncurses shows nothing */
+ /* getch(); alternate mode (port devel/ncurses) shows nothing */
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
diff --git a/lib/bsddialog.3 b/lib/bsddialog.3
index 12db1f039d59..9cc68a90ff62 100644
--- a/lib/bsddialog.3
+++ b/lib/bsddialog.3
@@ -22,11 +22,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 29, 2022
+.Dd September 23, 2022
.Dt BSDDIALOG 3
.Os
.Sh NAME
.Nm bsddialog_backtitle ,
+.Nm bsddialog_calendar ,
.Nm bsddialog_clearterminal ,
.Nm bsddialog_color ,
.Nm bsddialog_color_attrs ,
@@ -62,6 +63,16 @@
.Ft int
.Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle"
.Ft int
+.Fo bsddialog_calendar
+.Fa "struct bsddialog_conf *conf"
+.Fa "const char *text"
+.Fa "int rows"
+.Fa "int cols"
+.Fa "unsigned int *yy"
+.Fa "unsigned int *mm"
+.Fa "unsigned int *dd"
+.Fc
+.Ft int
.Fo bsddialog_checklist
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
@@ -75,7 +86,7 @@
.Ft int
.Fn bsddialog_clearterminal "void"
.Ft int
-.Fo bsddialog_datebox"
+.Fo bsddialog_datebox
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
.Fa "int rows"
@@ -476,7 +487,8 @@ function.
buttons always active, avoidind focus switch between buttons and input fields or
input boxes in
.Fn bsddialog_form ,
-.Fn bsddialog_datebox
+.Fn bsddialog_datebox ,
+.Fn bsddialog_calendar
and
.Fn bsddialog_timebox .
.It Fa conf.button.without_ok
@@ -515,7 +527,10 @@ to true,
and
.Fa conf.x
to
-.Dv BSDDIALOG_CENTER .
+.Dv BSDDIALOG_CENTER ,
+.Fa conf.text.cols_per_row
+to
+.Dv 10 .
.Pp
.Fn bsddialog_infobox
builds a dialog without buttons and returns instantly.
@@ -531,8 +546,10 @@ builds a dialog waiting until the timeout in
.Fa seconds
expires or a button is pressed.
.Pp
+.Fn bsddialog_calendar
+and
.Fn bsddialog_datebox
-builds a dialog to select a date,
+build a dialog to select a date,
.Fa yy ,
.Fa mm ,
and
@@ -606,14 +623,14 @@ builds a dialog with collections of checklists, radiolists and separators.
A collection is a set defined like:
.Pp
.Bd -literal -offset indent -compact
-enum bsddialog_grouptype {
+enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
- enum bsddialog_grouptype type;
+ enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@@ -1013,7 +1030,7 @@ struct bsddialog_menuitem check[2] = {
struct bsddialog_menuitem sep[1] = {
{ "3", true, 0, "Radiolist", "(desc)", "" }
};
-struct bsddialog_menuitem radio[5] = {
+struct bsddialog_menuitem radio[2] = {
{ "4", true, 0, "Name 1", "Desc 1", "Radio Bottom Desc 1" },
{ "5", false, 0, "Name 2", "Desc 2", "Radio Bottom Desc 2" }
};
diff --git a/lib/bsddialog.h b/lib/bsddialog.h
index 6f13da3fa667..ce6aac6d4632 100644
--- a/lib/bsddialog.h
+++ b/lib/bsddialog.h
@@ -30,7 +30,7 @@
#include <stdbool.h>
-#define LIBBSDDIALOG_VERSION "0.3"
+#define LIBBSDDIALOG_VERSION "0.4"
/* Exit status */
#define BSDDIALOG_ERROR -1
@@ -136,14 +136,14 @@ struct bsddialog_menuitem {
const char *bottomdesc;
};
-enum bsddialog_grouptype {
+enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
- enum bsddialog_grouptype type;
+ enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@@ -174,6 +174,10 @@ const char *bsddialog_geterror(void);
/* Dialogs */
int
+bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd);
+
+int
bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem);
diff --git a/lib/calendarbox.c b/lib/calendarbox.c
new file mode 100644
index 000000000000..3b55b26a13b8
--- /dev/null
+++ b/lib/calendarbox.c
@@ -0,0 +1,520 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Alfonso Sabato Siciliano
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+
+#include <curses.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bsddialog.h"
+#include "bsddialog_theme.h"
+#include "lib_util.h"
+
+#define MINHCAL 13
+#define MINWCAL 36 /* 34 calendar, 1 + 1 margins */
+#define MINYEAR 1900
+#define MAXYEAR 999999999
+
+static int month_days(int yy, int mm)
+{
+ int days;
+
+ if (mm == 2)
+ days = ISLEAP(yy) ? 29 : 28;
+ else if (mm == 4 || mm == 6 || mm == 9 || mm == 11)
+ days = 30;
+ else
+ days = 31;
+
+ return (days);
+}
+
+enum operation {
+ UP_DAY,
+ DOWN_DAY,
+ LEFT_DAY,
+ RIGHT_DAY,
+ UP_MONTH,
+ DOWN_MONTH,
+ UP_YEAR,
+ DOWN_YEAR
+};
+
+static void datectl(enum operation op, int *yy, int *mm, int *dd)
+{
+ int ndays;
+
+ ndays = month_days(*yy, *mm);
+
+ switch (op) {
+ case UP_DAY:
+ if (*dd > 7)
+ *dd -= 7;
+ else {
+ if (*mm == 1) {
+ *yy -= 1;
+ *mm = 12;
+ } else
+ *mm -= 1;
+ ndays = month_days(*yy, *mm);
+ *dd = ndays - abs(7 - *dd);
+ }
+ break;
+ case DOWN_DAY:
+ if (*dd + 7 < ndays)
+ *dd += 7;
+ else {
+ if (*mm == 12) {
+ *yy += 1;
+ *mm = 1;
+ } else
+ *mm += 1;
+ *dd = *dd + 7 - ndays;
+ }
+ break;
+ case LEFT_DAY:
+ if (*dd > 1)
+ *dd -= 1;
+ else {
+ if (*mm == 1) {
+ *yy -= 1;
+ *mm = 12;
+ } else
+ *mm -= 1;
+ *dd = month_days(*yy, *mm);
+ }
+ break;
+ case RIGHT_DAY:
+ if (*dd < ndays)
+ *dd += 1;
+ else {
+ if (*mm == 12) {
+ *yy += 1;
+ *mm = 1;
+ } else
+ *mm += 1;
+ *dd = 1;
+ }
+ break;
+ case UP_MONTH:
+ if (*mm == 1) {
+ *mm = 12;
+ *yy -= 1;
+ } else
+ *mm -= 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case DOWN_MONTH:
+ if (*mm == 12) {
+ *mm = 1;
+ *yy += 1;
+ } else
+ *mm += 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case UP_YEAR:
+ *yy -= 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case DOWN_YEAR:
+ *yy += 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ }
+
+ if (*yy < MINYEAR) {
+ *yy = MINYEAR;
+ *mm = 1;
+ *dd = 1;
+ }
+ if (*yy > MAXYEAR) {
+ *yy = MAXYEAR;
+ *mm = 12;
+ *dd = 31;
+ }
+}
+
+static int week_day(int yy, int mm, int dd)
+{
+ int wd;
+
+ dd += mm < 3 ? yy-- : yy - 2;
+ wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400;
+ wd %= 7;
+
+ return (wd);
+}
+
+static void
+print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
+ bool active)
+{
+ int ndays, i, y, x, wd, h, w;
+
+ getmaxyx(win, h, w);
+ wclear(win);
+ draw_borders(conf, win, h, w, RAISED);
+ if (active) {
+ wattron(win, t.dialog.arrowcolor);
+ mvwhline(win, 0, 15, conf->ascii_lines ? '^' : ACS_UARROW, 4);
+ mvwhline(win, h-1, 15, conf->ascii_lines ? 'v' : ACS_DARROW, 4);
+ mvwvline(win, 3, 0, conf->ascii_lines ? '<' : ACS_LARROW, 3);
+ mvwvline(win, 3, w-1, conf->ascii_lines ? '>' : ACS_RARROW, 3);
+ wattroff(win, t.dialog.arrowcolor);
+ }
+
+ mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat");
+ ndays = month_days(yy, mm);
+ y = 2;
+ wd = week_day(yy, mm, 1);
+ for (i = 1; i <= ndays; i++) {
+ x = 5 + (4 * wd); /* x has to be 6 with week number */
+ wmove(win, y, x);
+ mvwprintw(win, y, x, "%2d", i);
+ if (i == dd) {
+ wattron(win, t.menu.f_namecolor);
+ mvwprintw(win, y, x, "%2d", i);
+ wattroff(win, t.menu.f_namecolor);
+ }
+ wd++;
+ if (wd > 6) {
+ wd = 0;
+ y++;
+ }
+ }
+
+ wrefresh(win);
+}
+
+static void
+drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
+ const void *value, bool focus)
+{
+ int h, w;
+
+ getmaxyx(win, h, w);
+ draw_borders(conf, win, h, w, RAISED);
+ if (focus) {
+ wattron(win, t.dialog.arrowcolor);
+ mvwhline(win, 0, 7, conf->ascii_lines ? '^' : ACS_UARROW, 3);
+ mvwhline(win, 2, 7, conf->ascii_lines ? 'v' : ACS_DARROW, 3);
+ wattroff(win, t.dialog.arrowcolor);
+ }
+
+ if (focus)
+ wattron(win, t.menu.f_namecolor);
+ if (strchr(fmt, 's') != NULL)
+ mvwprintw(win, 1, 1, fmt, (const char*)value);
+ else
+ mvwprintw(win, 1, 1, fmt, *((const int*)value));
+ if (focus)
+ wattroff(win, t.menu.f_namecolor);
+
+ wrefresh(win);
+}
+
+static int
+calendar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
+ int *w, const char *text, struct buttons bs)
+{
+ int htext, wtext;
+
+ if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
+ if (text_size(conf, rows, cols, text, &bs, MINHCAL, MINWCAL,
+ &htext, &wtext) != 0)
+ return (BSDDIALOG_ERROR);
+ }
+
+ if (cols == BSDDIALOG_AUTOSIZE)
+ *w = widget_min_width(conf, wtext, MINWCAL, &bs);
+
+ if (rows == BSDDIALOG_AUTOSIZE)
+ *h = widget_min_height(conf, htext, MINHCAL, true);
+
+ return (0);
+}
+
+static int calendar_checksize(int rows, int cols, struct buttons bs)
+{
+ int mincols;
+
+ mincols = MAX(MINWCAL, buttons_min_width(bs));
+ mincols += VBORDERS;
+
+ if (cols < mincols)
+ RETURN_ERROR("Few cols for this calendar (at least 38)");
+
+ if (rows < MINHCAL + 2 + 2) /* 2 buttons + 2 borders */
+ RETURN_ERROR("Few rows for calendar (at least 17)");
+
+ return (0);
+}
+
+int
+bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
+{
+ bool loop, focusbuttons;
+ int retval, y, x, h, w, sel, ycal, xcal, year, month, day;
+ wint_t input;
+ WINDOW *widget, *textpad, *shadow, *yearwin, *monthwin, *daywin;
+ struct buttons bs;
+ const char *m[12] = {
+ "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December"
+ };
+
+ if (yy == NULL || mm == NULL || dd == NULL)
+ RETURN_ERROR("yy / mm / dd cannot be NULL");
+
+ year = *yy > MAXYEAR ? MAXYEAR : *yy;
+ if (year < MINYEAR)
+ year = MINYEAR;
+ month = *mm > 12 ? 12 : *mm;
+ if (month == 0)
+ month = 1;
+ day = *dd == 0 ? 1 : *dd;
+ if(day > month_days(year, month))
+ day = month_days(year, month);
+
+ get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_checksize(h, w, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return (BSDDIALOG_ERROR);
+
+ if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
+ true) != 0)
+ return (BSDDIALOG_ERROR);
+
+ pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
+ doupdate();
+
+ ycal = y + h - 15;
+ xcal = x + w/2 - 17;
+ mvwaddstr(widget, h - 16, w/2 - 17, "Month");
+ monthwin = new_boxed_window(conf, ycal, xcal, 3, 17, RAISED);
+ mvwaddstr(widget, h - 16, w/2, "Year");
+ yearwin = new_boxed_window(conf, ycal, xcal + 17, 3, 17, RAISED);
+ daywin = new_boxed_window(conf, ycal + 3, xcal, 9, 34, RAISED);
+
+ wrefresh(widget);
+
+ sel = -1;
+ loop = focusbuttons = true;
+ while (loop) {
+ drawsquare(conf, monthwin, "%15s", m[month - 1], sel == 0);
+ drawsquare(conf, yearwin, "%15d", &year, sel == 1);
+ print_calendar(conf, daywin, year, month, day, sel == 2);
+
+ if (get_wch(&input) == ERR)
+ continue;
+ switch(input) {
+ case KEY_ENTER:
+ case 10: /* Enter */
+ if (focusbuttons || conf->button.always_active) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
+ break;
+ case 27: /* Esc */
+ if (conf->key.enable_esc) {
+ retval = BSDDIALOG_ESC;
+ loop = false;
+ }
+ break;
+ case '\t': /* TAB */
+ if (focusbuttons) {
+ bs.curr++;
+ if (bs.curr >= (int)bs.nbuttons) {
+ focusbuttons = false;
+ sel = 0;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else {
+ sel++;
+ if (sel > 2) {
+ focusbuttons = true;
+ sel = -1;
+ bs.curr = 0;
+ }
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_RIGHT:
+ if (focusbuttons) {
+ bs.curr++;
+ if (bs.curr >= (int)bs.nbuttons) {
+ focusbuttons = false;
+ sel = 0;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else if (sel == 2) {
+ datectl(RIGHT_DAY, &year, &month, &day);
+ } else { /* Month or Year*/
+ sel++;
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_LEFT:
+ if (focusbuttons) {
+ bs.curr--;
+ if (bs.curr < 0) {
+ focusbuttons = false;
+ sel = 2;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else if (sel == 2) {
+ datectl(LEFT_DAY, &year, &month, &day);
+ } else if (sel == 1) {
+ sel = 0;
+ } else { /* sel = 0, Month */
+ focusbuttons = true;
+ sel = -1;
+ bs.curr = 0;
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_UP:
+ if (focusbuttons) {
+ sel = 2;
+ focusbuttons = false;
+ bs.curr = conf->button.always_active ? 0 : -1;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else if (sel == 0) {
+ datectl(UP_MONTH, &year, &month, &day);
+ } else if (sel == 1) {
+ datectl(UP_YEAR, &year, &month, &day);
+ } else { /* sel = 2 */
+ datectl(UP_DAY, &year, &month, &day);
+ }
+ break;
+ case KEY_DOWN:
+ if (focusbuttons) {
+ break;
+ } else if (sel == 0) {
+ datectl(DOWN_MONTH, &year, &month, &day);
+ } else if (sel == 1) {
+ datectl(DOWN_YEAR, &year, &month, &day);
+ } else { /* sel = 2 */
+ datectl(DOWN_DAY, &year, &month, &day);
+ }
+ break;
+ case KEY_HOME:
+ datectl(UP_MONTH, &year, &month, &day);
+ break;
+ case KEY_END:
+ datectl(DOWN_MONTH, &year, &month, &day);
+ break;
+ case KEY_PPAGE:
+ datectl(UP_YEAR, &year, &month, &day);
+ break;
+ case KEY_NPAGE:
+ datectl(DOWN_YEAR, &year, &month, &day);
+ break;
+ case KEY_F(1):
+ if (conf->key.f1_file == NULL &&
+ conf->key.f1_message == NULL)
+ break;
+ if (f1help(conf) != 0)
+ return (BSDDIALOG_ERROR);
+ /* No break, screen size can change */
+ case KEY_RESIZE:
+ /* Important for decreasing screen */
+ hide_widget(y, x, h, w, conf->shadow);
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_autosize(conf, rows, cols, &h, &w, text,
+ bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_checksize(h, w, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return (BSDDIALOG_ERROR);
+
+ if (update_dialog(conf, shadow, widget, y, x, h, w,
+ textpad, text, &bs, true) != 0)
+ return (BSDDIALOG_ERROR);
+ pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
+ doupdate();
+
+ ycal = y + h - 15;
+ xcal = x + w/2 - 17;
+ mvwaddstr(widget, h - 16, w/2 - 17, "Month");
+ mvwin(monthwin, ycal, xcal);
+ mvwaddstr(widget, h - 16, w/2, "Year");
+ mvwin(yearwin, ycal, xcal + 17);
+ mvwin(daywin, ycal + 3, xcal);
+ wrefresh(widget);
+
+ /* Important to avoid grey lines expanding screen */
+ refresh();
+ break;
+ default:
+ if (shortcut_buttons(input, &bs)) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
+ }
+ }
+
+ if (retval == BSDDIALOG_OK) {
+ *yy = year;
+ *mm = month;
+ *dd = day;
+ }
+
+ delwin(yearwin);
+ delwin(monthwin);
+ delwin(daywin);
+ end_dialog(conf, shadow, widget, textpad);
+
+ return (retval);
+} \ No newline at end of file
diff --git a/lib/formbox.c b/lib/formbox.c
index cd29919417be..5b1d2ab61de2 100644
--- a/lib/formbox.c
+++ b/lib/formbox.c
@@ -424,34 +424,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
} else
notext += *menurows;
- /* cols autosize, rows autosize, rows fullscreen, menu particularity */
- if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) {
- if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4,
- &htext, &wtext) != 0)
- return (BSDDIALOG_ERROR);
- }
+ if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext,
+ &wtext) != 0)
+ return (BSDDIALOG_ERROR);
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, linelen + 4, &bs);
if (rows == BSDDIALOG_AUTOSIZE) {
- if (*menurows == 0) {
+ if (*menurows == BSDDIALOG_AUTOSIZE) {
menusize = widget_max_height(conf) - HBORDERS -
2 /*buttons*/ - htext;
menusize = MIN(menusize, nitems + 2);
*menurows = menusize - 2 < 0 ? 0 : menusize - 2;
- }
- else /* h autosize with fixed menurows */
+ } else /* h autosize with fixed menurows */
menusize = *menurows + 2;
*h = widget_min_height(conf, htext, menusize, true);
- /*
- * avoid menurows overflow and
- * with rows=AUTOSIZE menurows!=0 becomes max-menurows
- */
- *menurows = MIN(*h - 6 - htext, (int)*menurows);
- } else {
- if (*menurows == 0) {
+ } else { /* fixed rows */
+ if (*menurows == BSDDIALOG_AUTOSIZE) {
if (*h - 6 - htext <= 0)
*menurows = 0; /* form_checksize() will check */
else
@@ -459,6 +450,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
}
}
+ /* avoid menurows overflow and menurows becomes at most menurows */
+ if (*h - 6 - htext <= 0)
+ *menurows = 0; /* form_checksize() will check */
+ else
+ *menurows = MIN(*h - 6 - htext, (int)*menurows);
+
return (0);
}
diff --git a/lib/lib_util.c b/lib/lib_util.c
index fcdf4c3d8769..d8c0f1d21b42 100644
--- a/lib/lib_util.c
+++ b/lib/lib_util.c
@@ -921,11 +921,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
*h = maxheight;
else if (rows < BSDDIALOG_FULLSCREEN)
RETURN_ERROR("Negative (less than -1) height");
- else if (rows > BSDDIALOG_AUTOSIZE) {
- if ((*h = rows) > maxheight)
- RETURN_ERROR("Height too big (> terminal height - "
- "shadow)");
- }
+ else if (rows > BSDDIALOG_AUTOSIZE) /* fixed rows */
+ *h = MIN(rows, maxheight); /* rows is at most maxheight */
/* rows == AUTOSIZE: each widget has to set its size */
if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR)
@@ -935,11 +932,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
*w = maxwidth;
else if (cols < BSDDIALOG_FULLSCREEN)
RETURN_ERROR("Negative (less than -1) width");
- else if (cols > BSDDIALOG_AUTOSIZE) {
- if ((*w = cols) > maxwidth)
- RETURN_ERROR("Width too big (> terminal width - "
- "shadow)");
- }
+ else if (cols > BSDDIALOG_AUTOSIZE) /* fixed cols */
+ *w = MIN(cols, maxwidth); /* cols is at most maxwidth */
/* cols == AUTOSIZE: each widget has to set its size */
return (0);
diff --git a/lib/lib_util.h b/lib/lib_util.h
index 238d3fda4675..17ea0e0d1368 100644
--- a/lib/lib_util.h
+++ b/lib/lib_util.h
@@ -43,6 +43,9 @@ extern bool hastermcolors;
refresh(); \
} while (0)
+/* date */
+#define ISLEAP(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+
/* unicode */
unsigned int strcols(const char *mbstring);
int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col);
diff --git a/lib/libbsddialog.c b/lib/libbsddialog.c
index 1a8188b0e7d3..73c1f5c2dd57 100644
--- a/lib/libbsddialog.c
+++ b/lib/libbsddialog.c
@@ -99,7 +99,9 @@ int bsddialog_end(void)
int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle)
{
- mvaddstr(0, 1, backtitle);
+ move(0, 1);
+ clrtoeol();
+ addstr(backtitle);
if (conf->no_lines != true)
mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE,
SCREENCOLS - 2);
diff --git a/lib/menubox.c b/lib/menubox.c
index 28b9c8a0923b..bd06a9e37df2 100644
--- a/lib/menubox.c
+++ b/lib/menubox.c
@@ -36,7 +36,6 @@
#include "bsddialog_theme.h"
#include "lib_util.h"
-#define DEPTH 2
#define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */
enum menumode {
@@ -277,7 +276,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
colorname = focus ? t.menu.f_namecolor : t.menu.namecolor;
if (conf->menu.no_name == false) {
wattron(pad, colorname);
- mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, item->name);
+ mvwaddstr(pad, y, pos.xname + item->depth, item->name);
wattroff(pad, colorname);
}
@@ -290,8 +289,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
if (conf->menu.no_desc == false) {
wattron(pad, colordesc);
if (conf->menu.no_name)
- mvwaddstr(pad, y, pos.xname + item->depth * DEPTH,
- item->desc);
+ mvwaddstr(pad, y, pos.xname + item->depth, item->desc);
else
mvwaddstr(pad, y, pos.xdesc, item->desc);
wattroff(pad, colordesc);
@@ -307,7 +305,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
mbtowc(&shortcut, item->desc, MB_CUR_MAX);
else
mbtowc(&shortcut, item->name, MB_CUR_MAX);
- mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut);
+ mvwaddwch(pad, y, pos.xname + item->depth, shortcut);
wattroff(pad, colorshortcut);
}
@@ -362,34 +360,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
} else
notext += *menurows;
- /* cols autosize, rows autosize, rows fullscreen, menu particularity */
- if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) {
- if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4,
- &htext, &wtext) != 0)
- return (BSDDIALOG_ERROR);
- }
+ if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext,
+ &wtext) != 0)
+ return (BSDDIALOG_ERROR);
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, linelen + 4, &bs);
if (rows == BSDDIALOG_AUTOSIZE) {
- if (*menurows == 0) {
+ if (*menurows == BSDDIALOG_AUTOSIZE) {
menusize = widget_max_height(conf) - HBORDERS -
2 /*buttons*/ - htext;
menusize = MIN(menusize, nitems + 2);
*menurows = menusize - 2 < 0 ? 0 : menusize - 2;
- }
- else /* h autosize with fixed menurows */
+ } else /* h autosize with fixed menurows */
menusize = *menurows + 2;
*h = widget_min_height(conf, htext, menusize, true);
- /*
- * avoid menurows overflow and
- * with rows=AUTOSIZE menurows!=0 becomes max-menurows
- */
- *menurows = MIN(*h - 6 - htext, (int)*menurows);
- } else {
- if (*menurows == 0) {
+ } else { /* fixed rows */
+ if (*menurows == BSDDIALOG_AUTOSIZE) {
if (*h - 6 - htext <= 0)
*menurows = 0; /* menu_checksize() will check */
else
@@ -397,6 +386,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
}
}
+ /* avoid menurows overflow and menurows becomes at most menurows */
+ if (*h - 6 - htext <= 0)
+ *menurows = 0; /* menu_checksize() will check */
+ else
+ *menurows = MIN(*h - 6 - htext, (int)*menurows);
+
return (0);
}
@@ -475,7 +470,6 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
}
pos.maxname = conf->menu.no_name ? 0 : pos.maxname;
pos.maxdesc = conf->menu.no_desc ? 0 : pos.maxdesc;
- pos.maxdepth = DEPTH * pos.maxdepth;
pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0);
pos.xname = pos.xselector + pos.selectorlen +
@@ -696,11 +690,15 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
movefocus = next != abs;
break;
case ' ': /* Space */
- if (pritems[abs].type == MENUMODE)
- break;
- else if (pritems[abs].type == CHECKLISTMODE)
+ if (pritems[abs].type == MENUMODE) {
+ retval = bs.value[bs.curr];
+ pritems[abs].on = true;
+ set_on_output(conf, retval, ngroups, groups,
+ pritems);
+ loop = false;
+ } else if (pritems[abs].type == CHECKLISTMODE) {
pritems[abs].on = !pritems[abs].on;
- else { /* RADIOLISTMODE */
+ } else { /* RADIOLISTMODE */
for (i = abs - pritems[abs].index;
i < totnitems &&
pritems[i].group == pritems[abs].group;
diff --git a/lib/messagebox.c b/lib/messagebox.c
index 06753be20c3d..7063ea9d273e 100644
--- a/lib/messagebox.c
+++ b/lib/messagebox.c
@@ -103,7 +103,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
struct buttons bs)
{
bool hastext, loop;
- int y, x, h, w, retval, ytextpad, htextpad, unused;
+ int y, x, h, w, retval, ytextpad, htextpad, printrows, unused;
WINDOW *widget, *textpad, *shadow;
wint_t input;
@@ -120,12 +120,13 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
true) != 0)
return (BSDDIALOG_ERROR);
+ printrows = h - 4;
ytextpad = 0;
getmaxyx(textpad, htextpad, unused);
unused++; /* fix unused error */
- textupdate(widget, textpad, htextpad, ytextpad, hastext);
loop = true;
while (loop) {
+ textupdate(widget, textpad, htextpad, ytextpad, hastext);
doupdate();
if (get_wch(&input) == ERR)
continue;
@@ -160,6 +161,30 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
wnoutrefresh(widget);
}
break;
+ case KEY_UP:
+ if (ytextpad > 0)
+ ytextpad--;
+ break;
+ case KEY_DOWN:
+ if (ytextpad + printrows < htextpad)
+ ytextpad++;
+ break;
+ case KEY_HOME:
+ ytextpad = 0;
+ break;
+ case KEY_END:
+ ytextpad = htextpad - printrows;
+ ytextpad = ytextpad < 0 ? 0 : ytextpad;
+ break;
+ case KEY_PPAGE:
+ ytextpad -= printrows;
+ ytextpad = ytextpad < 0 ? 0 : ytextpad;
+ break;
+ case KEY_NPAGE:
+ ytextpad += printrows;
+ if (ytextpad + printrows > htextpad)
+ ytextpad = htextpad - printrows;
+ break;
case KEY_F(1):
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
@@ -186,6 +211,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
+ printrows = h - 4;
getmaxyx(textpad, htextpad, unused);
ytextpad = 0;
textupdate(widget, textpad, htextpad, ytextpad, hastext);
@@ -193,18 +219,6 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
/* Important to fix grey lines expanding screen */
refresh();
break;
- case KEY_UP:
- if (ytextpad == 0)
- break;
- ytextpad--;
- textupdate(widget, textpad, htextpad, ytextpad, hastext);
- break;
- case KEY_DOWN:
- if (ytextpad + h - 4 >= htextpad)
- break;
- ytextpad++;
- textupdate(widget, textpad, htextpad, ytextpad, hastext);
- break;
default:
if (shortcut_buttons(input, &bs)) {
retval = bs.value[bs.curr];
diff --git a/lib/theme.c b/lib/theme.c
index 40310d58cda4..6e53eb356825 100644
--- a/lib/theme.c
+++ b/lib/theme.c
@@ -258,7 +258,6 @@ int bsddialog_set_theme(struct bsddialog_theme *theme)
int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
{
-
if (newtheme == BSDDIALOG_THEME_FLAT) {
bsddialog_set_theme(&dialogtheme);
t.dialog.lineraisecolor = t.dialog.linelowercolor;
diff --git a/lib/timebox.c b/lib/timebox.c
index 529563b49bca..53989bb97157 100644
--- a/lib/timebox.c
+++ b/lib/timebox.c
@@ -39,7 +39,7 @@
#define MINWTIME 14 /* 3 windows and their borders */
static void
-drawquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
+drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
const void *value, bool focus)
{
int h, l, w;
@@ -167,7 +167,7 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
loop = focusbuttons = true;
while (loop) {
for (i = 0; i < 3; i++)
- drawquare(conf, c[i].win, "%02d", &c[i].value,
+ drawsquare(conf, c[i].win, "%02d", &c[i].value,
sel == i);
if (get_wch(&input) == ERR)
@@ -341,8 +341,6 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
{ "October", 31 }, { "November", 30 }, { "December", 31 }
};
-#define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
-
for (i = 0 ; i < 3; i++) {
if (c[i].value > c[i].max)
c[i].value = c[i].max;
@@ -350,7 +348,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
c[i].value = 1;
}
c[2].max = m[c[1].value -1].days;
- if (c[1].value == 2 && ISLEAF(c[0].value))
+ if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
if (c[2].value > c[2].max)
c[2].value = c[2].max;
@@ -385,10 +383,10 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
sel = -1;
loop = focusbuttons = true;
while (loop) {
- drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
- drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
+ drawsquare(conf, c[0].win, "%4d", &c[0].value, sel == 0);
+ drawsquare(conf, c[1].win, "%9s", m[c[1].value-1].name,
sel == 1);
- drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
+ drawsquare(conf, c[2].win, "%02d", &c[2].value, sel == 2);
if (get_wch(&input) == ERR)
continue;
@@ -456,7 +454,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* if year change */
- if (c[1].value == 2 && ISLEAF(c[0].value))
+ if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
/* set new day */
if (c[2].value > c[2].max)
@@ -471,7 +469,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
/* if mount change */
c[2].max = m[c[1].value -1].days;
/* if year change */
- if (c[1].value == 2 && ISLEAF(c[0].value))
+ if (c[1].value == 2 && ISLEAP(c[0].value))
c[2].max = 29;
/* set new day */
if (c[2].value > c[2].max)
@@ -539,4 +537,4 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
end_dialog(conf, shadow, widget, textpad);
return (retval);
-}
+} \ No newline at end of file