diff options
Diffstat (limited to 'contrib/bsddialog/lib/barbox.c')
-rw-r--r-- | contrib/bsddialog/lib/barbox.c | 980 |
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); } |