freebsd-dev/contrib/bsddialog/lib/barbox.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

750 lines
19 KiB
C
Raw Normal View History

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
2022-01-28 08:14:55 +00:00
* Copyright (c) 2021-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.
*/
2021-12-06 10:35:28 +00:00
#include <sys/param.h>
#include <ctype.h>
2022-01-28 08:14:55 +00:00
#include <curses.h>
2021-12-21 15:06:19 +00:00
#include <stdlib.h>
#include <string.h>
#include <time.h>
2022-01-28 08:14:55 +00:00
#include <unistd.h>
#include "bsddialog.h"
2021-12-21 15:06:19 +00:00
#include "bsddialog_progressview.h"
#include "bsddialog_theme.h"
2022-01-28 08:14:55 +00:00
#include "lib_util.h"
#define BARPADDING 2
#define MINBARLEN 15
#define MINBARWIDTH (2 + 2 * BARPADDING + MINBARLEN)
#define MINMGBARLEN 18
#define MINMGBARWIDTH (2 + 2 * BARPADDING + MINMGBARLEN)
2021-12-21 15:06:19 +00:00
bool bsddialog_interruptprogview;
bool bsddialog_abortprogview;
int bsddialog_total_progview;
static void
draw_bar(WINDOW *win, int y, int x, int barlen, int perc, bool withlabel,
2021-12-06 10:35:28 +00:00
int label)
{
int i, blue_x, color, stringlen;
2022-01-28 08:14:55 +00:00
char labelstr[128];
blue_x = perc > 0 ? (perc * barlen) / 100 : -1;
wmove(win, y, x);
for (i = 0; i < barlen; i++) {
2021-12-06 10:35:28 +00:00
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);
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 ) ?
2021-12-06 10:35:28 +00:00
t.bar.color : t.bar.f_color;
wattron(win, color);
waddch(win, labelstr[i]);
wattroff(win, color);
}
}
2021-12-06 10:35:28 +00:00
static int
bar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
2022-01-28 08:14:55 +00:00
const char *text, struct buttons *bs)
{
2022-01-28 08:14:55 +00:00
int htext, wtext;
2022-01-28 08:14:55 +00:00
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, bs, 3, MINBARWIDTH,
&htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
}
2022-01-28 08:14:55 +00:00
if (cols == BSDDIALOG_AUTOSIZE)
*w = widget_min_width(conf, wtext, MINBARWIDTH, bs);
2022-01-28 08:14:55 +00:00
if (rows == BSDDIALOG_AUTOSIZE)
*h = widget_min_height(conf, htext, 3 /* bar */, bs != NULL);
2021-12-06 10:35:28 +00:00
return (0);
}
2021-12-06 10:35:28 +00:00
static int
2022-01-28 08:14:55 +00:00
bar_checksize(int rows, int cols, struct buttons *bs)
2021-12-06 10:35:28 +00:00
{
int minheight, minwidth;
minwidth = 0;
if (bs != NULL) /* gauge has not buttons */
minwidth = buttons_min_width(*bs);
2022-01-28 08:14:55 +00:00
minwidth = MAX(minwidth, MINBARWIDTH);
minwidth += VBORDERS;
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (cols < minwidth)
RETURN_ERROR("Few cols to draw bar and/or buttons");
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
minheight = HBORDERS + 3;
if (bs != NULL)
minheight += 2;
2021-12-06 10:35:28 +00:00
if (rows < minheight)
2022-01-28 08:14:55 +00:00
RETURN_ERROR("Few rows to draw bar");
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
return (0);
2021-12-06 10:35:28 +00:00
}
int
2022-01-28 08:14:55 +00:00
bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int perc, int fd, const char *sep)
2021-12-06 10:35:28 +00:00
{
bool mainloop;
2022-01-28 08:14:55 +00:00
int y, x, h, w, fd2;
FILE *input;
WINDOW *widget, *textpad, *bar, *shadow;
char inputbuf[2048], ntext[2048], *pntext;
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (bar_autosize(conf, rows, cols, &h, &w, text, NULL) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
if (bar_checksize(h, w, NULL) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, NULL,
false) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
input = NULL;
if (fd >= 0) {
2022-01-28 08:14:55 +00:00
fd2 = dup(fd);
if ((input = fdopen(fd2, "r")) == NULL)
2022-01-28 08:14:55 +00:00
RETURN_ERROR("Cannot build FILE* from fd");
}
2022-01-28 08:14:55 +00:00
mainloop = true;
2021-12-06 10:35:28 +00:00
while (mainloop) {
wrefresh(widget);
2022-01-28 08:14:55 +00:00
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4,
x+w-1-TEXTHMARGIN);
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) {
2022-01-28 08:14:55 +00:00
fscanf(input, "%s", inputbuf);
if (strcmp(inputbuf,"EOF") == 0) {
mainloop = false;
break;
}
2022-01-28 08:14:55 +00:00
if (strcmp(inputbuf, sep) == 0)
break;
}
2022-01-28 08:14:55 +00:00
if (mainloop == false)
break;
fscanf(input, "%d", &perc);
perc = perc > 100 ? 100 : perc;
2021-12-06 10:35:28 +00:00
pntext = &ntext[0];
ntext[0] = '\0';
while (true) {
2022-01-28 08:14:55 +00:00
fscanf(input, "%s", inputbuf);
if (strcmp(inputbuf,"EOF") == 0) {
mainloop = false;
break;
}
2022-01-28 08:14:55 +00:00
if (strcmp(inputbuf, sep) == 0)
break;
2022-01-28 08:14:55 +00:00
strcpy(pntext, inputbuf);
pntext += strlen(inputbuf); /* end string, no strlen */
2021-12-06 10:35:28 +00:00
pntext[0] = ' ';
pntext++;
}
pntext[0] = '\0';
2022-01-28 08:14:55 +00:00
if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
ntext, NULL, false) != 0)
return (BSDDIALOG_ERROR);
}
2022-01-28 08:14:55 +00:00
if (input != NULL)
fclose(input);
delwin(bar);
2022-01-28 08:14:55 +00:00
end_dialog(conf, shadow, widget, textpad);
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_OK);
}
2021-12-21 15:06:19 +00:00
/* Mixedgauge */
static int
2022-01-28 08:14:55 +00:00
do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int mainperc, unsigned int nminibars, const char **minilabels,
2021-12-21 15:06:19 +00:00
int *minipercs, bool color)
{
int i, retval, miniperc, y, x, h, w, ypad, max_minbarlen;
2022-01-28 08:14:55 +00:00
int htextpad, htext, wtext;
2021-12-21 15:06:19 +00:00
int colorperc, red, green;
2022-01-28 08:14:55 +00:00
WINDOW *widget, *textpad, *bar, *shadow;
2021-12-21 15:06:19 +00:00
char states[12][14] = {
2022-01-28 08:14:55 +00:00
" 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 */
2021-12-06 10:35:28 +00:00
};
2021-12-21 15:06:19 +00:00
red = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_RED, BSDDIALOG_BOLD);
green = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_GREEN,BSDDIALOG_BOLD);
2021-12-06 10:35:28 +00:00
max_minbarlen = 0;
2022-01-28 08:14:55 +00:00
for (i = 0; i < (int)nminibars; i++)
max_minbarlen = MAX(max_minbarlen, (int)strcols(minilabels[i]));
max_minbarlen += 3 + 16; /* seps + [...] */
max_minbarlen = MAX(max_minbarlen, MINMGBARWIDTH); /* mainbar */
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
/* mixedgauge autosize */
2022-01-28 08:14:55 +00:00
if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
if (text_size(conf, rows, cols, text, NULL, nminibars + 3,
max_minbarlen, &htext, &wtext) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
}
2022-01-28 08:14:55 +00:00
if (cols == BSDDIALOG_AUTOSIZE)
w = widget_min_width(conf, wtext, max_minbarlen, NULL);
if (rows == BSDDIALOG_AUTOSIZE)
h = widget_min_height(conf, htext, nminibars + 3, false);
2021-12-06 10:35:28 +00:00
/* mixedgauge checksize */
if (w < max_minbarlen + 2)
RETURN_ERROR("Few cols for this mixedgauge");
2022-01-28 08:14:55 +00:00
if (h < 5 + (int)nminibars)
2021-12-06 10:35:28 +00:00
RETURN_ERROR("Few rows for this mixedgauge");
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
retval = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
2022-01-28 08:14:55 +00:00
NULL, false);
if (retval == BSDDIALOG_ERROR)
return (retval);
/* mini bars */
2022-01-28 08:14:55 +00:00
for (i = 0; i < (int)nminibars; i++) {
2021-12-13 07:54:07 +00:00
miniperc = minipercs[i];
2022-01-28 08:14:55 +00:00
if (miniperc == BSDDIALOG_MG_BLANK)
continue;
2021-12-21 15:06:19 +00:00
/* label */
2022-01-28 08:14:55 +00:00
if (color && (miniperc >= 0))
2021-12-21 15:06:19 +00:00
wattron(widget, A_BOLD);
2021-12-13 07:54:07 +00:00
mvwaddstr(widget, i+1, 2, minilabels[i]);
if (color && (miniperc >= 0))
2021-12-21 15:06:19 +00:00
wattroff(widget, A_BOLD);
/* perc */
2022-01-28 08:14:55 +00:00
if (miniperc < -11)
2021-12-13 07:54:07 +00:00
mvwaddstr(widget, i+1, w-2-15, states[11]);
2022-01-28 08:14:55 +00:00
else if (miniperc < 0) {
2021-12-21 15:06:19 +00:00
mvwaddstr(widget, i+1, w-2-15, "[ ]");
2022-01-28 08:14:55 +00:00
colorperc = -1;
if (color && miniperc == BSDDIALOG_MG_FAILED)
2021-12-21 15:06:19 +00:00
colorperc = red;
2022-01-28 08:14:55 +00:00
if (color && miniperc == BSDDIALOG_MG_DONE)
2021-12-21 15:06:19 +00:00
colorperc = green;
2022-01-28 08:14:55 +00:00
if (colorperc != -1)
2021-12-21 15:06:19 +00:00
wattron(widget, colorperc);
2022-01-28 08:14:55 +00:00
miniperc = abs(miniperc + 1);
2021-12-21 15:06:19 +00:00
mvwaddstr(widget, i+1, 1+w-2-15, states[miniperc]);
2022-01-28 08:14:55 +00:00
if (colorperc != -1)
2021-12-21 15:06:19 +00:00
wattroff(widget, colorperc);
}
2022-01-28 08:14:55 +00:00
else { /* miniperc >= 0 */
if (miniperc > 100)
miniperc = 100;
2021-12-06 10:35:28 +00:00
mvwaddstr(widget, i+1, w-2-15, "[ ]");
2022-01-28 08:14:55 +00:00
draw_bar(widget, i+1, 1+w-2-15, 13, miniperc, false,
-1 /*unused*/);
}
}
2021-12-06 10:35:28 +00:00
wrefresh(widget);
2022-01-28 08:14:55 +00:00
getmaxyx(textpad, htextpad, i /* unused */);
ypad = y + h - 4 - htextpad;
ypad = ypad < y+(int)nminibars ? y+(int)nminibars : ypad;
2021-12-06 10:35:28 +00:00
prefresh(textpad, 0, 0, ypad, x+2, y+h-4, x+w-2);
2022-01-28 08:14:55 +00:00
/* main bar */
2021-12-06 10:35:28 +00:00
bar = new_boxed_window(conf, y+h -4, x+3, 3, w-6, RAISED);
2022-01-28 08:14:55 +00:00
draw_bar(bar, 1, 1, w-8, mainperc, false, -1 /*unused*/);
2021-12-06 10:35:28 +00:00
wattron(bar, t.bar.color);
mvwaddstr(bar, 0, 2, "Overall Progress");
2021-12-06 10:35:28 +00:00
wattroff(bar, t.bar.color);
wrefresh(bar);
/* getch(); alternate mode (port devel/ncurses) shows nothing */
delwin(bar);
2022-01-28 08:14:55 +00:00
end_dialog(conf, shadow, widget, textpad);
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_OK);
}
2021-12-21 15:06:19 +00:00
int
2022-01-28 08:14:55 +00:00
bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int mainperc, unsigned int nminibars,
const char **minilabels, int *minipercs)
2021-12-21 15:06:19 +00:00
{
int retval;
2021-12-21 15:06:19 +00:00
retval = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
2021-12-21 15:06:19 +00:00
minilabels, minipercs, false);
return (retval);
2021-12-21 15:06:19 +00:00
}
int
2022-01-28 08:14:55 +00:00
bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
2021-12-21 15:06:19 +00:00
int cols, struct bsddialog_progviewconf *pvconf, unsigned int nminibar,
struct bsddialog_fileminibar *minibar)
{
bool update;
int perc, retval, *minipercs;
2022-01-28 08:14:55 +00:00
unsigned int i, mainperc, totaltodo;
2021-12-21 15:06:19 +00:00
float readforsec;
2022-01-28 08:14:55 +00:00
const char **minilabels;
time_t tstart, told, tnew, refresh;
2021-12-21 15:06:19 +00:00
if ((minilabels = calloc(nminibar, sizeof(char*))) == NULL)
2022-01-28 08:14:55 +00:00
RETURN_ERROR("Cannot allocate memory for minilabels");
2021-12-21 15:06:19 +00:00
if ((minipercs = calloc(nminibar, sizeof(int))) == NULL)
2022-01-28 08:14:55 +00:00
RETURN_ERROR("Cannot allocate memory for minipercs");
2021-12-21 15:06:19 +00:00
totaltodo = 0;
2022-01-28 08:14:55 +00:00
for (i = 0; i < nminibar; i++) {
totaltodo += minibar[i].size;
2021-12-21 15:06:19 +00:00
minilabels[i] = minibar[i].label;
2022-01-28 08:14:55 +00:00
minipercs[i] = minibar[i].status;
2021-12-21 15:06:19 +00:00
}
refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
retval = BSDDIALOG_OK;
2021-12-21 15:06:19 +00:00
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,
2021-12-21 15:06:19 +00:00
nminibar, minilabels, minipercs, true);
if (retval == BSDDIALOG_ERROR)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-21 15:06:19 +00:00
2022-01-28 08:14:55 +00:00
move(SCREENLINES - 1, 2);
2021-12-21 15:06:19 +00:00
clrtoeol();
2022-01-28 08:14:55 +00:00
readforsec = ((tnew - tstart) == 0) ? 0 :
bsddialog_total_progview / (float)(tnew - tstart);
2021-12-21 15:06:19 +00:00
printw(pvconf->fmtbottomstr, bsddialog_total_progview,
readforsec);
refresh();
time(&told);
update = false;
}
if (i >= nminibar)
break;
2022-01-28 08:14:55 +00:00
if (minibar[i].status == BSDDIALOG_MG_FAILED)
2021-12-21 15:06:19 +00:00
break;
perc = pvconf->callback(&minibar[i]);
2022-01-28 08:14:55 +00:00
if (minibar[i].status == BSDDIALOG_MG_DONE) { /*||perc >= 100)*/
minipercs[i] = BSDDIALOG_MG_DONE;
2021-12-21 15:06:19 +00:00
update = true;
i++;
2022-01-28 08:14:55 +00:00
} else if (minibar[i].status == BSDDIALOG_MG_FAILED || perc < 0) {
minipercs[i] = BSDDIALOG_MG_FAILED;
2021-12-21 15:06:19 +00:00
update = true;
2022-01-28 08:14:55 +00:00
} else /* perc >= 0 */
minipercs[i] = perc;
2021-12-21 15:06:19 +00:00
}
free(minilabels);
free(minipercs);
return (retval);
2021-12-21 15:06:19 +00:00
}
int
2022-01-28 08:14:55 +00:00
bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
int cols, int min, int max, int *value)
{
bool loop, buttupdate, barupdate;
2022-01-28 08:14:55 +00:00
int y, x, h, w;
int currvalue, retval, sizebar, bigchange, positions;
wint_t input;
float perc;
2022-01-28 08:14:55 +00:00
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
2021-12-06 10:35:28 +00:00
if (value == NULL)
RETURN_ERROR("*value cannot be NULL");
if (min >= max)
RETURN_ERROR("min >= max");
2021-12-06 10:35:28 +00:00
currvalue = *value;
positions = max - min + 1;
2022-01-28 08:14:55 +00:00
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
if (bar_checksize(h, w, &bs) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
true) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
doupdate();
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, x+w-1-TEXTHMARGIN);
sizebar = w - HBORDERS - (2 * BARPADDING) - 2;
2021-12-06 10:35:28 +00:00
bigchange = MAX(1, sizebar/10);
2022-01-28 08:14:55 +00:00
bar = new_boxed_window(conf, y + h - 6, x + 1 + BARPADDING, 3,
2021-12-06 10:35:28 +00:00
sizebar + 2, RAISED);
loop = buttupdate = barupdate = true;
2022-01-28 08:14:55 +00:00
while (loop) {
2021-12-06 10:35:28 +00:00
if (buttupdate) {
2022-01-28 08:14:55 +00:00
draw_buttons(widget, bs, true);
2021-12-06 10:35:28 +00:00
wrefresh(widget);
buttupdate = false;
}
if (barupdate) {
2021-12-06 10:35:28 +00:00
perc = ((float)(currvalue - min)*100) / (positions-1);
2022-01-28 08:14:55 +00:00
draw_bar(bar, 1, 1, sizebar, perc, true, currvalue);
barupdate = false;
wrefresh(bar);
}
if (get_wch(&input) == ERR)
continue;
switch(input) {
2021-12-06 10:35:28 +00:00
case KEY_ENTER:
case 10: /* Enter */
retval = bs.value[bs.curr];
*value = currvalue;
loop = false;
break;
case 27: /* Esc */
2022-01-28 08:14:55 +00:00
if (conf->key.enable_esc) {
retval = BSDDIALOG_ESC;
2022-01-28 08:14:55 +00:00
loop = false;
}
break;
2021-12-06 10:35:28 +00:00
case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
2021-12-06 10:35:28 +00:00
case KEY_HOME:
currvalue = max;
barupdate = true;
break;
case KEY_END:
currvalue = min;
barupdate = true;
break;
case KEY_NPAGE:
currvalue -= bigchange;
if (currvalue < min)
currvalue = min;
barupdate = true;
break;
case KEY_PPAGE:
currvalue += bigchange;
if (currvalue > max)
currvalue = max;
barupdate = true;
break;
case KEY_UP:
if (currvalue < max) {
currvalue++;
barupdate = true;
}
break;
case KEY_DOWN:
if (currvalue > min) {
currvalue--;
barupdate = true;
}
break;
2021-12-06 10:35:28 +00:00
case KEY_F(1):
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
2021-12-06 10:35:28 +00:00
break;
if (f1help(conf) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
/* No break, screen size can change */
2021-12-06 10:35:28 +00:00
case KEY_RESIZE:
2022-01-28 08:14:55 +00:00
/* Important for decreasing screen */
hide_widget(y, x, h, w, conf->shadow);
2021-12-06 10:35:28 +00:00
refresh();
2022-01-28 08:14:55 +00:00
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
if (bar_autosize(conf, rows, cols, &h, &w, text,
&bs) != 0)
return (BSDDIALOG_ERROR);
if (bar_checksize(h, w, &bs) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (update_dialog(conf, shadow, widget,y, x, h, w,
textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
doupdate();
2021-12-06 10:35:28 +00:00
sizebar = w - HBORDERS - (2 * BARPADDING) - 2;
2021-12-06 10:35:28 +00:00
bigchange = MAX(1, sizebar/10);
wclear(bar);
2022-01-28 08:14:55 +00:00
mvwin(bar, y + h - 6, x + 1 + BARPADDING);
2021-12-06 10:35:28 +00:00
wresize(bar, 3, sizebar + 2);
2022-01-28 08:14:55 +00:00
draw_borders(conf, bar, 3, sizebar+2, RAISED);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7,
x+w-1-TEXTHMARGIN);
2021-12-06 10:35:28 +00:00
barupdate = true;
break;
default:
2022-01-28 08:14:55 +00:00
if (shortcut_buttons(input, &bs)) {
retval = bs.value[bs.curr];
2022-01-28 08:14:55 +00:00
loop = false;
2021-12-06 10:35:28 +00:00
}
}
}
delwin(bar);
2022-01-28 08:14:55 +00:00
end_dialog(conf, shadow, widget, textpad);
return (retval);
}
2021-12-06 10:35:28 +00:00
int
2022-01-28 08:14:55 +00:00
bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int sec)
{
bool loop, buttupdate, barupdate;
int retval, y, x, h, w, tout, sizebar;
wint_t input;
float perc;
2022-01-28 08:14:55 +00:00
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
2022-01-28 08:14:55 +00:00
get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
if (bar_checksize(h, w, &bs) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
true) != 0)
return (BSDDIALOG_ERROR);
doupdate();
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, x+w-1-TEXTHMARGIN);
sizebar = w - HBORDERS - (2 * BARPADDING) - 2;
2022-01-28 08:14:55 +00:00
bar = new_boxed_window(conf, y + h - 6, x + 1 + BARPADDING, 3,
2021-12-06 10:35:28 +00:00
sizebar + 2, RAISED);
tout = sec;
nodelay(stdscr, TRUE);
timeout(1000);
loop = buttupdate = barupdate = true;
2022-01-28 08:14:55 +00:00
while (loop) {
if (barupdate) {
2021-12-06 10:35:28 +00:00
perc = (float)tout * 100 / sec;
2022-01-28 08:14:55 +00:00
draw_bar(bar, 1, 1, sizebar, perc, true, tout);
barupdate = false;
wrefresh(bar);
}
if (buttupdate) {
2022-01-28 08:14:55 +00:00
draw_buttons(widget, bs, true);
wrefresh(widget);
buttupdate = false;
}
if (get_wch(&input) == ERR) { /* timeout */
2021-12-06 10:35:28 +00:00
tout--;
if (tout < 0) {
retval = BSDDIALOG_TIMEOUT;
break;
}
else {
barupdate = true;
continue;
}
}
switch(input) {
2021-12-06 10:35:28 +00:00
case KEY_ENTER:
case 10: /* Enter */
retval = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
2022-01-28 08:14:55 +00:00
if (conf->key.enable_esc) {
retval = BSDDIALOG_ESC;
2022-01-28 08:14:55 +00:00
loop = false;
}
break;
2021-12-06 10:35:28 +00:00
case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
buttupdate = true;
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
buttupdate = true;
}
break;
2021-12-06 10:35:28 +00:00
case KEY_F(1):
if (conf->key.f1_file == NULL &&
conf->key.f1_message == NULL)
2021-12-06 10:35:28 +00:00
break;
if (f1help(conf) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
/* No break, screen size can change */
2021-12-06 10:35:28 +00:00
case KEY_RESIZE:
2022-01-28 08:14:55 +00:00
/* Important for decreasing screen */
hide_widget(y, x, h, w, conf->shadow);
2021-12-06 10:35:28 +00:00
refresh();
2022-01-28 08:14:55 +00:00
2021-12-06 10:35:28 +00:00
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
if (bar_autosize(conf, rows, cols, &h, &w, text,
&bs) != 0)
return (BSDDIALOG_ERROR);
if (bar_checksize(h, w, &bs) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
if (set_widget_position(conf, &y, &x, h, w) != 0)
2022-01-28 08:14:55 +00:00
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
if (update_dialog(conf, shadow, widget,y, x, h, w,
textpad, text, &bs, true) != 0)
return (BSDDIALOG_ERROR);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
doupdate();
2021-12-06 10:35:28 +00:00
sizebar = w - HBORDERS - (2 * BARPADDING) - 2;
2021-12-06 10:35:28 +00:00
wclear(bar);
2022-01-28 08:14:55 +00:00
mvwin(bar, y + h - 6, x + 1 + BARPADDING);
2021-12-06 10:35:28 +00:00
wresize(bar, 3, sizebar + 2);
2022-01-28 08:14:55 +00:00
draw_borders(conf, bar, 3, sizebar+2, LOWERED);
2021-12-06 10:35:28 +00:00
2022-01-28 08:14:55 +00:00
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7,
x+w-1-TEXTHMARGIN);
2021-12-06 10:35:28 +00:00
barupdate = true;
break;
default:
2022-01-28 08:14:55 +00:00
if (shortcut_buttons(input, &bs)) {
retval = bs.value[bs.curr];
2022-01-28 08:14:55 +00:00
loop = false;
2021-12-06 10:35:28 +00:00
}
}
}
nodelay(stdscr, FALSE);
delwin(bar);
2022-01-28 08:14:55 +00:00
end_dialog(conf, shadow, widget, textpad);
return (retval);
2022-01-28 08:14:55 +00:00
}