1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4*a6d8be45SAlfonso S. Siciliano * Copyright (c) 2021-2024 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 28b319d934SAlfonso S. Siciliano #include <curses.h> 29b319d934SAlfonso S. Siciliano #include <limits.h> 30d93b4d32SBaptiste Daroussin #include <stdlib.h> 31d93b4d32SBaptiste Daroussin #include <string.h> 32c76f0793SBaptiste Daroussin 33c76f0793SBaptiste Daroussin #include "bsddialog.h" 34c76f0793SBaptiste Daroussin #include "bsddialog_theme.h" 35263660c0SAlfonso Siciliano #include "lib_util.h" 36c76f0793SBaptiste Daroussin 3761ba55bcSBaptiste Daroussin enum field_action { 3861ba55bcSBaptiste Daroussin MOVE_CURSOR_BEGIN, 3961ba55bcSBaptiste Daroussin MOVE_CURSOR_END, 4061ba55bcSBaptiste Daroussin MOVE_CURSOR_RIGHT, 4161ba55bcSBaptiste Daroussin MOVE_CURSOR_LEFT, 4261ba55bcSBaptiste Daroussin DEL_LETTER 4361ba55bcSBaptiste Daroussin }; 4461ba55bcSBaptiste Daroussin 45b319d934SAlfonso S. Siciliano struct privateitem { 46b319d934SAlfonso S. Siciliano const char *label; /* formitem.label */ 47b319d934SAlfonso S. Siciliano unsigned int ylabel; /* formitem.ylabel */ 48b319d934SAlfonso S. Siciliano unsigned int xlabel; /* formitem.xlabel */ 49b319d934SAlfonso S. Siciliano unsigned int yfield; /* formitem.yfield */ 50b319d934SAlfonso S. Siciliano unsigned int xfield; /* formitem.xfield */ 51b319d934SAlfonso S. Siciliano bool secure; /* formitem.flags & BSDDIALOG_FIELDHIDDEN */ 52b319d934SAlfonso S. Siciliano bool readonly; /* formitem.flags & BSDDIALOG_FIELDREADONLY */ 53b319d934SAlfonso S. Siciliano bool fieldnocolor; /* formitem.flags & BSDDIALOG_FIELDNOCOLOR */ 54b319d934SAlfonso S. Siciliano bool extendfield; /* formitem.flags & BSDDIALOG_FIELDEXTEND */ 55b319d934SAlfonso S. Siciliano bool fieldonebyte; /* formitem.flags & BSDDIALOG_FIELDSINGLEBYTE */ 56b319d934SAlfonso S. Siciliano bool cursorend; /* formitem.flags & BSDDIALOG_FIELDCURSOREND */ 57b319d934SAlfonso S. Siciliano bool cursor; /* field cursor visibility */ 58b319d934SAlfonso S. Siciliano const char *bottomdesc; /* formitem.bottomdesc */ 59c76f0793SBaptiste Daroussin 60b319d934SAlfonso S. Siciliano wchar_t *privwbuf; /* formitem.value */ 61b319d934SAlfonso S. Siciliano wchar_t *pubwbuf; /* string for drawitem() */ 62b319d934SAlfonso S. Siciliano unsigned int maxletters; /* formitem.maxvaluelen, [priv|pub]wbuf size */ 63b319d934SAlfonso S. Siciliano unsigned int nletters; /* letters in privwbuf and pubwbuf */ 64b319d934SAlfonso S. Siciliano unsigned int pos; /* pos in privwbuf and pubwbuf */ 65b319d934SAlfonso S. Siciliano unsigned int fieldcols; /* formitem.fieldlen */ 66b319d934SAlfonso S. Siciliano unsigned int xcursor; /* position in fieldcols [0 - fieldcols-1] */ 67b319d934SAlfonso S. Siciliano unsigned int xposdraw; /* first pubwbuf index to draw */ 68f499134dSBaptiste Daroussin }; 69f499134dSBaptiste Daroussin 70b319d934SAlfonso S. Siciliano struct privateform { 7161ba55bcSBaptiste Daroussin WINDOW *box; /* window to draw borders */ 72b319d934SAlfonso S. Siciliano WINDOW *pad; 73b319d934SAlfonso S. Siciliano unsigned int h; /* only to create pad */ 74b319d934SAlfonso S. Siciliano unsigned int w; /* only to create pad */ 75b319d934SAlfonso S. Siciliano unsigned int wmin; /* to refresh, w can change for FIELDEXTEND */ 76b319d934SAlfonso S. Siciliano unsigned int ys; /* to refresh */ 77b319d934SAlfonso S. Siciliano unsigned int ye; /* to refresh */ 78b319d934SAlfonso S. Siciliano unsigned int xs; /* to refresh */ 79b319d934SAlfonso S. Siciliano unsigned int xe; /* to refresh */ 80b319d934SAlfonso S. Siciliano unsigned int y; /* changes moving focus around items */ 8161ba55bcSBaptiste Daroussin unsigned int formheight; /* API formheight */ 82b319d934SAlfonso S. Siciliano unsigned int viewrows; /* visible rows, real formheight */ 83b319d934SAlfonso S. Siciliano unsigned int minviewrows; /* min viewrows, ylabel != yfield */ 84b319d934SAlfonso S. Siciliano wchar_t securewch; /* wide char of conf.form.secure[mb]ch */ 85*a6d8be45SAlfonso S. Siciliano unsigned int nitems; /* like API nitems */ 8661ba55bcSBaptiste Daroussin struct privateitem *pritems; 8761ba55bcSBaptiste Daroussin int sel; /* selected item in pritem, can be -1 */ 8861ba55bcSBaptiste Daroussin bool hasbottomdesc; /* some item has bottomdesc */ 89b319d934SAlfonso S. Siciliano }; 90b319d934SAlfonso S. Siciliano 9161ba55bcSBaptiste Daroussin static int 9261ba55bcSBaptiste Daroussin build_privateform(struct bsddialog_conf*conf, unsigned int nitems, 9361ba55bcSBaptiste Daroussin struct bsddialog_formitem *items, struct privateform *f) 9461ba55bcSBaptiste Daroussin { 9561ba55bcSBaptiste Daroussin bool insecurecursor; 9661ba55bcSBaptiste Daroussin int mbchsize; 9761ba55bcSBaptiste Daroussin unsigned int i, j, itemybeg, itemxbeg, tmp; 9861ba55bcSBaptiste Daroussin wchar_t *winit; 9961ba55bcSBaptiste Daroussin struct privateitem *item; 100b319d934SAlfonso S. Siciliano 10161ba55bcSBaptiste Daroussin /* checks */ 10261ba55bcSBaptiste Daroussin CHECK_ARRAY(nitems, items); 10361ba55bcSBaptiste Daroussin for (i = 0; i < nitems; i++) { 10461ba55bcSBaptiste Daroussin if (items[i].fieldlen == 0) 10561ba55bcSBaptiste Daroussin RETURN_FMTERROR("item %u [0-%u] fieldlen = 0", 10661ba55bcSBaptiste Daroussin i, nitems); 107*a6d8be45SAlfonso S. Siciliano if (items[i].maxvaluelen == 0) 108*a6d8be45SAlfonso S. Siciliano RETURN_FMTERROR("item %u [0-%u] maxvaluelen = 0", 109*a6d8be45SAlfonso S. Siciliano i, nitems); 11061ba55bcSBaptiste Daroussin } 11161ba55bcSBaptiste Daroussin f->nitems = nitems; 11261ba55bcSBaptiste Daroussin 11361ba55bcSBaptiste Daroussin /* insecure ch */ 11461ba55bcSBaptiste Daroussin insecurecursor = false; 11561ba55bcSBaptiste Daroussin if (conf->form.securembch != NULL) { 11661ba55bcSBaptiste Daroussin mbchsize = mblen(conf->form.securembch, MB_LEN_MAX); 11761ba55bcSBaptiste Daroussin if (mbtowc(&f->securewch, conf->form.securembch, mbchsize) < 0) 11861ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot convert securembch to wchar_t"); 11961ba55bcSBaptiste Daroussin insecurecursor = true; 12061ba55bcSBaptiste Daroussin } else if (conf->form.securech != '\0') { 12161ba55bcSBaptiste Daroussin f->securewch = btowc(conf->form.securech); 12261ba55bcSBaptiste Daroussin insecurecursor = true; 12361ba55bcSBaptiste Daroussin } else { 12461ba55bcSBaptiste Daroussin f->securewch = L' '; 12561ba55bcSBaptiste Daroussin } 12661ba55bcSBaptiste Daroussin 12761ba55bcSBaptiste Daroussin /* alloc and set private items */ 12861ba55bcSBaptiste Daroussin f->pritems = malloc(f->nitems * sizeof(struct privateitem)); 12961ba55bcSBaptiste Daroussin if (f->pritems == NULL) 13061ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot allocate internal form.pritems"); 13161ba55bcSBaptiste Daroussin f->hasbottomdesc = false; 13261ba55bcSBaptiste Daroussin f->h = f->w = f->minviewrows = 0; 13361ba55bcSBaptiste Daroussin for (i = 0; i < f->nitems; i++) { 13461ba55bcSBaptiste Daroussin item = &f->pritems[i]; 13561ba55bcSBaptiste Daroussin item->label = CHECK_STR(items[i].label); 13661ba55bcSBaptiste Daroussin item->ylabel = items[i].ylabel; 13761ba55bcSBaptiste Daroussin item->xlabel = items[i].xlabel; 13861ba55bcSBaptiste Daroussin item->yfield = items[i].yfield; 13961ba55bcSBaptiste Daroussin item->xfield = items[i].xfield; 14061ba55bcSBaptiste Daroussin item->secure = items[i].flags & BSDDIALOG_FIELDHIDDEN; 14161ba55bcSBaptiste Daroussin item->readonly = items[i].flags & BSDDIALOG_FIELDREADONLY; 14261ba55bcSBaptiste Daroussin item->fieldnocolor = items[i].flags & BSDDIALOG_FIELDNOCOLOR; 14361ba55bcSBaptiste Daroussin item->extendfield = items[i].flags & BSDDIALOG_FIELDEXTEND; 14461ba55bcSBaptiste Daroussin item->fieldonebyte = items[i].flags & 14561ba55bcSBaptiste Daroussin BSDDIALOG_FIELDSINGLEBYTE; 14661ba55bcSBaptiste Daroussin item->cursorend = items[i].flags & BSDDIALOG_FIELDCURSOREND; 14761ba55bcSBaptiste Daroussin item->bottomdesc = CHECK_STR(items[i].bottomdesc); 14861ba55bcSBaptiste Daroussin if (items[i].bottomdesc != NULL) 14961ba55bcSBaptiste Daroussin f->hasbottomdesc = true; 15061ba55bcSBaptiste Daroussin if (item->readonly || (item->secure && !insecurecursor)) 15161ba55bcSBaptiste Daroussin item->cursor = false; 15261ba55bcSBaptiste Daroussin else 15361ba55bcSBaptiste Daroussin item->cursor = true; 15461ba55bcSBaptiste Daroussin 15561ba55bcSBaptiste Daroussin item->maxletters = items[i].maxvaluelen; 15661ba55bcSBaptiste Daroussin item->privwbuf = calloc(item->maxletters + 1, sizeof(wchar_t)); 15761ba55bcSBaptiste Daroussin if (item->privwbuf == NULL) 15861ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot allocate item private buffer"); 15961ba55bcSBaptiste Daroussin memset(item->privwbuf, 0, item->maxletters + 1); 16061ba55bcSBaptiste Daroussin item->pubwbuf = calloc(item->maxletters + 1, sizeof(wchar_t)); 16161ba55bcSBaptiste Daroussin if (item->pubwbuf == NULL) 16261ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot allocate item private buffer"); 16361ba55bcSBaptiste Daroussin memset(item->pubwbuf, 0, item->maxletters + 1); 16461ba55bcSBaptiste Daroussin 16561ba55bcSBaptiste Daroussin if ((winit = alloc_mbstows(CHECK_STR(items[i].init))) == NULL) 16661ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot allocate item.init in wchar_t*"); 16761ba55bcSBaptiste Daroussin wcsncpy(item->privwbuf, winit, item->maxletters); 16861ba55bcSBaptiste Daroussin wcsncpy(item->pubwbuf, winit, item->maxletters); 16961ba55bcSBaptiste Daroussin free(winit); 17061ba55bcSBaptiste Daroussin item->nletters = wcslen(item->pubwbuf); 17161ba55bcSBaptiste Daroussin if (item->secure) { 17261ba55bcSBaptiste Daroussin for (j = 0; j < item->nletters; j++) 17361ba55bcSBaptiste Daroussin item->pubwbuf[j] = f->securewch; 17461ba55bcSBaptiste Daroussin } 17561ba55bcSBaptiste Daroussin 17661ba55bcSBaptiste Daroussin item->fieldcols = items[i].fieldlen; 17761ba55bcSBaptiste Daroussin item->xposdraw = 0; 17861ba55bcSBaptiste Daroussin item->xcursor = 0; 17961ba55bcSBaptiste Daroussin item->pos = 0; 18061ba55bcSBaptiste Daroussin 18161ba55bcSBaptiste Daroussin /* size and position */ 18261ba55bcSBaptiste Daroussin f->h = MAX(f->h, item->ylabel); 18361ba55bcSBaptiste Daroussin f->h = MAX(f->h, item->yfield); 18461ba55bcSBaptiste Daroussin f->w = MAX(f->w, item->xlabel + strcols(item->label)); 18561ba55bcSBaptiste Daroussin f->w = MAX(f->w, item->xfield + item->fieldcols); 18661ba55bcSBaptiste Daroussin if (i == 0) { 18761ba55bcSBaptiste Daroussin itemybeg = MIN(item->ylabel, item->yfield); 18861ba55bcSBaptiste Daroussin itemxbeg = MIN(item->xlabel, item->xfield); 18961ba55bcSBaptiste Daroussin } else { 19061ba55bcSBaptiste Daroussin tmp = MIN(item->ylabel, item->yfield); 19161ba55bcSBaptiste Daroussin itemybeg = MIN(itemybeg, tmp); 19261ba55bcSBaptiste Daroussin tmp = MIN(item->xlabel, item->xfield); 19361ba55bcSBaptiste Daroussin itemxbeg = MIN(itemxbeg, tmp); 19461ba55bcSBaptiste Daroussin } 19561ba55bcSBaptiste Daroussin tmp = abs((int)item->ylabel - (int)item->yfield); 19661ba55bcSBaptiste Daroussin f->minviewrows = MAX(f->minviewrows, tmp); 19761ba55bcSBaptiste Daroussin } 19861ba55bcSBaptiste Daroussin if (f->nitems > 0) { 19961ba55bcSBaptiste Daroussin f->h = f->h + 1 - itemybeg; 20061ba55bcSBaptiste Daroussin f->w -= itemxbeg; 20161ba55bcSBaptiste Daroussin f->minviewrows += 1; 20261ba55bcSBaptiste Daroussin } 20361ba55bcSBaptiste Daroussin f->wmin = f->w; 20461ba55bcSBaptiste Daroussin for (i = 0; i < f->nitems; i++) { 20561ba55bcSBaptiste Daroussin f->pritems[i].ylabel -= itemybeg; 20661ba55bcSBaptiste Daroussin f->pritems[i].yfield -= itemybeg; 20761ba55bcSBaptiste Daroussin f->pritems[i].xlabel -= itemxbeg; 20861ba55bcSBaptiste Daroussin f->pritems[i].xfield -= itemxbeg; 20961ba55bcSBaptiste Daroussin } 21061ba55bcSBaptiste Daroussin 21161ba55bcSBaptiste Daroussin return (0); 21261ba55bcSBaptiste Daroussin } 21361ba55bcSBaptiste Daroussin 21461ba55bcSBaptiste Daroussin static bool fieldctl(struct privateitem *item, enum field_action act) 215b319d934SAlfonso S. Siciliano { 216b319d934SAlfonso S. Siciliano bool change; 217b319d934SAlfonso S. Siciliano int width, oldwidth, nextwidth, cols; 218b319d934SAlfonso S. Siciliano unsigned int i; 219b319d934SAlfonso S. Siciliano 220b319d934SAlfonso S. Siciliano change = false; 22161ba55bcSBaptiste Daroussin switch (act){ 222b319d934SAlfonso S. Siciliano case MOVE_CURSOR_BEGIN: 223b319d934SAlfonso S. Siciliano if (item->pos == 0 && item->xcursor == 0) 224b319d934SAlfonso S. Siciliano break; 225b319d934SAlfonso S. Siciliano /* here the cursor is changed */ 226b319d934SAlfonso S. Siciliano change = true; 227b319d934SAlfonso S. Siciliano item->pos = 0; 228b319d934SAlfonso S. Siciliano item->xcursor = 0; 229b319d934SAlfonso S. Siciliano item->xposdraw = 0; 230b319d934SAlfonso S. Siciliano break; 231b319d934SAlfonso S. Siciliano case MOVE_CURSOR_END: 232b319d934SAlfonso S. Siciliano while (fieldctl(item, MOVE_CURSOR_RIGHT)) 233b319d934SAlfonso S. Siciliano change = true; 234b319d934SAlfonso S. Siciliano break; 235b319d934SAlfonso S. Siciliano case MOVE_CURSOR_LEFT: 236b319d934SAlfonso S. Siciliano if (item->pos == 0) 237b319d934SAlfonso S. Siciliano break; 238b319d934SAlfonso S. Siciliano /* check redundant by item->pos == 0 because of 'while' below */ 239b319d934SAlfonso S. Siciliano if (item->xcursor == 0 && item->xposdraw == 0) 240b319d934SAlfonso S. Siciliano break; 241b319d934SAlfonso S. Siciliano /* here some letter to left */ 242b319d934SAlfonso S. Siciliano change = true; 243b319d934SAlfonso S. Siciliano item->pos -= 1; 244b319d934SAlfonso S. Siciliano width = wcwidth(item->pubwbuf[item->pos]); 245b319d934SAlfonso S. Siciliano if (((int)item->xcursor) - width < 0) { 246b319d934SAlfonso S. Siciliano item->xcursor = 0; 247b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 248b319d934SAlfonso S. Siciliano } else 249b319d934SAlfonso S. Siciliano item->xcursor -= width; 250b319d934SAlfonso S. Siciliano 251b319d934SAlfonso S. Siciliano while (true) { 252b319d934SAlfonso S. Siciliano if (item->xposdraw == 0) 253b319d934SAlfonso S. Siciliano break; 254b319d934SAlfonso S. Siciliano if (item->xcursor >= item->fieldcols / 2) 255b319d934SAlfonso S. Siciliano break; 256b319d934SAlfonso S. Siciliano if (wcwidth(item->pubwbuf[item->xposdraw - 1]) + 257b319d934SAlfonso S. Siciliano item->xcursor + width > item->fieldcols) 258b319d934SAlfonso S. Siciliano break; 259b319d934SAlfonso S. Siciliano 260b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 261b319d934SAlfonso S. Siciliano item->xcursor += 262b319d934SAlfonso S. Siciliano wcwidth(item->pubwbuf[item->xposdraw]); 263b319d934SAlfonso S. Siciliano } 264b319d934SAlfonso S. Siciliano break; 265b319d934SAlfonso S. Siciliano case DEL_LETTER: 266b319d934SAlfonso S. Siciliano if (item->nletters == 0) 267b319d934SAlfonso S. Siciliano break; 268b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) 269b319d934SAlfonso S. Siciliano break; 270b319d934SAlfonso S. Siciliano /* here a letter under the cursor */ 271b319d934SAlfonso S. Siciliano change = true; 272b319d934SAlfonso S. Siciliano for (i = item->pos; i < item->nletters; i++) { 273b319d934SAlfonso S. Siciliano item->privwbuf[i] = item->privwbuf[i+1]; 274b319d934SAlfonso S. Siciliano item->pubwbuf[i] = item->pubwbuf[i+1]; 275b319d934SAlfonso S. Siciliano } 276b319d934SAlfonso S. Siciliano item->nletters -= 1; 277b319d934SAlfonso S. Siciliano item->privwbuf[i] = L'\0'; 278b319d934SAlfonso S. Siciliano item->pubwbuf[i] = L'\0'; 279b319d934SAlfonso S. Siciliano break; 280b319d934SAlfonso S. Siciliano case MOVE_CURSOR_RIGHT: /* used also by "insert", see handler loop */ 281b319d934SAlfonso S. Siciliano if (item->pos + 1 == item->maxletters) 282b319d934SAlfonso S. Siciliano break; 283b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) 284b319d934SAlfonso S. Siciliano break; 285b319d934SAlfonso S. Siciliano /* here a change to right */ 286b319d934SAlfonso S. Siciliano change = true; 287b319d934SAlfonso S. Siciliano oldwidth = wcwidth(item->pubwbuf[item->pos]); 288b319d934SAlfonso S. Siciliano item->pos += 1; 289b319d934SAlfonso S. Siciliano if (item->pos == item->nletters) { /* empty column */ 290b319d934SAlfonso S. Siciliano nextwidth = 1; 291b319d934SAlfonso S. Siciliano } else { /* a letter to right */ 292b319d934SAlfonso S. Siciliano nextwidth = wcwidth(item->pubwbuf[item->pos]); 293b319d934SAlfonso S. Siciliano } 294b319d934SAlfonso S. Siciliano if (item->xcursor + oldwidth + nextwidth - 1 >= item->fieldcols) { 295b319d934SAlfonso S. Siciliano cols = nextwidth; 296b319d934SAlfonso S. Siciliano item->xposdraw = item->pos; 297b319d934SAlfonso S. Siciliano while (item->xposdraw != 0) { 298b319d934SAlfonso S. Siciliano cols += wcwidth(item->pubwbuf[item->xposdraw - 1]); 299b319d934SAlfonso S. Siciliano if (cols > (int)item->fieldcols) 300b319d934SAlfonso S. Siciliano break; 301b319d934SAlfonso S. Siciliano item->xposdraw -= 1; 302b319d934SAlfonso S. Siciliano } 303b319d934SAlfonso S. Siciliano item->xcursor = 0; 304b319d934SAlfonso S. Siciliano for (i = item->xposdraw; i < item->pos ; i++) 305b319d934SAlfonso S. Siciliano item->xcursor += wcwidth(item->pubwbuf[i]); 306b319d934SAlfonso S. Siciliano } 307b319d934SAlfonso S. Siciliano else { 308b319d934SAlfonso S. Siciliano item->xcursor += oldwidth; 309b319d934SAlfonso S. Siciliano } 310b319d934SAlfonso S. Siciliano 311b319d934SAlfonso S. Siciliano break; 312b319d934SAlfonso S. Siciliano } 313b319d934SAlfonso S. Siciliano 314b319d934SAlfonso S. Siciliano return (change); 315b319d934SAlfonso S. Siciliano } 316b319d934SAlfonso S. Siciliano 31761ba55bcSBaptiste Daroussin static bool insertch(struct privateitem *item, wchar_t wch, wchar_t securewch) 318c76f0793SBaptiste Daroussin { 319f499134dSBaptiste Daroussin int i; 320f499134dSBaptiste Daroussin 321b319d934SAlfonso S. Siciliano if (item->nletters >= item->maxletters) 322b319d934SAlfonso S. Siciliano return (false); 323f499134dSBaptiste Daroussin 324b319d934SAlfonso S. Siciliano for (i = (int)item->nletters - 1; i >= (int)item->pos; i--) { 325b319d934SAlfonso S. Siciliano item->privwbuf[i+1] = item->privwbuf[i]; 326b319d934SAlfonso S. Siciliano item->pubwbuf[i+1] = item->pubwbuf[i]; 327c76f0793SBaptiste Daroussin } 328c76f0793SBaptiste Daroussin 329b319d934SAlfonso S. Siciliano item->privwbuf[item->pos] = wch; 33061ba55bcSBaptiste Daroussin item->pubwbuf[item->pos] = item->secure ? securewch : wch; 331b319d934SAlfonso S. Siciliano item->nletters += 1; 332b319d934SAlfonso S. Siciliano item->privwbuf[item->nletters] = L'\0'; 333b319d934SAlfonso S. Siciliano item->pubwbuf[item->nletters] = L'\0'; 334b319d934SAlfonso S. Siciliano 335b319d934SAlfonso S. Siciliano return (true); 336f499134dSBaptiste Daroussin } 337f499134dSBaptiste Daroussin 338b319d934SAlfonso S. Siciliano static char* alloc_wstomb(wchar_t *wstr) 339f499134dSBaptiste Daroussin { 340b319d934SAlfonso S. Siciliano int len, nbytes, i; 341b319d934SAlfonso S. Siciliano char mbch[MB_LEN_MAX], *mbstr; 342f499134dSBaptiste Daroussin 343b319d934SAlfonso S. Siciliano nbytes = MB_LEN_MAX; /* to ensure a null terminated string */ 344b319d934SAlfonso S. Siciliano len = wcslen(wstr); 345b319d934SAlfonso S. Siciliano for (i = 0; i < len; i++) { 346b319d934SAlfonso S. Siciliano wctomb(mbch, wstr[i]); 347b319d934SAlfonso S. Siciliano nbytes += mblen(mbch, MB_LEN_MAX); 348f499134dSBaptiste Daroussin } 349b319d934SAlfonso S. Siciliano if ((mbstr = malloc(nbytes)) == NULL) 350b319d934SAlfonso S. Siciliano return (NULL); 351f499134dSBaptiste Daroussin 352b319d934SAlfonso S. Siciliano wcstombs(mbstr, wstr, nbytes); 353c76f0793SBaptiste Daroussin 354b319d934SAlfonso S. Siciliano return (mbstr); 355bce40c02SAlfonso S. Siciliano } 356bce40c02SAlfonso S. Siciliano 357bce40c02SAlfonso S. Siciliano static int 35861ba55bcSBaptiste Daroussin return_values(struct bsddialog_conf *conf, struct privateform *f, 35961ba55bcSBaptiste Daroussin struct bsddialog_formitem *items) 360d93b4d32SBaptiste Daroussin { 36161ba55bcSBaptiste Daroussin unsigned int i; 362d93b4d32SBaptiste Daroussin 36361ba55bcSBaptiste Daroussin for (i = 0; i < f->nitems; i++) { 36461ba55bcSBaptiste Daroussin if (conf->form.value_wchar) 36561ba55bcSBaptiste Daroussin items[i].value = (char*)wcsdup(f->pritems[i].privwbuf); 36661ba55bcSBaptiste Daroussin else 36761ba55bcSBaptiste Daroussin items[i].value = alloc_wstomb(f->pritems[i].privwbuf); 368d93b4d32SBaptiste Daroussin 36961ba55bcSBaptiste Daroussin if (items[i].value == NULL) 37061ba55bcSBaptiste Daroussin RETURN_FMTERROR( 37161ba55bcSBaptiste Daroussin "Cannot allocate memory for item[%d].value", i); 372d93b4d32SBaptiste Daroussin } 373d93b4d32SBaptiste Daroussin 37461ba55bcSBaptiste Daroussin return (0); 37561ba55bcSBaptiste Daroussin } 37661ba55bcSBaptiste Daroussin 37761ba55bcSBaptiste Daroussin static void set_first_with_default(struct privateform *f, int *focusitem) 37861ba55bcSBaptiste Daroussin { 37961ba55bcSBaptiste Daroussin unsigned int i; 38061ba55bcSBaptiste Daroussin 38161ba55bcSBaptiste Daroussin f->sel = -1; 38261ba55bcSBaptiste Daroussin if (focusitem != NULL && *focusitem >=0 && *focusitem < (int)f->nitems) 38361ba55bcSBaptiste Daroussin if (f->pritems[*focusitem].readonly == false) { 38461ba55bcSBaptiste Daroussin f->sel = *focusitem; 38561ba55bcSBaptiste Daroussin return; 38661ba55bcSBaptiste Daroussin } 38761ba55bcSBaptiste Daroussin for (i = 0 ; i < f->nitems; i++) 38861ba55bcSBaptiste Daroussin if (f->pritems[i].readonly == false) { 38961ba55bcSBaptiste Daroussin f->sel = i; 39061ba55bcSBaptiste Daroussin break; 39161ba55bcSBaptiste Daroussin } 392d93b4d32SBaptiste Daroussin } 393d93b4d32SBaptiste Daroussin 394b319d934SAlfonso S. Siciliano static unsigned int firstitem(unsigned int nitems, struct privateitem *items) 395c76f0793SBaptiste Daroussin { 396b319d934SAlfonso S. Siciliano int i; 397c76f0793SBaptiste Daroussin 398b319d934SAlfonso S. Siciliano for (i = 0; i < (int)nitems; i++) 399b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 400b319d934SAlfonso S. Siciliano break; 401263660c0SAlfonso Siciliano 402b319d934SAlfonso S. Siciliano return (i); 403b319d934SAlfonso S. Siciliano } 404263660c0SAlfonso Siciliano 405b319d934SAlfonso S. Siciliano static unsigned int lastitem(unsigned int nitems, struct privateitem *items) 406b319d934SAlfonso S. Siciliano { 407b319d934SAlfonso S. Siciliano int i; 408b319d934SAlfonso S. Siciliano 409b319d934SAlfonso S. Siciliano for (i = nitems - 1; i >= 0 ; i--) 410b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 411b319d934SAlfonso S. Siciliano break; 412b319d934SAlfonso S. Siciliano 413b319d934SAlfonso S. Siciliano return (i); 414c76f0793SBaptiste Daroussin } 415b319d934SAlfonso S. Siciliano 416b319d934SAlfonso S. Siciliano static unsigned int 417b319d934SAlfonso S. Siciliano previtem(unsigned int nitems, struct privateitem *items, int curritem) 418b319d934SAlfonso S. Siciliano { 419b319d934SAlfonso S. Siciliano int i; 420b319d934SAlfonso S. Siciliano 421b319d934SAlfonso S. Siciliano for (i = curritem - 1; i >= 0; i--) 422b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 423b319d934SAlfonso S. Siciliano return(i); 424b319d934SAlfonso S. Siciliano 425b319d934SAlfonso S. Siciliano for (i = nitems - 1; i > curritem - 1; i--) 426b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 427b319d934SAlfonso S. Siciliano return(i); 428b319d934SAlfonso S. Siciliano 429b319d934SAlfonso S. Siciliano return (curritem); 430263660c0SAlfonso Siciliano } 431b319d934SAlfonso S. Siciliano 432b319d934SAlfonso S. Siciliano static unsigned int 433b319d934SAlfonso S. Siciliano nextitem(unsigned int nitems, struct privateitem *items, int curritem) 434b319d934SAlfonso S. Siciliano { 435b319d934SAlfonso S. Siciliano int i; 436b319d934SAlfonso S. Siciliano 437b319d934SAlfonso S. Siciliano for (i = curritem + 1; i < (int)nitems; i++) 438b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 439b319d934SAlfonso S. Siciliano return(i); 440b319d934SAlfonso S. Siciliano 441b319d934SAlfonso S. Siciliano for (i = 0; i < curritem; i++) 442b319d934SAlfonso S. Siciliano if (items[i].readonly == false) 443b319d934SAlfonso S. Siciliano return(i); 444b319d934SAlfonso S. Siciliano 445b319d934SAlfonso S. Siciliano return (curritem); 446c76f0793SBaptiste Daroussin } 447b319d934SAlfonso S. Siciliano 44861ba55bcSBaptiste Daroussin static void redrawbuttons(struct dialog *d, bool focus, bool shortcut) 449b319d934SAlfonso S. Siciliano { 450b319d934SAlfonso S. Siciliano int selected; 451b319d934SAlfonso S. Siciliano 45261ba55bcSBaptiste Daroussin selected = d->bs.curr; 453b319d934SAlfonso S. Siciliano if (focus == false) 45461ba55bcSBaptiste Daroussin d->bs.curr = -1; 45561ba55bcSBaptiste Daroussin d->bs.shortcut = shortcut; 45661ba55bcSBaptiste Daroussin draw_buttons(d); 45761ba55bcSBaptiste Daroussin d->bs.curr = selected; 458c76f0793SBaptiste Daroussin } 459b319d934SAlfonso S. Siciliano 460b319d934SAlfonso S. Siciliano static void 46161ba55bcSBaptiste Daroussin drawitem(struct privateform *f, int idx, bool focus) 46261ba55bcSBaptiste Daroussin { 46361ba55bcSBaptiste Daroussin int color; 46461ba55bcSBaptiste Daroussin unsigned int n, cols; 46561ba55bcSBaptiste Daroussin struct privateitem *item; 46661ba55bcSBaptiste Daroussin 46761ba55bcSBaptiste Daroussin item = &f->pritems[idx]; 46861ba55bcSBaptiste Daroussin 46961ba55bcSBaptiste Daroussin /* Label */ 47061ba55bcSBaptiste Daroussin wattron(f->pad, t.dialog.color); 47161ba55bcSBaptiste Daroussin mvwaddstr(f->pad, item->ylabel, item->xlabel, item->label); 47261ba55bcSBaptiste Daroussin wattroff(f->pad, t.dialog.color); 47361ba55bcSBaptiste Daroussin 47461ba55bcSBaptiste Daroussin /* Field */ 47561ba55bcSBaptiste Daroussin if (item->readonly) 47661ba55bcSBaptiste Daroussin color = t.form.readonlycolor; 47761ba55bcSBaptiste Daroussin else if (item->fieldnocolor) 47861ba55bcSBaptiste Daroussin color = t.dialog.color; 47961ba55bcSBaptiste Daroussin else 48061ba55bcSBaptiste Daroussin color = focus ? t.form.f_fieldcolor : t.form.fieldcolor; 48161ba55bcSBaptiste Daroussin wattron(f->pad, color); 48261ba55bcSBaptiste Daroussin mvwhline(f->pad, item->yfield, item->xfield, ' ', item->fieldcols); 48361ba55bcSBaptiste Daroussin n = 0; 48461ba55bcSBaptiste Daroussin cols = wcwidth(item->pubwbuf[item->xposdraw]); 48561ba55bcSBaptiste Daroussin while (cols <= item->fieldcols && 48661ba55bcSBaptiste Daroussin item->xposdraw + n < wcslen(item->pubwbuf)) { 48761ba55bcSBaptiste Daroussin n++; 48861ba55bcSBaptiste Daroussin cols += wcwidth(item->pubwbuf[item->xposdraw + n]); 48961ba55bcSBaptiste Daroussin 49061ba55bcSBaptiste Daroussin } 49161ba55bcSBaptiste Daroussin mvwaddnwstr(f->pad, item->yfield, item->xfield, 49261ba55bcSBaptiste Daroussin &item->pubwbuf[item->xposdraw], n); 49361ba55bcSBaptiste Daroussin wattroff(f->pad, color); 49461ba55bcSBaptiste Daroussin 49561ba55bcSBaptiste Daroussin /* Bottom Desc */ 49661ba55bcSBaptiste Daroussin if (f->hasbottomdesc) { 49761ba55bcSBaptiste Daroussin move(SCREENLINES - 1, 2); 49861ba55bcSBaptiste Daroussin clrtoeol(); 49961ba55bcSBaptiste Daroussin if (item->bottomdesc != NULL && focus) { 50061ba55bcSBaptiste Daroussin attron(t.form.bottomdesccolor); 50161ba55bcSBaptiste Daroussin addstr(item->bottomdesc); 50261ba55bcSBaptiste Daroussin attroff(t.form.bottomdesccolor); 50361ba55bcSBaptiste Daroussin refresh(); 50461ba55bcSBaptiste Daroussin } 50561ba55bcSBaptiste Daroussin } 50661ba55bcSBaptiste Daroussin 50761ba55bcSBaptiste Daroussin /* Cursor */ 50861ba55bcSBaptiste Daroussin curs_set((focus && item->cursor) ? 1 : 0); 50961ba55bcSBaptiste Daroussin wmove(f->pad, item->yfield, item->xfield + item->xcursor); 51061ba55bcSBaptiste Daroussin } 51161ba55bcSBaptiste Daroussin 51261ba55bcSBaptiste Daroussin /* 51361ba55bcSBaptiste Daroussin * Trick: draw 2 times an item switching focus. 51461ba55bcSBaptiste Daroussin * Problem: curses tries to optimize the rendering but sometimes it misses some 51561ba55bcSBaptiste Daroussin * updates or draws old stuff. libformw has a similar problem fixed by the 51661ba55bcSBaptiste Daroussin * same trick. 51761ba55bcSBaptiste Daroussin * Case 1: KEY_DC and KEY_BACKSPACE, deleted multicolumn letters are drawn 51861ba55bcSBaptiste Daroussin * again. It seems fixed by new items pad and prefresh(), previously WINDOW. 51961ba55bcSBaptiste Daroussin * Case2: some terminal, tmux and ssh does not show the cursor. 52061ba55bcSBaptiste Daroussin */ 52161ba55bcSBaptiste Daroussin #define DRAWITEM_TRICK(f, idx, focus) do { \ 52261ba55bcSBaptiste Daroussin drawitem(f, idx, !focus); \ 52361ba55bcSBaptiste Daroussin prefresh((f)->pad, (f)->y, 0, (f)->ys, (f)->xs, (f)->ye, (f)->xe); \ 52461ba55bcSBaptiste Daroussin drawitem(f, idx, focus); \ 52561ba55bcSBaptiste Daroussin prefresh((f)->pad, (f)->y, 0, (f)->ys, (f)->xs, (f)->ye, (f)->xe); \ 52661ba55bcSBaptiste Daroussin } while (0) 52761ba55bcSBaptiste Daroussin 52861ba55bcSBaptiste Daroussin static void update_formbox(struct bsddialog_conf *conf, struct privateform *f) 529b319d934SAlfonso S. Siciliano { 530b319d934SAlfonso S. Siciliano int h, w; 531b319d934SAlfonso S. Siciliano 53261ba55bcSBaptiste Daroussin getmaxyx(f->box, h, w); 53361ba55bcSBaptiste Daroussin draw_borders(conf, f->box, LOWERED); 534b319d934SAlfonso S. Siciliano 53561ba55bcSBaptiste Daroussin if (f->viewrows < f->h) { 53661ba55bcSBaptiste Daroussin wattron(f->box, t.dialog.arrowcolor); 53761ba55bcSBaptiste Daroussin if (f->y > 0) 538*a6d8be45SAlfonso S. Siciliano mvwhline(f->box, 0, (w / 2) - 2, UARROW(conf), 5); 539b319d934SAlfonso S. Siciliano 54061ba55bcSBaptiste Daroussin if (f->y + f->viewrows < f->h) 541*a6d8be45SAlfonso S. Siciliano mvwhline(f->box, h-1, (w / 2) - 2, DARROW(conf), 5); 54261ba55bcSBaptiste Daroussin wattroff(f->box, t.dialog.arrowcolor); 543c76f0793SBaptiste Daroussin } 544c76f0793SBaptiste Daroussin } 545c76f0793SBaptiste Daroussin 54661ba55bcSBaptiste Daroussin static void curriteminview(struct privateform *f, struct privateitem *item) 547b319d934SAlfonso S. Siciliano { 548b319d934SAlfonso S. Siciliano unsigned int yup, ydown; 549b319d934SAlfonso S. Siciliano 550b319d934SAlfonso S. Siciliano yup = MIN(item->ylabel, item->yfield); 551b319d934SAlfonso S. Siciliano ydown = MAX(item->ylabel, item->yfield); 552b319d934SAlfonso S. Siciliano 55361ba55bcSBaptiste Daroussin /* selected item in view */ 55461ba55bcSBaptiste Daroussin if (f->y > yup && f->y > 0) 55561ba55bcSBaptiste Daroussin f->y = yup; 55661ba55bcSBaptiste Daroussin if ((int)(f->y + f->viewrows) - 1 < (int)ydown) 55761ba55bcSBaptiste Daroussin f->y = ydown - f->viewrows + 1; 55861ba55bcSBaptiste Daroussin /* lower pad after a terminal expansion */ 55961ba55bcSBaptiste Daroussin if (f->y > 0 && (f->h - f->y) < f->viewrows) 56061ba55bcSBaptiste Daroussin f->y = f->h - f->viewrows; 56161ba55bcSBaptiste Daroussin } 56261ba55bcSBaptiste Daroussin 56361ba55bcSBaptiste Daroussin static int form_size_position(struct dialog *d, struct privateform *f) 56461ba55bcSBaptiste Daroussin { 56561ba55bcSBaptiste Daroussin int htext, hform; 56661ba55bcSBaptiste Daroussin 56761ba55bcSBaptiste Daroussin if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0) 56861ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 56961ba55bcSBaptiste Daroussin 57061ba55bcSBaptiste Daroussin /* autosize */ 57161ba55bcSBaptiste Daroussin hform = (int) f->viewrows; 57261ba55bcSBaptiste Daroussin if (f->viewrows == BSDDIALOG_AUTOSIZE) 57361ba55bcSBaptiste Daroussin hform = MAX(f->h, f->minviewrows); 57461ba55bcSBaptiste Daroussin hform += 2; /* formborders */ 57561ba55bcSBaptiste Daroussin 57661ba55bcSBaptiste Daroussin if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w, 57761ba55bcSBaptiste Daroussin d->text, &htext, &d->bs, hform, f->w + 4) != 0) 57861ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 57961ba55bcSBaptiste Daroussin /* formheight: avoid overflow, "at most" and at least minviewrows */ 58061ba55bcSBaptiste Daroussin if (d->h - BORDERS - htext - HBUTTONS < 2 + (int)f->minviewrows) { 58161ba55bcSBaptiste Daroussin f->viewrows = f->minviewrows; /* for widget_checksize() */ 58261ba55bcSBaptiste Daroussin } else if (f->viewrows == BSDDIALOG_AUTOSIZE) { 58361ba55bcSBaptiste Daroussin f->viewrows = MIN(d->h - BORDERS - htext - HBUTTONS, hform) - 2; 58461ba55bcSBaptiste Daroussin f->viewrows = MAX(f->viewrows, f->minviewrows); 58561ba55bcSBaptiste Daroussin } else { 58661ba55bcSBaptiste Daroussin f->viewrows = MIN(d->h - BORDERS - htext - HBUTTONS, hform) - 2; 58761ba55bcSBaptiste Daroussin } 58861ba55bcSBaptiste Daroussin 58961ba55bcSBaptiste Daroussin /* checksize */ 59061ba55bcSBaptiste Daroussin if (f->viewrows < f->minviewrows) 59161ba55bcSBaptiste Daroussin RETURN_FMTERROR("formheight, current: %u needed at least %u", 59261ba55bcSBaptiste Daroussin f->viewrows, f->minviewrows); 59361ba55bcSBaptiste Daroussin if (widget_checksize(d->h, d->w, &d->bs, 59461ba55bcSBaptiste Daroussin 2 /* borders */ + f->minviewrows, f->w + 4) != 0) 59561ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 59661ba55bcSBaptiste Daroussin 59761ba55bcSBaptiste Daroussin if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0) 59861ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 59961ba55bcSBaptiste Daroussin 60061ba55bcSBaptiste Daroussin return (0); 60161ba55bcSBaptiste Daroussin } 60261ba55bcSBaptiste Daroussin 60361ba55bcSBaptiste Daroussin static int 60461ba55bcSBaptiste Daroussin form_redraw(struct dialog *d, struct privateform *f, bool focusinform) 60561ba55bcSBaptiste Daroussin { 60661ba55bcSBaptiste Daroussin unsigned int i; 60761ba55bcSBaptiste Daroussin 60861ba55bcSBaptiste Daroussin if (d->built) { 60961ba55bcSBaptiste Daroussin hide_dialog(d); 61061ba55bcSBaptiste Daroussin refresh(); /* Important for decreasing screen */ 61161ba55bcSBaptiste Daroussin } 61261ba55bcSBaptiste Daroussin f->viewrows = f->formheight; 61361ba55bcSBaptiste Daroussin f->w = f->wmin; 61461ba55bcSBaptiste Daroussin if (form_size_position(d, f) != 0) 61561ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 61661ba55bcSBaptiste Daroussin if (draw_dialog(d) != 0) 61761ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 61861ba55bcSBaptiste Daroussin if (d->built) 61961ba55bcSBaptiste Daroussin refresh(); /* Important to fix grey lines expanding screen */ 62061ba55bcSBaptiste Daroussin TEXTPAD(d, 2 /* box borders */ + f->viewrows + HBUTTONS); 62161ba55bcSBaptiste Daroussin 62261ba55bcSBaptiste Daroussin update_box(d->conf, f->box, d->y + d->h - 5 - f->viewrows, d->x + 2, 62361ba55bcSBaptiste Daroussin f->viewrows + 2, d->w - 4, LOWERED); 62461ba55bcSBaptiste Daroussin 62561ba55bcSBaptiste Daroussin for (i = 0; i < f->nitems; i++) { 62661ba55bcSBaptiste Daroussin fieldctl(&f->pritems[i], MOVE_CURSOR_BEGIN); 62761ba55bcSBaptiste Daroussin if (f->pritems[i].extendfield) { 62861ba55bcSBaptiste Daroussin f->w = d->w - 6; 62961ba55bcSBaptiste Daroussin f->pritems[i].fieldcols = f->w - f->pritems[i].xfield; 63061ba55bcSBaptiste Daroussin } 63161ba55bcSBaptiste Daroussin if (f->pritems[i].cursorend) 63261ba55bcSBaptiste Daroussin fieldctl(&f->pritems[i], MOVE_CURSOR_END); 63361ba55bcSBaptiste Daroussin } 63461ba55bcSBaptiste Daroussin 63561ba55bcSBaptiste Daroussin wresize(f->pad, f->h, f->w); 63661ba55bcSBaptiste Daroussin for (i = 0; i < f->nitems; i++) 63761ba55bcSBaptiste Daroussin drawitem(f, i, false); 63861ba55bcSBaptiste Daroussin 63961ba55bcSBaptiste Daroussin f->ys = d->y + d->h - 5 - f->viewrows + 1; 64061ba55bcSBaptiste Daroussin f->ye = d->y + d->h - 5 ; 64161ba55bcSBaptiste Daroussin if ((int)f->w >= d->w - 6) { /* left */ 64261ba55bcSBaptiste Daroussin f->xs = d->x + 3; 64361ba55bcSBaptiste Daroussin f->xe = f->xs + d->w - 7; 64461ba55bcSBaptiste Daroussin } else { /* center */ 64561ba55bcSBaptiste Daroussin f->xs = d->x + 3 + (d->w - 6)/2 - f->w/2; 64661ba55bcSBaptiste Daroussin f->xe = f->xs + d->w - 5; 64761ba55bcSBaptiste Daroussin } 64861ba55bcSBaptiste Daroussin 64961ba55bcSBaptiste Daroussin if (f->sel != -1) { /* at least 1 writable item */ 65061ba55bcSBaptiste Daroussin redrawbuttons(d, 65161ba55bcSBaptiste Daroussin d->conf->button.always_active || !focusinform, 65261ba55bcSBaptiste Daroussin !focusinform); 65361ba55bcSBaptiste Daroussin wnoutrefresh(d->widget); 65461ba55bcSBaptiste Daroussin curriteminview(f, &f->pritems[f->sel]); 65561ba55bcSBaptiste Daroussin update_formbox(d->conf, f); 65661ba55bcSBaptiste Daroussin wnoutrefresh(f->box); 65761ba55bcSBaptiste Daroussin DRAWITEM_TRICK(f, f->sel, focusinform); 65861ba55bcSBaptiste Daroussin } else if (f->sel == -1 && f->nitems > 0) { /* all read only */ 65961ba55bcSBaptiste Daroussin redrawbuttons(d, true, true); 66061ba55bcSBaptiste Daroussin wnoutrefresh(d->widget); 66161ba55bcSBaptiste Daroussin update_formbox(d->conf, f); 66261ba55bcSBaptiste Daroussin wnoutrefresh(f->box); 66361ba55bcSBaptiste Daroussin DRAWITEM_TRICK(f, 0, false); /* to refresh pad*/ 66461ba55bcSBaptiste Daroussin } else { /* no item */ 66561ba55bcSBaptiste Daroussin wnoutrefresh(f->box); 66661ba55bcSBaptiste Daroussin } 66761ba55bcSBaptiste Daroussin 66861ba55bcSBaptiste Daroussin return (0); 669b319d934SAlfonso S. Siciliano } 670b319d934SAlfonso S. Siciliano 671b319d934SAlfonso S. Siciliano /* API */ 672f499134dSBaptiste Daroussin int 673263660c0SAlfonso Siciliano bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows, 674263660c0SAlfonso Siciliano int cols, unsigned int formheight, unsigned int nitems, 67561ba55bcSBaptiste Daroussin struct bsddialog_formitem *items, int *focusitem) 676f499134dSBaptiste Daroussin { 67761ba55bcSBaptiste Daroussin bool switchfocus, changeitem, focusinform, loop; 67861ba55bcSBaptiste Daroussin int next, retval, wchtype; 67961ba55bcSBaptiste Daroussin unsigned int i; 680b319d934SAlfonso S. Siciliano wint_t input; 68161ba55bcSBaptiste Daroussin struct privateitem *item; 682b319d934SAlfonso S. Siciliano struct privateform form; 68361ba55bcSBaptiste Daroussin struct dialog d; 684c76f0793SBaptiste Daroussin 68561ba55bcSBaptiste Daroussin if (prepare_dialog(conf, text, rows, cols, &d) != 0) 686263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 68761ba55bcSBaptiste Daroussin set_buttons(&d, true, OK_LABEL, CANCEL_LABEL); 68861ba55bcSBaptiste Daroussin 68961ba55bcSBaptiste Daroussin if (build_privateform(conf, nitems, items, &form) != 0) 690263660c0SAlfonso Siciliano return (BSDDIALOG_ERROR); 691c76f0793SBaptiste Daroussin 69261ba55bcSBaptiste Daroussin if ((form.box = newwin(1, 1, 1, 1)) == NULL) 69361ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot build WINDOW form box"); 69461ba55bcSBaptiste Daroussin wbkgd(form.box, t.dialog.color); 69561ba55bcSBaptiste Daroussin if ((form.pad = newpad(1, 1)) == NULL) 69661ba55bcSBaptiste Daroussin RETURN_ERROR("Cannot build WINDOW form pad"); 697b319d934SAlfonso S. Siciliano wbkgd(form.pad, t.dialog.color); 698c76f0793SBaptiste Daroussin 69961ba55bcSBaptiste Daroussin set_first_with_default(&form, focusitem); 70061ba55bcSBaptiste Daroussin if (form.sel != -1) { 701b319d934SAlfonso S. Siciliano focusinform = true; 702b319d934SAlfonso S. Siciliano form.y = 0; 70361ba55bcSBaptiste Daroussin item = &form.pritems[form.sel]; 704b319d934SAlfonso S. Siciliano } else { 705b319d934SAlfonso S. Siciliano item = NULL; 706b319d934SAlfonso S. Siciliano focusinform = false; 707b319d934SAlfonso S. Siciliano } 708f499134dSBaptiste Daroussin 70961ba55bcSBaptiste Daroussin form.formheight = formheight; 71061ba55bcSBaptiste Daroussin if (form_redraw(&d, &form, focusinform) != 0) 71161ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 71261ba55bcSBaptiste Daroussin 713b319d934SAlfonso S. Siciliano changeitem = switchfocus = false; 714b319d934SAlfonso S. Siciliano loop = true; 715b319d934SAlfonso S. Siciliano while (loop) { 71661ba55bcSBaptiste Daroussin doupdate(); 717b319d934SAlfonso S. Siciliano if ((wchtype = get_wch(&input)) == ERR) 718b319d934SAlfonso S. Siciliano continue; 719b319d934SAlfonso S. Siciliano switch(input) { 720b319d934SAlfonso S. Siciliano case KEY_ENTER: 721b319d934SAlfonso S. Siciliano case 10: /* Enter */ 722b319d934SAlfonso S. Siciliano if (focusinform && conf->button.always_active == false) 723b319d934SAlfonso S. Siciliano break; 72461ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs); 725b319d934SAlfonso S. Siciliano loop = false; 726b319d934SAlfonso S. Siciliano break; 727b319d934SAlfonso S. Siciliano case 27: /* Esc */ 728b319d934SAlfonso S. Siciliano if (conf->key.enable_esc) { 72961ba55bcSBaptiste Daroussin retval = BSDDIALOG_ESC; 730b319d934SAlfonso S. Siciliano loop = false; 731b319d934SAlfonso S. Siciliano } 732b319d934SAlfonso S. Siciliano break; 733b319d934SAlfonso S. Siciliano case '\t': /* TAB */ 734b319d934SAlfonso S. Siciliano if (focusinform) { 735b319d934SAlfonso S. Siciliano switchfocus = true; 736b319d934SAlfonso S. Siciliano } else { 73761ba55bcSBaptiste Daroussin if (d.bs.curr + 1 < (int)d.bs.nbuttons) { 73861ba55bcSBaptiste Daroussin d.bs.curr++; 739b319d934SAlfonso S. Siciliano } else { 74061ba55bcSBaptiste Daroussin d.bs.curr = 0; 74161ba55bcSBaptiste Daroussin if (form.sel != -1) { 742b319d934SAlfonso S. Siciliano switchfocus = true; 743b319d934SAlfonso S. Siciliano } 744b319d934SAlfonso S. Siciliano } 74561ba55bcSBaptiste Daroussin redrawbuttons(&d, true, true); 74661ba55bcSBaptiste Daroussin wnoutrefresh(d.widget); 747b319d934SAlfonso S. Siciliano } 748b319d934SAlfonso S. Siciliano break; 749b319d934SAlfonso S. Siciliano case KEY_LEFT: 750b319d934SAlfonso S. Siciliano if (focusinform) { 751b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_LEFT)) 75261ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 75361ba55bcSBaptiste Daroussin } else if (d.bs.curr > 0) { 75461ba55bcSBaptiste Daroussin d.bs.curr--; 75561ba55bcSBaptiste Daroussin redrawbuttons(&d, true, true); 75661ba55bcSBaptiste Daroussin wnoutrefresh(d.widget); 75761ba55bcSBaptiste Daroussin } else if (form.sel != -1) { 758b319d934SAlfonso S. Siciliano switchfocus = true; 759b319d934SAlfonso S. Siciliano } 760b319d934SAlfonso S. Siciliano break; 761b319d934SAlfonso S. Siciliano case KEY_RIGHT: 762b319d934SAlfonso S. Siciliano if (focusinform) { 763b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_RIGHT)) 76461ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 76561ba55bcSBaptiste Daroussin } else if (d.bs.curr < (int) d.bs.nbuttons - 1) { 76661ba55bcSBaptiste Daroussin d.bs.curr++; 76761ba55bcSBaptiste Daroussin redrawbuttons(&d, true, true); 76861ba55bcSBaptiste Daroussin wnoutrefresh(d.widget); 76961ba55bcSBaptiste Daroussin } else if (form.sel != -1) { 770b319d934SAlfonso S. Siciliano switchfocus = true; 771b319d934SAlfonso S. Siciliano } 772b319d934SAlfonso S. Siciliano break; 773*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('p'): 774b319d934SAlfonso S. Siciliano case KEY_UP: 775b319d934SAlfonso S. Siciliano if (focusinform) { 77661ba55bcSBaptiste Daroussin next = previtem(form.nitems, form.pritems, 77761ba55bcSBaptiste Daroussin form.sel); 77861ba55bcSBaptiste Daroussin changeitem = form.sel != next; 77961ba55bcSBaptiste Daroussin } else if (form.sel != -1) { 780b319d934SAlfonso S. Siciliano switchfocus = true; 781b319d934SAlfonso S. Siciliano } 782b319d934SAlfonso S. Siciliano break; 783*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('n'): 784b319d934SAlfonso S. Siciliano case KEY_DOWN: 785b319d934SAlfonso S. Siciliano if (focusinform == false) 786b319d934SAlfonso S. Siciliano break; 78761ba55bcSBaptiste Daroussin if (form.nitems == 1) { 788b319d934SAlfonso S. Siciliano switchfocus = true; 789b319d934SAlfonso S. Siciliano } else { 79061ba55bcSBaptiste Daroussin next = nextitem(form.nitems, form.pritems, 79161ba55bcSBaptiste Daroussin form.sel); 79261ba55bcSBaptiste Daroussin changeitem = form.sel != next; 793b319d934SAlfonso S. Siciliano } 794b319d934SAlfonso S. Siciliano break; 795b319d934SAlfonso S. Siciliano case KEY_PPAGE: 796b319d934SAlfonso S. Siciliano if (focusinform) { 79761ba55bcSBaptiste Daroussin next = firstitem(form.nitems, form.pritems); 79861ba55bcSBaptiste Daroussin changeitem = form.sel != next; 799b319d934SAlfonso S. Siciliano } 800b319d934SAlfonso S. Siciliano break; 801b319d934SAlfonso S. Siciliano case KEY_NPAGE: 802b319d934SAlfonso S. Siciliano if (focusinform) { 80361ba55bcSBaptiste Daroussin next = lastitem(form.nitems, form.pritems); 80461ba55bcSBaptiste Daroussin changeitem = form.sel != next; 805b319d934SAlfonso S. Siciliano } 806b319d934SAlfonso S. Siciliano break; 807b319d934SAlfonso S. Siciliano case KEY_BACKSPACE: 808b319d934SAlfonso S. Siciliano case 127: /* Backspace */ 809b319d934SAlfonso S. Siciliano if (focusinform == false) 810b319d934SAlfonso S. Siciliano break; 811b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_LEFT)) 812b319d934SAlfonso S. Siciliano if (fieldctl(item, DEL_LETTER)) 81361ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 814b319d934SAlfonso S. Siciliano break; 815b319d934SAlfonso S. Siciliano case KEY_DC: 816b319d934SAlfonso S. Siciliano if (focusinform == false) 817b319d934SAlfonso S. Siciliano break; 818b319d934SAlfonso S. Siciliano if (fieldctl(item, DEL_LETTER)) 81961ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 820b319d934SAlfonso S. Siciliano break; 821b319d934SAlfonso S. Siciliano case KEY_HOME: 822b319d934SAlfonso S. Siciliano if (focusinform == false) 823b319d934SAlfonso S. Siciliano break; 824b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_BEGIN)) 82561ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 826b319d934SAlfonso S. Siciliano break; 827b319d934SAlfonso S. Siciliano case KEY_END: 828b319d934SAlfonso S. Siciliano if (focusinform == false) 829b319d934SAlfonso S. Siciliano break; 830b319d934SAlfonso S. Siciliano if (fieldctl(item, MOVE_CURSOR_END)) 83161ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 832b319d934SAlfonso S. Siciliano break; 833b319d934SAlfonso S. Siciliano case KEY_F(1): 834b319d934SAlfonso S. Siciliano if (conf->key.f1_file == NULL && 835b319d934SAlfonso S. Siciliano conf->key.f1_message == NULL) 836b319d934SAlfonso S. Siciliano break; 837b319d934SAlfonso S. Siciliano curs_set(0); 83861ba55bcSBaptiste Daroussin if (f1help_dialog(conf) != 0) { 839b319d934SAlfonso S. Siciliano retval = BSDDIALOG_ERROR; 840b319d934SAlfonso S. Siciliano loop = false; 841b319d934SAlfonso S. Siciliano } 84261ba55bcSBaptiste Daroussin if (form_redraw(&d, &form, focusinform) != 0) 84361ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 84461ba55bcSBaptiste Daroussin break; 845*a6d8be45SAlfonso S. Siciliano case KEY_CTRL('l'): 846b319d934SAlfonso S. Siciliano case KEY_RESIZE: 84761ba55bcSBaptiste Daroussin if (form_redraw(&d, &form, focusinform) != 0) 848b319d934SAlfonso S. Siciliano return (BSDDIALOG_ERROR); 849b319d934SAlfonso S. Siciliano break; 850b319d934SAlfonso S. Siciliano default: 851b319d934SAlfonso S. Siciliano if (wchtype == KEY_CODE_YES) 852b319d934SAlfonso S. Siciliano break; 853b319d934SAlfonso S. Siciliano if (focusinform) { 854b319d934SAlfonso S. Siciliano if (item->fieldonebyte && wctob(input) == EOF) 855b319d934SAlfonso S. Siciliano break; 856b319d934SAlfonso S. Siciliano /* 857b319d934SAlfonso S. Siciliano * MOVE_CURSOR_RIGHT manages new positions 858b319d934SAlfonso S. Siciliano * because the cursor remains on the new letter, 859b319d934SAlfonso S. Siciliano * "if" and "while" update the positions. 860b319d934SAlfonso S. Siciliano */ 86161ba55bcSBaptiste Daroussin if (insertch(item, input, form.securewch)) { 862b319d934SAlfonso S. Siciliano fieldctl(item, MOVE_CURSOR_RIGHT); 863b319d934SAlfonso S. Siciliano /* 864b319d934SAlfonso S. Siciliano * no if (fieldctl), update always 865b319d934SAlfonso S. Siciliano * because it fails with maxletters. 866b319d934SAlfonso S. Siciliano */ 86761ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 868b319d934SAlfonso S. Siciliano } 869b319d934SAlfonso S. Siciliano } else { 87061ba55bcSBaptiste Daroussin if (shortcut_buttons(input, &d.bs)) { 87161ba55bcSBaptiste Daroussin DRAW_BUTTONS(d); 87261ba55bcSBaptiste Daroussin doupdate(); 87361ba55bcSBaptiste Daroussin retval = BUTTONVALUE(d.bs); 874b319d934SAlfonso S. Siciliano loop = false; 875b319d934SAlfonso S. Siciliano } 876b319d934SAlfonso S. Siciliano } 877b319d934SAlfonso S. Siciliano break; 87861ba55bcSBaptiste Daroussin } /* end switch get_wch() */ 879b319d934SAlfonso S. Siciliano 880b319d934SAlfonso S. Siciliano if (switchfocus) { 881b319d934SAlfonso S. Siciliano focusinform = !focusinform; 88261ba55bcSBaptiste Daroussin d.bs.curr = 0; 88361ba55bcSBaptiste Daroussin redrawbuttons(&d, 884b319d934SAlfonso S. Siciliano conf->button.always_active || !focusinform, 885b319d934SAlfonso S. Siciliano !focusinform); 88661ba55bcSBaptiste Daroussin wnoutrefresh(d.widget); 88761ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, focusinform); 888b319d934SAlfonso S. Siciliano switchfocus = false; 889b319d934SAlfonso S. Siciliano } 890b319d934SAlfonso S. Siciliano 891b319d934SAlfonso S. Siciliano if (changeitem) { 89261ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, false); 89361ba55bcSBaptiste Daroussin form.sel = next; 89461ba55bcSBaptiste Daroussin item = &form.pritems[form.sel]; 895b319d934SAlfonso S. Siciliano curriteminview(&form, item); 89661ba55bcSBaptiste Daroussin update_formbox(conf, &form); 89761ba55bcSBaptiste Daroussin wnoutrefresh(form.box); 89861ba55bcSBaptiste Daroussin DRAWITEM_TRICK(&form, form.sel, true); 899b319d934SAlfonso S. Siciliano changeitem = false; 900b319d934SAlfonso S. Siciliano } 90161ba55bcSBaptiste Daroussin } /* end while (loop) */ 902b319d934SAlfonso S. Siciliano 903b319d934SAlfonso S. Siciliano curs_set(0); 904b319d934SAlfonso S. Siciliano 90561ba55bcSBaptiste Daroussin if (return_values(conf, &form, items) == BSDDIALOG_ERROR) 90661ba55bcSBaptiste Daroussin return (BSDDIALOG_ERROR); 90761ba55bcSBaptiste Daroussin 90861ba55bcSBaptiste Daroussin if (focusitem != NULL) 90961ba55bcSBaptiste Daroussin *focusitem = form.sel; 91061ba55bcSBaptiste Daroussin 91161ba55bcSBaptiste Daroussin if (form.hasbottomdesc && conf->clear) { 91261ba55bcSBaptiste Daroussin move(SCREENLINES - 1, 2); 91361ba55bcSBaptiste Daroussin clrtoeol(); 914b319d934SAlfonso S. Siciliano } 91561ba55bcSBaptiste Daroussin for (i = 0; i < form.nitems; i++) { 91661ba55bcSBaptiste Daroussin free(form.pritems[i].privwbuf); 91761ba55bcSBaptiste Daroussin free(form.pritems[i].pubwbuf); 91861ba55bcSBaptiste Daroussin } 91961ba55bcSBaptiste Daroussin delwin(form.pad); 92061ba55bcSBaptiste Daroussin delwin(form.box); 92161ba55bcSBaptiste Daroussin end_dialog(&d); 922c76f0793SBaptiste Daroussin 923b319d934SAlfonso S. Siciliano return (retval); 924c76f0793SBaptiste Daroussin } 925