aboutsummaryrefslogtreecommitdiff
path: root/contrib/bsddialog/lib/barbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bsddialog/lib/barbox.c')
-rw-r--r--contrib/bsddialog/lib/barbox.c980
1 files changed, 489 insertions, 491 deletions
diff --git a/contrib/bsddialog/lib/barbox.c b/contrib/bsddialog/lib/barbox.c
index b0d5c0febcf8..cd9fee836f8a 100644
--- a/contrib/bsddialog/lib/barbox.c
+++ b/contrib/bsddialog/lib/barbox.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2021 Alfonso Sabato Siciliano
+ * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,643 +25,641 @@
* SUCH DAMAGE.
*/
-#include <sys/param.h>
-
-#include <ctype.h>
+#include <curses.h>
#include <stdlib.h>
#include <string.h>
-
-#ifdef PORTNCURSES
-#include <ncurses/curses.h>
-#else
-#include <curses.h>
-#endif
+#include <time.h>
+#include <unistd.h>
#include "bsddialog.h"
-#include "lib_util.h"
+#include "bsddialog_progressview.h"
#include "bsddialog_theme.h"
+#include "lib_util.h"
-#define BARMARGIN 3
-#define MINBARWIDTH 10
-#define MINWIDTH (VBORDERS + MINBARWIDTH + BARMARGIN * 2)
-#define MINHEIGHT 7 /* without text */
-
-/* "Bar": gauge - mixedgauge - rangebox - pause */
-
-extern struct bsddialog_theme t;
-
-static void
-draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel,
- int label)
+#define BARPADDING 2 /* widget border | BARPADDING | box bar */
+#define BOXBORDERS 2
+#define MIN_WBAR 15
+#define MIN_WBOX (BARPADDING + BOXBORDERS + MIN_WBAR + BARPADDING)
+#define MIN_WMGBAR 18
+#define MIN_WMGBOX (BARPADDING + BOXBORDERS + MIN_WMGBAR + BARPADDING)
+#define HBOX 3
+#define WBOX(d) ((d)->w - BORDERS - BARPADDING - BARPADDING)
+#define WBAR(d) (WBOX(d) - BOXBORDERS)
+
+bool bsddialog_interruptprogview;
+bool bsddialog_abortprogview;
+long long int bsddialog_total_progview;
+
+static const char states[12][14] = {
+ " Succeeded ", /* -1 */
+ " Failed ", /* -2 */
+ " Passed ", /* -3 */
+ " Completed ", /* -4 */
+ " Checked ", /* -5 */
+ " Done ", /* -6 */
+ " Skipped ", /* -7 */
+ " In Progress ", /* -8 */
+ "(blank) ", /* -9 */
+ " N/A ", /* -10 */
+ " Pending ", /* -11 */
+ " UNKNOWN ", /* < -11, no API */
+};
+
+struct bar {
+ bool toupdate;
+ WINDOW *win;
+ int y; /* bar y in win */
+ int x; /* bar x in win */
+ int w; /* width in win */
+ int perc; /* barlen = (w * perc) / 100 */
+ const char* fmt; /* format for label */
+ int label; /* rangebox and pause perc!=label */
+};
+
+static void draw_bar(struct bar *b)
{
- char labelstr[128];
- int i, blue_x, color;
-
- blue_x = (int)((perc*(size))/100);
-
- wmove(win, y, x);
- for (i = 0; i < size; i++) {
- color = (i <= blue_x) ? t.bar.f_color : t.bar.color;
- wattron(win, color);
- waddch(win, ' ');
- wattroff(win, color);
- }
-
- if (withlabel)
- sprintf(labelstr, "%d", label);
- else
- sprintf(labelstr, "%3d%%", perc);
- wmove(win, y, x + size/2 - 2);
- for (i=0; i < (int) strlen(labelstr); i++) {
- color = (blue_x + 1 <= size/2 - (int)strlen(labelstr)/2 + i ) ?
- t.bar.color : t.bar.f_color;
- wattron(win, color);
- waddch(win, labelstr[i]);
- wattroff(win, color);
- }
+ int barlen, xlabel;
+ chtype ch;
+ char label[128];
+
+ barlen = b->perc > 0 ? (b->perc * b->w) / 100 : 0;
+
+ ch = ' ' | t.bar.f_color;
+ mvwhline(b->win, b->y, b->x, ch, barlen);
+ ch = ' ' | t.bar.color;
+ mvwhline(b->win, b->y, b->x + barlen, ch, b->w - barlen);
+
+ sprintf(label, b->fmt, b->label);
+ xlabel = b->x + b->w/2 - (int)strlen(label)/2; /* 1-byte-char string */
+ wattron(b->win, t.bar.color); /* x+barlen < xlabel */
+ mvwaddstr(b->win, b->y, xlabel, label);
+ wattroff(b->win, t.bar.color);
+ wattron(b->win, t.bar.f_color); /* x+barlen >= xlabel */
+ mvwaddnstr(b->win, b->y, xlabel, label, MAX((b->x+barlen) - xlabel, 0));
+ wattroff(b->win, t.bar.f_color);
+
+ if (b->toupdate)
+ wnoutrefresh(b->win);
+ b->toupdate = false;
}
-static int
-bar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
- char *text, struct buttons *bs)
+static void update_barbox(struct dialog *d, struct bar *b, bool buttons)
{
- int maxword, maxline, nlines, buttonswidth;
-
- if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
- return BSDDIALOG_ERROR;
-
- buttonswidth = 0;
- if (bs != NULL) { /* gauge has not buttons */
- buttonswidth= bs->nbuttons * bs->sizebutton;
- if (bs->nbuttons > 0)
- buttonswidth += (bs->nbuttons-1) * t.button.space;
- }
+ int y;
- if (cols == BSDDIALOG_AUTOSIZE) {
- *w = VBORDERS;
- /* buttons size */
- *w += buttonswidth;
- /* bar size */
- *w = MAX(*w, MINWIDTH);
- /* text size*/
- *w = MAX((int)(maxline + VBORDERS + t.text.hmargin * 2), *w);
- /* avoid terminal overflow */
- *w = MIN(*w, widget_max_width(conf));
- }
-
- if (rows == BSDDIALOG_AUTOSIZE) {
- *h = MINHEIGHT;
- if (maxword > 0)
- *h += 1;
- /* avoid terminal overflow */
- *h = MIN(*h, widget_max_height(conf));
- }
-
- return (0);
-}
-
-static int
-bar_checksize(char *text, int rows, int cols, struct buttons *bs)
-{
- int minheight, minwidth;
-
- minwidth = 0;
- if (bs != NULL) { /* gauge has not buttons */
- minwidth = bs->nbuttons * bs->sizebutton;
- if (bs->nbuttons > 0)
- minwidth += (bs->nbuttons-1) * t.button.space;
- }
- minwidth = MAX(minwidth + VBORDERS, MINBARWIDTH);
-
- if (cols< minwidth)
- RETURN_ERROR("Few cols for this widget");
-
- minheight = MINHEIGHT + ((text != NULL && strlen(text) > 0) ? 1 : 0);
- if (rows < minheight)
- RETURN_ERROR("Few rows for this mixedgauge");
-
- return 0;
+ y = d->y + d->h - BORDER - HBOX;
+ if (buttons)
+ y -= HBUTTONS;
+ update_box(d->conf, b->win, y, d->x + BORDER + BARPADDING, HBOX,
+ WBOX(d), RAISED);
}
int
-bsddialog_gauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
- unsigned int perc)
+bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int perc, int fd, const char *sep, const char *end)
{
- WINDOW *widget, *textpad, *bar, *shadow;
- char input[2048], ntext[2048], *pntext;
- int y, x, h, w, htextpad;
bool mainloop;
+ int fd2;
+ FILE *input;
+ char inputbuf[2048], ntext[2048], *pntext;
+ struct bar b;
+ struct dialog d;
+
+ if (prepare_dialog(conf, text, rows, cols, &d) != 0)
+ return (BSDDIALOG_ERROR);
+ if ((b.win = newwin(1, 1, 1, 1)) == NULL)
+ RETURN_ERROR("Cannot build WINDOW bar");
+ b.y = b.x = 1;
+ b.fmt = "%3d%%";
+
+ input = NULL;
+ if (fd >= 0) {
+ CHECK_PTR(sep);
+ CHECK_PTR(end);
+
+ fd2 = dup(fd);
+ if ((input = fdopen(fd2, "r")) == NULL)
+ RETURN_FMTERROR("Cannot build FILE* from fd %d", fd);
+ }
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
- if (bar_autosize(conf, rows, cols, &h, &w, text, NULL) != 0)
- return BSDDIALOG_ERROR;
- if (bar_checksize(text, h, w, NULL) != 0)
- return BSDDIALOG_ERROR;
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
- &textpad, &htextpad, text, false) != 0)
- return BSDDIALOG_ERROR;
-
- bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
-
+ perc = MIN(perc, 100);
mainloop = true;
while (mainloop) {
- wrefresh(widget);
- prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-4,
- x+w-1-t.text.hmargin);
- draw_perc_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
- wrefresh(bar);
+ if (d.built) {
+ hide_dialog(&d);
+ refresh(); /* Important for decreasing screen */
+ }
+ if (dialog_size_position(&d, HBOX, MIN_WBOX, NULL) != 0)
+ return (BSDDIALOG_ERROR);
+ if (draw_dialog(&d))
+ return (BSDDIALOG_ERROR);
+ if (d.built)
+ refresh(); /* fix grey lines expanding screen */
+ TEXTPAD(&d, HBOX);
+ update_barbox(&d, &b, false);
+ b.w = WBAR(&d);
+ b.perc = b.label = perc;
+ b.toupdate = true;
+ draw_bar(&b);
+ doupdate();
+ if (input == NULL) /* that is fd < 0 */
+ break;
while (true) {
- scanf("%s", input);
- if (strcmp(input,"EOF") == 0) {
+ fscanf(input, "%s", inputbuf);
+ if (strcmp(inputbuf, end) == 0) {
mainloop = false;
break;
}
- if (strcmp(input,"XXX") == 0)
+ if (strcmp(inputbuf, sep) == 0)
break;
}
- scanf("%d", &perc);
- perc = perc < 0 ? 0 : perc;
- perc = perc > 100 ? 100 : perc;
- htextpad = 1;
- wclear(textpad);
+ if (mainloop == false)
+ break;
+ fscanf(input, "%d", &perc);
+ perc = MIN(perc, 100);
pntext = &ntext[0];
ntext[0] = '\0';
while (true) {
- scanf("%s", input);
- if (strcmp(input,"EOF") == 0) {
+ fscanf(input, "%s", inputbuf);
+ if (strcmp(inputbuf, end) == 0) {
mainloop = false;
break;
}
- if (strcmp(input,"XXX") == 0)
+ if (strcmp(inputbuf, sep) == 0)
break;
+ strcpy(pntext, inputbuf);
+ pntext += strlen(inputbuf); /* end string, no strlen */
pntext[0] = ' ';
pntext++;
- strcpy(pntext, input);
- pntext += strlen(input);
}
- print_textpad(conf, textpad, &htextpad, w-2-t.text.hmargin*2,
- ntext);
+ pntext[0] = '\0';
+ d.text = ntext;
}
- delwin(bar);
- end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
+ if (input != NULL)
+ fclose(input);
+ delwin(b.win);
+ end_dialog(&d);
- return BSDDIALOG_YESOK;
+ return (BSDDIALOG_OK);
}
-int
-bsddialog_mixedgauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
- unsigned int mainperc, unsigned int nminbars, char **minibars)
+/* Mixedgauge */
+static int
+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)
{
- WINDOW *widget, *textpad, *bar, *shadow;
- int i, output, miniperc, y, x, h, w, max_minbarlen;
- int maxword, maxline, nlines, htextpad, ypad;
- char states[11][16] = {
- "[ Succeeded ]",
- "[ Failed ]",
- "[ Passed ]",
- "[ Completed ]",
- "[ Checked ]",
- "[ Done ]",
- "[ Skipped ]",
- "[ In Progress ]",
- "!!! BLANK !!!",
- "[ N/A ]",
- "[ UNKNOWN ]",
- };
-
- if (nminbars % 2 !=0)
- RETURN_ERROR("Mixedgauge wants a pair name/perc");
-
- max_minbarlen = 0;
- for (i=0; i < (int)(nminbars/2); i++)
- max_minbarlen = MAX(max_minbarlen, (int) strlen(minibars[i*2]));
- max_minbarlen += 3 + 16 /* seps + [...] or mainbar */;
-
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
-
- /* mixedgauge autosize */
- if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
- return BSDDIALOG_ERROR;
-
- if (cols == BSDDIALOG_AUTOSIZE) {
- w = max_minbarlen + HBORDERS;
- w = MAX(max_minbarlen, maxline + 4);
- w = MIN(w, widget_max_width(conf) - 1);
- }
- if (rows == BSDDIALOG_AUTOSIZE) {
- h = 5; /* borders + mainbar */
- h += nminbars/2;
- h += (strlen(text) > 0 ? 3 : 0);
- h = MIN(h, widget_max_height(conf) -1);
- }
-
- /* mixedgauge checksize */
- if (w < max_minbarlen + 2)
- RETURN_ERROR("Few cols for this mixedgauge");
- if (h < 5 + (int)nminbars/2 + (strlen(text) > 0 ? 1 : 0))
- RETURN_ERROR("Few rows for this mixedgauge");
-
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- output = new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w,
- RAISED, &textpad, &htextpad, text, false);
- if (output == BSDDIALOG_ERROR)
- return output;
+ int i, miniperc, max_minibarlen;
+ int ystext, htext;
+ int minicolor, red, green;
+ struct bar b;
+ struct dialog d;
+
+ CHECK_ARRAY(nminibars, minilabels);
+ CHECK_ARRAY(nminibars, minipercs);
+
+ red = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_RED, BSDDIALOG_BOLD);
+ green = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_GREEN,BSDDIALOG_BOLD);
+
+ max_minibarlen = 0;
+ for (i = 0; i < (int)nminibars; i++)
+ max_minibarlen = MAX(max_minibarlen,
+ (int)strcols(CHECK_STR(minilabels[i])));
+ max_minibarlen += 3 + 16; /* seps + [...] */
+ max_minibarlen = MAX(max_minibarlen, MIN_WMGBOX); /* mainbar */
+
+ if (prepare_dialog(conf, text, rows, cols, &d) != 0)
+ return (BSDDIALOG_ERROR);
+ if (dialog_size_position(&d, nminibars + HBOX, max_minibarlen,
+ &htext) != 0)
+ return (BSDDIALOG_ERROR);
+ if (draw_dialog(&d) != 0)
+ return (BSDDIALOG_ERROR);
/* mini bars */
- for (i=0; i < (int)nminbars/2; i++) {
- miniperc = atol(minibars[i*2 + 1]);
- if (miniperc == 8)
+ b.win = d.widget;
+ b.x = 1 + d.w - 2 - 15;
+ b.w = 13;
+ b.fmt = "%3d%%";
+ b.toupdate = false;
+ for (i = 0; i < (int)nminibars; i++) {
+ miniperc = minipercs[i];
+ /* label */
+ if (color && miniperc >= 0)
+ wattron(d.widget, A_BOLD);
+ mvwaddstr(d.widget, i+1, 2, CHECK_STR(minilabels[i]));
+ if (color && miniperc >= 0)
+ wattroff(d.widget, A_BOLD);
+ /* perc */
+ if (miniperc == BSDDIALOG_MG_BLANK)
continue;
- mvwaddstr(widget, i+1, 2, minibars[i*2]);
- if (miniperc > 9)
- mvwaddstr(widget, i+1, w-2-15, states[10]);
- else if (miniperc >= 0 && miniperc <= 9)
- mvwaddstr(widget, i+1, w-2-15, states[miniperc]);
- else { //miniperc < 0
- miniperc = abs(miniperc);
- mvwaddstr(widget, i+1, w-2-15, "[ ]");
- draw_perc_bar(widget, i+1, 1+w-2-15, 13, miniperc,
- false, -1 /*unused*/);
+ mvwaddstr(d.widget, i+1, d.w-2-15, "[ ]");
+ if (miniperc >= 0) {
+ b.y = i + 1;
+ b.perc = b.label = MIN(miniperc, 100);
+ draw_bar(&b);
+ } else { /* miniperc < 0 */
+ if (miniperc < BSDDIALOG_MG_PENDING)
+ miniperc = -12; /* UNKNOWN */
+ minicolor = t.dialog.color;
+ if (color && miniperc == BSDDIALOG_MG_FAILED)
+ minicolor = red;
+ else if (color && miniperc == BSDDIALOG_MG_DONE)
+ minicolor = green;
+ wattron(d.widget, minicolor);
+ miniperc = abs(miniperc + 1);
+ mvwaddstr(d.widget, i+1, 1+d.w-2-15, states[miniperc]);
+ wattroff(d.widget, minicolor);
}
}
+ wnoutrefresh(d.widget);
+
+ /* text */
+ ystext = MAX(d.h - BORDERS - htext - HBOX, (int)nminibars);
+ rtextpad(&d, 0, 0, ystext, HBOX);
- wrefresh(widget);
- ypad = y + h - 5 - htextpad;
- ypad = ypad < y+(int)nminbars/2 ? y+nminbars/2 : ypad;
- prefresh(textpad, 0, 0, ypad, x+2, y+h-4, x+w-2);
-
/* main bar */
- bar = new_boxed_window(conf, y+h -4, x+3, 3, w-6, RAISED);
-
- draw_perc_bar(bar, 1, 1, w-8, mainperc, false, -1 /*unused*/);
+ if ((b.win = newwin(1, 1, 1, 1)) == NULL)
+ RETURN_ERROR("Cannot build WINDOW bar");
+ update_barbox(&d, &b, false);
+ wattron(b.win, t.bar.color);
+ mvwaddstr(b.win, 0, 2, "Overall Progress");
+ wattroff(b.win, t.bar.color);
+
+ b.y = b.x = 1;
+ b.w = WBAR(&d);
+ b.fmt = "%3d%%";
+ b.perc = b.label = MIN(mainperc, 100);
+ b.toupdate = true;
+ draw_bar(&b);
+
+ doupdate();
+ /* getch(); to test with "alternate mode" */
+
+ delwin(b.win);
+ end_dialog(&d);
+
+ return (BSDDIALOG_OK);
+}
- wattron(bar, t.bar.color);
- mvwaddstr(bar, 0, 2, "Overall Progress");
- wattroff(bar, t.bar.color);
+int
+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 retval;
- wrefresh(bar);
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
+ minilabels, minipercs, false);
- /* getch(); port ncurses shows nothing */
+ return (retval);
+}
- delwin(bar);
- end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
+int
+bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, struct bsddialog_progviewconf *pvconf, unsigned int nminibar,
+ struct bsddialog_fileminibar *minibar)
+{
+ bool update;
+ int perc, retval, *minipercs;
+ unsigned int i, mainperc, totaltodo;
+ float readforsec;
+ const char **minilabels;
+ time_t tstart, told, tnew, refresh;
+
+ if ((minilabels = calloc(nminibar, sizeof(char*))) == NULL)
+ RETURN_ERROR("Cannot allocate memory for minilabels");
+ if ((minipercs = calloc(nminibar, sizeof(int))) == NULL)
+ RETURN_ERROR("Cannot allocate memory for minipercs");
+
+ totaltodo = 0;
+ for (i = 0; i < nminibar; i++) {
+ totaltodo += minibar[i].size;
+ minilabels[i] = minibar[i].label;
+ minipercs[i] = minibar[i].status;
+ }
+
+ refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
+ retval = BSDDIALOG_OK;
+ i = 0;
+ update = true;
+ time(&told);
+ tstart = told;
+ while (!(bsddialog_interruptprogview || bsddialog_abortprogview)) {
+ if (bsddialog_total_progview == 0 || totaltodo == 0)
+ mainperc = 0;
+ else
+ mainperc = (bsddialog_total_progview * 100) / totaltodo;
+
+ time(&tnew);
+ if (update || tnew > told + refresh) {
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc,
+ nminibar, minilabels, minipercs, true);
+ if (retval == BSDDIALOG_ERROR)
+ return (BSDDIALOG_ERROR);
+
+ move(SCREENLINES - 1, 2);
+ clrtoeol();
+ readforsec = ((tnew - tstart) == 0) ? 0 :
+ bsddialog_total_progview / (float)(tnew - tstart);
+ printw(pvconf->fmtbottomstr, bsddialog_total_progview,
+ readforsec);
+ refresh();
- return BSDDIALOG_YESOK;
+ time(&told);
+ update = false;
+ }
+
+ if (i >= nminibar)
+ break;
+ if (minibar[i].status == BSDDIALOG_MG_FAILED)
+ break;
+
+ perc = pvconf->callback(&minibar[i]);
+
+ if (minibar[i].status == BSDDIALOG_MG_DONE) { /*||perc >= 100)*/
+ minipercs[i] = BSDDIALOG_MG_DONE;
+ update = true;
+ i++;
+ } else if (minibar[i].status == BSDDIALOG_MG_FAILED ||
+ perc < 0) {
+ minipercs[i] = BSDDIALOG_MG_FAILED;
+ update = true;
+ } else /* perc >= 0 */
+ minipercs[i] = perc;
+ }
+
+ free(minilabels);
+ free(minipercs);
+ return (retval);
}
-int
-bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
- int min, int max, int *value)
+static int rangebox_redraw(struct dialog *d, struct bar *b, int *bigchange)
{
- WINDOW *widget, *textpad, *bar, *shadow;
- int i, y, x, h, w, htextpad;
- bool loop, buttupdate, barupdate;
- int input, currvalue, output, sizebar, bigchange, positions;
- float perc;
- struct buttons bs;
+ if (d->built) {
+ hide_dialog(d);
+ refresh(); /* Important for decreasing screen */
+ }
+ if (dialog_size_position(d, HBOX, MIN_WBOX, NULL) != 0)
+ return (BSDDIALOG_ERROR);
+ if (draw_dialog(d) != 0)
+ return (BSDDIALOG_ERROR);
+ if (d->built)
+ refresh(); /* Important to fix grey lines expanding screen */
+ TEXTPAD(d, HBOX + HBUTTONS);
+
+ b->w = WBAR(d);
+ *bigchange = MAX(1, b->w / 10);
+ update_barbox(d, b, true);
+ b->toupdate = true;
+
+ return (0);
+}
- if (value == NULL)
- RETURN_ERROR("*value cannot be NULL");
+int
+bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, int min, int max, int *value)
+{
+ bool loop;
+ int currvalue, retval, bigchange, positions;
+ wint_t input;
+ struct bar b;
+ struct dialog d;
+ CHECK_PTR(value);
if (min >= max)
- RETURN_ERROR("min >= max");
+ RETURN_FMTERROR("min (%d) >= max (%d)", min, max);
+ if (*value < min)
+ RETURN_FMTERROR("value (%d) < min (%d)", *value, min);
+ if (*value > max)
+ RETURN_FMTERROR("value (%d) > max (%d)", *value, max);
currvalue = *value;
positions = max - min + 1;
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
-
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
- if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (bar_checksize(text, h, w, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
- &textpad, &htextpad, text, true) != 0)
- return BSDDIALOG_ERROR;
-
- prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
- x+w-1-t.text.hmargin);
-
- sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
- bigchange = MAX(1, sizebar/10);
-
- bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3,
- sizebar + 2, RAISED);
-
- loop = buttupdate = barupdate = true;
- while(loop) {
- if (buttupdate) {
- draw_buttons(widget, h-2, w, bs, true);
- wrefresh(widget);
- buttupdate = false;
+ if (prepare_dialog(conf, text, rows, cols, &d) != 0)
+ return (BSDDIALOG_ERROR);
+ set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
+ if ((b.win = newwin(1, 1, 1, 1)) == NULL)
+ RETURN_ERROR("Cannot build WINDOW bar");
+ b.y = b.x = 1;
+ b.fmt = "%d";
+ if (rangebox_redraw(&d, &b, &bigchange) != 0)
+ return (BSDDIALOG_ERROR);
+
+ loop = true;
+ while (loop) {
+ if (b.toupdate) {
+ b.perc = ((float)(currvalue - min)*100) / (positions-1);
+ b.label = currvalue;
+ draw_bar(&b);
}
- if (barupdate) {
- perc = ((float)(currvalue - min)*100) / (positions-1);
- draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue);
- barupdate = false;
- wrefresh(bar);
- }
-
- input = getch();
+ doupdate();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
- *value = currvalue;
+ retval = BUTTONVALUE(d.bs);
loop = false;
break;
case 27: /* Esc */
- output = BSDDIALOG_ESC;
- loop = false;
+ if (conf->key.enable_esc) {
+ retval = BSDDIALOG_ESC;
+ loop = false;
+ }
break;
case '\t': /* TAB */
- bs.curr = (bs.curr + 1) % bs.nbuttons;
- buttupdate = true;
+ case KEY_RIGHT:
+ d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
+ DRAW_BUTTONS(d);
break;
case KEY_LEFT:
- if (bs.curr > 0) {
- bs.curr--;
- buttupdate = true;
- }
- break;
- case KEY_RIGHT:
- if (bs.curr < (int) bs.nbuttons - 1) {
- bs.curr++;
- buttupdate = true;
- }
+ d.bs.curr--;
+ if (d.bs.curr < 0)
+ d.bs.curr = d.bs.nbuttons - 1;
+ DRAW_BUTTONS(d);
break;
case KEY_HOME:
currvalue = max;
- barupdate = true;
+ b.toupdate = true;
break;
case KEY_END:
currvalue = min;
- barupdate = true;
+ b.toupdate = true;
break;
case KEY_NPAGE:
currvalue -= bigchange;
if (currvalue < min)
currvalue = min;
- barupdate = true;
+ b.toupdate = true;
break;
case KEY_PPAGE:
currvalue += bigchange;
if (currvalue > max)
currvalue = max;
- barupdate = true;
+ b.toupdate = true;
break;
case KEY_UP:
if (currvalue < max) {
currvalue++;
- barupdate = true;
+ b.toupdate = true;
}
break;
case KEY_DOWN:
if (currvalue > min) {
currvalue--;
- barupdate = true;
+ b.toupdate = true;
}
break;
case KEY_F(1):
- if (conf->hfile == NULL)
+ if (conf->key.f1_file == NULL &&
+ conf->key.f1_message == NULL)
break;
- if (f1help(conf) != 0)
- return BSDDIALOG_ERROR;
- /* No break! the terminal size can change */
+ if (f1help_dialog(conf) != 0)
+ return (BSDDIALOG_ERROR);
+ if (rangebox_redraw(&d, &b, &bigchange) != 0)
+ return (BSDDIALOG_ERROR);
+ break;
case KEY_RESIZE:
- hide_widget(y, x, h, w,conf->shadow);
-
- /*
- * Unnecessary, but, when the columns decrease the
- * following "refresh" seem not work
- */
- refresh();
-
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
- if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (bar_checksize(text, h, w, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- wclear(shadow);
- mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
- wresize(shadow, h, w);
-
- wclear(widget);
- mvwin(widget, y, x);
- wresize(widget, h, w);
-
- htextpad = 1;
- wclear(textpad);
- wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
-
- sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
- bigchange = MAX(1, sizebar/10);
- wclear(bar);
- mvwin(bar, y + h - 6, x + 1 + BARMARGIN);
- wresize(bar, 3, sizebar + 2);
-
- if(update_widget_withtextpad(conf, shadow, widget, h, w,
- RAISED, textpad, &htextpad, text, true) != 0)
- return BSDDIALOG_ERROR;
-
- prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
- x+w-1-t.text.hmargin);
-
- draw_borders(conf, bar, 3, sizebar + 2, RAISED);
-
- barupdate = true;
- buttupdate = true;
+ if (rangebox_redraw(&d, &b, &bigchange) != 0)
+ return (BSDDIALOG_ERROR);
break;
default:
- for (i = 0; i < (int) bs.nbuttons; i++)
- if (tolower(input) == tolower((bs.label[i])[0])) {
- output = bs.value[i];
- loop = false;
+ if (shortcut_buttons(input, &d.bs)) {
+ DRAW_BUTTONS(d);
+ doupdate();
+ retval = BUTTONVALUE(d.bs);
+ loop = false;
}
}
}
- delwin(bar);
- end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
+ *value = currvalue;
- return output;
+ delwin(b.win);
+ end_dialog(&d);
+
+ return (retval);
+}
+
+static int pause_redraw(struct dialog *d, struct bar *b)
+{
+ if (d->built) {
+ hide_dialog(d);
+ refresh(); /* Important for decreasing screen */
+ }
+ if (dialog_size_position(d, HBOX, MIN_WBOX, NULL) != 0)
+ return (BSDDIALOG_ERROR);
+ if (draw_dialog(d) != 0)
+ return (BSDDIALOG_ERROR);
+ if (d->built)
+ refresh(); /* Important to fix grey lines expanding screen */
+ TEXTPAD(d, HBOX + HBUTTONS);
+
+ b->w = WBAR(d);
+ update_barbox(d, b, true);
+ b->toupdate = true;
+
+ return (0);
}
int
-bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols,
- unsigned int sec)
+bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int *seconds)
{
- WINDOW *widget, *textpad, *bar, *shadow;
- int i, output, y, x, h, w, htextpad;
- bool loop, buttupdate, barupdate;
- int input, tout, sizebar;
- float perc;
- struct buttons bs;
-
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
-
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
- if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (bar_checksize(text, h, w, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
- &textpad, &htextpad, text, true) != 0)
- return BSDDIALOG_ERROR;
-
- prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
- x+w-1-t.text.hmargin);
-
- sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
- bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3,
- sizebar + 2, RAISED);
-
- tout = sec;
+ bool loop;
+ int retval, tout;
+ wint_t input;
+ struct bar b;
+ struct dialog d;
+
+ CHECK_PTR(seconds);
+ if (prepare_dialog(conf, text, rows, cols, &d) != 0)
+ return (BSDDIALOG_ERROR);
+ set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
+ if ((b.win = newwin(1, 1, 1, 1)) == NULL)
+ RETURN_ERROR("Cannot build WINDOW bar");
+ b.y = b.x = 1;
+ b.fmt = "%d";
+ if (pause_redraw(&d, &b) != 0)
+ return (BSDDIALOG_ERROR);
+
+ tout = *seconds;
nodelay(stdscr, TRUE);
timeout(1000);
- loop = buttupdate = barupdate = true;
- while(loop) {
- if (barupdate) {
- perc = (float)tout * 100 / sec;
- draw_perc_bar(bar, 1, 1, sizebar, perc, true, tout);
- barupdate = false;
- wrefresh(bar);
- }
-
- if (buttupdate) {
- draw_buttons(widget, h-2, w, bs, true);
- wrefresh(widget);
- buttupdate = false;
+ loop = true;
+ while (loop) {
+ if (b.toupdate) {
+ b.perc = (float)tout * 100 / *seconds;
+ b.label = tout;
+ draw_bar(&b);
}
-
- input = getch();
- if(input < 0) { /* timeout */
+ doupdate();
+ if (get_wch(&input) == ERR) { /* timeout */
tout--;
if (tout < 0) {
- output = BSDDIALOG_TIMEOUT;
+ retval = BSDDIALOG_TIMEOUT;
break;
}
else {
- barupdate = true;
+ b.toupdate = true;
continue;
}
}
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = BUTTONVALUE(d.bs);
loop = false;
break;
case 27: /* Esc */
- output = BSDDIALOG_ESC;
- loop = false;
+ if (conf->key.enable_esc) {
+ retval = BSDDIALOG_ESC;
+ loop = false;
+ }
break;
case '\t': /* TAB */
- bs.curr = (bs.curr + 1) % bs.nbuttons;
- buttupdate = true;
+ case KEY_RIGHT:
+ d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
+ DRAW_BUTTONS(d);
break;
case KEY_LEFT:
- if (bs.curr > 0) {
- bs.curr--;
- buttupdate = true;
- }
- break;
- case KEY_RIGHT:
- if (bs.curr < (int) bs.nbuttons - 1) {
- bs.curr++;
- buttupdate = true;
- }
+ d.bs.curr--;
+ if (d.bs.curr < 0)
+ d.bs.curr = d.bs.nbuttons - 1;
+ DRAW_BUTTONS(d);
break;
case KEY_F(1):
- if (conf->hfile == NULL)
+ if (conf->key.f1_file == NULL &&
+ conf->key.f1_message == NULL)
break;
- if (f1help(conf) != 0)
- return BSDDIALOG_ERROR;
- /* No break! the terminal size can change */
+ if (f1help_dialog(conf) != 0)
+ return (BSDDIALOG_ERROR);
+ if (pause_redraw(&d, &b) != 0)
+ return (BSDDIALOG_ERROR);
+ break;
case KEY_RESIZE:
- hide_widget(y, x, h, w,conf->shadow);
-
- /*
- * Unnecessary, but, when the columns decrease the
- * following "refresh" seem not work
- */
- refresh();
-
- if (set_widget_size(conf, rows, cols, &h, &w) != 0)
- return BSDDIALOG_ERROR;
- if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (bar_checksize(text, h, w, &bs) != 0)
- return BSDDIALOG_ERROR;
- if (set_widget_position(conf, &y, &x, h, w) != 0)
- return BSDDIALOG_ERROR;
-
- wclear(shadow);
- mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
- wresize(shadow, h, w);
-
- wclear(widget);
- mvwin(widget, y, x);
- wresize(widget, h, w);
-
- htextpad = 1;
- wclear(textpad);
- wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
-
- sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
- wclear(bar);
- mvwin(bar, y + h - 6, x + 1 + BARMARGIN);
- wresize(bar, 3, sizebar + 2);
-
- if(update_widget_withtextpad(conf, shadow, widget, h, w,
- RAISED, textpad, &htextpad, text, true) != 0)
- return BSDDIALOG_ERROR;
-
- prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
- x+w-1-t.text.hmargin);
-
- draw_borders(conf, bar, 3, sizebar + 2, RAISED);
-
- barupdate = true;
- buttupdate = true;
+ if (pause_redraw(&d, &b) != 0)
+ return (BSDDIALOG_ERROR);
break;
default:
- for (i = 0; i < (int) bs.nbuttons; i++)
- if (tolower(input) == tolower((bs.label[i])[0])) {
- output = bs.value[i];
- loop = false;
+ if (shortcut_buttons(input, &d.bs)) {
+ DRAW_BUTTONS(d);
+ doupdate();
+ retval = BUTTONVALUE(d.bs);
+ loop = false;
}
}
}
-
nodelay(stdscr, FALSE);
- delwin(bar);
- end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
+ *seconds = MAX(tout, 0);
+
+ delwin(b.win);
+ end_dialog(&d);
- return output;
+ return (retval);
}