1*c76f0793SBaptiste Daroussin /*- 2*c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3*c76f0793SBaptiste Daroussin * 4*c76f0793SBaptiste Daroussin * Copyright (c) 2021 Alfonso Sabato Siciliano 5*c76f0793SBaptiste Daroussin * 6*c76f0793SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 7*c76f0793SBaptiste Daroussin * modification, are permitted provided that the following conditions 8*c76f0793SBaptiste Daroussin * are met: 9*c76f0793SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 10*c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 11*c76f0793SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 12*c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 13*c76f0793SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 14*c76f0793SBaptiste Daroussin * 15*c76f0793SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*c76f0793SBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*c76f0793SBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*c76f0793SBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*c76f0793SBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*c76f0793SBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*c76f0793SBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*c76f0793SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*c76f0793SBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*c76f0793SBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*c76f0793SBaptiste Daroussin * SUCH DAMAGE. 26*c76f0793SBaptiste Daroussin */ 27*c76f0793SBaptiste Daroussin 28*c76f0793SBaptiste Daroussin 29*c76f0793SBaptiste Daroussin #include <sys/param.h> 30*c76f0793SBaptiste Daroussin 31*c76f0793SBaptiste Daroussin #include <string.h> 32*c76f0793SBaptiste Daroussin 33*c76f0793SBaptiste Daroussin #ifdef PORTNCURSES 34*c76f0793SBaptiste Daroussin #include <ncurses/curses.h> 35*c76f0793SBaptiste Daroussin #else 36*c76f0793SBaptiste Daroussin #include <curses.h> 37*c76f0793SBaptiste Daroussin #endif 38*c76f0793SBaptiste Daroussin 39*c76f0793SBaptiste Daroussin #include "bsddialog.h" 40*c76f0793SBaptiste Daroussin #include "lib_util.h" 41*c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 42*c76f0793SBaptiste Daroussin 43*c76f0793SBaptiste Daroussin /* "Text": tailbox - tailboxbg - textbox */ 44*c76f0793SBaptiste Daroussin 45*c76f0793SBaptiste Daroussin #define BUTTON_TEXTBOX "HELP" 46*c76f0793SBaptiste Daroussin 47*c76f0793SBaptiste Daroussin extern struct bsddialog_theme t; 48*c76f0793SBaptiste Daroussin 49*c76f0793SBaptiste Daroussin enum textmode { TAILMODE, TAILBGMODE, TEXTMODE}; 50*c76f0793SBaptiste Daroussin 51*c76f0793SBaptiste Daroussin static void 52*c76f0793SBaptiste Daroussin textbox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w, 53*c76f0793SBaptiste Daroussin int hpad, int wpad) 54*c76f0793SBaptiste Daroussin { 55*c76f0793SBaptiste Daroussin 56*c76f0793SBaptiste Daroussin if (cols == BSDDIALOG_AUTOSIZE) { 57*c76f0793SBaptiste Daroussin *w = VBORDERS; 58*c76f0793SBaptiste Daroussin /* buttons size */ 59*c76f0793SBaptiste Daroussin *w += strlen(BUTTON_TEXTBOX) + 2 /* text delims*/; 60*c76f0793SBaptiste Daroussin /* text size */ 61*c76f0793SBaptiste Daroussin *w = MAX(*w, wpad + VBORDERS); 62*c76f0793SBaptiste Daroussin /* avoid terminal overflow */ 63*c76f0793SBaptiste Daroussin *w = MIN(*w, widget_max_width(conf)-1); /* again -1, fix util.c */ 64*c76f0793SBaptiste Daroussin } 65*c76f0793SBaptiste Daroussin 66*c76f0793SBaptiste Daroussin if (rows == BSDDIALOG_AUTOSIZE) { 67*c76f0793SBaptiste Daroussin *h = hpad + 4; /* HBORDERS + button border */ 68*c76f0793SBaptiste Daroussin /* avoid terminal overflow */ 69*c76f0793SBaptiste Daroussin *h = MIN(*h, widget_max_height(conf)); 70*c76f0793SBaptiste Daroussin } 71*c76f0793SBaptiste Daroussin } 72*c76f0793SBaptiste Daroussin 73*c76f0793SBaptiste Daroussin static int textbox_checksize(int rows, int cols, int hpad, int wpad) 74*c76f0793SBaptiste Daroussin { 75*c76f0793SBaptiste Daroussin int mincols; 76*c76f0793SBaptiste Daroussin 77*c76f0793SBaptiste Daroussin mincols = VBORDERS + strlen(BUTTON_TEXTBOX) + 2 /* text delims */; 78*c76f0793SBaptiste Daroussin 79*c76f0793SBaptiste Daroussin if (cols < mincols) 80*c76f0793SBaptiste Daroussin RETURN_ERROR("Few cols for the textbox"); 81*c76f0793SBaptiste Daroussin 82*c76f0793SBaptiste Daroussin if (rows < 4 /* HBORDERS + button*/ + (hpad > 0 ? 1 : 0)) 83*c76f0793SBaptiste Daroussin RETURN_ERROR("Few rows for the textbox"); 84*c76f0793SBaptiste Daroussin 85*c76f0793SBaptiste Daroussin return 0; 86*c76f0793SBaptiste Daroussin } 87*c76f0793SBaptiste Daroussin 88*c76f0793SBaptiste Daroussin static int 89*c76f0793SBaptiste Daroussin do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows, int cols) 90*c76f0793SBaptiste Daroussin { 91*c76f0793SBaptiste Daroussin WINDOW *widget, *pad, *shadow; 92*c76f0793SBaptiste Daroussin int i, input, y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows; 93*c76f0793SBaptiste Daroussin char buf[BUFSIZ], *exitbutt; 94*c76f0793SBaptiste Daroussin FILE *fp; 95*c76f0793SBaptiste Daroussin bool loop; 96*c76f0793SBaptiste Daroussin int output; 97*c76f0793SBaptiste Daroussin 98*c76f0793SBaptiste Daroussin if (mode == TAILMODE || mode == TAILBGMODE) { 99*c76f0793SBaptiste Daroussin bsddialog_msgbox(conf, "Tailbox and Tailboxbg unimplemented", rows, cols); 100*c76f0793SBaptiste Daroussin RETURN_ERROR("Tailbox and Tailboxbg unimplemented"); 101*c76f0793SBaptiste Daroussin } 102*c76f0793SBaptiste Daroussin 103*c76f0793SBaptiste Daroussin if ((fp = fopen(path, "r")) == NULL) 104*c76f0793SBaptiste Daroussin RETURN_ERROR("Cannot open file"); 105*c76f0793SBaptiste Daroussin /*if (mode == TAILMODE) { 106*c76f0793SBaptiste Daroussin fseek (fp, 0, SEEK_END); 107*c76f0793SBaptiste Daroussin i = nlines = 0; 108*c76f0793SBaptiste Daroussin while (i < hpad) { 109*c76f0793SBaptiste Daroussin line = ; 110*c76f0793SBaptiste Daroussin } 111*c76f0793SBaptiste Daroussin for (i=hpad-1; i--; i>=0) { 112*c76f0793SBaptiste Daroussin } 113*c76f0793SBaptiste Daroussin }*/ 114*c76f0793SBaptiste Daroussin hpad = 1; 115*c76f0793SBaptiste Daroussin wpad = 1; 116*c76f0793SBaptiste Daroussin pad = newpad(hpad, wpad); 117*c76f0793SBaptiste Daroussin wbkgd(pad, t.widgetcolor); 118*c76f0793SBaptiste Daroussin i = 0; 119*c76f0793SBaptiste Daroussin while(fgets(buf, BUFSIZ, fp) != NULL) { 120*c76f0793SBaptiste Daroussin if ((int) strlen(buf) > wpad) { 121*c76f0793SBaptiste Daroussin wpad = strlen(buf); 122*c76f0793SBaptiste Daroussin wresize(pad, hpad, wpad); 123*c76f0793SBaptiste Daroussin } 124*c76f0793SBaptiste Daroussin if (i > hpad-1) { 125*c76f0793SBaptiste Daroussin hpad++; 126*c76f0793SBaptiste Daroussin wresize(pad, hpad, wpad); 127*c76f0793SBaptiste Daroussin } 128*c76f0793SBaptiste Daroussin mvwaddstr(pad, i, 0, buf); 129*c76f0793SBaptiste Daroussin i++; 130*c76f0793SBaptiste Daroussin } 131*c76f0793SBaptiste Daroussin fclose(fp); 132*c76f0793SBaptiste Daroussin 133*c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 134*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 135*c76f0793SBaptiste Daroussin textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad); 136*c76f0793SBaptiste Daroussin if (textbox_checksize(h, w, hpad, wpad) != 0) 137*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 138*c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 139*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 140*c76f0793SBaptiste Daroussin 141*c76f0793SBaptiste Daroussin if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, 142*c76f0793SBaptiste Daroussin NULL, NULL, NULL, true) != 0) 143*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 144*c76f0793SBaptiste Daroussin 145*c76f0793SBaptiste Daroussin exitbutt = conf.button.exit_label == NULL ? BUTTON_TEXTBOX : conf.button.exit_label; 146*c76f0793SBaptiste Daroussin draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, strlen(exitbutt)+2, 147*c76f0793SBaptiste Daroussin exitbutt, true, true); 148*c76f0793SBaptiste Daroussin 149*c76f0793SBaptiste Daroussin wrefresh(widget); 150*c76f0793SBaptiste Daroussin 151*c76f0793SBaptiste Daroussin ys = y + 1; 152*c76f0793SBaptiste Daroussin xs = x + 1; 153*c76f0793SBaptiste Daroussin ye = ys + h - 5; 154*c76f0793SBaptiste Daroussin xe = xs + w - 3; 155*c76f0793SBaptiste Daroussin ypad = xpad = 0; 156*c76f0793SBaptiste Daroussin printrows = h-4; 157*c76f0793SBaptiste Daroussin loop = true; 158*c76f0793SBaptiste Daroussin while(loop) { 159*c76f0793SBaptiste Daroussin prefresh(pad, ypad, xpad, ys, xs, ye, xe); 160*c76f0793SBaptiste Daroussin input = getch(); 161*c76f0793SBaptiste Daroussin switch(input) { 162*c76f0793SBaptiste Daroussin case KEY_ENTER: 163*c76f0793SBaptiste Daroussin case 10: /* Enter */ 164*c76f0793SBaptiste Daroussin output = BSDDIALOG_YESOK; 165*c76f0793SBaptiste Daroussin loop = false; 166*c76f0793SBaptiste Daroussin break; 167*c76f0793SBaptiste Daroussin case 27: /* Esc */ 168*c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 169*c76f0793SBaptiste Daroussin loop = false; 170*c76f0793SBaptiste Daroussin break; 171*c76f0793SBaptiste Daroussin case KEY_HOME: 172*c76f0793SBaptiste Daroussin ypad = 0; 173*c76f0793SBaptiste Daroussin break; 174*c76f0793SBaptiste Daroussin case KEY_END: 175*c76f0793SBaptiste Daroussin ypad = hpad - printrows; 176*c76f0793SBaptiste Daroussin ypad = ypad < 0 ? 0 : ypad; 177*c76f0793SBaptiste Daroussin break; 178*c76f0793SBaptiste Daroussin case KEY_PPAGE: 179*c76f0793SBaptiste Daroussin ypad -= printrows; 180*c76f0793SBaptiste Daroussin ypad = ypad < 0 ? 0 : ypad; 181*c76f0793SBaptiste Daroussin break; 182*c76f0793SBaptiste Daroussin case KEY_NPAGE: 183*c76f0793SBaptiste Daroussin ypad += printrows; 184*c76f0793SBaptiste Daroussin ypad = ypad + printrows > hpad ? hpad - printrows : ypad; 185*c76f0793SBaptiste Daroussin break; 186*c76f0793SBaptiste Daroussin case '0': 187*c76f0793SBaptiste Daroussin xpad = 0; 188*c76f0793SBaptiste Daroussin case KEY_LEFT: 189*c76f0793SBaptiste Daroussin case 'h': 190*c76f0793SBaptiste Daroussin xpad = xpad > 0 ? xpad - 1 : 0; 191*c76f0793SBaptiste Daroussin break; 192*c76f0793SBaptiste Daroussin case KEY_RIGHT: 193*c76f0793SBaptiste Daroussin case 'l': 194*c76f0793SBaptiste Daroussin xpad = (xpad + w-2) < wpad-1 ? xpad + 1 : xpad; 195*c76f0793SBaptiste Daroussin break; 196*c76f0793SBaptiste Daroussin case KEY_UP: 197*c76f0793SBaptiste Daroussin case 'k': 198*c76f0793SBaptiste Daroussin ypad = ypad > 0 ? ypad - 1 : 0; 199*c76f0793SBaptiste Daroussin break; 200*c76f0793SBaptiste Daroussin case KEY_DOWN: 201*c76f0793SBaptiste Daroussin case'j': 202*c76f0793SBaptiste Daroussin ypad = ypad + printrows <= hpad -1 ? ypad + 1 : ypad; 203*c76f0793SBaptiste Daroussin break; 204*c76f0793SBaptiste Daroussin case KEY_F(1): 205*c76f0793SBaptiste Daroussin if (conf.hfile == NULL) 206*c76f0793SBaptiste Daroussin break; 207*c76f0793SBaptiste Daroussin if (f1help(conf) != 0) 208*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 209*c76f0793SBaptiste Daroussin /* No break! the terminal size can change */ 210*c76f0793SBaptiste Daroussin case KEY_RESIZE: 211*c76f0793SBaptiste Daroussin hide_widget(y, x, h, w,conf.shadow); 212*c76f0793SBaptiste Daroussin 213*c76f0793SBaptiste Daroussin /* 214*c76f0793SBaptiste Daroussin * Unnecessary, but, when the columns decrease the 215*c76f0793SBaptiste Daroussin * following "refresh" seem not work 216*c76f0793SBaptiste Daroussin */ 217*c76f0793SBaptiste Daroussin refresh(); 218*c76f0793SBaptiste Daroussin 219*c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 220*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 221*c76f0793SBaptiste Daroussin textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad); 222*c76f0793SBaptiste Daroussin if (textbox_checksize(h, w, hpad, wpad) != 0) 223*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 224*c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 225*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 226*c76f0793SBaptiste Daroussin 227*c76f0793SBaptiste Daroussin wclear(shadow); 228*c76f0793SBaptiste Daroussin mvwin(shadow, y + t.shadowrows, x + t.shadowcols); 229*c76f0793SBaptiste Daroussin wresize(shadow, h, w); 230*c76f0793SBaptiste Daroussin 231*c76f0793SBaptiste Daroussin wclear(widget); 232*c76f0793SBaptiste Daroussin mvwin(widget, y, x); 233*c76f0793SBaptiste Daroussin wresize(widget, h, w); 234*c76f0793SBaptiste Daroussin 235*c76f0793SBaptiste Daroussin ys = y + 1; 236*c76f0793SBaptiste Daroussin xs = x + 1; 237*c76f0793SBaptiste Daroussin ye = ys + h - 5; 238*c76f0793SBaptiste Daroussin xe = xs + w - 3; 239*c76f0793SBaptiste Daroussin ypad = xpad = 0; 240*c76f0793SBaptiste Daroussin printrows = h - 4; 241*c76f0793SBaptiste Daroussin 242*c76f0793SBaptiste Daroussin if(update_widget_withtextpad(conf, shadow, widget, h, w, 243*c76f0793SBaptiste Daroussin RAISED, NULL, NULL, NULL, true) != 0) 244*c76f0793SBaptiste Daroussin return BSDDIALOG_ERROR; 245*c76f0793SBaptiste Daroussin 246*c76f0793SBaptiste Daroussin draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, 247*c76f0793SBaptiste Daroussin strlen(exitbutt)+2, exitbutt, true, true); 248*c76f0793SBaptiste Daroussin 249*c76f0793SBaptiste Daroussin wrefresh(widget); /* for button */ 250*c76f0793SBaptiste Daroussin 251*c76f0793SBaptiste Daroussin /* Important to fix grey lines expanding screen */ 252*c76f0793SBaptiste Daroussin refresh(); 253*c76f0793SBaptiste Daroussin break; 254*c76f0793SBaptiste Daroussin } 255*c76f0793SBaptiste Daroussin } 256*c76f0793SBaptiste Daroussin 257*c76f0793SBaptiste Daroussin end_widget_withtextpad(conf, widget, h, w, pad, shadow); 258*c76f0793SBaptiste Daroussin 259*c76f0793SBaptiste Daroussin return output; 260*c76f0793SBaptiste Daroussin } 261*c76f0793SBaptiste Daroussin 262*c76f0793SBaptiste Daroussin int bsddialog_tailbox(struct bsddialog_conf conf, char* text, int rows, int cols) 263*c76f0793SBaptiste Daroussin { 264*c76f0793SBaptiste Daroussin 265*c76f0793SBaptiste Daroussin return (do_textbox(TAILMODE, conf, text, rows, cols)); 266*c76f0793SBaptiste Daroussin } 267*c76f0793SBaptiste Daroussin 268*c76f0793SBaptiste Daroussin int bsddialog_tailboxbg(struct bsddialog_conf conf, char* text, int rows, int cols) 269*c76f0793SBaptiste Daroussin { 270*c76f0793SBaptiste Daroussin 271*c76f0793SBaptiste Daroussin return (do_textbox(TAILBGMODE, conf, text, rows, cols)); 272*c76f0793SBaptiste Daroussin } 273*c76f0793SBaptiste Daroussin 274*c76f0793SBaptiste Daroussin 275*c76f0793SBaptiste Daroussin int bsddialog_textbox(struct bsddialog_conf conf, char* text, int rows, int cols) 276*c76f0793SBaptiste Daroussin { 277*c76f0793SBaptiste Daroussin 278*c76f0793SBaptiste Daroussin return (do_textbox(TEXTMODE, conf, text, rows, cols)); 279*c76f0793SBaptiste Daroussin } 280*c76f0793SBaptiste Daroussin 281