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 30c76f0793SBaptiste Daroussin #include <ctype.h> 31263660c0SAlfonso Siciliano #include <curses.h> 32263660c0SAlfonso Siciliano #include <stdlib.h> 33d93b4d32SBaptiste Daroussin #include <string.h> 34d93b4d32SBaptiste Daroussin 35c76f0793SBaptiste Daroussin #include "bsddialog.h" 36c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 37263660c0SAlfonso Siciliano #include "lib_util.h" 38c76f0793SBaptiste Daroussin 39*bce40c02SAlfonso S. Siciliano #define DEPTH 2 40c76f0793SBaptiste Daroussin #define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */ 41c76f0793SBaptiste Daroussin 42c76f0793SBaptiste Daroussin enum menumode { 43c76f0793SBaptiste Daroussin CHECKLISTMODE, 44c76f0793SBaptiste Daroussin MENUMODE, 45c76f0793SBaptiste Daroussin MIXEDLISTMODE, 46c76f0793SBaptiste Daroussin RADIOLISTMODE, 47c76f0793SBaptiste Daroussin SEPARATORMODE 48c76f0793SBaptiste Daroussin }; 49c76f0793SBaptiste Daroussin 50c76f0793SBaptiste Daroussin struct lineposition { 51c76f0793SBaptiste Daroussin unsigned int maxsepstr; 52c76f0793SBaptiste Daroussin unsigned int maxprefix; 53c76f0793SBaptiste Daroussin unsigned int xselector; 54c76f0793SBaptiste Daroussin unsigned int selectorlen; 55c76f0793SBaptiste Daroussin unsigned int maxdepth; 56c76f0793SBaptiste Daroussin unsigned int xname; 57c76f0793SBaptiste Daroussin unsigned int maxname; 58c76f0793SBaptiste Daroussin unsigned int xdesc; 59c76f0793SBaptiste Daroussin unsigned int maxdesc; 60c76f0793SBaptiste Daroussin unsigned int line; 61c76f0793SBaptiste Daroussin }; 62c76f0793SBaptiste Daroussin 63263660c0SAlfonso Siciliano struct privateitem { 64263660c0SAlfonso Siciliano bool on; 65263660c0SAlfonso Siciliano int group; 66263660c0SAlfonso Siciliano int index; 67263660c0SAlfonso Siciliano enum menumode type; 68c76f0793SBaptiste Daroussin struct bsddialog_menuitem *item; 69263660c0SAlfonso Siciliano }; 70c76f0793SBaptiste Daroussin 71263660c0SAlfonso Siciliano static void 72263660c0SAlfonso Siciliano set_on_output(struct bsddialog_conf *conf, int output, int ngroups, 73263660c0SAlfonso Siciliano struct bsddialog_menugroup *groups, struct privateitem *pritems) 74263660c0SAlfonso Siciliano { 75263660c0SAlfonso Siciliano int i, j, abs; 76263660c0SAlfonso Siciliano 77263660c0SAlfonso Siciliano if (output != BSDDIALOG_OK && !conf->menu.on_without_ok) 78c76f0793SBaptiste Daroussin return; 79c76f0793SBaptiste Daroussin 80263660c0SAlfonso Siciliano for(i = abs = 0; i < ngroups; i++) { 81c76f0793SBaptiste Daroussin if (groups[i].type == BSDDIALOG_SEPARATOR) { 82263660c0SAlfonso Siciliano abs += groups[i].nitems; 83c76f0793SBaptiste Daroussin continue; 84c76f0793SBaptiste Daroussin } 85263660c0SAlfonso Siciliano 86c76f0793SBaptiste Daroussin for(j = 0; j < (int)groups[i].nitems; j++) { 87263660c0SAlfonso Siciliano groups[i].items[j].on = pritems[abs].on; 88263660c0SAlfonso Siciliano abs++; 89c76f0793SBaptiste Daroussin } 90c76f0793SBaptiste Daroussin } 91c76f0793SBaptiste Daroussin } 92c76f0793SBaptiste Daroussin 93263660c0SAlfonso Siciliano static int getprev(struct privateitem *pritems, int abs) 94c76f0793SBaptiste Daroussin { 95263660c0SAlfonso Siciliano int i; 96c76f0793SBaptiste Daroussin 97263660c0SAlfonso Siciliano for (i = abs - 1; i >= 0; i--) { 98263660c0SAlfonso Siciliano if (pritems[i].type == SEPARATORMODE) 99c76f0793SBaptiste Daroussin continue; 100263660c0SAlfonso Siciliano return (i); 101c76f0793SBaptiste Daroussin } 102c76f0793SBaptiste Daroussin 103263660c0SAlfonso Siciliano return (abs); 104263660c0SAlfonso Siciliano } 105263660c0SAlfonso Siciliano 106263660c0SAlfonso Siciliano static int getnext(int npritems, struct privateitem *pritems, int abs) 107c76f0793SBaptiste Daroussin { 108263660c0SAlfonso Siciliano int i; 109c76f0793SBaptiste Daroussin 110263660c0SAlfonso Siciliano for (i = abs + 1; i < npritems; i++) { 111263660c0SAlfonso Siciliano if (pritems[i].type == SEPARATORMODE) 112c76f0793SBaptiste Daroussin continue; 113263660c0SAlfonso Siciliano return (i); 114c76f0793SBaptiste Daroussin } 115c76f0793SBaptiste Daroussin 116263660c0SAlfonso Siciliano return (abs); 117263660c0SAlfonso Siciliano } 118263660c0SAlfonso Siciliano 119263660c0SAlfonso Siciliano static int 120263660c0SAlfonso Siciliano getfirst_with_default(int npritems, struct privateitem *pritems, int ngroups, 121263660c0SAlfonso Siciliano struct bsddialog_menugroup *groups, int *focusgroup, int *focusitem) 122263660c0SAlfonso Siciliano { 123263660c0SAlfonso Siciliano int i, abs; 124263660c0SAlfonso Siciliano 125263660c0SAlfonso Siciliano if ((abs = getnext(npritems, pritems, -1)) < 0) 126263660c0SAlfonso Siciliano return (abs); 127263660c0SAlfonso Siciliano 128263660c0SAlfonso Siciliano if (focusgroup == NULL || focusitem == NULL) 129263660c0SAlfonso Siciliano return (abs); 130263660c0SAlfonso Siciliano if (*focusgroup < 0 || *focusgroup >= ngroups) 131263660c0SAlfonso Siciliano return (abs); 132263660c0SAlfonso Siciliano if (groups[*focusgroup].type == BSDDIALOG_SEPARATOR) 133263660c0SAlfonso Siciliano return (abs); 134263660c0SAlfonso Siciliano if (*focusitem < 0 || *focusitem >= (int)groups[*focusgroup].nitems) 135263660c0SAlfonso Siciliano return (abs); 136263660c0SAlfonso Siciliano 137263660c0SAlfonso Siciliano for (i = abs; i < npritems; i++) { 138263660c0SAlfonso Siciliano if (pritems[i].group == *focusgroup && 139263660c0SAlfonso Siciliano pritems[i].index == *focusitem) 140263660c0SAlfonso Siciliano return (i); 141263660c0SAlfonso Siciliano } 142263660c0SAlfonso Siciliano 143263660c0SAlfonso Siciliano return (abs); 144263660c0SAlfonso Siciliano } 145263660c0SAlfonso Siciliano 146263660c0SAlfonso Siciliano static int 147263660c0SAlfonso Siciliano getfastnext(int menurows, int npritems, struct privateitem *pritems, int abs) 148c76f0793SBaptiste Daroussin { 149c76f0793SBaptiste Daroussin int a, start, i; 150c76f0793SBaptiste Daroussin 151263660c0SAlfonso Siciliano start = abs; 152c76f0793SBaptiste Daroussin i = menurows; 153c76f0793SBaptiste Daroussin do { 154263660c0SAlfonso Siciliano a = abs; 155263660c0SAlfonso Siciliano abs = getnext(npritems, pritems, abs); 156c76f0793SBaptiste Daroussin i--; 157263660c0SAlfonso Siciliano } while (abs != a && abs < start + menurows && i > 0); 158263660c0SAlfonso Siciliano 159263660c0SAlfonso Siciliano return (abs); 160c76f0793SBaptiste Daroussin } 161c76f0793SBaptiste Daroussin 162263660c0SAlfonso Siciliano static int 163263660c0SAlfonso Siciliano getfastprev(int menurows, struct privateitem *pritems, int abs) 164c76f0793SBaptiste Daroussin { 165c76f0793SBaptiste Daroussin int a, start, i; 166c76f0793SBaptiste Daroussin 167263660c0SAlfonso Siciliano start = abs; 168c76f0793SBaptiste Daroussin i = menurows; 169c76f0793SBaptiste Daroussin do { 170263660c0SAlfonso Siciliano a = abs; 171263660c0SAlfonso Siciliano abs = getprev(pritems, abs); 172c76f0793SBaptiste Daroussin i--; 173263660c0SAlfonso Siciliano } while (abs != a && abs > start - menurows && i > 0); 174263660c0SAlfonso Siciliano 175263660c0SAlfonso Siciliano return (abs); 176c76f0793SBaptiste Daroussin } 177c76f0793SBaptiste Daroussin 178263660c0SAlfonso Siciliano static int 179263660c0SAlfonso Siciliano getnextshortcut(struct bsddialog_conf *conf, int npritems, 180263660c0SAlfonso Siciliano struct privateitem *pritems, int abs, int key) 1818c4f4028SBaptiste Daroussin { 182263660c0SAlfonso Siciliano int i, ch, next; 1838c4f4028SBaptiste Daroussin 184263660c0SAlfonso Siciliano next = -1; 185263660c0SAlfonso Siciliano for (i = 0; i < npritems; i++) { 186263660c0SAlfonso Siciliano if (pritems[i].type == SEPARATORMODE) 1878c4f4028SBaptiste Daroussin continue; 1888c4f4028SBaptiste Daroussin 1898c4f4028SBaptiste Daroussin if (conf->menu.no_name) 190263660c0SAlfonso Siciliano ch = pritems[i].item->desc[0]; 1918c4f4028SBaptiste Daroussin else 192263660c0SAlfonso Siciliano ch = pritems[i].item->name[0]; 1938c4f4028SBaptiste Daroussin 1948c4f4028SBaptiste Daroussin if (ch == key) { 195263660c0SAlfonso Siciliano if (i > abs) 196263660c0SAlfonso Siciliano return (i); 197263660c0SAlfonso Siciliano 198263660c0SAlfonso Siciliano if (i < abs && next == -1) 199263660c0SAlfonso Siciliano next = i; 2008c4f4028SBaptiste Daroussin } 2018c4f4028SBaptiste Daroussin } 2028c4f4028SBaptiste Daroussin 203263660c0SAlfonso Siciliano return (next != -1 ? next : abs); 2048c4f4028SBaptiste Daroussin } 2058c4f4028SBaptiste Daroussin 206c76f0793SBaptiste Daroussin static enum menumode 207c76f0793SBaptiste Daroussin getmode(enum menumode mode, struct bsddialog_menugroup group) 208c76f0793SBaptiste Daroussin { 209c76f0793SBaptiste Daroussin if (mode == MIXEDLISTMODE) { 210c76f0793SBaptiste Daroussin if (group.type == BSDDIALOG_SEPARATOR) 211c76f0793SBaptiste Daroussin mode = SEPARATORMODE; 212c76f0793SBaptiste Daroussin else if (group.type == BSDDIALOG_RADIOLIST) 213c76f0793SBaptiste Daroussin mode = RADIOLISTMODE; 214c76f0793SBaptiste Daroussin else if (group.type == BSDDIALOG_CHECKLIST) 215c76f0793SBaptiste Daroussin mode = CHECKLISTMODE; 216c76f0793SBaptiste Daroussin } 217c76f0793SBaptiste Daroussin 218263660c0SAlfonso Siciliano return (mode); 219c76f0793SBaptiste Daroussin } 220c76f0793SBaptiste Daroussin 221c76f0793SBaptiste Daroussin static void 222*bce40c02SAlfonso S. Siciliano drawseparators(struct bsddialog_conf *conf, WINDOW *pad, int linelen, 223*bce40c02SAlfonso S. Siciliano int nitems, struct privateitem *pritems) 224c76f0793SBaptiste Daroussin { 225*bce40c02SAlfonso S. Siciliano int i, linech, labellen; 226*bce40c02SAlfonso S. Siciliano const char *desc, *name; 227263660c0SAlfonso Siciliano 228*bce40c02SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 229*bce40c02SAlfonso S. Siciliano if (pritems[i].type != SEPARATORMODE) 230*bce40c02SAlfonso S. Siciliano continue; 231f499134dSBaptiste Daroussin if (conf->no_lines == false) { 232f499134dSBaptiste Daroussin wattron(pad, t.menu.desccolor); 233f499134dSBaptiste Daroussin linech = conf->ascii_lines ? '-' : ACS_HLINE; 234*bce40c02SAlfonso S. Siciliano mvwhline(pad, i, 0, linech, linelen); 235f499134dSBaptiste Daroussin wattroff(pad, t.menu.desccolor); 236c76f0793SBaptiste Daroussin } 237*bce40c02SAlfonso S. Siciliano name = pritems[i].item->name; 238*bce40c02SAlfonso S. Siciliano desc = pritems[i].item->desc; 239*bce40c02SAlfonso S. Siciliano labellen = strlen(name) + strlen(desc) + 1; 240*bce40c02SAlfonso S. Siciliano wmove(pad, i, labellen < linelen ? linelen/2 - labellen/2 : 0); 241f499134dSBaptiste Daroussin wattron(pad, t.menu.namesepcolor); 242263660c0SAlfonso Siciliano waddstr(pad, name); 243f499134dSBaptiste Daroussin wattroff(pad, t.menu.namesepcolor); 244263660c0SAlfonso Siciliano if (strlen(name) > 0 && strlen(desc) > 0) 245c76f0793SBaptiste Daroussin waddch(pad, ' '); 246f499134dSBaptiste Daroussin wattron(pad, t.menu.descsepcolor); 247263660c0SAlfonso Siciliano waddstr(pad, desc); 248f499134dSBaptiste Daroussin wattroff(pad, t.menu.descsepcolor); 249*bce40c02SAlfonso S. Siciliano } 250c76f0793SBaptiste Daroussin } 251c76f0793SBaptiste Daroussin 252*bce40c02SAlfonso S. Siciliano static void 253*bce40c02SAlfonso S. Siciliano drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, 254*bce40c02SAlfonso S. Siciliano struct lineposition pos, struct privateitem *pritem, bool focus) 255*bce40c02SAlfonso S. Siciliano { 256*bce40c02SAlfonso S. Siciliano int colordesc, colorname, colorshortcut; 257*bce40c02SAlfonso S. Siciliano const char *shortcut; 258*bce40c02SAlfonso S. Siciliano struct bsddialog_menuitem *item; 259*bce40c02SAlfonso S. Siciliano 260*bce40c02SAlfonso S. Siciliano item = pritem->item; 261*bce40c02SAlfonso S. Siciliano 262c76f0793SBaptiste Daroussin /* prefix */ 263*bce40c02SAlfonso S. Siciliano if (item->prefix != NULL && item->prefix[0] != '\0') 264*bce40c02SAlfonso S. Siciliano mvwaddstr(pad, y, 0, item->prefix); 265c76f0793SBaptiste Daroussin 266c76f0793SBaptiste Daroussin /* selector */ 267c76f0793SBaptiste Daroussin wmove(pad, y, pos.xselector); 268*bce40c02SAlfonso S. Siciliano wattron(pad, focus ? t.menu.f_selectorcolor : t.menu.selectorcolor); 269*bce40c02SAlfonso S. Siciliano if (pritem->type == CHECKLISTMODE) 270263660c0SAlfonso Siciliano wprintw(pad, "[%c]", pritem->on ? 'X' : ' '); 271*bce40c02SAlfonso S. Siciliano if (pritem->type == RADIOLISTMODE) 272263660c0SAlfonso Siciliano wprintw(pad, "(%c)", pritem->on ? '*' : ' '); 273*bce40c02SAlfonso S. Siciliano wattroff(pad, focus ? t.menu.f_selectorcolor : t.menu.selectorcolor); 274c76f0793SBaptiste Daroussin 275c76f0793SBaptiste Daroussin /* name */ 276263660c0SAlfonso Siciliano colorname = focus ? t.menu.f_namecolor : t.menu.namecolor; 277263660c0SAlfonso Siciliano if (conf->menu.no_name == false) { 278c76f0793SBaptiste Daroussin wattron(pad, colorname); 279*bce40c02SAlfonso S. Siciliano mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, item->name); 280c76f0793SBaptiste Daroussin wattroff(pad, colorname); 281c76f0793SBaptiste Daroussin } 282c76f0793SBaptiste Daroussin 283c76f0793SBaptiste Daroussin /* description */ 2848c4f4028SBaptiste Daroussin if (conf->menu.no_name) 285263660c0SAlfonso Siciliano colordesc = focus ? t.menu.f_namecolor : t.menu.namecolor; 2868c4f4028SBaptiste Daroussin else 287263660c0SAlfonso Siciliano colordesc = focus ? t.menu.f_desccolor : t.menu.desccolor; 288263660c0SAlfonso Siciliano 289263660c0SAlfonso Siciliano if (conf->menu.no_desc == false) { 2908c4f4028SBaptiste Daroussin wattron(pad, colordesc); 291f499134dSBaptiste Daroussin if (conf->menu.no_name) 292*bce40c02SAlfonso S. Siciliano mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, 293*bce40c02SAlfonso S. Siciliano item->desc); 294c76f0793SBaptiste Daroussin else 295*bce40c02SAlfonso S. Siciliano mvwaddstr(pad, y, pos.xdesc, item->desc); 2968c4f4028SBaptiste Daroussin wattroff(pad, colordesc); 297c76f0793SBaptiste Daroussin } 298c76f0793SBaptiste Daroussin 2998c4f4028SBaptiste Daroussin /* shortcut */ 300263660c0SAlfonso Siciliano if (conf->menu.shortcut_buttons == false) { 301263660c0SAlfonso Siciliano colorshortcut = focus ? 302263660c0SAlfonso Siciliano t.menu.f_shortcutcolor : t.menu.shortcutcolor; 3038c4f4028SBaptiste Daroussin wattron(pad, colorshortcut); 3048c4f4028SBaptiste Daroussin 3058c4f4028SBaptiste Daroussin if (conf->menu.no_name) 306*bce40c02SAlfonso S. Siciliano shortcut = item->desc; 3078c4f4028SBaptiste Daroussin else 308*bce40c02SAlfonso S. Siciliano shortcut = item->name; 309*bce40c02SAlfonso S. Siciliano wmove(pad, y, pos.xname + item->depth * DEPTH); 3108c4f4028SBaptiste Daroussin if (shortcut != NULL && shortcut[0] != '\0') 3118c4f4028SBaptiste Daroussin waddch(pad, shortcut[0]); 3128c4f4028SBaptiste Daroussin wattroff(pad, colorshortcut); 3138c4f4028SBaptiste Daroussin } 3148c4f4028SBaptiste Daroussin 3158c4f4028SBaptiste Daroussin /* bottom description */ 316263660c0SAlfonso Siciliano move(SCREENLINES - 1, 2); 317c76f0793SBaptiste Daroussin clrtoeol(); 318*bce40c02SAlfonso S. Siciliano if (item->bottomdesc != NULL && focus) { 319*bce40c02SAlfonso S. Siciliano addstr(item->bottomdesc); 320c76f0793SBaptiste Daroussin refresh(); 321c76f0793SBaptiste Daroussin } 322c76f0793SBaptiste Daroussin } 323c76f0793SBaptiste Daroussin 324263660c0SAlfonso Siciliano static int 325f499134dSBaptiste Daroussin menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, 326263660c0SAlfonso Siciliano const char *text, int linelen, unsigned int *menurows, int nitems, 327c76f0793SBaptiste Daroussin struct buttons bs) 328c76f0793SBaptiste Daroussin { 329263660c0SAlfonso Siciliano int htext, wtext, menusize, notext; 330c76f0793SBaptiste Daroussin 331263660c0SAlfonso Siciliano notext = 2; 332263660c0SAlfonso Siciliano if (*menurows == BSDDIALOG_AUTOSIZE) { 333263660c0SAlfonso Siciliano /* algo 1): grows vertically */ 334263660c0SAlfonso Siciliano /* notext = 1; */ 335*bce40c02SAlfonso S. Siciliano /* algo 2): grows horizontally, better with little screens */ 336263660c0SAlfonso Siciliano notext += nitems; 337263660c0SAlfonso Siciliano notext = MIN(notext, widget_max_height(conf) - HBORDERS - 3); 338263660c0SAlfonso Siciliano } else 339263660c0SAlfonso Siciliano notext += *menurows; 340c76f0793SBaptiste Daroussin 341*bce40c02SAlfonso S. Siciliano /* cols autosize, rows autosize, rows fullscreen, menu particularity */ 342*bce40c02SAlfonso S. Siciliano if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) { 343*bce40c02SAlfonso S. Siciliano if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, 344263660c0SAlfonso Siciliano &htext, &wtext) != 0) 345263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 346c76f0793SBaptiste Daroussin } 347c76f0793SBaptiste Daroussin 348263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE) 349*bce40c02SAlfonso S. Siciliano *w = widget_min_width(conf, wtext, linelen + 4, &bs); 350263660c0SAlfonso Siciliano 351c76f0793SBaptiste Daroussin if (rows == BSDDIALOG_AUTOSIZE) { 352c76f0793SBaptiste Daroussin if (*menurows == 0) { 353263660c0SAlfonso Siciliano menusize = widget_max_height(conf) - HBORDERS - 354263660c0SAlfonso Siciliano 2 /*buttons*/ - htext; 355263660c0SAlfonso Siciliano menusize = MIN(menusize, nitems + 2); 356263660c0SAlfonso Siciliano *menurows = menusize - 2 < 0 ? 0 : menusize - 2; 357c76f0793SBaptiste Daroussin } 358263660c0SAlfonso Siciliano else /* h autosize with fixed menurows */ 359263660c0SAlfonso Siciliano menusize = *menurows + 2; 360c76f0793SBaptiste Daroussin 361263660c0SAlfonso Siciliano *h = widget_min_height(conf, htext, menusize, true); 362263660c0SAlfonso Siciliano /* 363263660c0SAlfonso Siciliano * avoid menurows overflow and 364263660c0SAlfonso Siciliano * with rows=AUTOSIZE menurows!=0 becomes max-menurows 365263660c0SAlfonso Siciliano */ 366263660c0SAlfonso Siciliano *menurows = MIN(*h - 6 - htext, (int)*menurows); 367263660c0SAlfonso Siciliano } else { 368c76f0793SBaptiste Daroussin if (*menurows == 0) 369*bce40c02SAlfonso S. Siciliano *menurows = MIN(*h-6-htext, nitems); 370c76f0793SBaptiste Daroussin } 371263660c0SAlfonso Siciliano 372263660c0SAlfonso Siciliano return (0); 373c76f0793SBaptiste Daroussin } 374c76f0793SBaptiste Daroussin 375c76f0793SBaptiste Daroussin static int 376263660c0SAlfonso Siciliano menu_checksize(int rows, int cols, const char *text, int menurows, int nitems, 377c76f0793SBaptiste Daroussin struct buttons bs) 378c76f0793SBaptiste Daroussin { 379c76f0793SBaptiste Daroussin int mincols, textrow, menusize; 380c76f0793SBaptiste Daroussin 381c76f0793SBaptiste Daroussin mincols = VBORDERS; 382c76f0793SBaptiste Daroussin /* buttons */ 383*bce40c02SAlfonso S. Siciliano mincols += buttons_width(bs); 384*bce40c02SAlfonso S. Siciliano 385263660c0SAlfonso Siciliano /* 386263660c0SAlfonso Siciliano * linelen check, comment to allow some hidden col otherwise portconfig 387263660c0SAlfonso Siciliano * could not show big menus like www/apache24 388263660c0SAlfonso Siciliano */ 389c76f0793SBaptiste Daroussin /* mincols = MAX(mincols, linelen); */ 390c76f0793SBaptiste Daroussin 391c76f0793SBaptiste Daroussin if (cols < mincols) 392263660c0SAlfonso Siciliano RETURN_ERROR("Few cols, width < size buttons or " 393c76f0793SBaptiste Daroussin "name + descripion of the items"); 394c76f0793SBaptiste Daroussin 395c76f0793SBaptiste Daroussin textrow = text != NULL && strlen(text) > 0 ? 1 : 0; 396c76f0793SBaptiste Daroussin 397c76f0793SBaptiste Daroussin if (nitems > 0 && menurows == 0) 398263660c0SAlfonso Siciliano RETURN_ERROR("items > 0 but menurows == 0, probably terminal " 399c76f0793SBaptiste Daroussin "too small"); 400c76f0793SBaptiste Daroussin 401c76f0793SBaptiste Daroussin menusize = nitems > 0 ? 3 : 0; 402c76f0793SBaptiste Daroussin if (rows < 2 + 2 + menusize + textrow) 403c76f0793SBaptiste Daroussin RETURN_ERROR("Few lines for this menus"); 404c76f0793SBaptiste Daroussin 405263660c0SAlfonso Siciliano return (0); 406c76f0793SBaptiste Daroussin } 407c76f0793SBaptiste Daroussin 408c76f0793SBaptiste Daroussin /* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */ 409c76f0793SBaptiste Daroussin static void 410f499134dSBaptiste Daroussin update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w, 411c76f0793SBaptiste Daroussin int totnitems, unsigned int menurows, int ymenupad) 412c76f0793SBaptiste Daroussin { 413c76f0793SBaptiste Daroussin draw_borders(conf, menuwin, h, w, LOWERED); 414c76f0793SBaptiste Daroussin 4158c4f4028SBaptiste Daroussin if (totnitems > (int)menurows) { 416*bce40c02SAlfonso S. Siciliano wattron(menuwin, t.dialog.arrowcolor); 417f499134dSBaptiste Daroussin 418f499134dSBaptiste Daroussin if (ymenupad > 0) 419f499134dSBaptiste Daroussin mvwprintw(menuwin, 0, 2, "^^^"); 420f499134dSBaptiste Daroussin 421*bce40c02SAlfonso S. Siciliano if ((ymenupad + (int)menurows) < totnitems) 422f499134dSBaptiste Daroussin mvwprintw(menuwin, h-1, 2, "vvv"); 423f499134dSBaptiste Daroussin 424*bce40c02SAlfonso S. Siciliano wattroff(menuwin, t.dialog.arrowcolor); 425c76f0793SBaptiste Daroussin 426c76f0793SBaptiste Daroussin mvwprintw(menuwin, h-1, w-10, "%3d%%", 427c76f0793SBaptiste Daroussin 100 * (ymenupad + menurows) / totnitems); 428c76f0793SBaptiste Daroussin } 429c76f0793SBaptiste Daroussin } 430c76f0793SBaptiste Daroussin 431c76f0793SBaptiste Daroussin static int 432263660c0SAlfonso Siciliano do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols, 433263660c0SAlfonso Siciliano unsigned int menurows, enum menumode mode, unsigned int ngroups, 434c76f0793SBaptiste Daroussin struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) 435c76f0793SBaptiste Daroussin { 436263660c0SAlfonso Siciliano bool loop, onetrue, movefocus, automenurows, shortcut_butts; 437263660c0SAlfonso Siciliano int i, j, y, x, h, w, output, input; 438263660c0SAlfonso Siciliano int ymenupad, ys, ye, xs, xe, abs, next, totnitems; 439c76f0793SBaptiste Daroussin WINDOW *shadow, *widget, *textpad, *menuwin, *menupad; 440c76f0793SBaptiste Daroussin struct buttons bs; 441c76f0793SBaptiste Daroussin struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 442263660c0SAlfonso Siciliano struct bsddialog_menuitem *item; 443263660c0SAlfonso Siciliano struct privateitem *pritems; 444c76f0793SBaptiste Daroussin 445263660c0SAlfonso Siciliano shortcut_butts = conf->menu.shortcut_buttons; 4468c4f4028SBaptiste Daroussin 447*bce40c02SAlfonso S. Siciliano automenurows = (menurows == BSDDIALOG_AUTOSIZE) ? true : false; 448c76f0793SBaptiste Daroussin 449c76f0793SBaptiste Daroussin totnitems = 0; 450263660c0SAlfonso Siciliano for (i = 0; i < (int)ngroups; i++) { 451263660c0SAlfonso Siciliano if (getmode(mode, groups[i]) == RADIOLISTMODE || 452263660c0SAlfonso Siciliano getmode(mode, groups[i]) == CHECKLISTMODE) 453c76f0793SBaptiste Daroussin pos.selectorlen = 3; 454c76f0793SBaptiste Daroussin 455c76f0793SBaptiste Daroussin for (j = 0; j < (int)groups[i].nitems; j++) { 456c76f0793SBaptiste Daroussin totnitems++; 457c76f0793SBaptiste Daroussin item = &groups[i].items[j]; 458c76f0793SBaptiste Daroussin 459c76f0793SBaptiste Daroussin if (groups[i].type == BSDDIALOG_SEPARATOR) { 460c76f0793SBaptiste Daroussin pos.maxsepstr = MAX(pos.maxsepstr, 461c76f0793SBaptiste Daroussin strlen(item->name) + strlen(item->desc)); 462c76f0793SBaptiste Daroussin continue; 463c76f0793SBaptiste Daroussin } 464c76f0793SBaptiste Daroussin 465c76f0793SBaptiste Daroussin pos.maxprefix = MAX(pos.maxprefix,strlen(item->prefix)); 4668c4f4028SBaptiste Daroussin pos.maxdepth = MAX(pos.maxdepth, item->depth); 467c76f0793SBaptiste Daroussin pos.maxname = MAX(pos.maxname, strlen(item->name)); 468c76f0793SBaptiste Daroussin pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc)); 469c76f0793SBaptiste Daroussin } 470c76f0793SBaptiste Daroussin } 471f499134dSBaptiste Daroussin pos.maxname = conf->menu.no_name ? 0 : pos.maxname; 472f499134dSBaptiste Daroussin pos.maxdesc = conf->menu.no_desc ? 0 : pos.maxdesc; 473*bce40c02SAlfonso S. Siciliano pos.maxdepth = DEPTH * pos.maxdepth; 474c76f0793SBaptiste Daroussin 475c76f0793SBaptiste Daroussin pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0); 476263660c0SAlfonso Siciliano pos.xname = pos.xselector + pos.selectorlen + 477263660c0SAlfonso Siciliano (pos.selectorlen > 0 ? 1 : 0); 478c76f0793SBaptiste Daroussin pos.xdesc = pos.maxdepth + pos.xname + pos.maxname; 479c76f0793SBaptiste Daroussin pos.xdesc += (pos.maxname != 0 ? 1 : 0); 480c76f0793SBaptiste Daroussin pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc); 481c76f0793SBaptiste Daroussin 482c76f0793SBaptiste Daroussin 483263660c0SAlfonso Siciliano get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); 484c76f0793SBaptiste Daroussin 485c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 486263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 487263660c0SAlfonso Siciliano if (menu_autosize(conf, rows, cols, &h, &w, text, pos.line, &menurows, 488263660c0SAlfonso Siciliano totnitems, bs) != 0) 489263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 490c76f0793SBaptiste Daroussin if (menu_checksize(h, w, text, menurows, totnitems, bs) != 0) 491263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 492c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 493263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 494c76f0793SBaptiste Daroussin 495263660c0SAlfonso Siciliano if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, 496263660c0SAlfonso Siciliano shortcut_butts) != 0) 497263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 498c76f0793SBaptiste Daroussin 499263660c0SAlfonso Siciliano doupdate(); 500263660c0SAlfonso Siciliano 501263660c0SAlfonso Siciliano prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, 502263660c0SAlfonso Siciliano y + h - menurows, x + 1 + w - TEXTHMARGIN); 503c76f0793SBaptiste Daroussin 504c76f0793SBaptiste Daroussin menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2, 505c76f0793SBaptiste Daroussin menurows+2, w-4, LOWERED); 506c76f0793SBaptiste Daroussin 507c76f0793SBaptiste Daroussin menupad = newpad(totnitems, pos.line); 5088c4f4028SBaptiste Daroussin wbkgd(menupad, t.dialog.color); 509c76f0793SBaptiste Daroussin 510263660c0SAlfonso Siciliano if ((pritems = calloc(totnitems, sizeof (struct privateitem))) == NULL) 511263660c0SAlfonso Siciliano RETURN_ERROR("Cannot allocate memory for internal menu items"); 512263660c0SAlfonso Siciliano 513263660c0SAlfonso Siciliano abs = 0; 514263660c0SAlfonso Siciliano for (i = 0; i < (int)ngroups; i++) { 515263660c0SAlfonso Siciliano onetrue = false; 516c76f0793SBaptiste Daroussin for (j = 0; j < (int)groups[i].nitems; j++) { 517c76f0793SBaptiste Daroussin item = &groups[i].items[j]; 518263660c0SAlfonso Siciliano 519263660c0SAlfonso Siciliano if (getmode(mode, groups[i]) == MENUMODE) { 520263660c0SAlfonso Siciliano pritems[abs].on = false; 521263660c0SAlfonso Siciliano } else if (getmode(mode, groups[i]) == RADIOLISTMODE) { 522263660c0SAlfonso Siciliano pritems[abs].on = onetrue ? false : item->on; 523263660c0SAlfonso Siciliano if (pritems[abs].on) 524263660c0SAlfonso Siciliano onetrue = true; 525263660c0SAlfonso Siciliano } else { 526263660c0SAlfonso Siciliano pritems[abs].on = item->on; 527263660c0SAlfonso Siciliano } 528263660c0SAlfonso Siciliano pritems[abs].group = i; 529263660c0SAlfonso Siciliano pritems[abs].index = j; 530263660c0SAlfonso Siciliano pritems[abs].type = getmode(mode, groups[i]); 531263660c0SAlfonso Siciliano pritems[abs].item = item; 532263660c0SAlfonso Siciliano 533263660c0SAlfonso Siciliano drawitem(conf, menupad, abs, pos, &pritems[abs], false); 534263660c0SAlfonso Siciliano abs++; 535c76f0793SBaptiste Daroussin } 536c76f0793SBaptiste Daroussin } 537*bce40c02SAlfonso S. Siciliano drawseparators(conf, menupad, MIN((int)pos.line, w-6), totnitems, 538*bce40c02SAlfonso S. Siciliano pritems); 539263660c0SAlfonso Siciliano abs = getfirst_with_default(totnitems, pritems, ngroups, groups, 540263660c0SAlfonso Siciliano focuslist, focusitem); 541263660c0SAlfonso Siciliano if (abs >= 0) 542263660c0SAlfonso Siciliano drawitem(conf, menupad, abs, pos, &pritems[abs], true); 543c76f0793SBaptiste Daroussin 544c76f0793SBaptiste Daroussin ys = y + h - 5 - menurows + 1; 545c76f0793SBaptiste Daroussin ye = y + h - 5 ; 546f499134dSBaptiste Daroussin if (conf->menu.align_left || (int)pos.line > w - 6) { 547c76f0793SBaptiste Daroussin xs = x + 3; 548c76f0793SBaptiste Daroussin xe = xs + w - 7; 549263660c0SAlfonso Siciliano } else { /* center */ 550c76f0793SBaptiste Daroussin xs = x + 3 + (w-6)/2 - pos.line/2; 551c76f0793SBaptiste Daroussin xe = xs + w - 5; 552c76f0793SBaptiste Daroussin } 553c76f0793SBaptiste Daroussin 554263660c0SAlfonso Siciliano ymenupad = 0; 555c76f0793SBaptiste Daroussin if ((int)(ymenupad + menurows) - 1 < abs) 556c76f0793SBaptiste Daroussin ymenupad = abs - menurows + 1; 557263660c0SAlfonso Siciliano update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, menurows, 558263660c0SAlfonso Siciliano ymenupad); 559c76f0793SBaptiste Daroussin wrefresh(menuwin); 560c76f0793SBaptiste Daroussin prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); 561c76f0793SBaptiste Daroussin 562263660c0SAlfonso Siciliano movefocus = false; 563c76f0793SBaptiste Daroussin loop = true; 564c76f0793SBaptiste Daroussin while (loop) { 565c76f0793SBaptiste Daroussin input = getch(); 566c76f0793SBaptiste Daroussin switch(input) { 567c76f0793SBaptiste Daroussin case KEY_ENTER: 568c76f0793SBaptiste Daroussin case 10: /* Enter */ 569c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; 570263660c0SAlfonso Siciliano if (abs >= 0 && pritems[abs].type == MENUMODE) 571263660c0SAlfonso Siciliano pritems[abs].on = true; 572263660c0SAlfonso Siciliano set_on_output(conf, output, ngroups, groups, pritems); 573c76f0793SBaptiste Daroussin loop = false; 574c76f0793SBaptiste Daroussin break; 575c76f0793SBaptiste Daroussin case 27: /* Esc */ 576263660c0SAlfonso Siciliano if (conf->key.enable_esc) { 577c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 578263660c0SAlfonso Siciliano if (abs >= 0 && pritems[abs].type == MENUMODE) 579263660c0SAlfonso Siciliano pritems[abs].on = true; 580263660c0SAlfonso Siciliano set_on_output(conf, output, ngroups, groups, 581263660c0SAlfonso Siciliano pritems); 582c76f0793SBaptiste Daroussin loop = false; 583263660c0SAlfonso Siciliano } 584c76f0793SBaptiste Daroussin break; 585c76f0793SBaptiste Daroussin case '\t': /* TAB */ 586c76f0793SBaptiste Daroussin bs.curr = (bs.curr + 1) % bs.nbuttons; 587263660c0SAlfonso Siciliano draw_buttons(widget, bs, shortcut_butts); 588c76f0793SBaptiste Daroussin wrefresh(widget); 589c76f0793SBaptiste Daroussin break; 590c76f0793SBaptiste Daroussin case KEY_LEFT: 591c76f0793SBaptiste Daroussin if (bs.curr > 0) { 592c76f0793SBaptiste Daroussin bs.curr--; 593263660c0SAlfonso Siciliano draw_buttons(widget, bs, shortcut_butts); 594c76f0793SBaptiste Daroussin wrefresh(widget); 595c76f0793SBaptiste Daroussin } 596c76f0793SBaptiste Daroussin break; 597c76f0793SBaptiste Daroussin case KEY_RIGHT: 598c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 599c76f0793SBaptiste Daroussin bs.curr++; 600263660c0SAlfonso Siciliano draw_buttons(widget, bs, shortcut_butts); 601c76f0793SBaptiste Daroussin wrefresh(widget); 602c76f0793SBaptiste Daroussin } 603c76f0793SBaptiste Daroussin break; 604c76f0793SBaptiste Daroussin case KEY_F(1): 605*bce40c02SAlfonso S. Siciliano if (conf->key.f1_file == NULL && 606*bce40c02SAlfonso S. Siciliano conf->key.f1_message == NULL) 607c76f0793SBaptiste Daroussin break; 608c76f0793SBaptiste Daroussin if (f1help(conf) != 0) 609263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 610263660c0SAlfonso Siciliano /* No break, screen size can change */ 611c76f0793SBaptiste Daroussin case KEY_RESIZE: 612263660c0SAlfonso Siciliano /* Important for decreasing screen */ 613f499134dSBaptiste Daroussin hide_widget(y, x, h, w, conf->shadow); 614c76f0793SBaptiste Daroussin refresh(); 615c76f0793SBaptiste Daroussin 616c76f0793SBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 617263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 618c76f0793SBaptiste Daroussin menurows = automenurows ? 0 : menurows; 619263660c0SAlfonso Siciliano if (menu_autosize(conf, rows, cols, &h, &w, text, 620263660c0SAlfonso Siciliano pos.line, &menurows, totnitems, bs) != 0) 621263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 622263660c0SAlfonso Siciliano if (menu_checksize(h, w, text, menurows, totnitems, 623263660c0SAlfonso Siciliano bs) != 0) 624263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 625c76f0793SBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 626263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 627c76f0793SBaptiste Daroussin 628263660c0SAlfonso Siciliano if (update_dialog(conf, shadow, widget, y, x, h, w, 629263660c0SAlfonso Siciliano textpad, text, &bs, shortcut_butts) != 0) 630263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 631c76f0793SBaptiste Daroussin 632263660c0SAlfonso Siciliano doupdate(); 633c76f0793SBaptiste Daroussin 634263660c0SAlfonso Siciliano prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, 635263660c0SAlfonso Siciliano y + h - menurows, x + 1 + w - TEXTHMARGIN); 636c76f0793SBaptiste Daroussin 637c76f0793SBaptiste Daroussin wclear(menuwin); 638c76f0793SBaptiste Daroussin mvwin(menuwin, y + h - 5 - menurows, x + 2); 639c76f0793SBaptiste Daroussin wresize(menuwin,menurows+2, w-4); 640263660c0SAlfonso Siciliano update_menuwin(conf, menuwin, menurows+2, w-4, 641263660c0SAlfonso Siciliano totnitems, menurows, ymenupad); 642c76f0793SBaptiste Daroussin wrefresh(menuwin); 643c76f0793SBaptiste Daroussin 644c76f0793SBaptiste Daroussin ys = y + h - 5 - menurows + 1; 645c76f0793SBaptiste Daroussin ye = y + h - 5 ; 646f499134dSBaptiste Daroussin if (conf->menu.align_left || (int)pos.line > w - 6) { 647c76f0793SBaptiste Daroussin xs = x + 3; 648c76f0793SBaptiste Daroussin xe = xs + w - 7; 649263660c0SAlfonso Siciliano } else { /* center */ 650c76f0793SBaptiste Daroussin xs = x + 3 + (w-6)/2 - pos.line/2; 651c76f0793SBaptiste Daroussin xe = xs + w - 5; 652c76f0793SBaptiste Daroussin } 653c76f0793SBaptiste Daroussin 654*bce40c02SAlfonso S. Siciliano drawseparators(conf, menupad, MIN((int)pos.line, w-6), 655*bce40c02SAlfonso S. Siciliano totnitems, pritems); 656*bce40c02SAlfonso S. Siciliano 657c76f0793SBaptiste Daroussin if ((int)(ymenupad + menurows) - 1 < abs) 658c76f0793SBaptiste Daroussin ymenupad = abs - menurows + 1; 659c76f0793SBaptiste Daroussin prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); 660c76f0793SBaptiste Daroussin 661c76f0793SBaptiste Daroussin refresh(); 662c76f0793SBaptiste Daroussin 663c76f0793SBaptiste Daroussin break; 664c76f0793SBaptiste Daroussin } 665c76f0793SBaptiste Daroussin 666c76f0793SBaptiste Daroussin if (abs < 0) 667c76f0793SBaptiste Daroussin continue; 668c76f0793SBaptiste Daroussin switch(input) { 669c76f0793SBaptiste Daroussin case KEY_HOME: 670263660c0SAlfonso Siciliano next = getnext(totnitems, pritems, -1); 671263660c0SAlfonso Siciliano movefocus = next != abs; 672c76f0793SBaptiste Daroussin break; 673263660c0SAlfonso Siciliano case KEY_UP: 674263660c0SAlfonso Siciliano next = getprev(pritems, abs); 675263660c0SAlfonso Siciliano movefocus = next != abs; 676263660c0SAlfonso Siciliano break; 677263660c0SAlfonso Siciliano case KEY_PPAGE: 678263660c0SAlfonso Siciliano next = getfastprev(menurows, pritems, abs); 679263660c0SAlfonso Siciliano movefocus = next != abs; 680c76f0793SBaptiste Daroussin break; 681c76f0793SBaptiste Daroussin case KEY_END: 682263660c0SAlfonso Siciliano next = getprev(pritems, totnitems); 683263660c0SAlfonso Siciliano movefocus = next != abs; 684263660c0SAlfonso Siciliano break; 685c76f0793SBaptiste Daroussin case KEY_DOWN: 686263660c0SAlfonso Siciliano next = getnext(totnitems, pritems, abs); 687263660c0SAlfonso Siciliano movefocus = next != abs; 688263660c0SAlfonso Siciliano break; 689c76f0793SBaptiste Daroussin case KEY_NPAGE: 690263660c0SAlfonso Siciliano next = getfastnext(menurows, totnitems, pritems, abs); 691263660c0SAlfonso Siciliano movefocus = next != abs; 692c76f0793SBaptiste Daroussin break; 693c76f0793SBaptiste Daroussin case ' ': /* Space */ 694263660c0SAlfonso Siciliano if (pritems[abs].type == MENUMODE) 695c76f0793SBaptiste Daroussin break; 696263660c0SAlfonso Siciliano else if (pritems[abs].type == CHECKLISTMODE) 697263660c0SAlfonso Siciliano pritems[abs].on = !pritems[abs].on; 698c76f0793SBaptiste Daroussin else { /* RADIOLISTMODE */ 699263660c0SAlfonso Siciliano for (i = abs - pritems[abs].index; 700263660c0SAlfonso Siciliano i < totnitems && 701263660c0SAlfonso Siciliano pritems[i].group == pritems[abs].group; 702263660c0SAlfonso Siciliano i++) { 703263660c0SAlfonso Siciliano if (i != abs && pritems[i].on) { 704263660c0SAlfonso Siciliano pritems[i].on = false; 705263660c0SAlfonso Siciliano drawitem(conf, menupad, i, pos, 706263660c0SAlfonso Siciliano &pritems[i], false); 707c76f0793SBaptiste Daroussin } 708c76f0793SBaptiste Daroussin } 709263660c0SAlfonso Siciliano pritems[abs].on = !pritems[abs].on; 710263660c0SAlfonso Siciliano } 711263660c0SAlfonso Siciliano drawitem(conf, menupad, abs, pos, &pritems[abs], true); 712c76f0793SBaptiste Daroussin prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); 713263660c0SAlfonso Siciliano break; 7148c4f4028SBaptiste Daroussin default: 715263660c0SAlfonso Siciliano if (shortcut_butts) { 716263660c0SAlfonso Siciliano if (shortcut_buttons(input, &bs)) { 717263660c0SAlfonso Siciliano output = bs.value[bs.curr]; 718263660c0SAlfonso Siciliano if (pritems[abs].type == MENUMODE) 719263660c0SAlfonso Siciliano pritems[abs].on = true; 720263660c0SAlfonso Siciliano set_on_output(conf, output, ngroups, 721263660c0SAlfonso Siciliano groups, pritems); 7228c4f4028SBaptiste Daroussin loop = false; 7238c4f4028SBaptiste Daroussin } 7248c4f4028SBaptiste Daroussin break; 7258c4f4028SBaptiste Daroussin } 7268c4f4028SBaptiste Daroussin 727263660c0SAlfonso Siciliano /* shourtcut items */ 728263660c0SAlfonso Siciliano next = getnextshortcut(conf, totnitems, pritems, abs, 729263660c0SAlfonso Siciliano input); 730263660c0SAlfonso Siciliano movefocus = next != abs; 731263660c0SAlfonso Siciliano } 732263660c0SAlfonso Siciliano 733263660c0SAlfonso Siciliano if (movefocus) { 734263660c0SAlfonso Siciliano drawitem(conf, menupad, abs, pos, &pritems[abs], false); 735263660c0SAlfonso Siciliano abs = next; 736263660c0SAlfonso Siciliano drawitem(conf, menupad, abs, pos, &pritems[abs], true); 7378c4f4028SBaptiste Daroussin if (ymenupad > abs && ymenupad > 0) 7388c4f4028SBaptiste Daroussin ymenupad = abs; 7398c4f4028SBaptiste Daroussin if ((int)(ymenupad + menurows) <= abs) 7408c4f4028SBaptiste Daroussin ymenupad = abs - menurows + 1; 741263660c0SAlfonso Siciliano update_menuwin(conf, menuwin, menurows+2, w-4, 742263660c0SAlfonso Siciliano totnitems, menurows, ymenupad); 7438c4f4028SBaptiste Daroussin wrefresh(menuwin); 7448c4f4028SBaptiste Daroussin prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); 745263660c0SAlfonso Siciliano movefocus = false; 746c76f0793SBaptiste Daroussin } 747c76f0793SBaptiste Daroussin } 748c76f0793SBaptiste Daroussin 749c76f0793SBaptiste Daroussin if (focuslist != NULL) 750263660c0SAlfonso Siciliano *focuslist = abs < 0 ? -1 : pritems[abs].group; 751c76f0793SBaptiste Daroussin if (focusitem !=NULL) 752263660c0SAlfonso Siciliano *focusitem = abs < 0 ? -1 : pritems[abs].index; 753c76f0793SBaptiste Daroussin 754c76f0793SBaptiste Daroussin delwin(menupad); 755c76f0793SBaptiste Daroussin delwin(menuwin); 756263660c0SAlfonso Siciliano end_dialog(conf, shadow, widget, textpad); 757263660c0SAlfonso Siciliano free(pritems); 758c76f0793SBaptiste Daroussin 759263660c0SAlfonso Siciliano return (output); 760c76f0793SBaptiste Daroussin } 761c76f0793SBaptiste Daroussin 762263660c0SAlfonso Siciliano /* API */ 763263660c0SAlfonso Siciliano int 764263660c0SAlfonso Siciliano bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, 765263660c0SAlfonso Siciliano int cols, unsigned int menurows, unsigned int ngroups, 766263660c0SAlfonso Siciliano struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) 767c76f0793SBaptiste Daroussin { 768c76f0793SBaptiste Daroussin int output; 769c76f0793SBaptiste Daroussin 770c76f0793SBaptiste Daroussin output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE, 771c76f0793SBaptiste Daroussin ngroups, groups, focuslist, focusitem); 772c76f0793SBaptiste Daroussin 773263660c0SAlfonso Siciliano return (output); 774c76f0793SBaptiste Daroussin } 775c76f0793SBaptiste Daroussin 776c76f0793SBaptiste Daroussin int 777263660c0SAlfonso Siciliano bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows, 778263660c0SAlfonso Siciliano int cols, unsigned int menurows, unsigned int nitems, 779263660c0SAlfonso Siciliano struct bsddialog_menuitem *items, int *focusitem) 780c76f0793SBaptiste Daroussin { 781263660c0SAlfonso Siciliano int output, focuslist = 0; 782c76f0793SBaptiste Daroussin struct bsddialog_menugroup group = { 783c76f0793SBaptiste Daroussin BSDDIALOG_CHECKLIST /* unused */, nitems, items}; 784c76f0793SBaptiste Daroussin 785c76f0793SBaptiste Daroussin output = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE, 786263660c0SAlfonso Siciliano 1, &group, &focuslist, focusitem); 787c76f0793SBaptiste Daroussin 788263660c0SAlfonso Siciliano return (output); 789c76f0793SBaptiste Daroussin } 790c76f0793SBaptiste Daroussin 791c76f0793SBaptiste Daroussin int 792263660c0SAlfonso Siciliano bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows, 793263660c0SAlfonso Siciliano int cols, unsigned int menurows, unsigned int nitems, 794263660c0SAlfonso Siciliano struct bsddialog_menuitem *items, int *focusitem) 795c76f0793SBaptiste Daroussin { 796263660c0SAlfonso Siciliano int output, focuslist = 0; 797c76f0793SBaptiste Daroussin struct bsddialog_menugroup group = { 798c76f0793SBaptiste Daroussin BSDDIALOG_CHECKLIST /* unused */, nitems, items}; 799c76f0793SBaptiste Daroussin 800c76f0793SBaptiste Daroussin output = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1, 801263660c0SAlfonso Siciliano &group, &focuslist, focusitem); 802c76f0793SBaptiste Daroussin 803263660c0SAlfonso Siciliano return (output); 804c76f0793SBaptiste Daroussin } 805c76f0793SBaptiste Daroussin 806c76f0793SBaptiste Daroussin int 807263660c0SAlfonso Siciliano bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows, 808263660c0SAlfonso Siciliano int cols, unsigned int menurows, unsigned int nitems, 809263660c0SAlfonso Siciliano struct bsddialog_menuitem *items, int *focusitem) 810c76f0793SBaptiste Daroussin { 811263660c0SAlfonso Siciliano int output, focuslist = 0; 812c76f0793SBaptiste Daroussin struct bsddialog_menugroup group = { 813c76f0793SBaptiste Daroussin BSDDIALOG_RADIOLIST /* unused */, nitems, items}; 814c76f0793SBaptiste Daroussin 815c76f0793SBaptiste Daroussin output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE, 816263660c0SAlfonso Siciliano 1, &group, &focuslist, focusitem); 817c76f0793SBaptiste Daroussin 818263660c0SAlfonso Siciliano return (output); 819c76f0793SBaptiste Daroussin } 820