1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4263660c0SAlfonso 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 30263660c0SAlfonso Siciliano #include <curses.h> 31d93b4d32SBaptiste Daroussin #include <string.h> 32c76f0793SBaptiste Daroussin 33c76f0793SBaptiste Daroussin #include "bsddialog.h" 34263660c0SAlfonso Siciliano #include "lib_util.h" 35c76f0793SBaptiste Daroussin 36c76f0793SBaptiste Daroussin static int 37d93b4d32SBaptiste Daroussin message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, 38263660c0SAlfonso Siciliano int *w, const char *text, struct buttons bs) 39c76f0793SBaptiste Daroussin { 40263660c0SAlfonso Siciliano int htext, wtext; 41c76f0793SBaptiste Daroussin 42263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { 43263660c0SAlfonso Siciliano if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2, 44263660c0SAlfonso Siciliano &htext, &wtext) != 0) 45263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 46c76f0793SBaptiste Daroussin } 47c76f0793SBaptiste Daroussin 48263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE) 49263660c0SAlfonso Siciliano *w = widget_min_width(conf, wtext, 0, &bs); 50c76f0793SBaptiste Daroussin 51263660c0SAlfonso Siciliano if (rows == BSDDIALOG_AUTOSIZE) 52263660c0SAlfonso Siciliano *h = widget_min_height(conf, htext, 0, true); 53263660c0SAlfonso Siciliano 54263660c0SAlfonso Siciliano return (0); 55c76f0793SBaptiste Daroussin } 56c76f0793SBaptiste Daroussin 57c76f0793SBaptiste Daroussin static int message_checksize(int rows, int cols, struct buttons bs) 58c76f0793SBaptiste Daroussin { 59c76f0793SBaptiste Daroussin int mincols; 60c76f0793SBaptiste Daroussin 61c76f0793SBaptiste Daroussin mincols = VBORDERS; 62*bce40c02SAlfonso S. Siciliano mincols += buttons_width(bs); 63c76f0793SBaptiste Daroussin 64c76f0793SBaptiste Daroussin if (cols < mincols) 65263660c0SAlfonso Siciliano RETURN_ERROR("Few cols, Msgbox and Yesno need at least width " 66c76f0793SBaptiste Daroussin "for borders, buttons and spaces between buttons"); 67c76f0793SBaptiste Daroussin 68263660c0SAlfonso Siciliano if (rows < HBORDERS + 2 /*buttons*/) 69263660c0SAlfonso Siciliano RETURN_ERROR("Msgbox and Yesno need at least height 4"); 70c76f0793SBaptiste Daroussin 71263660c0SAlfonso Siciliano return (0); 72c76f0793SBaptiste Daroussin } 73c76f0793SBaptiste Daroussin 74c76f0793SBaptiste Daroussin static void 75263660c0SAlfonso Siciliano textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad) 76c76f0793SBaptiste Daroussin { 77263660c0SAlfonso Siciliano int y, x, h, w; 78c76f0793SBaptiste Daroussin 79263660c0SAlfonso Siciliano getbegyx(widget, y, x); 80263660c0SAlfonso Siciliano getmaxyx(widget, h, w); 81263660c0SAlfonso Siciliano 82c76f0793SBaptiste Daroussin if (htextpad > h - 4) { 83c76f0793SBaptiste Daroussin mvwprintw(widget, h-3, w-6, "%3d%%", 84263660c0SAlfonso Siciliano 100 * (ytextpad+h-4)/ htextpad); 85c76f0793SBaptiste Daroussin wnoutrefresh(widget); 86c76f0793SBaptiste Daroussin } 87c76f0793SBaptiste Daroussin 88263660c0SAlfonso Siciliano pnoutrefresh(textpad, ytextpad, 0, y+1, x+2, y+h-4, x+w-2); 89c76f0793SBaptiste Daroussin } 90c76f0793SBaptiste Daroussin 91c76f0793SBaptiste Daroussin static int 92263660c0SAlfonso Siciliano do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, 93d93b4d32SBaptiste Daroussin struct buttons bs) 94c76f0793SBaptiste Daroussin { 95c76f0793SBaptiste Daroussin bool loop; 96263660c0SAlfonso Siciliano int y, x, h, w, input, output, ytextpad, htextpad, unused; 97263660c0SAlfonso Siciliano WINDOW *widget, *textpad, *shadow; 98c76f0793SBaptiste Daroussin 99c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 100263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 101c76f0793SBaptiste Daroussin if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) 102263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 103c76f0793SBaptiste Daroussin if (message_checksize(h, w, bs) != 0) 104263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 105c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 106263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 107c76f0793SBaptiste Daroussin 108263660c0SAlfonso Siciliano if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, 109263660c0SAlfonso Siciliano true) != 0) 110263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 111c76f0793SBaptiste Daroussin 112263660c0SAlfonso Siciliano ytextpad = 0; 113263660c0SAlfonso Siciliano getmaxyx(textpad, htextpad, unused); 114263660c0SAlfonso Siciliano unused++; /* fix unused error */ 115263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 116c76f0793SBaptiste Daroussin loop = true; 117c76f0793SBaptiste Daroussin while (loop) { 118c76f0793SBaptiste Daroussin doupdate(); 119c76f0793SBaptiste Daroussin input = getch(); 120c76f0793SBaptiste Daroussin switch (input) { 121263660c0SAlfonso Siciliano case KEY_ENTER: 122c76f0793SBaptiste Daroussin case 10: /* Enter */ 123c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; 124c76f0793SBaptiste Daroussin loop = false; 125c76f0793SBaptiste Daroussin break; 126c76f0793SBaptiste Daroussin case 27: /* Esc */ 127263660c0SAlfonso Siciliano if (conf->key.enable_esc) { 128c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 129c76f0793SBaptiste Daroussin loop = false; 130263660c0SAlfonso Siciliano } 131c76f0793SBaptiste Daroussin break; 132c76f0793SBaptiste Daroussin case '\t': /* TAB */ 133c76f0793SBaptiste Daroussin bs.curr = (bs.curr + 1) % bs.nbuttons; 134263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 135263660c0SAlfonso Siciliano wnoutrefresh(widget); 136c76f0793SBaptiste Daroussin break; 137c76f0793SBaptiste Daroussin case KEY_LEFT: 138c76f0793SBaptiste Daroussin if (bs.curr > 0) { 139c76f0793SBaptiste Daroussin bs.curr--; 140263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 141263660c0SAlfonso Siciliano wnoutrefresh(widget); 142c76f0793SBaptiste Daroussin } 143c76f0793SBaptiste Daroussin break; 144c76f0793SBaptiste Daroussin case KEY_RIGHT: 145c76f0793SBaptiste Daroussin if (bs.curr < (int)bs.nbuttons - 1) { 146c76f0793SBaptiste Daroussin bs.curr++; 147263660c0SAlfonso Siciliano draw_buttons(widget, bs, true); 148263660c0SAlfonso Siciliano wnoutrefresh(widget); 149c76f0793SBaptiste Daroussin } 150c76f0793SBaptiste Daroussin break; 151263660c0SAlfonso Siciliano case KEY_F(1): 152*bce40c02SAlfonso S. Siciliano if (conf->key.f1_file == NULL && 153*bce40c02SAlfonso S. Siciliano conf->key.f1_message == NULL) 154263660c0SAlfonso Siciliano break; 155263660c0SAlfonso Siciliano if (f1help(conf) != 0) 156263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 157263660c0SAlfonso Siciliano /* No break, screen size can change */ 158263660c0SAlfonso Siciliano case KEY_RESIZE: 159263660c0SAlfonso Siciliano /* Important for decreasing screen */ 160263660c0SAlfonso Siciliano hide_widget(y, x, h, w, conf->shadow); 161263660c0SAlfonso Siciliano refresh(); 162263660c0SAlfonso Siciliano 163263660c0SAlfonso Siciliano if (set_widget_size(conf, rows, cols, &h, &w) != 0) 164263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 165263660c0SAlfonso Siciliano if (message_autosize(conf, rows, cols, &h, &w, text, 166263660c0SAlfonso Siciliano bs) != 0) 167263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 168263660c0SAlfonso Siciliano if (message_checksize(h, w, bs) != 0) 169263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 170263660c0SAlfonso Siciliano if (set_widget_position(conf, &y, &x, h, w) != 0) 171263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 172263660c0SAlfonso Siciliano 173263660c0SAlfonso Siciliano if (update_dialog(conf, shadow, widget, y, x, h, w, 174263660c0SAlfonso Siciliano textpad, text, &bs, true) != 0) 175263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 176263660c0SAlfonso Siciliano 177263660c0SAlfonso Siciliano getmaxyx(textpad, htextpad, unused); 178263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 179263660c0SAlfonso Siciliano 180263660c0SAlfonso Siciliano /* Important to fix grey lines expanding screen */ 181263660c0SAlfonso Siciliano refresh(); 182263660c0SAlfonso Siciliano break; 183263660c0SAlfonso Siciliano case KEY_UP: 184263660c0SAlfonso Siciliano if (ytextpad == 0) 185263660c0SAlfonso Siciliano break; 186263660c0SAlfonso Siciliano ytextpad--; 187263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 188263660c0SAlfonso Siciliano break; 189263660c0SAlfonso Siciliano case KEY_DOWN: 190263660c0SAlfonso Siciliano if (ytextpad + h - 4 >= htextpad) 191263660c0SAlfonso Siciliano break; 192263660c0SAlfonso Siciliano ytextpad++; 193263660c0SAlfonso Siciliano textupdate(widget, textpad, htextpad, ytextpad); 194263660c0SAlfonso Siciliano break; 195c76f0793SBaptiste Daroussin default: 196263660c0SAlfonso Siciliano if (shortcut_buttons(input, &bs)) { 197263660c0SAlfonso Siciliano output = bs.value[bs.curr]; 198c76f0793SBaptiste Daroussin loop = false; 199c76f0793SBaptiste Daroussin } 200c76f0793SBaptiste Daroussin } 201c76f0793SBaptiste Daroussin } 202c76f0793SBaptiste Daroussin 203263660c0SAlfonso Siciliano end_dialog(conf, shadow, widget, textpad); 204c76f0793SBaptiste Daroussin 205263660c0SAlfonso Siciliano return (output); 206c76f0793SBaptiste Daroussin } 207c76f0793SBaptiste Daroussin 208c76f0793SBaptiste Daroussin /* API */ 209c76f0793SBaptiste Daroussin int 210263660c0SAlfonso Siciliano bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows, 211263660c0SAlfonso Siciliano int cols) 212c76f0793SBaptiste Daroussin { 213c76f0793SBaptiste Daroussin struct buttons bs; 214c76f0793SBaptiste Daroussin 215263660c0SAlfonso Siciliano get_buttons(conf, &bs, BUTTON_OK_LABEL, NULL); 216c76f0793SBaptiste Daroussin 217263660c0SAlfonso Siciliano return (do_message(conf, text, rows, cols, bs)); 218c76f0793SBaptiste Daroussin } 219c76f0793SBaptiste Daroussin 220c76f0793SBaptiste Daroussin int 221263660c0SAlfonso Siciliano bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows, 222263660c0SAlfonso Siciliano int cols) 223c76f0793SBaptiste Daroussin { 224c76f0793SBaptiste Daroussin struct buttons bs; 225c76f0793SBaptiste Daroussin 226263660c0SAlfonso Siciliano get_buttons(conf, &bs, "Yes", "No"); 227c76f0793SBaptiste Daroussin 228263660c0SAlfonso Siciliano return (do_message(conf, text, rows, cols, bs)); 229c76f0793SBaptiste Daroussin }