1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4*a6d8be45SAlfonso S. Siciliano * Copyright (c) 2021-2024 Alfonso Sabato Siciliano 5c76f0793SBaptiste Daroussin * 6c76f0793SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 7c76f0793SBaptiste Daroussin * modification, are permitted provided that the following conditions 8c76f0793SBaptiste Daroussin * are met: 9c76f0793SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 10c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 11c76f0793SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 12c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 13c76f0793SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 14c76f0793SBaptiste Daroussin * 15c76f0793SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16c76f0793SBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17c76f0793SBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18c76f0793SBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19c76f0793SBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20c76f0793SBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21c76f0793SBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22c76f0793SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23c76f0793SBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24c76f0793SBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25c76f0793SBaptiste Daroussin * SUCH DAMAGE. 26c76f0793SBaptiste Daroussin */ 27c76f0793SBaptiste Daroussin 28263660c0SAlfonso Siciliano #include <curses.h> 29f499134dSBaptiste Daroussin 30c76f0793SBaptiste Daroussin #include "bsddialog.h" 31b319d934SAlfonso S. Siciliano #include "bsddialog_theme.h" 32263660c0SAlfonso Siciliano #include "lib_util.h" 33c76f0793SBaptiste Daroussin 34263660c0SAlfonso Siciliano #define MINWTIME 14 /* 3 windows and their borders */ 3561ba55bcSBaptiste Daroussin #define HBOX 3 3661ba55bcSBaptiste Daroussin #define WBOX 4 37f499134dSBaptiste Daroussin 3861ba55bcSBaptiste Daroussin struct clock { 39c76f0793SBaptiste Daroussin unsigned int max; 40f499134dSBaptiste Daroussin unsigned int value; 41c76f0793SBaptiste Daroussin WINDOW *win; 42f499134dSBaptiste Daroussin }; 43c76f0793SBaptiste Daroussin 4461ba55bcSBaptiste Daroussin static void 4561ba55bcSBaptiste Daroussin drawsquare(struct bsddialog_conf *conf, WINDOW *win, unsigned int value, 4661ba55bcSBaptiste Daroussin bool focus) 4761ba55bcSBaptiste Daroussin { 4861ba55bcSBaptiste Daroussin draw_borders(conf, win, LOWERED); 4961ba55bcSBaptiste Daroussin if (focus) { 5061ba55bcSBaptiste Daroussin wattron(win, t.dialog.arrowcolor); 51*a6d8be45SAlfonso S. Siciliano mvwhline(win, 0, 1, UARROW(conf), 2); 52*a6d8be45SAlfonso S. Siciliano mvwhline(win, 2, 1, DARROW(conf), 2); 5361ba55bcSBaptiste Daroussin wattroff(win, t.dialog.arrowcolor); 5461ba55bcSBaptiste Daroussin } 55c76f0793SBaptiste Daroussin 5661ba55bcSBaptiste Daroussin if (focus) 5761ba55bcSBaptiste Daroussin wattron(win, t.menu.f_namecolor); 5861ba55bcSBaptiste Daroussin mvwprintw(win, 1, 1, "%02u", value); 5961ba55bcSBaptiste Daroussin if (focus) 6061ba55bcSBaptiste Daroussin wattroff(win, t.menu.f_namecolor); 6161ba55bcSBaptiste Daroussin 6261ba55bcSBaptiste Daroussin wnoutrefresh(win); 6361ba55bcSBaptiste Daroussin } 6461ba55bcSBaptiste Daroussin 6561ba55bcSBaptiste Daroussin static int timebox_redraw(struct dialog *d, struct clock *c) 6661ba55bcSBaptiste Daroussin { 6761ba55bcSBaptiste Daroussin int y, x; 6861ba55bcSBaptiste Daroussin 6961ba55bcSBaptiste Daroussin if (d->built) { 7061ba55bcSBaptiste Daroussin hide_dialog(d); 7161ba55bcSBaptiste Daroussin refresh(); /* Important for decreasing screen */ 7261ba55bcSBaptiste Daroussin } 7361ba55bcSBaptiste Daroussin if (dialog_size_position(d, HBOX, MINWTIME, NULL) != 0) 7461ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 7561ba55bcSBaptiste Daroussin if (draw_dialog(d) != 0) 7661ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 7761ba55bcSBaptiste Daroussin if (d->built) 7861ba55bcSBaptiste Daroussin refresh(); /* Important to fix grey lines expanding screen */ 7961ba55bcSBaptiste Daroussin TEXTPAD(d, HBOX + HBUTTONS); 8061ba55bcSBaptiste Daroussin 8161ba55bcSBaptiste Daroussin y = d->y + d->h - BORDER - HBUTTONS - HBOX; 8261ba55bcSBaptiste Daroussin x = d->x + d->w/2 - 7; 8361ba55bcSBaptiste Daroussin update_box(d->conf, c[0].win, y, x, HBOX, WBOX, LOWERED); 8461ba55bcSBaptiste Daroussin mvwaddch(d->widget, d->h - 5, d->w/2 - 3, ':'); 8561ba55bcSBaptiste Daroussin update_box(d->conf, c[1].win, y, x += 5, HBOX, WBOX, LOWERED); 8661ba55bcSBaptiste Daroussin mvwaddch(d->widget, d->h - 5, d->w/2 + 2, ':'); 8761ba55bcSBaptiste Daroussin update_box(d->conf, c[2].win, y, x + 5, HBOX, WBOX, LOWERED); 8861ba55bcSBaptiste Daroussin wnoutrefresh(d->widget); /* for mvwaddch(':') */ 8961ba55bcSBaptiste Daroussin 9061ba55bcSBaptiste Daroussin return (0); 9161ba55bcSBaptiste Daroussin } 9261ba55bcSBaptiste Daroussin 9361ba55bcSBaptiste Daroussin /* API */ 9461ba55bcSBaptiste Daroussin int 9561ba55bcSBaptiste Daroussin bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows, 9661ba55bcSBaptiste Daroussin int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss) 9761ba55bcSBaptiste Daroussin { 9861ba55bcSBaptiste Daroussin bool loop, focusbuttons; 9961ba55bcSBaptiste Daroussin int i, retval, sel; 10061ba55bcSBaptiste Daroussin wint_t input; 10161ba55bcSBaptiste Daroussin struct dialog d; 10261ba55bcSBaptiste Daroussin struct clock c[3] = { 103f499134dSBaptiste Daroussin {23, *hh, NULL}, 104f499134dSBaptiste Daroussin {59, *mm, NULL}, 105f499134dSBaptiste Daroussin {59, *ss, NULL} 106f499134dSBaptiste Daroussin }; 107f499134dSBaptiste Daroussin 10861ba55bcSBaptiste Daroussin CHECK_PTR(hh); 10961ba55bcSBaptiste Daroussin CHECK_PTR(mm); 11061ba55bcSBaptiste Daroussin CHECK_PTR(ss); 11161ba55bcSBaptiste Daroussin if (prepare_dialog(conf, text, rows, cols, &d) != 0) 11261ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 11361ba55bcSBaptiste Daroussin set_buttons(&d, true, OK_LABEL, CANCEL_LABEL); 114f499134dSBaptiste Daroussin for (i=0; i<3; i++) { 11561ba55bcSBaptiste Daroussin if ((c[i].win = newwin(1, 1, 1, 1)) == NULL) 11661ba55bcSBaptiste Daroussin RETURN_FMTERROR("Cannot build WINDOW for time[%d]", i); 11761ba55bcSBaptiste Daroussin wbkgd(c[i].win, t.dialog.color); 11861ba55bcSBaptiste Daroussin c[i].value = MIN(c[i].value, c[i].max); 119f499134dSBaptiste Daroussin } 12061ba55bcSBaptiste Daroussin if (timebox_redraw(&d, c) != 0) 121263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 122f499134dSBaptiste Daroussin 123b319d934SAlfonso S. Siciliano sel = -1; 124bce40c02SAlfonso S. Siciliano loop = focusbuttons = true; 125c76f0793SBaptiste Daroussin while (loop) { 126b319d934SAlfonso S. Siciliano for (i = 0; i < 3; i++) 12761ba55bcSBaptiste Daroussin drawsquare(conf, c[i].win, c[i].value, sel == i); 12861ba55bcSBaptiste Daroussin doupdate(); 129b319d934SAlfonso S. Siciliano if (get_wch(&input) == ERR) 130b319d934SAlfonso S. Siciliano continue; 131c76f0793SBaptiste Daroussin switch(input) { 132f499134dSBaptiste Daroussin case KEY_ENTER: 133c76f0793SBaptiste Daroussin case 10: /* Enter */ 134b319d934SAlfonso S. Siciliano if (focusbuttons || conf->button.always_active) { 13561ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs); 136c76f0793SBaptiste Daroussin loop = false; 137b319d934SAlfonso S. Siciliano } 138c76f0793SBaptiste Daroussin break; 139c76f0793SBaptiste Daroussin case 27: /* Esc */ 140263660c0SAlfonso Siciliano if (conf->key.enable_esc) { 141b319d934SAlfonso S. Siciliano retval = BSDDIALOG_ESC; 142c76f0793SBaptiste Daroussin loop = false; 143263660c0SAlfonso Siciliano } 144c76f0793SBaptiste Daroussin break; 145c76f0793SBaptiste Daroussin case '\t': /* TAB */ 146*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('n'): 147*a6d8be45SAlfonso S. Siciliano case KEY_RIGHT: 148bce40c02SAlfonso S. Siciliano if (focusbuttons) { 14961ba55bcSBaptiste Daroussin d.bs.curr++; 15061ba55bcSBaptiste Daroussin focusbuttons = d.bs.curr < (int)d.bs.nbuttons ? 151bce40c02SAlfonso S. Siciliano true : false; 152bce40c02SAlfonso S. Siciliano if (focusbuttons == false) { 153bce40c02SAlfonso S. Siciliano sel = 0; 15461ba55bcSBaptiste Daroussin d.bs.curr = 15561ba55bcSBaptiste Daroussin conf->button.always_active ? 0 : -1; 156bce40c02SAlfonso S. Siciliano } 157bce40c02SAlfonso S. Siciliano } else { 158bce40c02SAlfonso S. Siciliano sel++; 159bce40c02SAlfonso S. Siciliano focusbuttons = sel > 2 ? true : false; 160bce40c02SAlfonso S. Siciliano if (focusbuttons) { 16161ba55bcSBaptiste Daroussin d.bs.curr = 0; 162bce40c02SAlfonso S. Siciliano } 163bce40c02SAlfonso S. Siciliano } 16461ba55bcSBaptiste Daroussin DRAW_BUTTONS(d); 165c76f0793SBaptiste Daroussin break; 166*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('p'): 167c76f0793SBaptiste Daroussin case KEY_LEFT: 168bce40c02SAlfonso S. Siciliano if (focusbuttons) { 16961ba55bcSBaptiste Daroussin d.bs.curr--; 17061ba55bcSBaptiste Daroussin focusbuttons = d.bs.curr < 0 ? false : true; 171bce40c02SAlfonso S. Siciliano if (focusbuttons == false) { 172bce40c02SAlfonso S. Siciliano sel = 2; 17361ba55bcSBaptiste Daroussin d.bs.curr = 17461ba55bcSBaptiste Daroussin conf->button.always_active ? 0 : -1; 175bce40c02SAlfonso S. Siciliano } 176bce40c02SAlfonso S. Siciliano } else { 177bce40c02SAlfonso S. Siciliano sel--; 178bce40c02SAlfonso S. Siciliano focusbuttons = sel < 0 ? true : false; 179b319d934SAlfonso S. Siciliano if (focusbuttons) 18061ba55bcSBaptiste Daroussin d.bs.curr = (int)d.bs.nbuttons - 1; 181bce40c02SAlfonso S. Siciliano } 18261ba55bcSBaptiste Daroussin DRAW_BUTTONS(d); 183c76f0793SBaptiste Daroussin break; 184*a6d8be45SAlfonso S. Siciliano case '-': 185*a6d8be45SAlfonso S. Siciliano if (focusbuttons == false) 186*a6d8be45SAlfonso S. Siciliano c[sel].value = c[sel].value > 0 ? 187*a6d8be45SAlfonso S. Siciliano c[sel].value - 1 : c[sel].max; 188*a6d8be45SAlfonso S. Siciliano break; 189c76f0793SBaptiste Daroussin case KEY_UP: 190b319d934SAlfonso S. Siciliano if (focusbuttons) { 191b319d934SAlfonso S. Siciliano sel = 0; 192b319d934SAlfonso S. Siciliano focusbuttons = false; 19361ba55bcSBaptiste Daroussin d.bs.curr = conf->button.always_active ? 0 : -1; 19461ba55bcSBaptiste Daroussin DRAW_BUTTONS(d); 19561ba55bcSBaptiste Daroussin } else { 19661ba55bcSBaptiste Daroussin c[sel].value = c[sel].value > 0 ? 197263660c0SAlfonso Siciliano c[sel].value - 1 : c[sel].max; 198b319d934SAlfonso S. Siciliano } 199c76f0793SBaptiste Daroussin break; 200*a6d8be45SAlfonso S. Siciliano case '+': 201bce40c02SAlfonso S. Siciliano case KEY_DOWN: 202bce40c02SAlfonso S. Siciliano if (focusbuttons) 203bce40c02SAlfonso S. Siciliano break; 204bce40c02SAlfonso S. Siciliano c[sel].value = c[sel].value < c[sel].max ? 205bce40c02SAlfonso S. Siciliano c[sel].value + 1 : 0; 206bce40c02SAlfonso S. Siciliano break; 207f499134dSBaptiste Daroussin case KEY_F(1): 208bce40c02SAlfonso S. Siciliano if (conf->key.f1_file == NULL && 209bce40c02SAlfonso S. Siciliano conf->key.f1_message == NULL) 210f499134dSBaptiste Daroussin break; 21161ba55bcSBaptiste Daroussin if (f1help_dialog(conf) != 0) 212263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 21361ba55bcSBaptiste Daroussin if (timebox_redraw(&d, c) != 0) 21461ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 21561ba55bcSBaptiste Daroussin break; 216*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('l'): 217f499134dSBaptiste Daroussin case KEY_RESIZE: 21861ba55bcSBaptiste Daroussin if (timebox_redraw(&d, c) != 0) 219263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 220f499134dSBaptiste Daroussin break; 221f499134dSBaptiste Daroussin default: 22261ba55bcSBaptiste Daroussin if (shortcut_buttons(input, &d.bs)) { 22361ba55bcSBaptiste Daroussin DRAW_BUTTONS(d); 22461ba55bcSBaptiste Daroussin doupdate(); 22561ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs); 226f499134dSBaptiste Daroussin loop = false; 227f499134dSBaptiste Daroussin } 228c76f0793SBaptiste Daroussin } 229c76f0793SBaptiste Daroussin } 230c76f0793SBaptiste Daroussin 231bce40c02SAlfonso S. Siciliano *hh = c[0].value; 232bce40c02SAlfonso S. Siciliano *mm = c[1].value; 233bce40c02SAlfonso S. Siciliano *ss = c[2].value; 234bce40c02SAlfonso S. Siciliano 235c76f0793SBaptiste Daroussin for (i = 0; i < 3; i++) 236c76f0793SBaptiste Daroussin delwin(c[i].win); 23761ba55bcSBaptiste Daroussin end_dialog(&d); 238c76f0793SBaptiste Daroussin 239b319d934SAlfonso S. Siciliano return (retval); 240c76f0793SBaptiste Daroussin } 241