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 28f499134dSBaptiste Daroussin #include <sys/param.h> 29f499134dSBaptiste Daroussin 30*b319d934SAlfonso S. Siciliano #include <curses.h> 31*b319d934SAlfonso S. Siciliano #include <limits.h> 32d93b4d32SBaptiste Daroussin #include <stdlib.h> 33d93b4d32SBaptiste Daroussin #include <string.h> 34*b319d934SAlfonso S. Siciliano #include <wchar.h> 35c76f0793SBaptiste Daroussin 36c76f0793SBaptiste Daroussin #include "bsddialog.h" 37c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 38263660c0SAlfonso Siciliano #include "lib_util.h" 39c76f0793SBaptiste Daroussin 40*b319d934SAlfonso S. Siciliano struct privateitem { 41*b319d934SAlfonso S. Siciliano const char *label; /* formitem.label */ 42*b319d934SAlfonso S. Siciliano unsigned int ylabel; /* formitem.ylabel */ 43*b319d934SAlfonso S. Siciliano unsigned int xlabel; /* formitem.xlabel */ 44*b319d934SAlfonso S. Siciliano unsigned int yfield; /* formitem.yfield */ 45*b319d934SAlfonso S. Siciliano unsigned int xfield; /* formitem.xfield */ 46*b319d934SAlfonso S. Siciliano bool secure; /* formitem.flags & BSDDIALOG_FIELDHIDDEN */ 47*b319d934SAlfonso S. Siciliano bool readonly; /* formitem.flags & BSDDIALOG_FIELDREADONLY */ 48*b319d934SAlfonso S. Siciliano bool fieldnocolor; /* formitem.flags & BSDDIALOG_FIELDNOCOLOR */ 49*b319d934SAlfonso S. Siciliano bool extendfield; /* formitem.flags & BSDDIALOG_FIELDEXTEND */ 50*b319d934SAlfonso S. Siciliano bool fieldonebyte; /* formitem.flags & BSDDIALOG_FIELDSINGLEBYTE */ 51*b319d934SAlfonso S. Siciliano bool cursorend; /* formitem.flags & BSDDIALOG_FIELDCURSOREND */ 52*b319d934SAlfonso S. Siciliano bool cursor; /* field cursor visibility */ 53*b319d934SAlfonso S. Siciliano const char *bottomdesc; /* formitem.bottomdesc */ 54c76f0793SBaptiste Daroussin 55*b319d934SAlfonso S. Siciliano wchar_t *privwbuf; /* formitem.value */ 56*b319d934SAlfonso S. Siciliano wchar_t *pubwbuf; /* string for drawitem() */ 57*b319d934SAlfonso S. Siciliano unsigned int maxletters; /* formitem.maxvaluelen, [priv|pub]wbuf size */ 58*b319d934SAlfonso S. Siciliano unsigned int nletters; /* letters in privwbuf and pubwbuf */ 59*b319d934SAlfonso S. Siciliano unsigned int pos; /* pos in privwbuf and pubwbuf */ 60*b319d934SAlfonso S. Siciliano unsigned int fieldcols; /* formitem.fieldlen */ 61*b319d934SAlfonso S. Siciliano unsigned int xcursor; /* position in fieldcols [0 - fieldcols-1] */ 62*b319d934SAlfonso S. Siciliano unsigned int xposdraw; /* first pubwbuf index to draw */ 63f499134dSBaptiste Daroussin }; 64f499134dSBaptiste Daroussin 65*b319d934SAlfonso S. Siciliano struct privateform { 66*b319d934SAlfonso S. Siciliano WINDOW *border; 67*b319d934SAlfonso S. Siciliano 68*b319d934SAlfonso S. Siciliano WINDOW *pad; 69*b319d934SAlfonso S. Siciliano unsigned int h; /* only to create pad */ 70*b319d934SAlfonso S. Siciliano unsigned int w; /* only to create pad */ 71*b319d934SAlfonso S. Siciliano unsigned int wmin; /* to refresh, w can change for FIELDEXTEND */ 72*b319d934SAlfonso S. Siciliano unsigned int ys; /* to refresh */ 73*b319d934SAlfonso S. Siciliano unsigned int ye; /* to refresh */ 74*b319d934SAlfonso S. Siciliano unsigned int xs; /* to refresh */ 75*b319d934SAlfonso S. Siciliano unsigned int xe; /* to refresh */ 76*b319d934SAlfonso S. Siciliano unsigned int y; /* changes moving focus around items */ 77*b319d934SAlfonso S. Siciliano unsigned int viewrows; /* visible rows, real formheight */ 78*b319d934SAlfonso S. Siciliano unsigned int minviewrows; /* min viewrows, ylabel != yfield */ 79*b319d934SAlfonso S. Siciliano 80*b319d934SAlfonso S. Siciliano wchar_t securewch; /* wide char of conf.form.secure[mb]ch */ 81*b319d934SAlfonso S. Siciliano }; 82*b319d934SAlfonso S. Siciliano 83*b319d934SAlfonso S. Siciliano enum operation { 84*b319d934SAlfonso S. Siciliano MOVE_CURSOR_BEGIN, 85*b319d934SAlfonso S. Siciliano MOVE_CURSOR_END, 86*b319d934SAlfonso S. Siciliano MOVE_CURSOR_RIGHT, 87*b319d934SAlfonso S. Siciliano MOVE_CURSOR_LEFT, 88*b319d934SAlfonso S. Siciliano DEL_LETTER 89*b319d934SAlfonso S. Siciliano }; 90*b319d934SAlfonso S. Siciliano 91*b319d934SAlfonso S. Siciliano static bool fieldctl(struct privateitem *item, enum operation op) 92*b319d934SAlfonso S. Siciliano { 93*b319d934SAlfonso S. Siciliano bool change; 94*b319d934SAlfonso S. Siciliano int width, oldwidth, nextwidth, cols; 95*b319d934SAlfonso S. Siciliano unsigned int i; 96*b319d934SAlfonso S. Siciliano 97*b319d934SAlfonso S. Siciliano change = false; 98*b319d934SAlfonso S. Siciliano switch (op){ 99*b319d934SAlfonso S. Siciliano case MOVE_CURSOR_BEGIN: 100*b319d934SAlfonso S. Siciliano if (item->pos == 0 && item->xcursor == 0) 101*b319d934SAlfonso S. Siciliano break; 102*b319d934SAlfonso S. Siciliano /* here the cursor is changed */ 103*b319d934SAlfonso S. Siciliano change = true; 104*b319d934SAlfonso S. Siciliano item->pos = 0; 105*b319d934SAlfonso S. Siciliano item->xcursor = 0; 106*b319d934SAlfonso S. Siciliano item->xposdraw = 0; 107*b319d934SAlfonso S. Siciliano break; 108*b319d934SAlfonso S. Siciliano case MOVE_CURSOR_END: 109*b319d934SAlfonso S. Siciliano while (fieldctl(item, MOVE_CURSOR_RIGHT)) 110*b319d934SAlfonso S. Siciliano change = true; 111*b319d934SAlfonso S. Siciliano break; 112*b319d934SAlfonso S. Siciliano case MOVE_CURSOR_LEFT: 113*b319d934SAlfonso S. Siciliano if (item->pos == 0) 114*b319d934SAlfonso S. Siciliano break; 115*b319d934SAlfonso S. Siciliano /* check redundant by item->pos == 0 because of 'while' below */ 116*b319d934SAlfonso S. Siciliano if (item->xcursor == 0 && item->xposdraw == 0) 117*b319d934SAlfonso S. Siciliano break; 118*b319d934SAlfonso S. Siciliano /* here some letter to left */ 119*b319d934SAlfonso S. Siciliano change = true; 120*b319d934SAlfonso S. Siciliano item->pos -= 1; 121*b319d934SAlfonso S. Siciliano width = wcwidth(item->pubwbuf[item->pos]); 122*b319d934SAlfonso S. Siciliano if (((int)item->xcursor) - width < 0) { 123*b319d934SAlfonso S. Siciliano item->xcursor = 0; 124*b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 125*b319d934SAlfonso S. Siciliano } else 126*b319d934SAlfonso S. Siciliano item->xcursor -= width; 127*b319d934SAlfonso S. Siciliano 128*b319d934SAlfonso S. Siciliano while (true) { 129*b319d934SAlfonso S. Siciliano if (item->xposdraw == 0) 130*b319d934SAlfonso S. Siciliano break; 131*b319d934SAlfonso S. Siciliano if (item->xcursor >= item->fieldcols / 2) 132*b319d934SAlfonso S. Siciliano break; 133*b319d934SAlfonso S. Siciliano if (wcwidth(item->pubwbuf[item->xposdraw - 1]) + 134*b319d934SAlfonso S. Siciliano item->xcursor + width > item->fieldcols) 135*b319d934SAlfonso S. Siciliano break; 136*b319d934SAlfonso S. Siciliano 137*b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 138*b319d934SAlfonso S. Siciliano item->xcursor += 139*b319d934SAlfonso S. Siciliano wcwidth(item->pubwbuf[item->xposdraw]); 140*b319d934SAlfonso S. Siciliano } 141*b319d934SAlfonso S. Siciliano break; 142*b319d934SAlfonso S. Siciliano case DEL_LETTER: 143*b319d934SAlfonso S. Siciliano if (item->nletters == 0) 144*b319d934SAlfonso S. Siciliano break; 145*b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) 146*b319d934SAlfonso S. Siciliano break; 147*b319d934SAlfonso S. Siciliano /* here a letter under the cursor */ 148*b319d934SAlfonso S. Siciliano change = true; 149*b319d934SAlfonso S. Siciliano for (i = item->pos; i < item->nletters; i++) { 150*b319d934SAlfonso S. Siciliano item->privwbuf[i] = item->privwbuf[i+1]; 151*b319d934SAlfonso S. Siciliano item->pubwbuf[i] = item->pubwbuf[i+1]; 152*b319d934SAlfonso S. Siciliano } 153*b319d934SAlfonso S. Siciliano item->nletters -= 1; 154*b319d934SAlfonso S. Siciliano item->privwbuf[i] = L'\0'; 155*b319d934SAlfonso S. Siciliano item->pubwbuf[i] = L'\0'; 156*b319d934SAlfonso S. Siciliano break; 157*b319d934SAlfonso S. Siciliano case MOVE_CURSOR_RIGHT: /* used also by "insert", see handler loop */ 158*b319d934SAlfonso S. Siciliano if (item->pos + 1 == item->maxletters) 159*b319d934SAlfonso S. Siciliano break; 160*b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) 161*b319d934SAlfonso S. Siciliano break; 162*b319d934SAlfonso S. Siciliano /* here a change to right */ 163*b319d934SAlfonso S. Siciliano change = true; 164*b319d934SAlfonso S. Siciliano oldwidth = wcwidth(item->pubwbuf[item->pos]); 165*b319d934SAlfonso S. Siciliano item->pos += 1; 166*b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) { /* empty column */ 167*b319d934SAlfonso S. Siciliano nextwidth = 1; 168*b319d934SAlfonso S. Siciliano } else { /* a letter to right */ 169*b319d934SAlfonso S. Siciliano nextwidth = wcwidth(item->pubwbuf[item->pos]); 170*b319d934SAlfonso S. Siciliano } 171*b319d934SAlfonso S. Siciliano if (item->xcursor + oldwidth + nextwidth - 1 >= item->fieldcols) { 172*b319d934SAlfonso S. Siciliano cols = nextwidth; 173*b319d934SAlfonso S. Siciliano item->xposdraw = item->pos; 174*b319d934SAlfonso S. Siciliano while (item->xposdraw != 0) { 175*b319d934SAlfonso S. Siciliano cols += wcwidth(item->pubwbuf[item->xposdraw - 1]); 176*b319d934SAlfonso S. Siciliano if (cols > (int)item->fieldcols) 177*b319d934SAlfonso S. Siciliano break; 178*b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 179*b319d934SAlfonso S. Siciliano } 180*b319d934SAlfonso S. Siciliano item->xcursor = 0; 181*b319d934SAlfonso S. Siciliano for (i = item->xposdraw; i < item->pos ; i++) 182*b319d934SAlfonso S. Siciliano item->xcursor += wcwidth(item->pubwbuf[i]); 183*b319d934SAlfonso S. Siciliano } 184*b319d934SAlfonso S. Siciliano else { 185*b319d934SAlfonso S. Siciliano item->xcursor += oldwidth; 186*b319d934SAlfonso S. Siciliano } 187*b319d934SAlfonso S. Siciliano 188*b319d934SAlfonso S. Siciliano break; 189*b319d934SAlfonso S. Siciliano } 190*b319d934SAlfonso S. Siciliano 191*b319d934SAlfonso S. Siciliano return (change); 192*b319d934SAlfonso S. Siciliano } 193*b319d934SAlfonso S. Siciliano 194*b319d934SAlfonso S. Siciliano static void 195*b319d934SAlfonso S. Siciliano drawitem(struct privateform *form, struct privateitem *item, bool focus) 196*b319d934SAlfonso S. Siciliano { 197*b319d934SAlfonso S. Siciliano int color; 198*b319d934SAlfonso S. Siciliano unsigned int n, cols; 199*b319d934SAlfonso S. Siciliano 200*b319d934SAlfonso S. Siciliano /* Label */ 201*b319d934SAlfonso S. Siciliano wattron(form->pad, t.dialog.color); 202*b319d934SAlfonso S. Siciliano mvwaddstr(form->pad, item->ylabel, item->xlabel, item->label); 203*b319d934SAlfonso S. Siciliano wattroff(form->pad, t.dialog.color); 204*b319d934SAlfonso S. Siciliano 205*b319d934SAlfonso S. Siciliano /* Field */ 206*b319d934SAlfonso S. Siciliano if (item->readonly) 207*b319d934SAlfonso S. Siciliano color = t.form.readonlycolor; 208*b319d934SAlfonso S. Siciliano else if (item->fieldnocolor) 209*b319d934SAlfonso S. Siciliano color = t.dialog.color; 210*b319d934SAlfonso S. Siciliano else 211*b319d934SAlfonso S. Siciliano color = focus ? t.form.f_fieldcolor : t.form.fieldcolor; 212*b319d934SAlfonso S. Siciliano wattron(form->pad, color); 213*b319d934SAlfonso S. Siciliano mvwhline(form->pad, item->yfield, item->xfield, ' ', item->fieldcols); 214*b319d934SAlfonso S. Siciliano n = 0; 215*b319d934SAlfonso S. Siciliano cols = wcwidth(item->pubwbuf[item->xposdraw]); 216*b319d934SAlfonso S. Siciliano while (cols <= item->fieldcols && item->xposdraw + n < 217*b319d934SAlfonso S. Siciliano wcslen(item->pubwbuf)) { 218*b319d934SAlfonso S. Siciliano n++; 219*b319d934SAlfonso S. Siciliano cols += wcwidth(item->pubwbuf[item->xposdraw + n]); 220*b319d934SAlfonso S. Siciliano 221*b319d934SAlfonso S. Siciliano } 222*b319d934SAlfonso S. Siciliano mvwaddnwstr(form->pad, item->yfield, item->xfield, 223*b319d934SAlfonso S. Siciliano &item->pubwbuf[item->xposdraw], n); 224*b319d934SAlfonso S. Siciliano wattroff(form->pad, color); 225*b319d934SAlfonso S. Siciliano 226*b319d934SAlfonso S. Siciliano /* Bottom Desc */ 227*b319d934SAlfonso S. Siciliano move(SCREENLINES - 1, 2); 228*b319d934SAlfonso S. Siciliano clrtoeol(); 229*b319d934SAlfonso S. Siciliano if (item->bottomdesc != NULL && focus) { 230*b319d934SAlfonso S. Siciliano attron(t.form.bottomdesccolor); 231*b319d934SAlfonso S. Siciliano addstr(item->bottomdesc); 232*b319d934SAlfonso S. Siciliano attroff(t.form.bottomdesccolor); 233*b319d934SAlfonso S. Siciliano refresh(); 234*b319d934SAlfonso S. Siciliano } 235*b319d934SAlfonso S. Siciliano 236*b319d934SAlfonso S. Siciliano /* Cursor */ 237*b319d934SAlfonso S. Siciliano curs_set((focus && item->cursor) ? 1 : 0); 238*b319d934SAlfonso S. Siciliano wmove(form->pad, item->yfield, item->xfield + item->xcursor); 239*b319d934SAlfonso S. Siciliano 240*b319d934SAlfonso S. Siciliano prefresh(form->pad, form->y, 0, form->ys, form->xs, form->ye, form->xe); 241*b319d934SAlfonso S. Siciliano } 242*b319d934SAlfonso S. Siciliano 243*b319d934SAlfonso S. Siciliano /* 244*b319d934SAlfonso S. Siciliano * Trick: draw 2 times an item switching focus. 245*b319d934SAlfonso S. Siciliano * Problem: curses tries to optimize the rendering but sometimes it misses some 246*b319d934SAlfonso S. Siciliano * updates or draws old stuff. libformw has a similar problem fixed by the 247*b319d934SAlfonso S. Siciliano * same trick. 248*b319d934SAlfonso S. Siciliano * Case 1: KEY_DC and KEY_BACKSPACE, deleted multicolumn letters are drawn 249*b319d934SAlfonso S. Siciliano * again. It seems fixed by new items pad and prefresh(), previously WINDOW. 250*b319d934SAlfonso S. Siciliano * Case2: some terminal, tmux and ssh does not show the cursor. 251*b319d934SAlfonso S. Siciliano */ 252*b319d934SAlfonso S. Siciliano #define DRAWITEM_TRICK(form,item,focus) do { \ 253*b319d934SAlfonso S. Siciliano drawitem(form, item, !focus); \ 254*b319d934SAlfonso S. Siciliano drawitem(form, item, focus); \ 255*b319d934SAlfonso S. Siciliano } while (0) 256*b319d934SAlfonso S. Siciliano 257*b319d934SAlfonso S. Siciliano static bool 258*b319d934SAlfonso S. Siciliano insertch(struct privateform *form, struct privateitem *item, wchar_t wch) 259c76f0793SBaptiste Daroussin { 260f499134dSBaptiste Daroussin int i; 261f499134dSBaptiste Daroussin 262*b319d934SAlfonso S. Siciliano if (item->nletters >= item->maxletters) 263*b319d934SAlfonso S. Siciliano return (false); 264f499134dSBaptiste Daroussin 265*b319d934SAlfonso S. Siciliano for (i = (int)item->nletters - 1; i >= (int)item->pos; i--) { 266*b319d934SAlfonso S. Siciliano item->privwbuf[i+1] = item->privwbuf[i]; 267*b319d934SAlfonso S. Siciliano item->pubwbuf[i+1] = item->pubwbuf[i]; 268c76f0793SBaptiste Daroussin } 269c76f0793SBaptiste Daroussin 270*b319d934SAlfonso S. Siciliano item->privwbuf[item->pos] = wch; 271*b319d934SAlfonso S. Siciliano item->pubwbuf[item->pos] = item->secure ? form->securewch : wch; 272*b319d934SAlfonso S. Siciliano item->nletters += 1; 273*b319d934SAlfonso S. Siciliano item->privwbuf[item->nletters] = L'\0'; 274*b319d934SAlfonso S. Siciliano item->pubwbuf[item->nletters] = L'\0'; 275*b319d934SAlfonso S. Siciliano 276*b319d934SAlfonso S. Siciliano return (true); 277f499134dSBaptiste Daroussin } 278f499134dSBaptiste Daroussin 279*b319d934SAlfonso S. Siciliano static char* alloc_wstomb(wchar_t *wstr) 280f499134dSBaptiste Daroussin { 281*b319d934SAlfonso S. Siciliano int len, nbytes, i; 282*b319d934SAlfonso S. Siciliano char mbch[MB_LEN_MAX], *mbstr; 283f499134dSBaptiste Daroussin 284*b319d934SAlfonso S. Siciliano nbytes = MB_LEN_MAX; /* to ensure a null terminated string */ 285*b319d934SAlfonso S. Siciliano len = wcslen(wstr); 286*b319d934SAlfonso S. Siciliano for (i = 0; i < len; i++) { 287*b319d934SAlfonso S. Siciliano wctomb(mbch, wstr[i]); 288*b319d934SAlfonso S. Siciliano nbytes += mblen(mbch, MB_LEN_MAX); 289f499134dSBaptiste Daroussin } 290*b319d934SAlfonso S. Siciliano if((mbstr = malloc(nbytes)) == NULL) 291*b319d934SAlfonso S. Siciliano return (NULL); 292f499134dSBaptiste Daroussin 293*b319d934SAlfonso S. Siciliano wcstombs(mbstr, wstr, nbytes); 294c76f0793SBaptiste Daroussin 295*b319d934SAlfonso S. Siciliano return (mbstr); 296bce40c02SAlfonso S. Siciliano } 297bce40c02SAlfonso S. Siciliano 298bce40c02SAlfonso S. Siciliano static int 299263660c0SAlfonso Siciliano return_values(struct bsddialog_conf *conf, int output, int nitems, 300*b319d934SAlfonso S. Siciliano struct bsddialog_formitem *apiitems, struct privateitem *items) 301d93b4d32SBaptiste Daroussin { 302263660c0SAlfonso Siciliano int i; 303d93b4d32SBaptiste Daroussin 304263660c0SAlfonso Siciliano if (output != BSDDIALOG_OK && conf->form.value_without_ok == false) 305263660c0SAlfonso Siciliano return (output); 306d93b4d32SBaptiste Daroussin 307d93b4d32SBaptiste Daroussin for (i = 0; i < nitems; i++) { 308*b319d934SAlfonso S. Siciliano if (conf->form.value_wchar) { 309*b319d934SAlfonso S. Siciliano apiitems[i].value = (char*)wcsdup(items[i].privwbuf); 310bce40c02SAlfonso S. Siciliano } else { 311*b319d934SAlfonso S. Siciliano apiitems[i].value = alloc_wstomb(items[i].privwbuf); 312bce40c02SAlfonso S. Siciliano } 313*b319d934SAlfonso S. Siciliano if (apiitems[i].value == NULL) 314d93b4d32SBaptiste Daroussin RETURN_ERROR("Cannot allocate memory for form value"); 315d93b4d32SBaptiste Daroussin } 316d93b4d32SBaptiste Daroussin 317d93b4d32SBaptiste Daroussin return (output); 318d93b4d32SBaptiste Daroussin } 319d93b4d32SBaptiste Daroussin 320*b319d934SAlfonso S. Siciliano static unsigned int firstitem(unsigned int nitems, struct privateitem *items) 321c76f0793SBaptiste Daroussin { 322*b319d934SAlfonso S. Siciliano int i; 323c76f0793SBaptiste Daroussin 324*b319d934SAlfonso S. Siciliano for (i = 0; i < (int)nitems; i++) 325*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 326*b319d934SAlfonso S. Siciliano break; 327263660c0SAlfonso Siciliano 328*b319d934SAlfonso S. Siciliano return (i); 329*b319d934SAlfonso S. Siciliano } 330263660c0SAlfonso Siciliano 331*b319d934SAlfonso S. Siciliano static unsigned int lastitem(unsigned int nitems, struct privateitem *items) 332*b319d934SAlfonso S. Siciliano { 333*b319d934SAlfonso S. Siciliano int i; 334*b319d934SAlfonso S. Siciliano 335*b319d934SAlfonso S. Siciliano for (i = nitems - 1; i >= 0 ; i--) 336*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 337*b319d934SAlfonso S. Siciliano break; 338*b319d934SAlfonso S. Siciliano 339*b319d934SAlfonso S. Siciliano return (i); 340c76f0793SBaptiste Daroussin } 341*b319d934SAlfonso S. Siciliano 342*b319d934SAlfonso S. Siciliano static unsigned int 343*b319d934SAlfonso S. Siciliano previtem(unsigned int nitems, struct privateitem *items, int curritem) 344*b319d934SAlfonso S. Siciliano { 345*b319d934SAlfonso S. Siciliano int i; 346*b319d934SAlfonso S. Siciliano 347*b319d934SAlfonso S. Siciliano for (i = curritem - 1; i >= 0; i--) 348*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 349*b319d934SAlfonso S. Siciliano return(i); 350*b319d934SAlfonso S. Siciliano 351*b319d934SAlfonso S. Siciliano for (i = nitems - 1; i > curritem - 1; i--) 352*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 353*b319d934SAlfonso S. Siciliano return(i); 354*b319d934SAlfonso S. Siciliano 355*b319d934SAlfonso S. Siciliano return (curritem); 356263660c0SAlfonso Siciliano } 357*b319d934SAlfonso S. Siciliano 358*b319d934SAlfonso S. Siciliano static unsigned int 359*b319d934SAlfonso S. Siciliano nextitem(unsigned int nitems, struct privateitem *items, int curritem) 360*b319d934SAlfonso S. Siciliano { 361*b319d934SAlfonso S. Siciliano int i; 362*b319d934SAlfonso S. Siciliano 363*b319d934SAlfonso S. Siciliano for (i = curritem + 1; i < (int)nitems; i++) 364*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 365*b319d934SAlfonso S. Siciliano return(i); 366*b319d934SAlfonso S. Siciliano 367*b319d934SAlfonso S. Siciliano for (i = 0; i < curritem; i++) 368*b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 369*b319d934SAlfonso S. Siciliano return(i); 370*b319d934SAlfonso S. Siciliano 371*b319d934SAlfonso S. Siciliano return (curritem); 372c76f0793SBaptiste Daroussin } 373*b319d934SAlfonso S. Siciliano 374*b319d934SAlfonso S. Siciliano static void 375*b319d934SAlfonso S. Siciliano redrawbuttons(WINDOW *window, struct buttons *bs, bool focus, bool shortcut) 376*b319d934SAlfonso S. Siciliano { 377*b319d934SAlfonso S. Siciliano int selected; 378*b319d934SAlfonso S. Siciliano 379*b319d934SAlfonso S. Siciliano selected = bs->curr; 380*b319d934SAlfonso S. Siciliano if (focus == false) 381*b319d934SAlfonso S. Siciliano bs->curr = -1; 382*b319d934SAlfonso S. Siciliano draw_buttons(window, *bs, shortcut); 383*b319d934SAlfonso S. Siciliano wrefresh(window); 384*b319d934SAlfonso S. Siciliano bs->curr = selected; 385c76f0793SBaptiste Daroussin } 386*b319d934SAlfonso S. Siciliano 387*b319d934SAlfonso S. Siciliano static void 388*b319d934SAlfonso S. Siciliano update_formborders(struct bsddialog_conf *conf, struct privateform *form) 389*b319d934SAlfonso S. Siciliano { 390*b319d934SAlfonso S. Siciliano int h, w; 391*b319d934SAlfonso S. Siciliano 392*b319d934SAlfonso S. Siciliano getmaxyx(form->border, h, w); 393*b319d934SAlfonso S. Siciliano draw_borders(conf, form->border, h, w, LOWERED); 394*b319d934SAlfonso S. Siciliano 395*b319d934SAlfonso S. Siciliano if (form->viewrows < form->h) { 396*b319d934SAlfonso S. Siciliano wattron(form->border, t.dialog.arrowcolor); 397*b319d934SAlfonso S. Siciliano if (form->y > 0) 398*b319d934SAlfonso S. Siciliano mvwhline(form->border, 0, (w / 2) - 2, 399*b319d934SAlfonso S. Siciliano conf->ascii_lines ? '^' : ACS_UARROW, 5); 400*b319d934SAlfonso S. Siciliano 401*b319d934SAlfonso S. Siciliano if (form->y + form->viewrows < form->h) 402*b319d934SAlfonso S. Siciliano mvwhline(form->border, h-1, (w / 2) - 2, 403*b319d934SAlfonso S. Siciliano conf->ascii_lines ? 'v' : ACS_DARROW, 5); 404*b319d934SAlfonso S. Siciliano wattroff(form->border, t.dialog.arrowcolor); 405*b319d934SAlfonso S. Siciliano wrefresh(form->border); 406c76f0793SBaptiste Daroussin } 407c76f0793SBaptiste Daroussin } 408c76f0793SBaptiste Daroussin 409*b319d934SAlfonso S. Siciliano /* use menu autosizing, linelen = form.w, nitems = form.h */ 410f499134dSBaptiste Daroussin static int 411*b319d934SAlfonso S. Siciliano menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, 412*b319d934SAlfonso S. Siciliano const char *text, int linelen, unsigned int *menurows, int nitems, 413f499134dSBaptiste Daroussin struct buttons bs) 414f499134dSBaptiste Daroussin { 415*b319d934SAlfonso S. Siciliano int htext, wtext, menusize, notext; 416263660c0SAlfonso Siciliano 417*b319d934SAlfonso S. Siciliano notext = 2; 418*b319d934SAlfonso S. Siciliano if (*menurows == BSDDIALOG_AUTOSIZE) { 419*b319d934SAlfonso S. Siciliano /* algo 1): grows vertically */ 420*b319d934SAlfonso S. Siciliano /* notext = 1; */ 421*b319d934SAlfonso S. Siciliano /* algo 2): grows horizontally, better with little screens */ 422*b319d934SAlfonso S. Siciliano notext += nitems; 423*b319d934SAlfonso S. Siciliano notext = MIN(notext, widget_max_height(conf) - HBORDERS - 3); 424*b319d934SAlfonso S. Siciliano } else 425*b319d934SAlfonso S. Siciliano notext += *menurows; 426*b319d934SAlfonso S. Siciliano 427*b319d934SAlfonso S. Siciliano /* cols autosize, rows autosize, rows fullscreen, menu particularity */ 428*b319d934SAlfonso S. Siciliano if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) { 429*b319d934SAlfonso S. Siciliano if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, 430*b319d934SAlfonso S. Siciliano &htext, &wtext) != 0) 431263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 432263660c0SAlfonso Siciliano } 433263660c0SAlfonso Siciliano 434263660c0SAlfonso Siciliano if (cols == BSDDIALOG_AUTOSIZE) 435*b319d934SAlfonso S. Siciliano *w = widget_min_width(conf, wtext, linelen + 4, &bs); 436263660c0SAlfonso Siciliano 437263660c0SAlfonso Siciliano if (rows == BSDDIALOG_AUTOSIZE) { 438*b319d934SAlfonso S. Siciliano if (*menurows == 0) { 439263660c0SAlfonso Siciliano menusize = widget_max_height(conf) - HBORDERS - 440263660c0SAlfonso Siciliano 2 /*buttons*/ - htext; 441263660c0SAlfonso Siciliano menusize = MIN(menusize, nitems + 2); 442*b319d934SAlfonso S. Siciliano *menurows = menusize - 2 < 0 ? 0 : menusize - 2; 443263660c0SAlfonso Siciliano } 444*b319d934SAlfonso S. Siciliano else /* h autosize with fixed menurows */ 445*b319d934SAlfonso S. Siciliano menusize = *menurows + 2; 446263660c0SAlfonso Siciliano 447263660c0SAlfonso Siciliano *h = widget_min_height(conf, htext, menusize, true); 448*b319d934SAlfonso S. Siciliano /* 449*b319d934SAlfonso S. Siciliano * avoid menurows overflow and 450*b319d934SAlfonso S. Siciliano * with rows=AUTOSIZE menurows!=0 becomes max-menurows 451*b319d934SAlfonso S. Siciliano */ 452*b319d934SAlfonso S. Siciliano *menurows = MIN(*h - 6 - htext, (int)*menurows); 453263660c0SAlfonso Siciliano } else { 454*b319d934SAlfonso S. Siciliano if (*menurows == 0) { 455*b319d934SAlfonso S. Siciliano if (*h - 6 - htext <= 0) 456*b319d934SAlfonso S. Siciliano *menurows = 0; /* form_checksize() will check */ 457*b319d934SAlfonso S. Siciliano else 458*b319d934SAlfonso S. Siciliano *menurows = MIN(*h-6-htext, nitems); 459*b319d934SAlfonso S. Siciliano } 460263660c0SAlfonso Siciliano } 461263660c0SAlfonso Siciliano 462263660c0SAlfonso Siciliano return (0); 463263660c0SAlfonso Siciliano } 464263660c0SAlfonso Siciliano 465263660c0SAlfonso Siciliano static int 466*b319d934SAlfonso S. Siciliano form_checksize(int rows, int cols, const char *text, struct privateform *form, 467*b319d934SAlfonso S. Siciliano int nitems, struct buttons bs) 468263660c0SAlfonso Siciliano { 469*b319d934SAlfonso S. Siciliano int mincols, textrow, menusize; 470f499134dSBaptiste Daroussin 471*b319d934SAlfonso S. Siciliano /* cols */ 472f499134dSBaptiste Daroussin mincols = VBORDERS; 473*b319d934SAlfonso S. Siciliano mincols += buttons_min_width(bs); 474*b319d934SAlfonso S. Siciliano mincols = MAX(mincols, (int)form->w + 6); 475f499134dSBaptiste Daroussin 476f499134dSBaptiste Daroussin if (cols < mincols) 477*b319d934SAlfonso S. Siciliano RETURN_ERROR("Form width, cols < buttons or xlabels/xfields"); 478f499134dSBaptiste Daroussin 479*b319d934SAlfonso S. Siciliano /* rows */ 480*b319d934SAlfonso S. Siciliano if (nitems > 0 && form->viewrows == 0) 481*b319d934SAlfonso S. Siciliano RETURN_ERROR("items > 0 but viewrows == 0, if formheight = 0 " 482f499134dSBaptiste Daroussin "terminal too small"); 483f499134dSBaptiste Daroussin 484*b319d934SAlfonso S. Siciliano if (form->viewrows < form->minviewrows) 485*b319d934SAlfonso S. Siciliano RETURN_ERROR("Few formheight rows, if formheight = 0 terminal " 486*b319d934SAlfonso S. Siciliano "too small"); 487*b319d934SAlfonso S. Siciliano 488*b319d934SAlfonso S. Siciliano textrow = text != NULL && text[0] != '\0' ? 1 : 0; 489*b319d934SAlfonso S. Siciliano menusize = nitems > 0 ? 3 : 0; 490*b319d934SAlfonso S. Siciliano if (rows < 2 + 2 + menusize + textrow) 491*b319d934SAlfonso S. Siciliano RETURN_ERROR("Few lines for this form"); 492f499134dSBaptiste Daroussin 493263660c0SAlfonso Siciliano return (0); 494f499134dSBaptiste Daroussin } 495f499134dSBaptiste Daroussin 496*b319d934SAlfonso S. Siciliano static void curriteminview(struct privateform *form, struct privateitem *item) 497*b319d934SAlfonso S. Siciliano { 498*b319d934SAlfonso S. Siciliano unsigned int yup, ydown; 499*b319d934SAlfonso S. Siciliano 500*b319d934SAlfonso S. Siciliano yup = MIN(item->ylabel, item->yfield); 501*b319d934SAlfonso S. Siciliano ydown = MAX(item->ylabel, item->yfield); 502*b319d934SAlfonso S. Siciliano 503*b319d934SAlfonso S. Siciliano if (form->y > yup && form->y > 0) 504*b319d934SAlfonso S. Siciliano form->y = yup; 505*b319d934SAlfonso S. Siciliano if ((int)(form->y + form->viewrows) - 1 < (int)ydown) 506*b319d934SAlfonso S. Siciliano form->y = ydown - form->viewrows + 1; 507*b319d934SAlfonso S. Siciliano } 508*b319d934SAlfonso S. Siciliano 509*b319d934SAlfonso S. Siciliano /* API */ 510f499134dSBaptiste Daroussin int 511263660c0SAlfonso Siciliano bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows, 512263660c0SAlfonso Siciliano int cols, unsigned int formheight, unsigned int nitems, 513*b319d934SAlfonso S. Siciliano struct bsddialog_formitem *apiitems) 514f499134dSBaptiste Daroussin { 515*b319d934SAlfonso S. Siciliano bool switchfocus, changeitem, focusinform, insecurecursor, loop; 516*b319d934SAlfonso S. Siciliano int curritem, mbchsize, next, retval, y, x, h, w, wchtype; 517*b319d934SAlfonso S. Siciliano unsigned int i, j, itemybeg, itemxbeg, tmp; 518*b319d934SAlfonso S. Siciliano wchar_t *winit; 519*b319d934SAlfonso S. Siciliano wint_t input; 520*b319d934SAlfonso S. Siciliano WINDOW *widget, *textpad, *shadow; 521*b319d934SAlfonso S. Siciliano struct privateitem *items, *item; 522c76f0793SBaptiste Daroussin struct buttons bs; 523*b319d934SAlfonso S. Siciliano struct privateform form; 524c76f0793SBaptiste Daroussin 525*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 526*b319d934SAlfonso S. Siciliano if (apiitems[i].maxvaluelen == 0) 527d93b4d32SBaptiste Daroussin RETURN_ERROR("maxvaluelen cannot be zero"); 528*b319d934SAlfonso S. Siciliano if (apiitems[i].fieldlen == 0) 529d93b4d32SBaptiste Daroussin RETURN_ERROR("fieldlen cannot be zero"); 530d93b4d32SBaptiste Daroussin } 531d93b4d32SBaptiste Daroussin 532*b319d934SAlfonso S. Siciliano insecurecursor = false; 533*b319d934SAlfonso S. Siciliano if (conf->form.securembch != NULL) { 534*b319d934SAlfonso S. Siciliano mbchsize = mblen(conf->form.securembch, MB_LEN_MAX); 535*b319d934SAlfonso S. Siciliano if(mbtowc(&form.securewch, conf->form.securembch, mbchsize) < 0) 536*b319d934SAlfonso S. Siciliano RETURN_ERROR("Cannot convert securembch to wchar_t"); 537*b319d934SAlfonso S. Siciliano insecurecursor = true; 538*b319d934SAlfonso S. Siciliano } else if (conf->form.securech != '\0') { 539*b319d934SAlfonso S. Siciliano form.securewch = btowc(conf->form.securech); 540*b319d934SAlfonso S. Siciliano insecurecursor = true; 541f499134dSBaptiste Daroussin } else { 542*b319d934SAlfonso S. Siciliano form.securewch = L' '; 543f499134dSBaptiste Daroussin } 544f499134dSBaptiste Daroussin 545*b319d934SAlfonso S. Siciliano if ((items = malloc(nitems * sizeof(struct privateitem))) == NULL) 546*b319d934SAlfonso S. Siciliano RETURN_ERROR("Cannot allocate internal items"); 547*b319d934SAlfonso S. Siciliano form.h = form.w = form.minviewrows = 0; 548*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 549*b319d934SAlfonso S. Siciliano item = &items[i]; 550*b319d934SAlfonso S. Siciliano item->label = apiitems[i].label; 551*b319d934SAlfonso S. Siciliano item->ylabel = apiitems[i].ylabel; 552*b319d934SAlfonso S. Siciliano item->xlabel = apiitems[i].xlabel; 553*b319d934SAlfonso S. Siciliano item->yfield = apiitems[i].yfield; 554*b319d934SAlfonso S. Siciliano item->xfield = apiitems[i].xfield; 555*b319d934SAlfonso S. Siciliano item->secure = apiitems[i].flags & BSDDIALOG_FIELDHIDDEN; 556*b319d934SAlfonso S. Siciliano item->readonly = apiitems[i].flags & BSDDIALOG_FIELDREADONLY; 557*b319d934SAlfonso S. Siciliano item->fieldnocolor = apiitems[i].flags & BSDDIALOG_FIELDNOCOLOR; 558*b319d934SAlfonso S. Siciliano item->extendfield = apiitems[i].flags & BSDDIALOG_FIELDEXTEND; 559*b319d934SAlfonso S. Siciliano item->fieldonebyte = apiitems[i].flags & 560*b319d934SAlfonso S. Siciliano BSDDIALOG_FIELDSINGLEBYTE; 561*b319d934SAlfonso S. Siciliano item->cursorend = apiitems[i].flags & BSDDIALOG_FIELDCURSOREND; 562*b319d934SAlfonso S. Siciliano item->bottomdesc = apiitems[i].bottomdesc; 563*b319d934SAlfonso S. Siciliano if (item->readonly || (item->secure && !insecurecursor)) 564*b319d934SAlfonso S. Siciliano item->cursor = false; 565*b319d934SAlfonso S. Siciliano else 566*b319d934SAlfonso S. Siciliano item->cursor = true; 567*b319d934SAlfonso S. Siciliano 568*b319d934SAlfonso S. Siciliano item->maxletters = apiitems[i].maxvaluelen; 569*b319d934SAlfonso S. Siciliano item->privwbuf = calloc(item->maxletters + 1, sizeof(wchar_t)); 570*b319d934SAlfonso S. Siciliano if (item->privwbuf == NULL) 571*b319d934SAlfonso S. Siciliano RETURN_ERROR("Cannot allocate item private buffer"); 572*b319d934SAlfonso S. Siciliano memset(item->privwbuf, 0, item->maxletters + 1); 573*b319d934SAlfonso S. Siciliano item->pubwbuf = calloc(item->maxletters + 1, sizeof(wchar_t)); 574*b319d934SAlfonso S. Siciliano if (item->pubwbuf == NULL) 575*b319d934SAlfonso S. Siciliano RETURN_ERROR("Cannot allocate item private buffer"); 576*b319d934SAlfonso S. Siciliano memset(item->pubwbuf, 0, item->maxletters + 1); 577*b319d934SAlfonso S. Siciliano 578*b319d934SAlfonso S. Siciliano if ((winit = alloc_mbstows(apiitems[i].init)) == NULL) 579*b319d934SAlfonso S. Siciliano RETURN_ERROR("Cannot allocate item.init in wchar_t*"); 580*b319d934SAlfonso S. Siciliano wcsncpy(item->privwbuf, winit, item->maxletters); 581*b319d934SAlfonso S. Siciliano wcsncpy(item->pubwbuf, winit, item->maxletters); 582*b319d934SAlfonso S. Siciliano free(winit); 583*b319d934SAlfonso S. Siciliano item->nletters = wcslen(item->pubwbuf); 584*b319d934SAlfonso S. Siciliano if (item->secure) { 585*b319d934SAlfonso S. Siciliano for (j = 0; j < item->nletters; j++) 586*b319d934SAlfonso S. Siciliano item->pubwbuf[j] = form.securewch; 587f499134dSBaptiste Daroussin } 588f499134dSBaptiste Daroussin 589*b319d934SAlfonso S. Siciliano item->fieldcols = apiitems[i].fieldlen; 590*b319d934SAlfonso S. Siciliano item->xposdraw = 0; 591*b319d934SAlfonso S. Siciliano item->xcursor = 0; 592*b319d934SAlfonso S. Siciliano item->pos = 0; 593*b319d934SAlfonso S. Siciliano 594*b319d934SAlfonso S. Siciliano form.h = MAX(form.h, items[i].ylabel); 595*b319d934SAlfonso S. Siciliano form.h = MAX(form.h, items[i].yfield); 596*b319d934SAlfonso S. Siciliano form.w = MAX(form.w, items[i].xlabel + strcols(items[i].label)); 597*b319d934SAlfonso S. Siciliano form.w = MAX(form.w, items[i].xfield + items[i].fieldcols); 598*b319d934SAlfonso S. Siciliano if (i == 0) { 599*b319d934SAlfonso S. Siciliano itemybeg = MIN(items[i].ylabel, items[i].yfield); 600*b319d934SAlfonso S. Siciliano itemxbeg = MIN(items[i].xlabel, items[i].xfield); 601*b319d934SAlfonso S. Siciliano } else { 602*b319d934SAlfonso S. Siciliano tmp = MIN(items[i].ylabel, items[i].yfield); 603*b319d934SAlfonso S. Siciliano itemybeg = MIN(itemybeg, tmp); 604*b319d934SAlfonso S. Siciliano tmp = MIN(items[i].xlabel, items[i].xfield); 605*b319d934SAlfonso S. Siciliano itemxbeg = MIN(itemxbeg, tmp); 606*b319d934SAlfonso S. Siciliano } 607*b319d934SAlfonso S. Siciliano tmp = abs((int)items[i].ylabel - (int)items[i].yfield); 608*b319d934SAlfonso S. Siciliano form.minviewrows = MAX(form.minviewrows, tmp); 609*b319d934SAlfonso S. Siciliano } 610*b319d934SAlfonso S. Siciliano if (nitems > 0) { 611*b319d934SAlfonso S. Siciliano form.h = form.h + 1 - itemybeg; 612*b319d934SAlfonso S. Siciliano form.w -= itemxbeg; 613*b319d934SAlfonso S. Siciliano form.minviewrows += 1; 614*b319d934SAlfonso S. Siciliano } 615*b319d934SAlfonso S. Siciliano form.wmin = form.w; 616*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 617*b319d934SAlfonso S. Siciliano items[i].ylabel -= itemybeg; 618*b319d934SAlfonso S. Siciliano items[i].yfield -= itemybeg; 619*b319d934SAlfonso S. Siciliano items[i].xlabel -= itemxbeg; 620*b319d934SAlfonso S. Siciliano items[i].xfield -= itemxbeg; 621f499134dSBaptiste Daroussin } 622c76f0793SBaptiste Daroussin 623263660c0SAlfonso Siciliano get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); 624*b319d934SAlfonso S. Siciliano form.viewrows = formheight; 625c76f0793SBaptiste Daroussin 626f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 627263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 628*b319d934SAlfonso S. Siciliano if (menu_autosize(conf, rows, cols, &h, &w, text, form.w, 629*b319d934SAlfonso S. Siciliano &form.viewrows, form.h, bs) != 0) 630263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 631*b319d934SAlfonso S. Siciliano if (form_checksize(h, w, text, &form, nitems, bs) != 0) 632263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 633f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 634263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 635c76f0793SBaptiste Daroussin 636263660c0SAlfonso Siciliano if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, 637263660c0SAlfonso Siciliano true) != 0) 638263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 639c76f0793SBaptiste Daroussin 640*b319d934SAlfonso S. Siciliano doupdate(); 641*b319d934SAlfonso S. Siciliano 642263660c0SAlfonso Siciliano prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, 643*b319d934SAlfonso S. Siciliano y + h - form.viewrows, x + 1 + w - TEXTHMARGIN); 644c76f0793SBaptiste Daroussin 645*b319d934SAlfonso S. Siciliano form.border = new_boxed_window(conf, y + h - 5 - form.viewrows, x + 2, 646*b319d934SAlfonso S. Siciliano form.viewrows + 2, w - 4, LOWERED); 647c76f0793SBaptiste Daroussin 648*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 649*b319d934SAlfonso S. Siciliano if (items[i].extendfield) { 650*b319d934SAlfonso S. Siciliano form.w = w - 6; 651*b319d934SAlfonso S. Siciliano items[i].fieldcols = form.w - items[i].xfield; 652*b319d934SAlfonso S. Siciliano } 653*b319d934SAlfonso S. Siciliano if (items[i].cursorend) 654*b319d934SAlfonso S. Siciliano fieldctl(item, MOVE_CURSOR_END); 655*b319d934SAlfonso S. Siciliano } 656c76f0793SBaptiste Daroussin 657*b319d934SAlfonso S. Siciliano form.pad = newpad(form.h, form.w); 658*b319d934SAlfonso S. Siciliano wbkgd(form.pad, t.dialog.color); 659c76f0793SBaptiste Daroussin 660*b319d934SAlfonso S. Siciliano form.ys = y + h - 5 - form.viewrows + 1; 661*b319d934SAlfonso S. Siciliano form.ye = y + h - 5 ; 662*b319d934SAlfonso S. Siciliano if ((int)form.w >= w - 6) { /* left */ 663*b319d934SAlfonso S. Siciliano form.xs = x + 3; 664*b319d934SAlfonso S. Siciliano form.xe = form.xs + w - 7; 665*b319d934SAlfonso S. Siciliano } else { /* center */ 666*b319d934SAlfonso S. Siciliano form.xs = x + 3 + (w-6)/2 - form.w/2; 667*b319d934SAlfonso S. Siciliano form.xe = form.xs + w - 5; 668*b319d934SAlfonso S. Siciliano } 669c76f0793SBaptiste Daroussin 670*b319d934SAlfonso S. Siciliano curritem = -1; 671*b319d934SAlfonso S. Siciliano for (i=0 ; i < nitems; i++) { 672*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, &items[i], false); 673*b319d934SAlfonso S. Siciliano if (curritem == -1 && items[i].readonly == false) 674*b319d934SAlfonso S. Siciliano curritem = i; 675*b319d934SAlfonso S. Siciliano } 676*b319d934SAlfonso S. Siciliano if (curritem != -1) { 677*b319d934SAlfonso S. Siciliano focusinform = true; 678*b319d934SAlfonso S. Siciliano redrawbuttons(widget, &bs, conf->button.always_active, false); 679*b319d934SAlfonso S. Siciliano form.y = 0; 680*b319d934SAlfonso S. Siciliano item = &items[curritem]; 681*b319d934SAlfonso S. Siciliano curriteminview(&form, item); 682*b319d934SAlfonso S. Siciliano update_formborders(conf, &form); 683*b319d934SAlfonso S. Siciliano wrefresh(form.border); 684*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 685*b319d934SAlfonso S. Siciliano } else { 686*b319d934SAlfonso S. Siciliano item = NULL; 687*b319d934SAlfonso S. Siciliano focusinform = false; 688*b319d934SAlfonso S. Siciliano wrefresh(form.border); 689*b319d934SAlfonso S. Siciliano } 690f499134dSBaptiste Daroussin 691*b319d934SAlfonso S. Siciliano changeitem = switchfocus = false; 692*b319d934SAlfonso S. Siciliano loop = true; 693*b319d934SAlfonso S. Siciliano while (loop) { 694*b319d934SAlfonso S. Siciliano if ((wchtype = get_wch(&input)) == ERR) 695*b319d934SAlfonso S. Siciliano continue; 696*b319d934SAlfonso S. Siciliano switch(input) { 697*b319d934SAlfonso S. Siciliano case KEY_ENTER: 698*b319d934SAlfonso S. Siciliano case 10: /* Enter */ 699*b319d934SAlfonso S. Siciliano if (focusinform && conf->button.always_active == false) 700*b319d934SAlfonso S. Siciliano break; 701*b319d934SAlfonso S. Siciliano retval = return_values(conf, bs.value[bs.curr], 702*b319d934SAlfonso S. Siciliano nitems, apiitems, items); 703*b319d934SAlfonso S. Siciliano loop = false; 704*b319d934SAlfonso S. Siciliano break; 705*b319d934SAlfonso S. Siciliano case 27: /* Esc */ 706*b319d934SAlfonso S. Siciliano if (conf->key.enable_esc) { 707*b319d934SAlfonso S. Siciliano retval = return_values(conf, BSDDIALOG_ESC, 708*b319d934SAlfonso S. Siciliano nitems, apiitems, items); 709*b319d934SAlfonso S. Siciliano loop = false; 710*b319d934SAlfonso S. Siciliano } 711*b319d934SAlfonso S. Siciliano break; 712*b319d934SAlfonso S. Siciliano case '\t': /* TAB */ 713*b319d934SAlfonso S. Siciliano if (focusinform) { 714*b319d934SAlfonso S. Siciliano switchfocus = true; 715*b319d934SAlfonso S. Siciliano } else { 716*b319d934SAlfonso S. Siciliano if (bs.curr + 1 < (int)bs.nbuttons) { 717*b319d934SAlfonso S. Siciliano bs.curr++; 718*b319d934SAlfonso S. Siciliano } else { 719*b319d934SAlfonso S. Siciliano bs.curr = 0; 720*b319d934SAlfonso S. Siciliano if (curritem != -1) { 721*b319d934SAlfonso S. Siciliano switchfocus = true; 722*b319d934SAlfonso S. Siciliano } 723*b319d934SAlfonso S. Siciliano } 724*b319d934SAlfonso S. Siciliano draw_buttons(widget, bs, true); 725*b319d934SAlfonso S. Siciliano wrefresh(widget); 726*b319d934SAlfonso S. Siciliano } 727*b319d934SAlfonso S. Siciliano break; 728*b319d934SAlfonso S. Siciliano case KEY_LEFT: 729*b319d934SAlfonso S. Siciliano if (focusinform) { 730*b319d934SAlfonso S. Siciliano if(fieldctl(item, MOVE_CURSOR_LEFT)) 731*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 732*b319d934SAlfonso S. Siciliano } else if (bs.curr > 0) { 733*b319d934SAlfonso S. Siciliano bs.curr--; 734*b319d934SAlfonso S. Siciliano draw_buttons(widget, bs, true); 735*b319d934SAlfonso S. Siciliano wrefresh(widget); 736*b319d934SAlfonso S. Siciliano } else if (curritem != -1) { 737*b319d934SAlfonso S. Siciliano switchfocus = true; 738*b319d934SAlfonso S. Siciliano } 739*b319d934SAlfonso S. Siciliano break; 740*b319d934SAlfonso S. Siciliano case KEY_RIGHT: 741*b319d934SAlfonso S. Siciliano if (focusinform) { 742*b319d934SAlfonso S. Siciliano if(fieldctl(item, MOVE_CURSOR_RIGHT)) 743*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 744*b319d934SAlfonso S. Siciliano } else if (bs.curr < (int) bs.nbuttons - 1) { 745*b319d934SAlfonso S. Siciliano bs.curr++; 746*b319d934SAlfonso S. Siciliano draw_buttons(widget, bs, true); 747*b319d934SAlfonso S. Siciliano wrefresh(widget); 748*b319d934SAlfonso S. Siciliano } else if (curritem != -1) { 749*b319d934SAlfonso S. Siciliano switchfocus = true; 750*b319d934SAlfonso S. Siciliano } 751*b319d934SAlfonso S. Siciliano break; 752*b319d934SAlfonso S. Siciliano case KEY_UP: 753*b319d934SAlfonso S. Siciliano if (focusinform) { 754*b319d934SAlfonso S. Siciliano next = previtem(nitems, items, curritem); 755*b319d934SAlfonso S. Siciliano changeitem = curritem != next; 756*b319d934SAlfonso S. Siciliano } else if (curritem != -1) { 757*b319d934SAlfonso S. Siciliano switchfocus = true; 758*b319d934SAlfonso S. Siciliano } 759*b319d934SAlfonso S. Siciliano break; 760*b319d934SAlfonso S. Siciliano case KEY_DOWN: 761*b319d934SAlfonso S. Siciliano if (focusinform == false) 762*b319d934SAlfonso S. Siciliano break; 763*b319d934SAlfonso S. Siciliano if (nitems == 1) { 764*b319d934SAlfonso S. Siciliano switchfocus = true; 765*b319d934SAlfonso S. Siciliano } else { 766*b319d934SAlfonso S. Siciliano next = nextitem(nitems, items, curritem); 767*b319d934SAlfonso S. Siciliano changeitem = curritem != next; 768*b319d934SAlfonso S. Siciliano } 769*b319d934SAlfonso S. Siciliano break; 770*b319d934SAlfonso S. Siciliano case KEY_PPAGE: 771*b319d934SAlfonso S. Siciliano if (focusinform) { 772*b319d934SAlfonso S. Siciliano next = firstitem(nitems, items); 773*b319d934SAlfonso S. Siciliano changeitem = curritem != next; 774*b319d934SAlfonso S. Siciliano } 775*b319d934SAlfonso S. Siciliano break; 776*b319d934SAlfonso S. Siciliano case KEY_NPAGE: 777*b319d934SAlfonso S. Siciliano if (focusinform) { 778*b319d934SAlfonso S. Siciliano next = lastitem(nitems, items); 779*b319d934SAlfonso S. Siciliano changeitem = curritem != next; 780*b319d934SAlfonso S. Siciliano } 781*b319d934SAlfonso S. Siciliano break; 782*b319d934SAlfonso S. Siciliano case KEY_BACKSPACE: 783*b319d934SAlfonso S. Siciliano case 127: /* Backspace */ 784*b319d934SAlfonso S. Siciliano if (focusinform == false) 785*b319d934SAlfonso S. Siciliano break; 786*b319d934SAlfonso S. Siciliano if(fieldctl(item, MOVE_CURSOR_LEFT)) 787*b319d934SAlfonso S. Siciliano if(fieldctl(item, DEL_LETTER)) 788*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 789*b319d934SAlfonso S. Siciliano break; 790*b319d934SAlfonso S. Siciliano case KEY_DC: 791*b319d934SAlfonso S. Siciliano if (focusinform == false) 792*b319d934SAlfonso S. Siciliano break; 793*b319d934SAlfonso S. Siciliano if(fieldctl(item, DEL_LETTER)) 794*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 795*b319d934SAlfonso S. Siciliano break; 796*b319d934SAlfonso S. Siciliano case KEY_HOME: 797*b319d934SAlfonso S. Siciliano if (focusinform == false) 798*b319d934SAlfonso S. Siciliano break; 799*b319d934SAlfonso S. Siciliano if(fieldctl(item, MOVE_CURSOR_BEGIN)) 800*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 801*b319d934SAlfonso S. Siciliano break; 802*b319d934SAlfonso S. Siciliano case KEY_END: 803*b319d934SAlfonso S. Siciliano if (focusinform == false) 804*b319d934SAlfonso S. Siciliano break; 805*b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_END)) 806*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 807*b319d934SAlfonso S. Siciliano break; 808*b319d934SAlfonso S. Siciliano case KEY_F(1): 809*b319d934SAlfonso S. Siciliano if (conf->key.f1_file == NULL && 810*b319d934SAlfonso S. Siciliano conf->key.f1_message == NULL) 811*b319d934SAlfonso S. Siciliano break; 812*b319d934SAlfonso S. Siciliano curs_set(0); 813*b319d934SAlfonso S. Siciliano if (f1help(conf) != 0) { 814*b319d934SAlfonso S. Siciliano retval = BSDDIALOG_ERROR; 815*b319d934SAlfonso S. Siciliano loop = false; 816*b319d934SAlfonso S. Siciliano } 817*b319d934SAlfonso S. Siciliano /* No break, screen size can change */ 818*b319d934SAlfonso S. Siciliano case KEY_RESIZE: 819*b319d934SAlfonso S. Siciliano /* Important for decreasing screen */ 820*b319d934SAlfonso S. Siciliano hide_widget(y, x, h, w, conf->shadow); 821*b319d934SAlfonso S. Siciliano refresh(); 822*b319d934SAlfonso S. Siciliano 823*b319d934SAlfonso S. Siciliano form.viewrows = formheight; 824*b319d934SAlfonso S. Siciliano form.w = form.wmin; 825*b319d934SAlfonso S. Siciliano if (set_widget_size(conf, rows, cols, &h, &w) != 0) 826*b319d934SAlfonso S. Siciliano return (BSDDIALOG_ERROR); 827*b319d934SAlfonso S. Siciliano if (menu_autosize(conf, rows, cols, &h, &w, text, form.w, 828*b319d934SAlfonso S. Siciliano &form.viewrows, form.h, bs) != 0) 829*b319d934SAlfonso S. Siciliano return (BSDDIALOG_ERROR); 830*b319d934SAlfonso S. Siciliano if (form_checksize(h, w, text, &form, nitems, bs) != 0) 831*b319d934SAlfonso S. Siciliano return (BSDDIALOG_ERROR); 832*b319d934SAlfonso S. Siciliano if (set_widget_position(conf, &y, &x, h, w) != 0) 833*b319d934SAlfonso S. Siciliano return (BSDDIALOG_ERROR); 834*b319d934SAlfonso S. Siciliano 835*b319d934SAlfonso S. Siciliano if (update_dialog(conf, shadow, widget, y, x, h, w, 836*b319d934SAlfonso S. Siciliano textpad, text, &bs, true) != 0) 837263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 838f499134dSBaptiste Daroussin 839263660c0SAlfonso Siciliano doupdate(); 840f499134dSBaptiste Daroussin 841263660c0SAlfonso Siciliano prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, 842*b319d934SAlfonso S. Siciliano y + h - form.viewrows, x + 1 + w - TEXTHMARGIN); 843f499134dSBaptiste Daroussin 844*b319d934SAlfonso S. Siciliano wclear(form.border); 845*b319d934SAlfonso S. Siciliano mvwin(form.border, y + h - 5 - form.viewrows, x + 2); 846*b319d934SAlfonso S. Siciliano wresize(form.border, form.viewrows + 2, w - 4); 847263660c0SAlfonso Siciliano 848*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 849*b319d934SAlfonso S. Siciliano fieldctl(&items[i], MOVE_CURSOR_BEGIN); 850*b319d934SAlfonso S. Siciliano if (items[i].extendfield) { 851*b319d934SAlfonso S. Siciliano form.w = w - 6; 852*b319d934SAlfonso S. Siciliano items[i].fieldcols = 853*b319d934SAlfonso S. Siciliano form.w - items[i].xfield; 854f499134dSBaptiste Daroussin } 855*b319d934SAlfonso S. Siciliano if (items[i].cursorend) 856*b319d934SAlfonso S. Siciliano fieldctl(&items[i], MOVE_CURSOR_END); 857*b319d934SAlfonso S. Siciliano } 858c76f0793SBaptiste Daroussin 859*b319d934SAlfonso S. Siciliano form.ys = y + h - 5 - form.viewrows + 1; 860*b319d934SAlfonso S. Siciliano form.ye = y + h - 5 ; 861*b319d934SAlfonso S. Siciliano if ((int)form.w >= w - 6) { /* left */ 862*b319d934SAlfonso S. Siciliano form.xs = x + 3; 863*b319d934SAlfonso S. Siciliano form.xe = form.xs + w - 7; 864*b319d934SAlfonso S. Siciliano } else { /* center */ 865*b319d934SAlfonso S. Siciliano form.xs = x + 3 + (w-6)/2 - form.w/2; 866*b319d934SAlfonso S. Siciliano form.xe = form.xs + w - 5; 867*b319d934SAlfonso S. Siciliano } 868*b319d934SAlfonso S. Siciliano 869*b319d934SAlfonso S. Siciliano if (curritem != -1) { 870*b319d934SAlfonso S. Siciliano redrawbuttons(widget, &bs, 871*b319d934SAlfonso S. Siciliano conf->button.always_active || !focusinform, 872*b319d934SAlfonso S. Siciliano !focusinform); 873*b319d934SAlfonso S. Siciliano curriteminview(&form, item); 874*b319d934SAlfonso S. Siciliano update_formborders(conf, &form); 875*b319d934SAlfonso S. Siciliano wrefresh(form.border); 876*b319d934SAlfonso S. Siciliano /* drawitem just to prefresh() pad */ 877*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, focusinform); 878*b319d934SAlfonso S. Siciliano } else { 879*b319d934SAlfonso S. Siciliano wrefresh(form.border); 880*b319d934SAlfonso S. Siciliano } 881*b319d934SAlfonso S. Siciliano break; 882*b319d934SAlfonso S. Siciliano default: 883*b319d934SAlfonso S. Siciliano if (wchtype == KEY_CODE_YES) 884*b319d934SAlfonso S. Siciliano break; 885*b319d934SAlfonso S. Siciliano if (focusinform) { 886*b319d934SAlfonso S. Siciliano if (item->fieldonebyte && wctob(input) == EOF) 887*b319d934SAlfonso S. Siciliano break; 888*b319d934SAlfonso S. Siciliano /* 889*b319d934SAlfonso S. Siciliano * MOVE_CURSOR_RIGHT manages new positions 890*b319d934SAlfonso S. Siciliano * because the cursor remains on the new letter, 891*b319d934SAlfonso S. Siciliano * "if" and "while" update the positions. 892*b319d934SAlfonso S. Siciliano */ 893*b319d934SAlfonso S. Siciliano if(insertch(&form, item, input)) { 894*b319d934SAlfonso S. Siciliano fieldctl(item, MOVE_CURSOR_RIGHT); 895*b319d934SAlfonso S. Siciliano /* 896*b319d934SAlfonso S. Siciliano * no if(fieldctl), update always 897*b319d934SAlfonso S. Siciliano * because it fails with maxletters. 898*b319d934SAlfonso S. Siciliano */ 899*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 900*b319d934SAlfonso S. Siciliano } 901*b319d934SAlfonso S. Siciliano } else { 902*b319d934SAlfonso S. Siciliano if (shortcut_buttons(input, &bs)) { 903*b319d934SAlfonso S. Siciliano retval = return_values(conf, 904*b319d934SAlfonso S. Siciliano bs.value[bs.curr], nitems, apiitems, 905*b319d934SAlfonso S. Siciliano items); 906*b319d934SAlfonso S. Siciliano loop = false; 907*b319d934SAlfonso S. Siciliano } 908*b319d934SAlfonso S. Siciliano } 909*b319d934SAlfonso S. Siciliano break; 910*b319d934SAlfonso S. Siciliano } /* end switch handler */ 911*b319d934SAlfonso S. Siciliano 912*b319d934SAlfonso S. Siciliano if (switchfocus) { 913*b319d934SAlfonso S. Siciliano focusinform = !focusinform; 914*b319d934SAlfonso S. Siciliano bs.curr = 0; 915*b319d934SAlfonso S. Siciliano redrawbuttons(widget, &bs, 916*b319d934SAlfonso S. Siciliano conf->button.always_active || !focusinform, 917*b319d934SAlfonso S. Siciliano !focusinform); 918*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, focusinform); 919*b319d934SAlfonso S. Siciliano switchfocus = false; 920*b319d934SAlfonso S. Siciliano } 921*b319d934SAlfonso S. Siciliano 922*b319d934SAlfonso S. Siciliano if (changeitem) { 923*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, false); 924*b319d934SAlfonso S. Siciliano curritem = next; 925*b319d934SAlfonso S. Siciliano item = &items[curritem]; 926*b319d934SAlfonso S. Siciliano curriteminview(&form, item); 927*b319d934SAlfonso S. Siciliano update_formborders(conf, &form); 928*b319d934SAlfonso S. Siciliano DRAWITEM_TRICK(&form, item, true); 929*b319d934SAlfonso S. Siciliano changeitem = false; 930*b319d934SAlfonso S. Siciliano } 931*b319d934SAlfonso S. Siciliano } /* end while handler */ 932*b319d934SAlfonso S. Siciliano 933*b319d934SAlfonso S. Siciliano curs_set(0); 934*b319d934SAlfonso S. Siciliano 935*b319d934SAlfonso S. Siciliano delwin(form.pad); 936*b319d934SAlfonso S. Siciliano delwin(form.border); 937*b319d934SAlfonso S. Siciliano for (i = 0; i < nitems; i++) { 938*b319d934SAlfonso S. Siciliano free(items[i].privwbuf); 939*b319d934SAlfonso S. Siciliano free(items[i].pubwbuf); 940*b319d934SAlfonso S. Siciliano } 941263660c0SAlfonso Siciliano end_dialog(conf, shadow, widget, textpad); 942c76f0793SBaptiste Daroussin 943*b319d934SAlfonso S. Siciliano return (retval); 944c76f0793SBaptiste Daroussin } 945