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
drawsquare(struct bsddialog_conf * conf,WINDOW * win,unsigned int value,bool focus)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
timebox_redraw(struct dialog * d,struct clock * c)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
bsddialog_timebox(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int * hh,unsigned int * mm,unsigned int * ss)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