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>
29c76f0793SBaptiste Daroussin
30c76f0793SBaptiste Daroussin #include "bsddialog.h"
31b319d934SAlfonso S. Siciliano #include "bsddialog_theme.h"
32263660c0SAlfonso Siciliano #include "lib_util.h"
33c76f0793SBaptiste Daroussin
3461ba55bcSBaptiste Daroussin struct scroll {
3561ba55bcSBaptiste Daroussin int ypad; /* y scrollable pad */
3661ba55bcSBaptiste Daroussin int htext; /* real h text to draw, to use with htextpad */
3761ba55bcSBaptiste Daroussin int htextpad; /* h textpad, draw_dialog() set at least 1 */
3861ba55bcSBaptiste Daroussin int printrows; /* h - BORDER - HBUTTONS - BORDER */
3961ba55bcSBaptiste Daroussin };
40c76f0793SBaptiste Daroussin
textupdate(struct dialog * d,struct scroll * s)4161ba55bcSBaptiste Daroussin static void textupdate(struct dialog *d, struct scroll *s)
4261ba55bcSBaptiste Daroussin {
4361ba55bcSBaptiste Daroussin if (s->htext > 0 && s->htextpad > s->printrows) {
4461ba55bcSBaptiste Daroussin wattron(d->widget, t.dialog.arrowcolor);
4561ba55bcSBaptiste Daroussin mvwprintw(d->widget, d->h - HBUTTONS - BORDER,
4661ba55bcSBaptiste Daroussin d->w - 4 - TEXTHMARGIN - BORDER,
4761ba55bcSBaptiste Daroussin "%3d%%", 100 * (s->ypad + s->printrows) / s->htextpad);
4861ba55bcSBaptiste Daroussin wattroff(d->widget, t.dialog.arrowcolor);
4961ba55bcSBaptiste Daroussin wnoutrefresh(d->widget);
5061ba55bcSBaptiste Daroussin }
5161ba55bcSBaptiste Daroussin rtextpad(d, s->ypad, 0, 0, HBUTTONS);
5261ba55bcSBaptiste Daroussin }
5361ba55bcSBaptiste Daroussin
message_size_position(struct dialog * d,int * htext)5461ba55bcSBaptiste Daroussin static int message_size_position(struct dialog *d, int *htext)
5561ba55bcSBaptiste Daroussin {
5661ba55bcSBaptiste Daroussin int minw;
5761ba55bcSBaptiste Daroussin
5861ba55bcSBaptiste Daroussin if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0)
59263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR);
6061ba55bcSBaptiste Daroussin if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w,
6161ba55bcSBaptiste Daroussin d->text, (*htext < 0) ? htext : NULL, &d->bs, 0, 0) != 0)
6261ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
6361ba55bcSBaptiste Daroussin minw = (*htext > 0) ? 1 + TEXTHMARGINS : 0 ;
6461ba55bcSBaptiste Daroussin if (widget_checksize(d->h, d->w, &d->bs, MIN(*htext, 1), minw) != 0)
6561ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
6661ba55bcSBaptiste Daroussin if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0)
6761ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
68263660c0SAlfonso Siciliano
69263660c0SAlfonso Siciliano return (0);
70c76f0793SBaptiste Daroussin }
71c76f0793SBaptiste Daroussin
message_draw(struct dialog * d,struct scroll * s)7261ba55bcSBaptiste Daroussin static int message_draw(struct dialog *d, struct scroll *s)
73c76f0793SBaptiste Daroussin {
7461ba55bcSBaptiste Daroussin int unused;
75c76f0793SBaptiste Daroussin
7661ba55bcSBaptiste Daroussin if (d->built) {
7761ba55bcSBaptiste Daroussin hide_dialog(d);
7861ba55bcSBaptiste Daroussin refresh(); /* Important for decreasing screen */
7961ba55bcSBaptiste Daroussin }
8061ba55bcSBaptiste Daroussin if (message_size_position(d, &s->htext) != 0)
8161ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
8261ba55bcSBaptiste Daroussin if (draw_dialog(d) != 0)
8361ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
8461ba55bcSBaptiste Daroussin if (d->built)
8561ba55bcSBaptiste Daroussin refresh(); /* Important to fix grey lines expanding screen */
86c76f0793SBaptiste Daroussin
8761ba55bcSBaptiste Daroussin s->printrows = d->h - BORDER - HBUTTONS - BORDER;
8861ba55bcSBaptiste Daroussin s->ypad = 0;
8961ba55bcSBaptiste Daroussin getmaxyx(d->textpad, s->htextpad, unused);
90*a6d8be45SAlfonso S. Siciliano (void)unused; /* fix unused error */
91c76f0793SBaptiste Daroussin
92263660c0SAlfonso Siciliano return (0);
93c76f0793SBaptiste Daroussin }
94c76f0793SBaptiste Daroussin
95c76f0793SBaptiste Daroussin static int
do_message(struct bsddialog_conf * conf,const char * text,int rows,int cols,const char * oklabel,const char * cancellabel)96263660c0SAlfonso Siciliano do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols,
9761ba55bcSBaptiste Daroussin const char *oklabel, const char *cancellabel)
98c76f0793SBaptiste Daroussin {
9961ba55bcSBaptiste Daroussin bool loop;
10061ba55bcSBaptiste Daroussin int retval;
101b319d934SAlfonso S. Siciliano wint_t input;
10261ba55bcSBaptiste Daroussin struct scroll s;
10361ba55bcSBaptiste Daroussin struct dialog d;
104c76f0793SBaptiste Daroussin
10561ba55bcSBaptiste Daroussin if (prepare_dialog(conf, text, rows, cols, &d) != 0)
106263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR);
10761ba55bcSBaptiste Daroussin set_buttons(&d, true, oklabel, cancellabel);
10861ba55bcSBaptiste Daroussin s.htext = -1;
10961ba55bcSBaptiste Daroussin if (message_draw(&d, &s) != 0)
110263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR);
111c76f0793SBaptiste Daroussin
112c76f0793SBaptiste Daroussin loop = true;
113c76f0793SBaptiste Daroussin while (loop) {
11461ba55bcSBaptiste Daroussin textupdate(&d, &s);
115c76f0793SBaptiste Daroussin doupdate();
116b319d934SAlfonso S. Siciliano if (get_wch(&input) == ERR)
117b319d934SAlfonso S. Siciliano continue;
118c76f0793SBaptiste Daroussin switch (input) {
119263660c0SAlfonso Siciliano case KEY_ENTER:
120c76f0793SBaptiste Daroussin case 10: /* Enter */
12161ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs);
122c76f0793SBaptiste Daroussin loop = false;
123c76f0793SBaptiste Daroussin break;
124c76f0793SBaptiste Daroussin case 27: /* Esc */
12561ba55bcSBaptiste Daroussin if (d.conf->key.enable_esc) {
126b319d934SAlfonso S. Siciliano retval = BSDDIALOG_ESC;
127c76f0793SBaptiste Daroussin loop = false;
128263660c0SAlfonso Siciliano }
129c76f0793SBaptiste Daroussin break;
130c76f0793SBaptiste Daroussin case '\t': /* TAB */
13161ba55bcSBaptiste Daroussin case KEY_RIGHT:
13261ba55bcSBaptiste Daroussin d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
13361ba55bcSBaptiste Daroussin DRAW_BUTTONS(d);
134c76f0793SBaptiste Daroussin break;
135c76f0793SBaptiste Daroussin case KEY_LEFT:
13661ba55bcSBaptiste Daroussin d.bs.curr--;
13761ba55bcSBaptiste Daroussin if (d.bs.curr < 0)
13861ba55bcSBaptiste Daroussin d.bs.curr = d.bs.nbuttons - 1;
13961ba55bcSBaptiste Daroussin DRAW_BUTTONS(d);
140c76f0793SBaptiste Daroussin break;
141*a6d8be45SAlfonso S. Siciliano case '-':
142*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('p'):
14384823cc7SAlfonso S. Siciliano case KEY_UP:
14461ba55bcSBaptiste Daroussin if (s.ypad > 0)
14561ba55bcSBaptiste Daroussin s.ypad--;
14684823cc7SAlfonso S. Siciliano break;
147*a6d8be45SAlfonso S. Siciliano case '+':
148*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('n'):
14984823cc7SAlfonso S. Siciliano case KEY_DOWN:
15061ba55bcSBaptiste Daroussin if (s.ypad + s.printrows < s.htextpad)
15161ba55bcSBaptiste Daroussin s.ypad++;
15284823cc7SAlfonso S. Siciliano break;
15384823cc7SAlfonso S. Siciliano case KEY_HOME:
15461ba55bcSBaptiste Daroussin s.ypad = 0;
15584823cc7SAlfonso S. Siciliano break;
15684823cc7SAlfonso S. Siciliano case KEY_END:
15761ba55bcSBaptiste Daroussin s.ypad = MAX(s.htextpad - s.printrows, 0);
15884823cc7SAlfonso S. Siciliano break;
15984823cc7SAlfonso S. Siciliano case KEY_PPAGE:
16061ba55bcSBaptiste Daroussin s.ypad = MAX(s.ypad - s.printrows, 0);
16184823cc7SAlfonso S. Siciliano break;
16284823cc7SAlfonso S. Siciliano case KEY_NPAGE:
16361ba55bcSBaptiste Daroussin s.ypad += s.printrows;
16461ba55bcSBaptiste Daroussin if (s.ypad + s.printrows > s.htextpad)
16561ba55bcSBaptiste Daroussin s.ypad = s.htextpad - s.printrows;
16684823cc7SAlfonso S. Siciliano break;
167263660c0SAlfonso Siciliano case KEY_F(1):
16861ba55bcSBaptiste Daroussin if (d.conf->key.f1_file == NULL &&
16961ba55bcSBaptiste Daroussin d.conf->key.f1_message == NULL)
170263660c0SAlfonso Siciliano break;
17161ba55bcSBaptiste Daroussin if (f1help_dialog(d.conf) != 0)
172263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR);
17361ba55bcSBaptiste Daroussin if (message_draw(&d, &s) != 0)
17461ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
17561ba55bcSBaptiste Daroussin break;
176*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('l'):
177263660c0SAlfonso Siciliano case KEY_RESIZE:
17861ba55bcSBaptiste Daroussin if (message_draw(&d, &s) != 0)
179263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR);
180263660c0SAlfonso Siciliano break;
181c76f0793SBaptiste Daroussin default:
18261ba55bcSBaptiste Daroussin if (shortcut_buttons(input, &d.bs)) {
18361ba55bcSBaptiste Daroussin DRAW_BUTTONS(d);
18461ba55bcSBaptiste Daroussin doupdate();
18561ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs);
186c76f0793SBaptiste Daroussin loop = false;
187c76f0793SBaptiste Daroussin }
188c76f0793SBaptiste Daroussin }
189c76f0793SBaptiste Daroussin }
190c76f0793SBaptiste Daroussin
19161ba55bcSBaptiste Daroussin end_dialog(&d);
192c76f0793SBaptiste Daroussin
193b319d934SAlfonso S. Siciliano return (retval);
194c76f0793SBaptiste Daroussin }
195c76f0793SBaptiste Daroussin
196c76f0793SBaptiste Daroussin /* API */
197c76f0793SBaptiste Daroussin int
bsddialog_msgbox(struct bsddialog_conf * conf,const char * text,int rows,int cols)198263660c0SAlfonso Siciliano bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows,
199263660c0SAlfonso Siciliano int cols)
200c76f0793SBaptiste Daroussin {
20161ba55bcSBaptiste Daroussin return (do_message(conf, text, rows, cols, OK_LABEL, NULL));
202c76f0793SBaptiste Daroussin }
203c76f0793SBaptiste Daroussin
204c76f0793SBaptiste Daroussin int
bsddialog_yesno(struct bsddialog_conf * conf,const char * text,int rows,int cols)205263660c0SAlfonso Siciliano bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows,
206263660c0SAlfonso Siciliano int cols)
207c76f0793SBaptiste Daroussin {
20861ba55bcSBaptiste Daroussin return (do_message(conf, text, rows, cols, "Yes", "No"));
20961ba55bcSBaptiste Daroussin }
210c76f0793SBaptiste Daroussin
21161ba55bcSBaptiste Daroussin int
bsddialog_infobox(struct bsddialog_conf * conf,const char * text,int rows,int cols)21261ba55bcSBaptiste Daroussin bsddialog_infobox(struct bsddialog_conf *conf, const char *text, int rows,
21361ba55bcSBaptiste Daroussin int cols)
21461ba55bcSBaptiste Daroussin {
21561ba55bcSBaptiste Daroussin int htext;
21661ba55bcSBaptiste Daroussin struct dialog d;
217c76f0793SBaptiste Daroussin
21861ba55bcSBaptiste Daroussin if (prepare_dialog(conf, text, rows, cols, &d) != 0)
21961ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
22061ba55bcSBaptiste Daroussin htext = -1;
22161ba55bcSBaptiste Daroussin if (message_size_position(&d, &htext) != 0)
22261ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
22361ba55bcSBaptiste Daroussin if (draw_dialog(&d) != 0)
22461ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR);
22561ba55bcSBaptiste Daroussin TEXTPAD(&d, 0);
22661ba55bcSBaptiste Daroussin doupdate();
22761ba55bcSBaptiste Daroussin
22861ba55bcSBaptiste Daroussin end_dialog(&d);
22961ba55bcSBaptiste Daroussin
23061ba55bcSBaptiste Daroussin return (BSDDIALOG_OK);
231c76f0793SBaptiste Daroussin }
232