1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4c76f0793SBaptiste Daroussin * Copyright (c) 2021 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 28f499134dSBaptiste Daroussin #include <sys/param.h> 29f499134dSBaptiste Daroussin 30f499134dSBaptiste Daroussin #include <ctype.h> 31c76f0793SBaptiste Daroussin #ifdef PORTNCURSES 32c76f0793SBaptiste Daroussin #include <ncurses/form.h> 33c76f0793SBaptiste Daroussin #else 34c76f0793SBaptiste Daroussin #include <form.h> 35c76f0793SBaptiste Daroussin #endif 36*d93b4d32SBaptiste Daroussin #include <stdlib.h> 37*d93b4d32SBaptiste Daroussin #include <string.h> 38c76f0793SBaptiste Daroussin 39c76f0793SBaptiste Daroussin #include "bsddialog.h" 40c76f0793SBaptiste Daroussin #include "lib_util.h" 41c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 42c76f0793SBaptiste Daroussin 43f499134dSBaptiste Daroussin #define REDRAWFORM 14021986 /* magic number */ 44f499134dSBaptiste Daroussin #define ISFIELDHIDDEN(item) (item.flags & BSDDIALOG_FIELDHIDDEN) 45f499134dSBaptiste Daroussin #define ISFIELDREADONLY(item) (item.flags & BSDDIALOG_FIELDREADONLY) 46f499134dSBaptiste Daroussin 47c76f0793SBaptiste Daroussin /* "Form": inputbox - passwordbox - form - passwordform - mixedform */ 48c76f0793SBaptiste Daroussin 49c76f0793SBaptiste Daroussin extern struct bsddialog_theme t; 50c76f0793SBaptiste Daroussin 51f499134dSBaptiste Daroussin /* util struct for private buffer and view options */ 52f499134dSBaptiste Daroussin struct myfield { 53*d93b4d32SBaptiste Daroussin int buflen; 54f499134dSBaptiste Daroussin char *buf; 55f499134dSBaptiste Daroussin int pos; 56*d93b4d32SBaptiste Daroussin int maxpos; 57f499134dSBaptiste Daroussin bool secure; 58f499134dSBaptiste Daroussin int securech; 598c4f4028SBaptiste Daroussin char *bottomdesc; 60f499134dSBaptiste Daroussin }; 61f499134dSBaptiste Daroussin #define GETMYFIELD(field) ((struct myfield*)field_userptr(field)) 62f499134dSBaptiste Daroussin #define GETMYFIELD2(form) ((struct myfield*)field_userptr(current_field(form))) 63f499134dSBaptiste Daroussin 64f499134dSBaptiste Daroussin static void insertch(struct myfield *mf, int ch) 65c76f0793SBaptiste Daroussin { 66f499134dSBaptiste Daroussin int i; 67f499134dSBaptiste Daroussin 68*d93b4d32SBaptiste Daroussin if (mf->buflen > mf->maxpos) 69f499134dSBaptiste Daroussin return; 70f499134dSBaptiste Daroussin 71*d93b4d32SBaptiste Daroussin for (i = mf->buflen; i >= mf->pos; i--) { 72f499134dSBaptiste Daroussin mf->buf[i+1] = mf->buf[i]; 73c76f0793SBaptiste Daroussin } 74c76f0793SBaptiste Daroussin 75f499134dSBaptiste Daroussin mf->buf[mf->pos] = ch; 76f499134dSBaptiste Daroussin mf->pos += 1; 77*d93b4d32SBaptiste Daroussin if (mf->pos > mf->maxpos) 78*d93b4d32SBaptiste Daroussin mf->pos = mf->maxpos; 79*d93b4d32SBaptiste Daroussin mf->buflen += 1; 80*d93b4d32SBaptiste Daroussin mf->buf[mf->buflen] = '\0'; 81f499134dSBaptiste Daroussin } 82f499134dSBaptiste Daroussin 83f499134dSBaptiste Daroussin static void shiftleft(struct myfield *mf) 84f499134dSBaptiste Daroussin { 85f499134dSBaptiste Daroussin int i, last; 86f499134dSBaptiste Daroussin 87*d93b4d32SBaptiste Daroussin for (i = mf->pos; i < mf->buflen -1; i++) { 88f499134dSBaptiste Daroussin mf->buf[i] = mf->buf[i+1]; 89f499134dSBaptiste Daroussin } 90f499134dSBaptiste Daroussin 91*d93b4d32SBaptiste Daroussin last = mf->buflen > 0 ? mf->buflen -1 : 0; 92f499134dSBaptiste Daroussin mf->buf[last] = '\0'; 93*d93b4d32SBaptiste Daroussin mf->buflen = last; 94f499134dSBaptiste Daroussin } 95c76f0793SBaptiste Daroussin 968c4f4028SBaptiste Daroussin static void print_bottomdesc(struct myfield *mf) 978c4f4028SBaptiste Daroussin { 988c4f4028SBaptiste Daroussin 998c4f4028SBaptiste Daroussin move(LINES-1, 2); 1008c4f4028SBaptiste Daroussin clrtoeol(); 1018c4f4028SBaptiste Daroussin if (mf->bottomdesc != NULL) { 1028c4f4028SBaptiste Daroussin addstr(mf->bottomdesc); 1038c4f4028SBaptiste Daroussin refresh(); 1048c4f4028SBaptiste Daroussin } 1058c4f4028SBaptiste Daroussin } 1068c4f4028SBaptiste Daroussin 107*d93b4d32SBaptiste Daroussin int 108*d93b4d32SBaptiste Daroussin return_values(struct bsddialog_conf *conf, struct buttons bs, int nitems, 109*d93b4d32SBaptiste Daroussin struct bsddialog_formitem *items, FORM *form, FIELD **cfield) 110*d93b4d32SBaptiste Daroussin { 111*d93b4d32SBaptiste Daroussin int i, output; 112*d93b4d32SBaptiste Daroussin struct myfield *mf; 113*d93b4d32SBaptiste Daroussin 114*d93b4d32SBaptiste Daroussin output = bs.value[bs.curr]; 115*d93b4d32SBaptiste Daroussin if (output == BSDDIALOG_HELP && conf->form.value_withhelp == false) 116*d93b4d32SBaptiste Daroussin return output; 117*d93b4d32SBaptiste Daroussin if (output == BSDDIALOG_EXTRA && conf->form.value_withextra == false) 118*d93b4d32SBaptiste Daroussin return output; 119*d93b4d32SBaptiste Daroussin if (output == BSDDIALOG_CANCEL && conf->form.value_withcancel == false) 120*d93b4d32SBaptiste Daroussin return output; 121*d93b4d32SBaptiste Daroussin if (output == BSDDIALOG_GENERIC1 || output == BSDDIALOG_GENERIC2) 122*d93b4d32SBaptiste Daroussin return output; 123*d93b4d32SBaptiste Daroussin 124*d93b4d32SBaptiste Daroussin /* BSDDIALOG_OK */ 125*d93b4d32SBaptiste Daroussin form_driver(form, REQ_NEXT_FIELD); 126*d93b4d32SBaptiste Daroussin form_driver(form, REQ_PREV_FIELD); 127*d93b4d32SBaptiste Daroussin for (i=0; i<nitems; i++) { 128*d93b4d32SBaptiste Daroussin mf = GETMYFIELD(cfield[i]); 129*d93b4d32SBaptiste Daroussin items[i].value = strdup(mf->buf); 130*d93b4d32SBaptiste Daroussin if (items[i].value == NULL) 131*d93b4d32SBaptiste Daroussin RETURN_ERROR("Cannot allocate memory for form value"); 132*d93b4d32SBaptiste Daroussin } 133*d93b4d32SBaptiste Daroussin 134*d93b4d32SBaptiste Daroussin return (output); 135*d93b4d32SBaptiste Daroussin } 136*d93b4d32SBaptiste Daroussin 137c76f0793SBaptiste Daroussin static int 138f499134dSBaptiste Daroussin form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, 139f499134dSBaptiste Daroussin struct buttons bs, WINDOW *formwin, FORM *form, FIELD **cfield, int nitems, 140f499134dSBaptiste Daroussin struct bsddialog_formitem *items) 141c76f0793SBaptiste Daroussin { 142f499134dSBaptiste Daroussin bool loop, buttupdate, informwin = true; 143f499134dSBaptiste Daroussin int i, input, output; 144f499134dSBaptiste Daroussin struct myfield *mf; 145c76f0793SBaptiste Daroussin 146f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 1478c4f4028SBaptiste Daroussin print_bottomdesc(mf); 148*d93b4d32SBaptiste Daroussin pos_form_cursor(form); 149*d93b4d32SBaptiste Daroussin form_driver(form, REQ_END_LINE); 150*d93b4d32SBaptiste Daroussin mf->pos = MIN(mf->buflen, mf->maxpos); 151*d93b4d32SBaptiste Daroussin curs_set(2); 152*d93b4d32SBaptiste Daroussin bs.curr = -1; 153*d93b4d32SBaptiste Daroussin loop = buttupdate = true; 154c76f0793SBaptiste Daroussin while(loop) { 155c76f0793SBaptiste Daroussin if (buttupdate) { 156f499134dSBaptiste Daroussin draw_buttons(widget, y, cols, bs, !informwin); 157c76f0793SBaptiste Daroussin wrefresh(widget); 158c76f0793SBaptiste Daroussin buttupdate = false; 159c76f0793SBaptiste Daroussin } 160f499134dSBaptiste Daroussin wrefresh(formwin); 161c76f0793SBaptiste Daroussin input = getch(); 162c76f0793SBaptiste Daroussin switch(input) { 163f499134dSBaptiste Daroussin case KEY_ENTER: 164f499134dSBaptiste Daroussin case 10: /* Enter */ 165f499134dSBaptiste Daroussin if (informwin) 166c76f0793SBaptiste Daroussin break; 1678c4f4028SBaptiste Daroussin loop = false; 168*d93b4d32SBaptiste Daroussin output = return_values(conf, bs, nitems, items, form, cfield); 169c76f0793SBaptiste Daroussin break; 170c76f0793SBaptiste Daroussin case 27: /* Esc */ 171c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 172c76f0793SBaptiste Daroussin loop = false; 173c76f0793SBaptiste Daroussin break; 174f499134dSBaptiste Daroussin case '\t': /* TAB */ 175f499134dSBaptiste Daroussin if (informwin) { 176c76f0793SBaptiste Daroussin bs.curr = 0; 177f499134dSBaptiste Daroussin informwin = false; 178c76f0793SBaptiste Daroussin curs_set(0); 179c76f0793SBaptiste Daroussin } else { 180c76f0793SBaptiste Daroussin bs.curr++; 181f499134dSBaptiste Daroussin informwin = bs.curr >= (int) bs.nbuttons ? 182f499134dSBaptiste Daroussin true : false; 183f499134dSBaptiste Daroussin if (informwin) { 184c76f0793SBaptiste Daroussin curs_set(2); 185c76f0793SBaptiste Daroussin pos_form_cursor(form); 186c76f0793SBaptiste Daroussin } 187c76f0793SBaptiste Daroussin } 188c76f0793SBaptiste Daroussin buttupdate = true; 189c76f0793SBaptiste Daroussin break; 190c76f0793SBaptiste Daroussin case KEY_LEFT: 191f499134dSBaptiste Daroussin if (informwin) { 192c76f0793SBaptiste Daroussin form_driver(form, REQ_PREV_CHAR); 193f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 194f499134dSBaptiste Daroussin if (mf->pos > 0) 195f499134dSBaptiste Daroussin mf->pos -= 1; 196c76f0793SBaptiste Daroussin } else { 197c76f0793SBaptiste Daroussin if (bs.curr > 0) { 198c76f0793SBaptiste Daroussin bs.curr--; 199c76f0793SBaptiste Daroussin buttupdate = true; 200c76f0793SBaptiste Daroussin } 201c76f0793SBaptiste Daroussin } 202c76f0793SBaptiste Daroussin break; 203c76f0793SBaptiste Daroussin case KEY_RIGHT: 204f499134dSBaptiste Daroussin if (informwin) { 205f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 206*d93b4d32SBaptiste Daroussin if (mf->pos >= mf->buflen) 207f499134dSBaptiste Daroussin break; 208f499134dSBaptiste Daroussin mf->pos += 1; 209c76f0793SBaptiste Daroussin form_driver(form, REQ_NEXT_CHAR); 210c76f0793SBaptiste Daroussin } else { 211c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 212c76f0793SBaptiste Daroussin bs.curr++; 213c76f0793SBaptiste Daroussin buttupdate = true; 214c76f0793SBaptiste Daroussin } 215c76f0793SBaptiste Daroussin } 216c76f0793SBaptiste Daroussin break; 217c76f0793SBaptiste Daroussin case KEY_UP: 218c76f0793SBaptiste Daroussin if (nitems < 2) 219c76f0793SBaptiste Daroussin break; 220f499134dSBaptiste Daroussin set_field_fore(current_field(form), t.form.fieldcolor); 221f499134dSBaptiste Daroussin set_field_back(current_field(form), t.form.fieldcolor); 222c76f0793SBaptiste Daroussin form_driver(form, REQ_PREV_FIELD); 223c76f0793SBaptiste Daroussin form_driver(form, REQ_END_LINE); 224f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 2258c4f4028SBaptiste Daroussin print_bottomdesc(mf); 226*d93b4d32SBaptiste Daroussin mf->pos = MIN(mf->buflen, mf->maxpos); 227f499134dSBaptiste Daroussin set_field_fore(current_field(form), t.form.f_fieldcolor); 228f499134dSBaptiste Daroussin set_field_back(current_field(form), t.form.f_fieldcolor); 229c76f0793SBaptiste Daroussin break; 230c76f0793SBaptiste Daroussin case KEY_DOWN: 231c76f0793SBaptiste Daroussin if (nitems < 2) 232c76f0793SBaptiste Daroussin break; 233f499134dSBaptiste Daroussin set_field_fore(current_field(form), t.form.fieldcolor); 234f499134dSBaptiste Daroussin set_field_back(current_field(form), t.form.fieldcolor); 235c76f0793SBaptiste Daroussin form_driver(form, REQ_NEXT_FIELD); 236c76f0793SBaptiste Daroussin form_driver(form, REQ_END_LINE); 237f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 2388c4f4028SBaptiste Daroussin print_bottomdesc(mf); 239*d93b4d32SBaptiste Daroussin mf->pos = MIN(mf->buflen, mf->maxpos); 240f499134dSBaptiste Daroussin set_field_fore(current_field(form), t.form.f_fieldcolor); 241f499134dSBaptiste Daroussin set_field_back(current_field(form), t.form.f_fieldcolor); 242c76f0793SBaptiste Daroussin break; 243c76f0793SBaptiste Daroussin case KEY_BACKSPACE: 244f499134dSBaptiste Daroussin case 127: /* Backspace */ 245f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 246f499134dSBaptiste Daroussin if (mf->pos <= 0) 247f499134dSBaptiste Daroussin break; 248c76f0793SBaptiste Daroussin form_driver(form, REQ_DEL_PREV); 249*d93b4d32SBaptiste Daroussin form_driver(form, REQ_BEG_LINE); 250*d93b4d32SBaptiste Daroussin mf->pos = mf->pos - 1; 251*d93b4d32SBaptiste Daroussin for (i=0; i<mf->pos; i++) 252*d93b4d32SBaptiste Daroussin form_driver(form, REQ_NEXT_CHAR); 253f499134dSBaptiste Daroussin shiftleft(mf); 254c76f0793SBaptiste Daroussin break; 255c76f0793SBaptiste Daroussin case KEY_DC: 256c76f0793SBaptiste Daroussin form_driver(form, REQ_DEL_CHAR); 257f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 258*d93b4d32SBaptiste Daroussin if (mf->pos < mf->buflen) 259f499134dSBaptiste Daroussin shiftleft(mf); 260f499134dSBaptiste Daroussin break; 261f499134dSBaptiste Daroussin case KEY_F(1): 2628c4f4028SBaptiste Daroussin if (conf->f1_file == NULL && conf->f1_message == NULL) 263f499134dSBaptiste Daroussin break; 264f499134dSBaptiste Daroussin if (f1help(conf) != 0) 265f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 266f499134dSBaptiste Daroussin /* No Break */ 267f499134dSBaptiste Daroussin case KEY_RESIZE: 268f499134dSBaptiste Daroussin output = REDRAWFORM; 269f499134dSBaptiste Daroussin loop = false; 270c76f0793SBaptiste Daroussin break; 271c76f0793SBaptiste Daroussin default: 272f499134dSBaptiste Daroussin /* 273f499134dSBaptiste Daroussin * user input, add unicode chars to "public" buffer 274f499134dSBaptiste Daroussin */ 275f499134dSBaptiste Daroussin if (informwin) { 276f499134dSBaptiste Daroussin mf = GETMYFIELD2(form); 277f499134dSBaptiste Daroussin if (mf->secure) 278f499134dSBaptiste Daroussin form_driver(form, mf->securech); 279f499134dSBaptiste Daroussin else 280c76f0793SBaptiste Daroussin form_driver(form, input); 281f499134dSBaptiste Daroussin insertch(mf, input); 282f499134dSBaptiste Daroussin } 283f499134dSBaptiste Daroussin else { 284f499134dSBaptiste Daroussin for (i = 0; i < (int) bs.nbuttons; i++) { 285f499134dSBaptiste Daroussin if (tolower(input) == 286f499134dSBaptiste Daroussin tolower((bs.label[i])[0])) { 287*d93b4d32SBaptiste Daroussin bs.curr = i; 288*d93b4d32SBaptiste Daroussin output = return_values(conf, bs, 289*d93b4d32SBaptiste Daroussin nitems, items, form, cfield); 290f499134dSBaptiste Daroussin loop = false; 291f499134dSBaptiste Daroussin } 292f499134dSBaptiste Daroussin } 293c76f0793SBaptiste Daroussin } 294c76f0793SBaptiste Daroussin break; 295c76f0793SBaptiste Daroussin } 296c76f0793SBaptiste Daroussin } 297c76f0793SBaptiste Daroussin 298c76f0793SBaptiste Daroussin curs_set(0); 299c76f0793SBaptiste Daroussin 300c76f0793SBaptiste Daroussin return output; 301c76f0793SBaptiste Daroussin } 302c76f0793SBaptiste Daroussin 303f499134dSBaptiste Daroussin static void 304f499134dSBaptiste Daroussin form_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, 305f499134dSBaptiste Daroussin char *text, int linelen, unsigned int *formheight, int nitems, 306f499134dSBaptiste Daroussin struct buttons bs) 307c76f0793SBaptiste Daroussin { 308f499134dSBaptiste Daroussin int textrow, menusize; 309f499134dSBaptiste Daroussin 310f499134dSBaptiste Daroussin textrow = text != NULL && strlen(text) > 0 ? 1 : 0; 311f499134dSBaptiste Daroussin 312f499134dSBaptiste Daroussin if (cols == BSDDIALOG_AUTOSIZE) { 313f499134dSBaptiste Daroussin *w = VBORDERS; 314f499134dSBaptiste Daroussin /* buttons size */ 315f499134dSBaptiste Daroussin *w += bs.nbuttons * bs.sizebutton; 316f499134dSBaptiste Daroussin *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; 317f499134dSBaptiste Daroussin /* line size */ 318f499134dSBaptiste Daroussin *w = MAX(*w, linelen + 3); 3198c4f4028SBaptiste Daroussin /* conf.auto_minwidth */ 3208c4f4028SBaptiste Daroussin *w = MAX(*w, (int)conf->auto_minwidth); 321f499134dSBaptiste Daroussin /* 322f499134dSBaptiste Daroussin * avoid terminal overflow, 323f499134dSBaptiste Daroussin * -1 fix false negative with big menu over the terminal and 324f499134dSBaptiste Daroussin * autosize, for example "portconfig /usr/ports/www/apache24/". 325f499134dSBaptiste Daroussin */ 326f499134dSBaptiste Daroussin *w = MIN(*w, widget_max_width(conf)-1); 327f499134dSBaptiste Daroussin } 328f499134dSBaptiste Daroussin 329f499134dSBaptiste Daroussin if (rows == BSDDIALOG_AUTOSIZE) { 330f499134dSBaptiste Daroussin *h = HBORDERS + 2 /* buttons */ + textrow; 331f499134dSBaptiste Daroussin 332f499134dSBaptiste Daroussin if (*formheight == 0) { 333f499134dSBaptiste Daroussin *h += nitems + 2; 334f499134dSBaptiste Daroussin *h = MIN(*h, widget_max_height(conf)); 335f499134dSBaptiste Daroussin menusize = MIN(nitems + 2, *h - (HBORDERS + 2 + textrow)); 336f499134dSBaptiste Daroussin menusize -=2; 337f499134dSBaptiste Daroussin *formheight = menusize < 0 ? 0 : menusize; 338f499134dSBaptiste Daroussin } 339f499134dSBaptiste Daroussin else /* h autosize with a fixed formheight */ 340f499134dSBaptiste Daroussin *h = *h + *formheight + 2; 341f499134dSBaptiste Daroussin 3428c4f4028SBaptiste Daroussin /* conf.auto_minheight */ 3438c4f4028SBaptiste Daroussin *h = MAX(*h, (int)conf->auto_minheight); 344f499134dSBaptiste Daroussin /* avoid terminal overflow */ 345f499134dSBaptiste Daroussin *h = MIN(*h, widget_max_height(conf)); 346f499134dSBaptiste Daroussin } 347f499134dSBaptiste Daroussin else { 348f499134dSBaptiste Daroussin if (*formheight == 0) 349f499134dSBaptiste Daroussin *formheight = MIN(rows-6-textrow, nitems); 350f499134dSBaptiste Daroussin } 351f499134dSBaptiste Daroussin } 352f499134dSBaptiste Daroussin 353f499134dSBaptiste Daroussin static int 354f499134dSBaptiste Daroussin form_checksize(int rows, int cols, char *text, int formheight, int nitems, 355f499134dSBaptiste Daroussin struct buttons bs) 356f499134dSBaptiste Daroussin { 357f499134dSBaptiste Daroussin int mincols, textrow, formrows; 358f499134dSBaptiste Daroussin 359f499134dSBaptiste Daroussin mincols = VBORDERS; 360f499134dSBaptiste Daroussin /* buttons */ 361f499134dSBaptiste Daroussin mincols += bs.nbuttons * bs.sizebutton; 362f499134dSBaptiste Daroussin mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; 363f499134dSBaptiste Daroussin /* line, comment to permet some cols hidden */ 364f499134dSBaptiste Daroussin /* mincols = MAX(mincols, linelen); */ 365f499134dSBaptiste Daroussin 366f499134dSBaptiste Daroussin if (cols < mincols) 367f499134dSBaptiste Daroussin RETURN_ERROR("Few cols, width < size buttons or "\ 368f499134dSBaptiste Daroussin "labels + forms"); 369f499134dSBaptiste Daroussin 370f499134dSBaptiste Daroussin textrow = text != NULL && strlen(text) > 0 ? 1 : 0; 371f499134dSBaptiste Daroussin 372f499134dSBaptiste Daroussin if (nitems > 0 && formheight == 0) 373f499134dSBaptiste Daroussin RETURN_ERROR("fields > 0 but formheight == 0, probably "\ 374f499134dSBaptiste Daroussin "terminal too small"); 375f499134dSBaptiste Daroussin 376f499134dSBaptiste Daroussin formrows = nitems > 0 ? 3 : 0; 377f499134dSBaptiste Daroussin if (rows < 2 + 2 + formrows + textrow) 378f499134dSBaptiste Daroussin RETURN_ERROR("Few lines for this menus"); 379f499134dSBaptiste Daroussin 380f499134dSBaptiste Daroussin return 0; 381f499134dSBaptiste Daroussin } 382f499134dSBaptiste Daroussin 383f499134dSBaptiste Daroussin int 384f499134dSBaptiste Daroussin bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, 385f499134dSBaptiste Daroussin unsigned int formheight, unsigned int nitems, 386f499134dSBaptiste Daroussin struct bsddialog_formitem *items) 387f499134dSBaptiste Daroussin { 388f499134dSBaptiste Daroussin WINDOW *widget, *formwin, *textpad, *shadow; 389f499134dSBaptiste Daroussin int i, output, color, y, x, h, w, htextpad; 390f499134dSBaptiste Daroussin FIELD **cfield; 391c76f0793SBaptiste Daroussin FORM *form; 392c76f0793SBaptiste Daroussin struct buttons bs; 393f499134dSBaptiste Daroussin struct myfield *myfields; 394f499134dSBaptiste Daroussin unsigned long maxline; 395c76f0793SBaptiste Daroussin 396f499134dSBaptiste Daroussin /* disable form scrolling like dialog */ 397f499134dSBaptiste Daroussin if (formheight < nitems) 398f499134dSBaptiste Daroussin formheight = nitems; 399c76f0793SBaptiste Daroussin 400*d93b4d32SBaptiste Daroussin for (i = 0; i < (int)nitems; i++) { 401*d93b4d32SBaptiste Daroussin if (items[i].maxvaluelen == 0) 402*d93b4d32SBaptiste Daroussin RETURN_ERROR("maxvaluelen cannot be zero"); 403*d93b4d32SBaptiste Daroussin if (items[i].fieldlen == 0) 404*d93b4d32SBaptiste Daroussin RETURN_ERROR("fieldlen cannot be zero"); 405*d93b4d32SBaptiste Daroussin if (items[i].fieldlen > items[i].maxvaluelen) 406*d93b4d32SBaptiste Daroussin RETURN_ERROR("fieldlen cannot be > maxvaluelen"); 407*d93b4d32SBaptiste Daroussin } 408*d93b4d32SBaptiste Daroussin 409f499134dSBaptiste Daroussin maxline = 0; 410f499134dSBaptiste Daroussin myfields = malloc(nitems * sizeof(struct myfield)); 411f499134dSBaptiste Daroussin cfield = calloc(nitems + 1, sizeof(FIELD*)); 412f499134dSBaptiste Daroussin for (i=0; i < (int)nitems; i++) { 413f499134dSBaptiste Daroussin cfield[i] = new_field(1, items[i].fieldlen, items[i].yfield-1, 414f499134dSBaptiste Daroussin items[i].xfield-1, 0, 0); 415f499134dSBaptiste Daroussin field_opts_off(cfield[i], O_STATIC); 416f499134dSBaptiste Daroussin set_max_field(cfield[i], items[i].maxvaluelen); 417f499134dSBaptiste Daroussin set_field_buffer(cfield[i], 0, items[i].init); 418f499134dSBaptiste Daroussin 419*d93b4d32SBaptiste Daroussin myfields[i].buf = malloc(items[i].maxvaluelen + 1); 420*d93b4d32SBaptiste Daroussin memset(myfields[i].buf, 0, items[i].maxvaluelen + 1); // end with '\0' for strdup 421*d93b4d32SBaptiste Daroussin strncpy(myfields[i].buf, items[i].init, items[i].maxvaluelen); 422*d93b4d32SBaptiste Daroussin 423*d93b4d32SBaptiste Daroussin myfields[i].buflen = strlen(myfields[i].buf); 424*d93b4d32SBaptiste Daroussin 425*d93b4d32SBaptiste Daroussin myfields[i].maxpos = items[i].maxvaluelen -1; 426*d93b4d32SBaptiste Daroussin myfields[i].pos = MIN(myfields[i].buflen, myfields[i].maxpos); 427*d93b4d32SBaptiste Daroussin 4288c4f4028SBaptiste Daroussin myfields[i].bottomdesc = items[i].bottomdesc; 429f499134dSBaptiste Daroussin set_field_userptr(cfield[i], &myfields[i]); 430f499134dSBaptiste Daroussin 431f499134dSBaptiste Daroussin field_opts_off(cfield[i], O_AUTOSKIP); 432f499134dSBaptiste Daroussin field_opts_off(cfield[i], O_BLANK); 433f499134dSBaptiste Daroussin /* field_opts_off(field[i], O_BS_OVERLOAD); */ 434f499134dSBaptiste Daroussin 435f499134dSBaptiste Daroussin if (ISFIELDHIDDEN(items[i])) { 436f499134dSBaptiste Daroussin /* field_opts_off(field[i], O_PUBLIC); old hidden */ 437f499134dSBaptiste Daroussin myfields[i].secure = true; 438f499134dSBaptiste Daroussin myfields[i].securech = ' '; 439f499134dSBaptiste Daroussin if (conf->form.securech != '\0') 440f499134dSBaptiste Daroussin myfields[i].securech = conf->form.securech; 441f499134dSBaptiste Daroussin } 442f499134dSBaptiste Daroussin else myfields[i].secure = false; 443f499134dSBaptiste Daroussin 444f499134dSBaptiste Daroussin if (ISFIELDREADONLY(items[i])) { 445f499134dSBaptiste Daroussin field_opts_off(cfield[i], O_EDIT); 446f499134dSBaptiste Daroussin field_opts_off(cfield[i], O_ACTIVE); 447f499134dSBaptiste Daroussin color = t.form.readonlycolor; 448f499134dSBaptiste Daroussin } else { 449f499134dSBaptiste Daroussin color = i == 0 ? t.form.f_fieldcolor : t.form.fieldcolor; 450f499134dSBaptiste Daroussin } 451f499134dSBaptiste Daroussin set_field_fore(cfield[i], color); 452f499134dSBaptiste Daroussin set_field_back(cfield[i], color); 453f499134dSBaptiste Daroussin 454f499134dSBaptiste Daroussin maxline = MAX(maxline, items[i].xlabel + strlen(items[i].label)); 455f499134dSBaptiste Daroussin maxline = MAX(maxline, items[i].xfield + items[i].fieldlen); 456f499134dSBaptiste Daroussin } 457f499134dSBaptiste Daroussin cfield[i] = NULL; 458f499134dSBaptiste Daroussin 459f499134dSBaptiste Daroussin /* disable focus with 1 item (inputbox or passwordbox) */ 460f499134dSBaptiste Daroussin if (formheight == 1 && nitems == 1 && strlen(items[0].label) == 0 && 461f499134dSBaptiste Daroussin items[0].xfield == 1 ) { 4628c4f4028SBaptiste Daroussin set_field_fore(cfield[0], t.dialog.color); 4638c4f4028SBaptiste Daroussin set_field_back(cfield[0], t.dialog.color); 464f499134dSBaptiste Daroussin } 465c76f0793SBaptiste Daroussin 466c76f0793SBaptiste Daroussin get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), 467c76f0793SBaptiste Daroussin BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); 468c76f0793SBaptiste Daroussin 469f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 470f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 471f499134dSBaptiste Daroussin form_autosize(conf, rows, cols, &h, &w, text, maxline, &formheight, 472f499134dSBaptiste Daroussin nitems, bs); 473f499134dSBaptiste Daroussin if (form_checksize(h, w, text, formheight, nitems, bs) != 0) 474f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 475f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 476f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 477c76f0793SBaptiste Daroussin 478f499134dSBaptiste Daroussin if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, 479f499134dSBaptiste Daroussin &textpad, &htextpad, text, true) != 0) 480f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 481c76f0793SBaptiste Daroussin 482f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, 483f499134dSBaptiste Daroussin y + h - formheight, x + 1 + w - t.text.hmargin); 484c76f0793SBaptiste Daroussin 485f499134dSBaptiste Daroussin formwin = new_boxed_window(conf, y + h - 3 - formheight -2, x +1, 486f499134dSBaptiste Daroussin formheight+2, w-2, LOWERED); 487c76f0793SBaptiste Daroussin 488f499134dSBaptiste Daroussin form = new_form(cfield); 489f499134dSBaptiste Daroussin set_form_win(form, formwin); 490f499134dSBaptiste Daroussin /* should be formheight */ 491f499134dSBaptiste Daroussin set_form_sub(form, derwin(formwin, nitems, w-4, 1, 1)); 492c76f0793SBaptiste Daroussin post_form(form); 493c76f0793SBaptiste Daroussin 494f499134dSBaptiste Daroussin for (i=0; i < (int)nitems; i++) 495f499134dSBaptiste Daroussin mvwaddstr(formwin, items[i].ylabel, items[i].xlabel, items[i].label); 496c76f0793SBaptiste Daroussin 497f499134dSBaptiste Daroussin wrefresh(formwin); 498c76f0793SBaptiste Daroussin 499f499134dSBaptiste Daroussin do { 500f499134dSBaptiste Daroussin output = form_handler(conf, widget, h-2, w, bs, formwin, form, 501f499134dSBaptiste Daroussin cfield, nitems, items); 502f499134dSBaptiste Daroussin 503f499134dSBaptiste Daroussin if(update_widget_withtextpad(conf, shadow, widget, h, w, 504f499134dSBaptiste Daroussin RAISED, textpad, &htextpad, text, true) != 0) 505f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 506f499134dSBaptiste Daroussin 507f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 508f499134dSBaptiste Daroussin wrefresh(widget); 509f499134dSBaptiste Daroussin 510f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, 511f499134dSBaptiste Daroussin y + h - formheight, x + 1 + w - t.text.hmargin); 512f499134dSBaptiste Daroussin 513f499134dSBaptiste Daroussin draw_borders(conf, formwin, formheight+2, w-2, LOWERED); 514f499134dSBaptiste Daroussin /* wrefresh(formwin); */ 515f499134dSBaptiste Daroussin } while (output == REDRAWFORM); 516c76f0793SBaptiste Daroussin 517c76f0793SBaptiste Daroussin unpost_form(form); 518c76f0793SBaptiste Daroussin free_form(form); 519f499134dSBaptiste Daroussin for (i=0; i < (int)nitems; i++) { 520f499134dSBaptiste Daroussin free_field(cfield[i]); 521f499134dSBaptiste Daroussin free(myfields[i].buf); 522f499134dSBaptiste Daroussin } 523f499134dSBaptiste Daroussin free(cfield); 524f499134dSBaptiste Daroussin free(myfields); 525c76f0793SBaptiste Daroussin 526f499134dSBaptiste Daroussin delwin(formwin); 527f499134dSBaptiste Daroussin end_widget_withtextpad(conf, widget, h, w, textpad, shadow); 528c76f0793SBaptiste Daroussin 529c76f0793SBaptiste Daroussin return output; 530c76f0793SBaptiste Daroussin } 531