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