xref: /freebsd/contrib/bsddialog/lib/formbox.c (revision a6d8be451f62d425b71a4874f7d4e133b9fb393c)
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