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 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 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 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 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 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 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 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