diff options
Diffstat (limited to 'contrib/bsddialog/lib/timebox.c')
-rw-r--r-- | contrib/bsddialog/lib/timebox.c | 525 |
1 files changed, 110 insertions, 415 deletions
diff --git a/contrib/bsddialog/lib/timebox.c b/contrib/bsddialog/lib/timebox.c index 7d69666c32b8..d683f9552b50 100644 --- a/contrib/bsddialog/lib/timebox.c +++ b/contrib/bsddialog/lib/timebox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021-2022 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,512 +25,207 @@ * SUCH DAMAGE. */ -#include <sys/param.h> - -#include <ctype.h> #include <curses.h> -#include <string.h> #include "bsddialog.h" +#include "bsddialog_theme.h" #include "lib_util.h" -#define MINWDATE 23 /* 3 windows and their borders */ #define MINWTIME 14 /* 3 windows and their borders */ - -static int -datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, - int *w, int minw, const char *text, struct buttons bs) +#define HBOX 3 +#define WBOX 4 + +struct clock { + unsigned int max; + unsigned int value; + WINDOW *win; +}; + +static void +drawsquare(struct bsddialog_conf *conf, WINDOW *win, unsigned int value, + bool focus) { - int htext, wtext; - - if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { - if (text_size(conf, rows, cols, text, &bs, 3, minw, &htext, - &wtext) != 0) - return (BSDDIALOG_ERROR); + draw_borders(conf, win, LOWERED); + if (focus) { + wattron(win, t.dialog.arrowcolor); + mvwhline(win, 0, 1, conf->ascii_lines ? '^' : ACS_UARROW, 2); + mvwhline(win, 2, 1, conf->ascii_lines ? 'v' : ACS_DARROW, 2); + wattroff(win, t.dialog.arrowcolor); } - if (cols == BSDDIALOG_AUTOSIZE) - *w = widget_min_width(conf, htext,minw, &bs); + if (focus) + wattron(win, t.menu.f_namecolor); + mvwprintw(win, 1, 1, "%02u", value); + if (focus) + wattroff(win, t.menu.f_namecolor); - if (rows == BSDDIALOG_AUTOSIZE) - *h = widget_min_height(conf, htext, 3 /* windows */, true); - - return (0); + wnoutrefresh(win); } -static int -datetime_checksize(int rows, int cols, int minw, struct buttons bs) +static int timebox_redraw(struct dialog *d, struct clock *c) { - int mincols; + int y, x; - mincols = VBORDERS; - mincols += buttons_width(bs); - mincols = MAX(minw, mincols); - - if (cols < mincols) - RETURN_ERROR("Few cols for this timebox/datebox"); - - if (rows < 7) /* 2 button + 2 borders + 3 windows */ - RETURN_ERROR("Few rows for this timebox/datebox, at least 7"); + if (d->built) { + hide_dialog(d); + refresh(); /* Important for decreasing screen */ + } + if (dialog_size_position(d, HBOX, MINWTIME, 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); + + y = d->y + d->h - BORDER - HBUTTONS - HBOX; + x = d->x + d->w/2 - 7; + update_box(d->conf, c[0].win, y, x, HBOX, WBOX, LOWERED); + mvwaddch(d->widget, d->h - 5, d->w/2 - 3, ':'); + update_box(d->conf, c[1].win, y, x += 5, HBOX, WBOX, LOWERED); + mvwaddch(d->widget, d->h - 5, d->w/2 + 2, ':'); + update_box(d->conf, c[2].win, y, x + 5, HBOX, WBOX, LOWERED); + wnoutrefresh(d->widget); /* for mvwaddch(':') */ return (0); } +/* API */ int bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows, int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss) { bool loop, focusbuttons; - int i, input, output, y, x, h, w, sel; - WINDOW *widget, *textpad, *shadow; - struct buttons bs; - struct myclockstruct { - unsigned int max; - unsigned int value; - WINDOW *win; - }; - - if (hh == NULL || mm == NULL || ss == NULL) - RETURN_ERROR("hh / mm / ss cannot be NULL"); - - struct myclockstruct c[3] = { + int i, retval, sel; + wint_t input; + struct dialog d; + struct clock c[3] = { {23, *hh, NULL}, {59, *mm, NULL}, {59, *ss, NULL} }; - for (i = 0 ; i < 3; i++) { - if (c[i].value > c[i].max) - c[i].value = c[i].max; - } - - get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); - - if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return (BSDDIALOG_ERROR); - if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, - bs) != 0) - return (BSDDIALOG_ERROR); - if (datetime_checksize(h, w, MINWTIME, bs) != 0) + CHECK_PTR(hh); + CHECK_PTR(mm); + CHECK_PTR(ss); + if (prepare_dialog(conf, text, rows, cols, &d) != 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) + set_buttons(&d, true, OK_LABEL, CANCEL_LABEL); + for (i=0; i<3; i++) { + if ((c[i].win = newwin(1, 1, 1, 1)) == NULL) + RETURN_FMTERROR("Cannot build WINDOW for time[%d]", i); + wbkgd(c[i].win, t.dialog.color); + c[i].value = MIN(c[i].value, c[i].max); + } + if (timebox_redraw(&d, c) != 0) return (BSDDIALOG_ERROR); - pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); - doupdate(); - - c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 7, 3, 4, LOWERED); - mvwaddch(widget, h - 5, w/2 - 3, ':'); - c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 2, 3, 4, LOWERED); - mvwaddch(widget, h - 5, w/2 + 2, ':'); - c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 3, 3, 4, LOWERED); - - wrefresh(widget); - + sel = -1; loop = focusbuttons = true; while (loop) { - for (i = 0; i < 3; i++) { - mvwprintw(c[i].win, 1, 1, "%2d", c[i].value); - wrefresh(c[i].win); - } - - if (focusbuttons == false) { - wmove(c[sel].win, 1, 2); - wrefresh(c[sel].win); - } - - input = getch(); + for (i = 0; i < 3; i++) + drawsquare(conf, c[i].win, c[i].value, sel == i); + doupdate(); + if (get_wch(&input) == ERR) + continue; switch(input) { case KEY_ENTER: case 10: /* Enter */ - if (focusbuttons == false) - break; - output = bs.value[bs.curr]; - loop = false; + if (focusbuttons || conf->button.always_active) { + retval = BUTTONVALUE(d.bs); + loop = false; + } break; case 27: /* Esc */ if (conf->key.enable_esc) { - output = BSDDIALOG_ESC; + retval = BSDDIALOG_ESC; loop = false; } break; case KEY_RIGHT: case '\t': /* TAB */ if (focusbuttons) { - bs.curr++; - focusbuttons = bs.curr < (int)bs.nbuttons ? + d.bs.curr++; + focusbuttons = d.bs.curr < (int)d.bs.nbuttons ? true : false; if (focusbuttons == false) { - curs_set(1); sel = 0; + d.bs.curr = + conf->button.always_active ? 0 : -1; } } else { sel++; focusbuttons = sel > 2 ? true : false; if (focusbuttons) { - curs_set(0); - bs.curr = 0; + d.bs.curr = 0; } } - draw_buttons(widget, bs, true); - wrefresh(widget); + DRAW_BUTTONS(d); break; case KEY_LEFT: if (focusbuttons) { - bs.curr--; - focusbuttons = bs.curr < 0 ? false : true; + d.bs.curr--; + focusbuttons = d.bs.curr < 0 ? false : true; if (focusbuttons == false) { - curs_set(1); sel = 2; + d.bs.curr = + conf->button.always_active ? 0 : -1; } } else { sel--; focusbuttons = sel < 0 ? true : false; - if (focusbuttons) { - curs_set(0); - bs.curr = (int)bs.nbuttons - 1; - } + if (focusbuttons) + d.bs.curr = (int)d.bs.nbuttons - 1; } - draw_buttons(widget, bs, true); - wrefresh(widget); + DRAW_BUTTONS(d); break; case KEY_UP: - if (focusbuttons) - break; - c[sel].value = c[sel].value > 0 ? - c[sel].value - 1 : c[sel].max; - break; - case KEY_DOWN: - if (focusbuttons) - break; - c[sel].value = c[sel].value < c[sel].max ? - c[sel].value + 1 : 0; - break; - case KEY_F(1): - if (conf->key.f1_file == NULL && - conf->key.f1_message == NULL) - break; - curs_set(0); - if (f1help(conf) != 0) - return (BSDDIALOG_ERROR); - curs_set(1); - /* No break, screen size can change */ - case KEY_RESIZE: - /* Important for decreasing screen */ - hide_widget(y, x, h, w, conf->shadow); - refresh(); - - if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return (BSDDIALOG_ERROR); - if (datetime_autosize(conf, rows, cols, &h, &w, - MINWTIME, text, bs) != 0) - return (BSDDIALOG_ERROR); - if (datetime_checksize(h, w, MINWTIME, 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); - - doupdate(); - - mvwaddch(widget, h - 5, w/2 - 3, ':'); - mvwaddch(widget, h - 5, w/2 + 2, ':'); - wrefresh(widget); - - prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); - - wclear(c[0].win); - mvwin(c[0].win, y + h - 6, x + w/2 - 7); - draw_borders(conf, c[0].win, 3, 4, LOWERED); - wrefresh(c[0].win); - - wclear(c[1].win); - mvwin(c[1].win, y + h - 6, x + w/2 - 2); - draw_borders(conf, c[1].win, 3, 4, LOWERED); - wrefresh(c[1].win); - - wclear(c[2].win); - mvwin(c[2].win, y + h - 6, x + w/2 + 3); - draw_borders(conf, c[2].win, 3, 4, LOWERED); - wrefresh(c[2].win); - - /* Important to avoid grey lines expanding screen */ - refresh(); - break; - default: - if (shortcut_buttons(input, &bs)) { - output = bs.value[bs.curr]; - loop = false; - } - } - } - - if (output == BSDDIALOG_OK) { - *hh = c[0].value; - *mm = c[1].value; - *ss = c[2].value; - } - - curs_set(0); - - for (i = 0; i < 3; i++) - delwin(c[i].win); - end_dialog(conf, shadow, widget, textpad); - - return (output); -} - -int -bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, - int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd) -{ - bool loop, focusbuttons; - int i, input, output, y, x, h, w, sel; - WINDOW *widget, *textpad, *shadow; - struct buttons bs; - struct calendar { - int max; - int value; - WINDOW *win; - unsigned int x; - }; - struct month { - const char *name; - unsigned int days; - }; - - if (yy == NULL || mm == NULL || dd == NULL) - RETURN_ERROR("yy / mm / dd cannot be NULL"); - - struct calendar c[3] = { - {9999, *yy, NULL, 4 }, - {12, *mm, NULL, 9 }, - {31, *dd, NULL, 2 } - }; - - struct month m[12] = { - { "January", 31 }, { "February", 28 }, { "March", 31 }, - { "April", 30 }, { "May", 31 }, { "June", 30 }, - { "July", 31 }, { "August", 31 }, { "September", 30 }, - { "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; - if (c[i].value < 1) - c[i].value = 1; - } - c[2].max = m[c[1].value -1].days; - if (c[1].value == 2 && ISLEAF(c[0].value)) - c[2].max = 29; - if (c[2].value > c[2].max) - c[2].value = c[2].max; - - get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); - - if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return (BSDDIALOG_ERROR); - if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, - bs) != 0) - return (BSDDIALOG_ERROR); - if (datetime_checksize(h, w, MINWDATE, 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-7, x+w-2); - doupdate(); - - c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 11, 3, 6, LOWERED); - mvwaddch(widget, h - 5, w/2 - 5, '/'); - c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 4, 3, 11, LOWERED); - mvwaddch(widget, h - 5, w/2 + 7, '/'); - c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 8, 3, 4, LOWERED); - - wrefresh(widget); - - loop = focusbuttons = true; - while (loop) { - mvwprintw(c[0].win, 1, 1, "%4d", c[0].value); - mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name); - mvwprintw(c[2].win, 1, 1, "%2d", c[2].value); - for (i = 0; i < 3; i++) { - wrefresh(c[i].win); - } - if (focusbuttons == false) { - wmove(c[sel].win, 1, c[sel].x); - wrefresh(c[sel].win); - } - - input = getch(); - switch(input) { - case KEY_ENTER: - case 10: /* Enter */ - if (focusbuttons == false) - break; - output = bs.value[bs.curr]; - loop = false; - break; - case 27: /* Esc */ - if (conf->key.enable_esc) { - output = BSDDIALOG_ESC; - loop = false; - } - break; - case KEY_RIGHT: - case '\t': /* TAB */ - if (focusbuttons) { - bs.curr++; - focusbuttons = bs.curr < (int)bs.nbuttons ? - true : false; - if (focusbuttons == false) { - curs_set(1); - sel = 0; - } - } else { - sel++; - focusbuttons = sel > 2 ? true : false; - if (focusbuttons) { - curs_set(0); - bs.curr = 0; - } - } - draw_buttons(widget, bs, true); - wrefresh(widget); - break; - case KEY_LEFT: if (focusbuttons) { - bs.curr--; - focusbuttons = bs.curr < 0 ? false : true; - if (focusbuttons == false) { - curs_set(1); - sel = 2; - } + sel = 0; + focusbuttons = false; + d.bs.curr = conf->button.always_active ? 0 : -1; + DRAW_BUTTONS(d); } else { - sel--; - focusbuttons = sel < 0 ? true : false; - if (focusbuttons) { - curs_set(0); - bs.curr = (int)bs.nbuttons - 1; - } + c[sel].value = c[sel].value > 0 ? + c[sel].value - 1 : c[sel].max; } - draw_buttons(widget, bs, true); - wrefresh(widget); - break; - case KEY_UP: - if (focusbuttons) - break; - c[sel].value = c[sel].value > 1 ? - c[sel].value - 1 : c[sel].max ; - /* if mount change */ - c[2].max = m[c[1].value -1].days; - /* if year change */ - if (c[1].value == 2 && ISLEAF(c[0].value)) - c[2].max = 29; - /* set new day */ - if (c[2].value > c[2].max) - c[2].value = c[2].max; break; case KEY_DOWN: if (focusbuttons) break; c[sel].value = c[sel].value < c[sel].max ? - c[sel].value + 1 : 1; - /* if mount change */ - c[2].max = m[c[1].value -1].days; - /* if year change */ - if (c[1].value == 2 && ISLEAF(c[0].value)) - c[2].max = 29; - /* set new day */ - if (c[2].value > c[2].max) - c[2].value = c[2].max; + c[sel].value + 1 : 0; break; case KEY_F(1): if (conf->key.f1_file == NULL && conf->key.f1_message == NULL) break; - curs_set(0); - if (f1help(conf) != 0) - return (BSDDIALOG_ERROR); - curs_set(1); - /* No break, screen size can change */ - case KEY_RESIZE: - /* Important for decreasing screen */ - hide_widget(y, x, h, w, conf->shadow); - refresh(); - - if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return (BSDDIALOG_ERROR); - if (datetime_autosize(conf, rows, cols, &h, &w, - MINWDATE, text, bs) != 0) + if (f1help_dialog(conf) != 0) return (BSDDIALOG_ERROR); - if (datetime_checksize(h, w, MINWDATE, bs) != 0) + if (timebox_redraw(&d, c) != 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) + break; + case KEY_RESIZE: + if (timebox_redraw(&d, c) != 0) return (BSDDIALOG_ERROR); - doupdate(); - - mvwaddch(widget, h - 5, w/2 - 5, '/'); - mvwaddch(widget, h - 5, w/2 + 7, '/'); - wrefresh(widget); - - prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); - - wclear(c[0].win); - mvwin(c[0].win, y + h - 6, x + w/2 - 11); - draw_borders(conf, c[0].win, 3, 6, LOWERED); - wrefresh(c[0].win); - - wclear(c[1].win); - mvwin(c[1].win, y + h - 6, x + w/2 - 4); - draw_borders(conf, c[1].win, 3, 11, LOWERED); - wrefresh(c[1].win); - - wclear(c[2].win); - mvwin(c[2].win, y + h - 6, x + w/2 + 8); - draw_borders(conf, c[2].win, 3, 4, LOWERED); - wrefresh(c[2].win); - - /* Important to avoid grey lines expanding screen */ - refresh(); break; default: - if (shortcut_buttons(input, &bs)) { - output = bs.value[bs.curr]; + if (shortcut_buttons(input, &d.bs)) { + DRAW_BUTTONS(d); + doupdate(); + retval = BUTTONVALUE(d.bs); loop = false; } } } - if (output == BSDDIALOG_OK) { - *yy = c[0].value; - *mm = c[1].value; - *dd = c[2].value; - } - - curs_set(0); + *hh = c[0].value; + *mm = c[1].value; + *ss = c[2].value; for (i = 0; i < 3; i++) delwin(c[i].win); - end_dialog(conf, shadow, widget, textpad); + end_dialog(&d); - return (output); + return (retval); } |