1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4*263660c0SAlfonso Siciliano * Copyright (c) 2021-2022 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 28c76f0793SBaptiste Daroussin #include <sys/param.h> 29c76f0793SBaptiste Daroussin 30*263660c0SAlfonso Siciliano #include <curses.h> 31d93b4d32SBaptiste Daroussin #include <string.h> 32c76f0793SBaptiste Daroussin 33c76f0793SBaptiste Daroussin #include "bsddialog.h" 34c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 35*263660c0SAlfonso Siciliano #include "lib_util.h" 36c76f0793SBaptiste Daroussin 37c76f0793SBaptiste Daroussin extern struct bsddialog_theme t; 38c76f0793SBaptiste Daroussin 39c76f0793SBaptiste Daroussin static int 40d93b4d32SBaptiste Daroussin message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, 41*263660c0SAlfonso Siciliano int *w, const char *text, struct buttons bs) 42c76f0793SBaptiste Daroussin { 43*263660c0SAlfonso Siciliano int htext, wtext; 44c76f0793SBaptiste Daroussin 45*263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { 46*263660c0SAlfonso Siciliano if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2, 47*263660c0SAlfonso Siciliano &htext, &wtext) != 0) 48*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 49c76f0793SBaptiste Daroussin } 50c76f0793SBaptiste Daroussin 51*263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE) 52*263660c0SAlfonso Siciliano *w = widget_min_width(conf, wtext, 0, &bs); 53c76f0793SBaptiste Daroussin 54*263660c0SAlfonso Siciliano if (rows == BSDDIALOG_AUTOSIZE) 55*263660c0SAlfonso Siciliano *h = widget_min_height(conf, htext, 0, true); 56*263660c0SAlfonso Siciliano 57*263660c0SAlfonso Siciliano return (0); 58c76f0793SBaptiste Daroussin } 59c76f0793SBaptiste Daroussin 60c76f0793SBaptiste Daroussin static int message_checksize(int rows, int cols, struct buttons bs) 61c76f0793SBaptiste Daroussin { 62c76f0793SBaptiste Daroussin int mincols; 63c76f0793SBaptiste Daroussin 64c76f0793SBaptiste Daroussin mincols = VBORDERS; 65c76f0793SBaptiste Daroussin mincols += bs.nbuttons * bs.sizebutton; 66f499134dSBaptiste Daroussin mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; 67c76f0793SBaptiste Daroussin 68c76f0793SBaptiste Daroussin if (cols < mincols) 69*263660c0SAlfonso Siciliano RETURN_ERROR("Few cols, Msgbox and Yesno need at least width " 70c76f0793SBaptiste Daroussin "for borders, buttons and spaces between buttons"); 71c76f0793SBaptiste Daroussin 72*263660c0SAlfonso Siciliano if (rows < HBORDERS + 2 /*buttons*/) 73*263660c0SAlfonso Siciliano RETURN_ERROR("Msgbox and Yesno need at least height 4"); 74c76f0793SBaptiste Daroussin 75*263660c0SAlfonso Siciliano return (0); 76c76f0793SBaptiste Daroussin } 77c76f0793SBaptiste Daroussin 78c76f0793SBaptiste Daroussin static void 79*263660c0SAlfonso Siciliano textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad) 80c76f0793SBaptiste Daroussin { 81*263660c0SAlfonso Siciliano int y, x, h, w; 82c76f0793SBaptiste Daroussin 83*263660c0SAlfonso Siciliano getbegyx(widget, y, x); 84*263660c0SAlfonso Siciliano getmaxyx(widget, h, w); 85*263660c0SAlfonso Siciliano 86c76f0793SBaptiste Daroussin if (htextpad > h - 4) { 87c76f0793SBaptiste Daroussin mvwprintw(widget, h-3, w-6, "%3d%%", 88*263660c0SAlfonso Siciliano 100 * (ytextpad+h-4)/ htextpad); 89c76f0793SBaptiste Daroussin wnoutrefresh(widget); 90c76f0793SBaptiste Daroussin } 91c76f0793SBaptiste Daroussin 92*263660c0SAlfonso Siciliano pnoutrefresh(textpad, ytextpad, 0, y+1, x+2, y+h-4, x+w-2); 93c76f0793SBaptiste Daroussin } 94c76f0793SBaptiste Daroussin 95c76f0793SBaptiste Daroussin static int 96*263660c0SAlfonso Siciliano do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, 97d93b4d32SBaptiste Daroussin struct buttons bs) 98c76f0793SBaptiste Daroussin { 99c76f0793SBaptiste Daroussin bool loop; 100*263660c0SAlfonso Siciliano int y, x, h, w, input, output, ytextpad, htextpad, unused; 101*263660c0SAlfonso Siciliano WINDOW *widget, *textpad, *shadow; 102c76f0793SBaptiste Daroussin 103c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 104*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 105c76f0793SBaptiste Daroussin if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) 106*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 107c76f0793SBaptiste Daroussin if (message_checksize(h, w, bs) != 0) 108*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 109c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 110*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 111c76f0793SBaptiste Daroussin 112*263660c0SAlfonso Siciliano if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, 113*263660c0SAlfonso Siciliano true) != 0) 114*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 115c76f0793SBaptiste Daroussin 116*263660c0SAlfonso Siciliano ytextpad = 0; 117*263660c0SAlfonso Siciliano getmaxyx(textpad, htextpad, unused); 118*263660c0SAlfonso Siciliano unused++; /* fix unused error */ 119*263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 120c76f0793SBaptiste Daroussin loop = true; 121c76f0793SBaptiste Daroussin while (loop) { 122c76f0793SBaptiste Daroussin doupdate(); 123c76f0793SBaptiste Daroussin input = getch(); 124c76f0793SBaptiste Daroussin switch (input) { 125*263660c0SAlfonso Siciliano case KEY_ENTER: 126c76f0793SBaptiste Daroussin case 10: /* Enter */ 127c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; 128c76f0793SBaptiste Daroussin loop = false; 129c76f0793SBaptiste Daroussin break; 130c76f0793SBaptiste Daroussin case 27: /* Esc */ 131*263660c0SAlfonso Siciliano if (conf->key.enable_esc) { 132c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 133c76f0793SBaptiste Daroussin loop = false; 134*263660c0SAlfonso Siciliano } 135c76f0793SBaptiste Daroussin break; 136c76f0793SBaptiste Daroussin case '\t': /* TAB */ 137c76f0793SBaptiste Daroussin bs.curr = (bs.curr + 1) % bs.nbuttons; 138*263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 139*263660c0SAlfonso Siciliano wnoutrefresh(widget); 140c76f0793SBaptiste Daroussin break; 141c76f0793SBaptiste Daroussin case KEY_LEFT: 142c76f0793SBaptiste Daroussin if (bs.curr > 0) { 143c76f0793SBaptiste Daroussin bs.curr--; 144*263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 145*263660c0SAlfonso Siciliano wnoutrefresh(widget); 146c76f0793SBaptiste Daroussin } 147c76f0793SBaptiste Daroussin break; 148c76f0793SBaptiste Daroussin case KEY_RIGHT: 149c76f0793SBaptiste Daroussin if (bs.curr < (int)bs.nbuttons - 1) { 150c76f0793SBaptiste Daroussin bs.curr++; 151*263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 152*263660c0SAlfonso Siciliano wnoutrefresh(widget); 153c76f0793SBaptiste Daroussin } 154c76f0793SBaptiste Daroussin break; 155*263660c0SAlfonso Siciliano case KEY_F(1): 156*263660c0SAlfonso Siciliano if (conf->f1_file == NULL && conf->f1_message == NULL) 157*263660c0SAlfonso Siciliano break; 158*263660c0SAlfonso Siciliano if (f1help(conf) != 0) 159*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 160*263660c0SAlfonso Siciliano /* No break, screen size can change */ 161*263660c0SAlfonso Siciliano case KEY_RESIZE: 162*263660c0SAlfonso Siciliano /* Important for decreasing screen */ 163*263660c0SAlfonso Siciliano hide_widget(y, x, h, w, conf->shadow); 164*263660c0SAlfonso Siciliano refresh(); 165*263660c0SAlfonso Siciliano 166*263660c0SAlfonso Siciliano if (set_widget_size(conf, rows, cols, &h, &w) != 0) 167*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 168*263660c0SAlfonso Siciliano if (message_autosize(conf, rows, cols, &h, &w, text, 169*263660c0SAlfonso Siciliano bs) != 0) 170*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 171*263660c0SAlfonso Siciliano if (message_checksize(h, w, bs) != 0) 172*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 173*263660c0SAlfonso Siciliano if (set_widget_position(conf, &y, &x, h, w) != 0) 174*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 175*263660c0SAlfonso Siciliano 176*263660c0SAlfonso Siciliano if (update_dialog(conf, shadow, widget, y, x, h, w, 177*263660c0SAlfonso Siciliano textpad, text, &bs, true) != 0) 178*263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 179*263660c0SAlfonso Siciliano 180*263660c0SAlfonso Siciliano getmaxyx(textpad, htextpad, unused); 181*263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 182*263660c0SAlfonso Siciliano 183*263660c0SAlfonso Siciliano /* Important to fix grey lines expanding screen */ 184*263660c0SAlfonso Siciliano refresh(); 185*263660c0SAlfonso Siciliano break; 186*263660c0SAlfonso Siciliano case KEY_UP: 187*263660c0SAlfonso Siciliano if (ytextpad == 0) 188*263660c0SAlfonso Siciliano break; 189*263660c0SAlfonso Siciliano ytextpad--; 190*263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 191*263660c0SAlfonso Siciliano break; 192*263660c0SAlfonso Siciliano case KEY_DOWN: 193*263660c0SAlfonso Siciliano if (ytextpad + h - 4 >= htextpad) 194*263660c0SAlfonso Siciliano break; 195*263660c0SAlfonso Siciliano ytextpad++; 196*263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 197*263660c0SAlfonso Siciliano break; 198c76f0793SBaptiste Daroussin default: 199*263660c0SAlfonso Siciliano if (shortcut_buttons(input, &bs)) { 200*263660c0SAlfonso Siciliano output = bs.value[bs.curr]; 201c76f0793SBaptiste Daroussin loop = false; 202c76f0793SBaptiste Daroussin } 203c76f0793SBaptiste Daroussin } 204c76f0793SBaptiste Daroussin } 205c76f0793SBaptiste Daroussin 206*263660c0SAlfonso Siciliano end_dialog(conf, shadow, widget, textpad); 207c76f0793SBaptiste Daroussin 208*263660c0SAlfonso Siciliano return (output); 209c76f0793SBaptiste Daroussin } 210c76f0793SBaptiste Daroussin 211c76f0793SBaptiste Daroussin /* API */ 212c76f0793SBaptiste Daroussin int 213*263660c0SAlfonso Siciliano bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows, 214*263660c0SAlfonso Siciliano int cols) 215c76f0793SBaptiste Daroussin { 216c76f0793SBaptiste Daroussin struct buttons bs; 217c76f0793SBaptiste Daroussin 218*263660c0SAlfonso Siciliano get_buttons(conf, &bs, BUTTON_OK_LABEL, NULL); 219c76f0793SBaptiste Daroussin 220*263660c0SAlfonso Siciliano return (do_message(conf, text, rows, cols, bs)); 221c76f0793SBaptiste Daroussin } 222c76f0793SBaptiste Daroussin 223c76f0793SBaptiste Daroussin int 224*263660c0SAlfonso Siciliano bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows, 225*263660c0SAlfonso Siciliano int cols) 226c76f0793SBaptiste Daroussin { 227c76f0793SBaptiste Daroussin struct buttons bs; 228c76f0793SBaptiste Daroussin 229*263660c0SAlfonso Siciliano get_buttons(conf, &bs, "Yes", "No"); 230c76f0793SBaptiste Daroussin 231*263660c0SAlfonso Siciliano return (do_message(conf, text, rows, cols, bs)); 232c76f0793SBaptiste Daroussin }