xref: /freebsd-src/contrib/bsddialog/lib/menubox.c (revision c76f07938c44264c7ebd400c23f218e561960d23)
1*c76f0793SBaptiste Daroussin /*-
2*c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3*c76f0793SBaptiste Daroussin  *
4*c76f0793SBaptiste Daroussin  * Copyright (c) 2021 Alfonso Sabato Siciliano
5*c76f0793SBaptiste Daroussin  *
6*c76f0793SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7*c76f0793SBaptiste Daroussin  * modification, are permitted provided that the following conditions
8*c76f0793SBaptiste Daroussin  * are met:
9*c76f0793SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10*c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11*c76f0793SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12*c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13*c76f0793SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14*c76f0793SBaptiste Daroussin  *
15*c76f0793SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*c76f0793SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*c76f0793SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*c76f0793SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*c76f0793SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*c76f0793SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*c76f0793SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*c76f0793SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*c76f0793SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*c76f0793SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*c76f0793SBaptiste Daroussin  * SUCH DAMAGE.
26*c76f0793SBaptiste Daroussin  */
27*c76f0793SBaptiste Daroussin 
28*c76f0793SBaptiste Daroussin #include <sys/param.h>
29*c76f0793SBaptiste Daroussin 
30*c76f0793SBaptiste Daroussin #include <ctype.h>
31*c76f0793SBaptiste Daroussin #include <string.h>
32*c76f0793SBaptiste Daroussin 
33*c76f0793SBaptiste Daroussin #ifdef PORTNCURSES
34*c76f0793SBaptiste Daroussin #include <ncurses/curses.h>
35*c76f0793SBaptiste Daroussin #else
36*c76f0793SBaptiste Daroussin #include <curses.h>
37*c76f0793SBaptiste Daroussin #endif
38*c76f0793SBaptiste Daroussin 
39*c76f0793SBaptiste Daroussin #include "bsddialog.h"
40*c76f0793SBaptiste Daroussin #include "lib_util.h"
41*c76f0793SBaptiste Daroussin #include "bsddialog_theme.h"
42*c76f0793SBaptiste Daroussin 
43*c76f0793SBaptiste Daroussin /* "Menu": checklist - menu - mixedlist - radiolist - treeview - buildlist */
44*c76f0793SBaptiste Daroussin 
45*c76f0793SBaptiste Daroussin #define DEPTHSPACE	4
46*c76f0793SBaptiste Daroussin #define MIN_HEIGHT	VBORDERS + 6 /* 2 buttons 1 text 3 menu */
47*c76f0793SBaptiste Daroussin 
48*c76f0793SBaptiste Daroussin extern struct bsddialog_theme t;
49*c76f0793SBaptiste Daroussin 
50*c76f0793SBaptiste Daroussin enum menumode {
51*c76f0793SBaptiste Daroussin 	BUILDLISTMODE,
52*c76f0793SBaptiste Daroussin 	CHECKLISTMODE,
53*c76f0793SBaptiste Daroussin 	MENUMODE,
54*c76f0793SBaptiste Daroussin 	MIXEDLISTMODE,
55*c76f0793SBaptiste Daroussin 	RADIOLISTMODE,
56*c76f0793SBaptiste Daroussin 	SEPARATORMODE
57*c76f0793SBaptiste Daroussin };
58*c76f0793SBaptiste Daroussin 
59*c76f0793SBaptiste Daroussin struct lineposition {
60*c76f0793SBaptiste Daroussin 	unsigned int maxsepstr;
61*c76f0793SBaptiste Daroussin 	unsigned int maxprefix;
62*c76f0793SBaptiste Daroussin 	unsigned int xselector;
63*c76f0793SBaptiste Daroussin 	unsigned int selectorlen;
64*c76f0793SBaptiste Daroussin 	unsigned int maxdepth;
65*c76f0793SBaptiste Daroussin 	unsigned int xname;
66*c76f0793SBaptiste Daroussin 	unsigned int maxname;
67*c76f0793SBaptiste Daroussin 	unsigned int xdesc;
68*c76f0793SBaptiste Daroussin 	unsigned int maxdesc;
69*c76f0793SBaptiste Daroussin 	unsigned int line;
70*c76f0793SBaptiste Daroussin };
71*c76f0793SBaptiste Daroussin 
72*c76f0793SBaptiste Daroussin static int checkradiolist(int nitems, struct bsddialog_menuitem *items)
73*c76f0793SBaptiste Daroussin {
74*c76f0793SBaptiste Daroussin 	int i, error;
75*c76f0793SBaptiste Daroussin 
76*c76f0793SBaptiste Daroussin 	error = 0;
77*c76f0793SBaptiste Daroussin 	for (i=0; i<nitems; i++) {
78*c76f0793SBaptiste Daroussin 		if (error > 0)
79*c76f0793SBaptiste Daroussin 			items[i].on = false;
80*c76f0793SBaptiste Daroussin 
81*c76f0793SBaptiste Daroussin 		if (items[i].on == true)
82*c76f0793SBaptiste Daroussin 			error++;
83*c76f0793SBaptiste Daroussin 	}
84*c76f0793SBaptiste Daroussin 
85*c76f0793SBaptiste Daroussin 	return (error == 0 ? 0 : -1);
86*c76f0793SBaptiste Daroussin }
87*c76f0793SBaptiste Daroussin 
88*c76f0793SBaptiste Daroussin static int checkmenu(int nitems, struct bsddialog_menuitem *items) // useful?
89*c76f0793SBaptiste Daroussin {
90*c76f0793SBaptiste Daroussin 	int i, error;
91*c76f0793SBaptiste Daroussin 
92*c76f0793SBaptiste Daroussin 	error = 0;
93*c76f0793SBaptiste Daroussin 	for (i=0; i<nitems; i++) {
94*c76f0793SBaptiste Daroussin 		if (items[i].on == true)
95*c76f0793SBaptiste Daroussin 			error++;
96*c76f0793SBaptiste Daroussin 
97*c76f0793SBaptiste Daroussin 		items[i].on = false;
98*c76f0793SBaptiste Daroussin 	}
99*c76f0793SBaptiste Daroussin 
100*c76f0793SBaptiste Daroussin 	return (error == 0 ? 0 : -1);
101*c76f0793SBaptiste Daroussin }
102*c76f0793SBaptiste Daroussin 
103*c76f0793SBaptiste Daroussin static void
104*c76f0793SBaptiste Daroussin getfirst(int ngroups, struct bsddialog_menugroup *groups, int *abs, int *group,
105*c76f0793SBaptiste Daroussin     int *rel)
106*c76f0793SBaptiste Daroussin {
107*c76f0793SBaptiste Daroussin 	int i, a;
108*c76f0793SBaptiste Daroussin 
109*c76f0793SBaptiste Daroussin 	*abs = *rel = *group = -1;
110*c76f0793SBaptiste Daroussin 	a = 0;
111*c76f0793SBaptiste Daroussin 	for (i=0; i<ngroups; i++) {
112*c76f0793SBaptiste Daroussin 		if (groups[i].type == BSDDIALOG_SEPARATOR) {
113*c76f0793SBaptiste Daroussin 			a += groups[i].nitems;
114*c76f0793SBaptiste Daroussin 			continue;
115*c76f0793SBaptiste Daroussin 		}
116*c76f0793SBaptiste Daroussin 		if (groups[i].nitems != 0) {
117*c76f0793SBaptiste Daroussin 			*group = i;
118*c76f0793SBaptiste Daroussin 			*abs = a;
119*c76f0793SBaptiste Daroussin 			*rel = 0;
120*c76f0793SBaptiste Daroussin 			break;
121*c76f0793SBaptiste Daroussin 		}
122*c76f0793SBaptiste Daroussin 	}
123*c76f0793SBaptiste Daroussin }
124*c76f0793SBaptiste Daroussin 
125*c76f0793SBaptiste Daroussin static void
126*c76f0793SBaptiste Daroussin getfirst_with_default(struct bsddialog_conf conf, int ngroups,
127*c76f0793SBaptiste Daroussin     struct bsddialog_menugroup *groups, int *abs, int *group, int *rel)
128*c76f0793SBaptiste Daroussin {
129*c76f0793SBaptiste Daroussin 	int i, j, a;
130*c76f0793SBaptiste Daroussin 	struct bsddialog_menuitem *item;
131*c76f0793SBaptiste Daroussin 
132*c76f0793SBaptiste Daroussin 	getfirst(ngroups, groups, abs, group, rel);
133*c76f0793SBaptiste Daroussin 	if (*abs < 0)
134*c76f0793SBaptiste Daroussin 		return;
135*c76f0793SBaptiste Daroussin 
136*c76f0793SBaptiste Daroussin 	a = *abs;
137*c76f0793SBaptiste Daroussin 
138*c76f0793SBaptiste Daroussin 	for (i=*group; i<ngroups; i++) {
139*c76f0793SBaptiste Daroussin 		if (groups[i].type == BSDDIALOG_SEPARATOR) {
140*c76f0793SBaptiste Daroussin 			a += groups[i].nitems;
141*c76f0793SBaptiste Daroussin 			continue;
142*c76f0793SBaptiste Daroussin 		}
143*c76f0793SBaptiste Daroussin 		for (j = 0; j < (int) groups[i].nitems; j++) {
144*c76f0793SBaptiste Daroussin 			item = &groups[i].items[j];
145*c76f0793SBaptiste Daroussin 			if (conf.menu.default_item != NULL && item->name != NULL) {
146*c76f0793SBaptiste Daroussin 				if (strcmp(item->name, conf.menu.default_item) == 0) {
147*c76f0793SBaptiste Daroussin 					*abs = a;
148*c76f0793SBaptiste Daroussin 					*group = i;
149*c76f0793SBaptiste Daroussin 					*rel = j;
150*c76f0793SBaptiste Daroussin 					return;
151*c76f0793SBaptiste Daroussin 				}
152*c76f0793SBaptiste Daroussin 			}
153*c76f0793SBaptiste Daroussin 			a++;
154*c76f0793SBaptiste Daroussin 		}
155*c76f0793SBaptiste Daroussin 	}
156*c76f0793SBaptiste Daroussin }
157*c76f0793SBaptiste Daroussin 
158*c76f0793SBaptiste Daroussin static void
159*c76f0793SBaptiste Daroussin getlast(int totnitems, int ngroups, struct bsddialog_menugroup *groups,
160*c76f0793SBaptiste Daroussin     int *abs, int *group, int *rel)
161*c76f0793SBaptiste Daroussin {
162*c76f0793SBaptiste Daroussin 	int i, a;
163*c76f0793SBaptiste Daroussin 
164*c76f0793SBaptiste Daroussin 	a = totnitems - 1;
165*c76f0793SBaptiste Daroussin 	for (i = ngroups-1; i>=0; i--) {
166*c76f0793SBaptiste Daroussin 		if (groups[i].type == BSDDIALOG_SEPARATOR) {
167*c76f0793SBaptiste Daroussin 			a -= groups[i].nitems;
168*c76f0793SBaptiste Daroussin 			continue;
169*c76f0793SBaptiste Daroussin 		}
170*c76f0793SBaptiste Daroussin 		if (groups[i].nitems != 0) {
171*c76f0793SBaptiste Daroussin 			*group = i;
172*c76f0793SBaptiste Daroussin 			*abs = a;
173*c76f0793SBaptiste Daroussin 			*rel = groups[i].nitems - 1;
174*c76f0793SBaptiste Daroussin 			break;
175*c76f0793SBaptiste Daroussin 		}
176*c76f0793SBaptiste Daroussin 	}
177*c76f0793SBaptiste Daroussin }
178*c76f0793SBaptiste Daroussin 
179*c76f0793SBaptiste Daroussin static void
180*c76f0793SBaptiste Daroussin getnext(int ngroups, struct bsddialog_menugroup *groups, int *abs, int *group,
181*c76f0793SBaptiste Daroussin     int *rel)
182*c76f0793SBaptiste Daroussin {
183*c76f0793SBaptiste Daroussin 	int i, a;
184*c76f0793SBaptiste Daroussin 
185*c76f0793SBaptiste Daroussin 	if (*abs < 0 || *group < 0 || *rel < 0)
186*c76f0793SBaptiste Daroussin 		return;
187*c76f0793SBaptiste Daroussin 
188*c76f0793SBaptiste Daroussin 	if (*rel + 1 < (int) groups[*group].nitems) {
189*c76f0793SBaptiste Daroussin 		*rel = *rel + 1;
190*c76f0793SBaptiste Daroussin 		*abs = *abs + 1;
191*c76f0793SBaptiste Daroussin 		return;
192*c76f0793SBaptiste Daroussin 	}
193*c76f0793SBaptiste Daroussin 
194*c76f0793SBaptiste Daroussin 	if (*group + 1 > ngroups)
195*c76f0793SBaptiste Daroussin 		return;
196*c76f0793SBaptiste Daroussin 
197*c76f0793SBaptiste Daroussin 	a = *abs;
198*c76f0793SBaptiste Daroussin 	for (i = *group + 1; i < ngroups; i++) {
199*c76f0793SBaptiste Daroussin 		if (groups[i].type == BSDDIALOG_SEPARATOR) {
200*c76f0793SBaptiste Daroussin 			a += groups[i].nitems;
201*c76f0793SBaptiste Daroussin 			continue;
202*c76f0793SBaptiste Daroussin 		}
203*c76f0793SBaptiste Daroussin 		if (groups[i].nitems != 0) {
204*c76f0793SBaptiste Daroussin 			*group = i;
205*c76f0793SBaptiste Daroussin 			*abs = a + 1;
206*c76f0793SBaptiste Daroussin 			*rel = 0;
207*c76f0793SBaptiste Daroussin 			break;
208*c76f0793SBaptiste Daroussin 		}
209*c76f0793SBaptiste Daroussin 	}
210*c76f0793SBaptiste Daroussin }
211*c76f0793SBaptiste Daroussin 
212*c76f0793SBaptiste Daroussin static void
213*c76f0793SBaptiste Daroussin getfastnext(int menurows, int ngroups, struct bsddialog_menugroup *groups,
214*c76f0793SBaptiste Daroussin     int *abs, int *group, int *rel)
215*c76f0793SBaptiste Daroussin {
216*c76f0793SBaptiste Daroussin 	int a, start, i;
217*c76f0793SBaptiste Daroussin 
218*c76f0793SBaptiste Daroussin 	start = *abs;
219*c76f0793SBaptiste Daroussin 	i = menurows;
220*c76f0793SBaptiste Daroussin 	do {
221*c76f0793SBaptiste Daroussin 		a = *abs;
222*c76f0793SBaptiste Daroussin 		getnext(ngroups, groups, abs, group, rel);
223*c76f0793SBaptiste Daroussin 		i--;
224*c76f0793SBaptiste Daroussin 	} while (*abs != a && *abs < start + menurows && i > 0);
225*c76f0793SBaptiste Daroussin }
226*c76f0793SBaptiste Daroussin 
227*c76f0793SBaptiste Daroussin static void
228*c76f0793SBaptiste Daroussin getprev(struct bsddialog_menugroup *groups, int *abs, int *group, int *rel)
229*c76f0793SBaptiste Daroussin {
230*c76f0793SBaptiste Daroussin 	int i, a;
231*c76f0793SBaptiste Daroussin 
232*c76f0793SBaptiste Daroussin 	if (*abs < 0 || *group < 0 || *rel < 0)
233*c76f0793SBaptiste Daroussin 		return;
234*c76f0793SBaptiste Daroussin 
235*c76f0793SBaptiste Daroussin 	if (*rel > 0) {
236*c76f0793SBaptiste Daroussin 		*rel = *rel - 1;
237*c76f0793SBaptiste Daroussin 		*abs = *abs - 1;
238*c76f0793SBaptiste Daroussin 		return;
239*c76f0793SBaptiste Daroussin 	}
240*c76f0793SBaptiste Daroussin 
241*c76f0793SBaptiste Daroussin 	if (*group - 1 < 0)
242*c76f0793SBaptiste Daroussin 		return;
243*c76f0793SBaptiste Daroussin 
244*c76f0793SBaptiste Daroussin 	a = *abs;
245*c76f0793SBaptiste Daroussin 	for (i = *group - 1; i >= 0; i--) {
246*c76f0793SBaptiste Daroussin 		if (groups[i].type == BSDDIALOG_SEPARATOR) {
247*c76f0793SBaptiste Daroussin 			a -= (int) groups[i].nitems;
248*c76f0793SBaptiste Daroussin 			continue;
249*c76f0793SBaptiste Daroussin 		}
250*c76f0793SBaptiste Daroussin 		if (groups[i].nitems != 0) {
251*c76f0793SBaptiste Daroussin 			*group = i;
252*c76f0793SBaptiste Daroussin 			*abs = a - 1;
253*c76f0793SBaptiste Daroussin 			*rel = (int) groups[i].nitems - 1;
254*c76f0793SBaptiste Daroussin 			break;
255*c76f0793SBaptiste Daroussin 		}
256*c76f0793SBaptiste Daroussin 	}
257*c76f0793SBaptiste Daroussin }
258*c76f0793SBaptiste Daroussin 
259*c76f0793SBaptiste Daroussin static void
260*c76f0793SBaptiste Daroussin getfastprev(int menurows, struct bsddialog_menugroup *groups, int *abs,
261*c76f0793SBaptiste Daroussin     int *group, int *rel)
262*c76f0793SBaptiste Daroussin {
263*c76f0793SBaptiste Daroussin 	int a, start, i;
264*c76f0793SBaptiste Daroussin 
265*c76f0793SBaptiste Daroussin 	start = *abs;
266*c76f0793SBaptiste Daroussin 	i = menurows;
267*c76f0793SBaptiste Daroussin 	do {
268*c76f0793SBaptiste Daroussin 		a = *abs;
269*c76f0793SBaptiste Daroussin 		getprev(groups, abs, group, rel);
270*c76f0793SBaptiste Daroussin 		i--;
271*c76f0793SBaptiste Daroussin 	} while (*abs != a && *abs > start - menurows && i > 0);
272*c76f0793SBaptiste Daroussin }
273*c76f0793SBaptiste Daroussin 
274*c76f0793SBaptiste Daroussin static enum menumode
275*c76f0793SBaptiste Daroussin getmode(enum menumode mode, struct bsddialog_menugroup group)
276*c76f0793SBaptiste Daroussin {
277*c76f0793SBaptiste Daroussin 
278*c76f0793SBaptiste Daroussin 	if (mode == MIXEDLISTMODE) {
279*c76f0793SBaptiste Daroussin 		if (group.type == BSDDIALOG_SEPARATOR)
280*c76f0793SBaptiste Daroussin 			mode = SEPARATORMODE;
281*c76f0793SBaptiste Daroussin 		else if (group.type == BSDDIALOG_RADIOLIST)
282*c76f0793SBaptiste Daroussin 			mode = RADIOLISTMODE;
283*c76f0793SBaptiste Daroussin 		else if (group.type == BSDDIALOG_CHECKLIST)
284*c76f0793SBaptiste Daroussin 			mode = CHECKLISTMODE;
285*c76f0793SBaptiste Daroussin 	}
286*c76f0793SBaptiste Daroussin 
287*c76f0793SBaptiste Daroussin 	return mode;
288*c76f0793SBaptiste Daroussin }
289*c76f0793SBaptiste Daroussin 
290*c76f0793SBaptiste Daroussin static void
291*c76f0793SBaptiste Daroussin drawitem(struct bsddialog_conf conf, WINDOW *pad, int y,
292*c76f0793SBaptiste Daroussin     struct bsddialog_menuitem item, enum menumode mode, struct lineposition pos,
293*c76f0793SBaptiste Daroussin     bool curr)
294*c76f0793SBaptiste Daroussin {
295*c76f0793SBaptiste Daroussin 	int color, colorname, linech;
296*c76f0793SBaptiste Daroussin 
297*c76f0793SBaptiste Daroussin 	color = curr ? t.curritemcolor : t.itemcolor;
298*c76f0793SBaptiste Daroussin 	colorname = curr ? t.currtagcolor : t.tagcolor;
299*c76f0793SBaptiste Daroussin 
300*c76f0793SBaptiste Daroussin 	if (mode == SEPARATORMODE) {
301*c76f0793SBaptiste Daroussin 		if (conf.no_lines == false) {
302*c76f0793SBaptiste Daroussin 			wattron(pad, t.itemcolor);
303*c76f0793SBaptiste Daroussin 			linech = conf.ascii_lines ? '-' : ACS_HLINE;
304*c76f0793SBaptiste Daroussin 			mvwhline(pad, y, 0, linech, pos.line);
305*c76f0793SBaptiste Daroussin 			wattroff(pad, t.itemcolor);
306*c76f0793SBaptiste Daroussin 		}
307*c76f0793SBaptiste Daroussin 		wmove(pad, y, pos.line/2 - (strlen(item.name)+strlen(item.desc))/2);
308*c76f0793SBaptiste Daroussin 		wattron(pad, t.namesepcolor);
309*c76f0793SBaptiste Daroussin 		waddstr(pad, item.name);
310*c76f0793SBaptiste Daroussin 		wattroff(pad, t.namesepcolor);
311*c76f0793SBaptiste Daroussin 		if (strlen(item.name) > 0 && strlen(item.desc) > 0)
312*c76f0793SBaptiste Daroussin 			waddch(pad, ' ');
313*c76f0793SBaptiste Daroussin 		wattron(pad, t.descsepcolor);
314*c76f0793SBaptiste Daroussin 		waddstr(pad, item.desc);
315*c76f0793SBaptiste Daroussin 		wattroff(pad, t.descsepcolor);
316*c76f0793SBaptiste Daroussin 		return;
317*c76f0793SBaptiste Daroussin 	}
318*c76f0793SBaptiste Daroussin 
319*c76f0793SBaptiste Daroussin 	/* prefix */
320*c76f0793SBaptiste Daroussin 	if (item.prefix != NULL && item.prefix[0] != '\0')
321*c76f0793SBaptiste Daroussin 		mvwaddstr(pad, y, 0, item.prefix);
322*c76f0793SBaptiste Daroussin 
323*c76f0793SBaptiste Daroussin 	/* selector */
324*c76f0793SBaptiste Daroussin 	wmove(pad, y, pos.xselector);
325*c76f0793SBaptiste Daroussin 	wattron(pad, color);
326*c76f0793SBaptiste Daroussin 	if (mode == CHECKLISTMODE)
327*c76f0793SBaptiste Daroussin 		wprintw(pad, "[%c]", item.on ? 'X' : ' ');
328*c76f0793SBaptiste Daroussin 	if (mode == RADIOLISTMODE)
329*c76f0793SBaptiste Daroussin 		wprintw(pad, "(%c)", item.on ? '*' : ' ');
330*c76f0793SBaptiste Daroussin 	wattroff(pad, color);
331*c76f0793SBaptiste Daroussin 
332*c76f0793SBaptiste Daroussin 	/* name */
333*c76f0793SBaptiste Daroussin 	if (mode != BUILDLISTMODE && conf.menu.no_tags == false) {
334*c76f0793SBaptiste Daroussin 		wattron(pad, colorname);
335*c76f0793SBaptiste Daroussin 		mvwaddstr(pad, y, pos.xname + item.depth * DEPTHSPACE, item.name);
336*c76f0793SBaptiste Daroussin 		wattroff(pad, colorname);
337*c76f0793SBaptiste Daroussin 	}
338*c76f0793SBaptiste Daroussin 
339*c76f0793SBaptiste Daroussin 	/* description */
340*c76f0793SBaptiste Daroussin 	if (conf.menu.no_items == false) {
341*c76f0793SBaptiste Daroussin 		if ((mode == BUILDLISTMODE || conf.menu.no_tags) && curr == false)
342*c76f0793SBaptiste Daroussin 			color = item.on ? t.tagcolor : t.itemcolor;
343*c76f0793SBaptiste Daroussin 		wattron(pad, color);
344*c76f0793SBaptiste Daroussin 		if (conf.menu.no_tags)
345*c76f0793SBaptiste Daroussin 			mvwaddstr(pad, y, pos.xname + item.depth * DEPTHSPACE, item.desc);
346*c76f0793SBaptiste Daroussin 		else
347*c76f0793SBaptiste Daroussin 			mvwaddstr(pad, y, pos.xdesc, item.desc);
348*c76f0793SBaptiste Daroussin 		wattroff(pad, color);
349*c76f0793SBaptiste Daroussin 	}
350*c76f0793SBaptiste Daroussin 
351*c76f0793SBaptiste Daroussin 	/* bottom desc (item help) */
352*c76f0793SBaptiste Daroussin 	if (item.bottomdesc != NULL && item.bottomdesc[0] != '\0') {
353*c76f0793SBaptiste Daroussin 		move(LINES-1, 2);
354*c76f0793SBaptiste Daroussin 		clrtoeol();
355*c76f0793SBaptiste Daroussin 		addstr(item.bottomdesc);
356*c76f0793SBaptiste Daroussin 
357*c76f0793SBaptiste Daroussin 		refresh();
358*c76f0793SBaptiste Daroussin 	}
359*c76f0793SBaptiste Daroussin }
360*c76f0793SBaptiste Daroussin 
361*c76f0793SBaptiste Daroussin static void
362*c76f0793SBaptiste Daroussin menu_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
363*c76f0793SBaptiste Daroussin     char *text, int linelen, unsigned int *menurows, int nitems,
364*c76f0793SBaptiste Daroussin     struct buttons bs)
365*c76f0793SBaptiste Daroussin {
366*c76f0793SBaptiste Daroussin 	int textrow, menusize;
367*c76f0793SBaptiste Daroussin 
368*c76f0793SBaptiste Daroussin 	textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
369*c76f0793SBaptiste Daroussin 
370*c76f0793SBaptiste Daroussin 	if (cols == BSDDIALOG_AUTOSIZE) {
371*c76f0793SBaptiste Daroussin 		*w = VBORDERS;
372*c76f0793SBaptiste Daroussin 		/* buttons size */
373*c76f0793SBaptiste Daroussin 		*w += bs.nbuttons * bs.sizebutton;
374*c76f0793SBaptiste Daroussin 		*w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
375*c76f0793SBaptiste Daroussin 		/* line size */
376*c76f0793SBaptiste Daroussin 		*w = MAX(*w, linelen + 6);
377*c76f0793SBaptiste Daroussin 		/*
378*c76f0793SBaptiste Daroussin 		* avoid terminal overflow,
379*c76f0793SBaptiste Daroussin 		* -1 fix false negative with big menu over the terminal and
380*c76f0793SBaptiste Daroussin 		* autosize, for example "portconfig /usr/ports/www/apache24/".
381*c76f0793SBaptiste Daroussin 		*/
382*c76f0793SBaptiste Daroussin 		*w = MIN(*w, widget_max_width(conf)-1);
383*c76f0793SBaptiste Daroussin 	}
384*c76f0793SBaptiste Daroussin 
385*c76f0793SBaptiste Daroussin 	if (rows == BSDDIALOG_AUTOSIZE) {
386*c76f0793SBaptiste Daroussin 		*h = HBORDERS + 2 /* buttons */ + textrow;
387*c76f0793SBaptiste Daroussin 
388*c76f0793SBaptiste Daroussin 		if (*menurows == 0) {
389*c76f0793SBaptiste Daroussin 			*h += nitems + 2;
390*c76f0793SBaptiste Daroussin 			*h = MIN(*h, widget_max_height(conf));
391*c76f0793SBaptiste Daroussin 			menusize = MIN(nitems + 2, *h - (HBORDERS + 2 + textrow));
392*c76f0793SBaptiste Daroussin 			menusize -=2;
393*c76f0793SBaptiste Daroussin 			*menurows = menusize < 0 ? 0 : menusize;
394*c76f0793SBaptiste Daroussin 		}
395*c76f0793SBaptiste Daroussin 		else /* h autosize with a fixed menurows */
396*c76f0793SBaptiste Daroussin 			*h = *h + *menurows + 2;
397*c76f0793SBaptiste Daroussin 
398*c76f0793SBaptiste Daroussin 		/* avoid terminal overflow */
399*c76f0793SBaptiste Daroussin 		*h = MIN(*h, widget_max_height(conf));
400*c76f0793SBaptiste Daroussin 	}
401*c76f0793SBaptiste Daroussin 	else {
402*c76f0793SBaptiste Daroussin 		if (*menurows == 0)
403*c76f0793SBaptiste Daroussin 			*menurows = MIN(rows-6-textrow, nitems);
404*c76f0793SBaptiste Daroussin 	}
405*c76f0793SBaptiste Daroussin }
406*c76f0793SBaptiste Daroussin 
407*c76f0793SBaptiste Daroussin static int
408*c76f0793SBaptiste Daroussin menu_checksize(int rows, int cols, char *text, int menurows, int nitems,
409*c76f0793SBaptiste Daroussin     struct buttons bs)
410*c76f0793SBaptiste Daroussin {
411*c76f0793SBaptiste Daroussin 	int mincols, textrow, menusize;
412*c76f0793SBaptiste Daroussin 
413*c76f0793SBaptiste Daroussin 	mincols = VBORDERS;
414*c76f0793SBaptiste Daroussin 	/* buttons */
415*c76f0793SBaptiste Daroussin 	mincols += bs.nbuttons * bs.sizebutton;
416*c76f0793SBaptiste Daroussin 	mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
417*c76f0793SBaptiste Daroussin 	/* line, comment to permet some cols hidden */
418*c76f0793SBaptiste Daroussin 	/* mincols = MAX(mincols, linelen); */
419*c76f0793SBaptiste Daroussin 
420*c76f0793SBaptiste Daroussin 	if (cols < mincols)
421*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Few cols, width < size buttons or "\
422*c76f0793SBaptiste Daroussin 		    "name+descripion of the items");
423*c76f0793SBaptiste Daroussin 
424*c76f0793SBaptiste Daroussin 	textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
425*c76f0793SBaptiste Daroussin 
426*c76f0793SBaptiste Daroussin 	if (nitems > 0 && menurows == 0)
427*c76f0793SBaptiste Daroussin 		RETURN_ERROR("items > 0 but menurows == 0, probably terminal "\
428*c76f0793SBaptiste Daroussin 		    "too small");
429*c76f0793SBaptiste Daroussin 
430*c76f0793SBaptiste Daroussin 	menusize = nitems > 0 ? 3 : 0;
431*c76f0793SBaptiste Daroussin 	if (rows < 2  + 2 + menusize + textrow)
432*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Few lines for this menus");
433*c76f0793SBaptiste Daroussin 
434*c76f0793SBaptiste Daroussin 	return 0;
435*c76f0793SBaptiste Daroussin }
436*c76f0793SBaptiste Daroussin 
437*c76f0793SBaptiste Daroussin /* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
438*c76f0793SBaptiste Daroussin static void
439*c76f0793SBaptiste Daroussin update_menuwin(struct bsddialog_conf conf, WINDOW *menuwin, int h, int w,
440*c76f0793SBaptiste Daroussin     int totnitems, unsigned int menurows, int ymenupad)
441*c76f0793SBaptiste Daroussin {
442*c76f0793SBaptiste Daroussin 
443*c76f0793SBaptiste Daroussin 	if (totnitems > (int) menurows) {
444*c76f0793SBaptiste Daroussin 		draw_borders(conf, menuwin, h, w, LOWERED);
445*c76f0793SBaptiste Daroussin 
446*c76f0793SBaptiste Daroussin 		if (ymenupad > 0) {
447*c76f0793SBaptiste Daroussin 			wattron(menuwin, t.lineraisecolor);
448*c76f0793SBaptiste Daroussin 			mvwprintw(menuwin, 0, 2, "^^");
449*c76f0793SBaptiste Daroussin 			wattroff(menuwin, t.lineraisecolor);
450*c76f0793SBaptiste Daroussin 		}
451*c76f0793SBaptiste Daroussin 		if ((int) (ymenupad + menurows) < totnitems) {
452*c76f0793SBaptiste Daroussin 			wattron(menuwin, t.linelowercolor);
453*c76f0793SBaptiste Daroussin 			mvwprintw(menuwin, h-1, 2, "vv");
454*c76f0793SBaptiste Daroussin 			wattroff(menuwin, t.linelowercolor);
455*c76f0793SBaptiste Daroussin 		}
456*c76f0793SBaptiste Daroussin 
457*c76f0793SBaptiste Daroussin 		mvwprintw(menuwin, h-1, w-10, "%3d%%",
458*c76f0793SBaptiste Daroussin 		    100 * (ymenupad + menurows) / totnitems);
459*c76f0793SBaptiste Daroussin 	}
460*c76f0793SBaptiste Daroussin }
461*c76f0793SBaptiste Daroussin 
462*c76f0793SBaptiste Daroussin static int
463*c76f0793SBaptiste Daroussin do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
464*c76f0793SBaptiste Daroussin     unsigned int menurows, enum menumode mode, int ngroups,
465*c76f0793SBaptiste Daroussin     struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
466*c76f0793SBaptiste Daroussin {
467*c76f0793SBaptiste Daroussin 	WINDOW  *shadow, *widget, *textpad, *menuwin, *menupad;
468*c76f0793SBaptiste Daroussin 	int i, j, y, x, h, w, htextpad, output, input;
469*c76f0793SBaptiste Daroussin 	int ymenupad, ys, ye, xs, xe, abs, g, rel, totnitems;
470*c76f0793SBaptiste Daroussin 	bool loop, automenurows;
471*c76f0793SBaptiste Daroussin 	struct buttons bs;
472*c76f0793SBaptiste Daroussin 	struct bsddialog_menuitem *item;
473*c76f0793SBaptiste Daroussin 	enum menumode currmode;
474*c76f0793SBaptiste Daroussin 	struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
475*c76f0793SBaptiste Daroussin 
476*c76f0793SBaptiste Daroussin 	automenurows = menurows == BSDDIALOG_AUTOSIZE ? true : false;
477*c76f0793SBaptiste Daroussin 
478*c76f0793SBaptiste Daroussin 	totnitems = 0;
479*c76f0793SBaptiste Daroussin 	for (i=0; i < ngroups; i++) {
480*c76f0793SBaptiste Daroussin 		currmode = getmode(mode, groups[i]);
481*c76f0793SBaptiste Daroussin 		if (currmode == RADIOLISTMODE)
482*c76f0793SBaptiste Daroussin 			checkradiolist(groups[i].nitems, groups[i].items);
483*c76f0793SBaptiste Daroussin 
484*c76f0793SBaptiste Daroussin 		if (currmode == MENUMODE)
485*c76f0793SBaptiste Daroussin 			checkmenu(groups[i].nitems, groups[i].items);
486*c76f0793SBaptiste Daroussin 
487*c76f0793SBaptiste Daroussin 		if (currmode == RADIOLISTMODE || currmode == CHECKLISTMODE)
488*c76f0793SBaptiste Daroussin 			pos.selectorlen = 3;
489*c76f0793SBaptiste Daroussin 
490*c76f0793SBaptiste Daroussin 		for (j=0; j < (int) groups[i].nitems; j++) {
491*c76f0793SBaptiste Daroussin 			totnitems++;
492*c76f0793SBaptiste Daroussin 			item = &groups[i].items[j];
493*c76f0793SBaptiste Daroussin 
494*c76f0793SBaptiste Daroussin 			if (groups[i].type == BSDDIALOG_SEPARATOR) {
495*c76f0793SBaptiste Daroussin 				pos.maxsepstr = MAX(pos.maxsepstr,
496*c76f0793SBaptiste Daroussin 				    strlen(item->name) + strlen(item->desc));
497*c76f0793SBaptiste Daroussin 				continue;
498*c76f0793SBaptiste Daroussin 			}
499*c76f0793SBaptiste Daroussin 
500*c76f0793SBaptiste Daroussin 			pos.maxprefix = MAX(pos.maxprefix, strlen(item->prefix));
501*c76f0793SBaptiste Daroussin 			pos.maxdepth  = MAX((int) pos.maxdepth, item->depth);
502*c76f0793SBaptiste Daroussin 			pos.maxname   = MAX(pos.maxname, strlen(item->name));
503*c76f0793SBaptiste Daroussin 			pos.maxdesc   = MAX(pos.maxdesc, strlen(item->desc));
504*c76f0793SBaptiste Daroussin 		}
505*c76f0793SBaptiste Daroussin 	}
506*c76f0793SBaptiste Daroussin 	pos.maxname = conf.menu.no_tags ? 0 : pos.maxname;
507*c76f0793SBaptiste Daroussin 	pos.maxdesc = conf.menu.no_items ? 0 : pos.maxdesc;
508*c76f0793SBaptiste Daroussin 	pos.maxdepth *= DEPTHSPACE;
509*c76f0793SBaptiste Daroussin 
510*c76f0793SBaptiste Daroussin 	pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0);
511*c76f0793SBaptiste Daroussin 	pos.xname = pos.xselector + pos.selectorlen + (pos.selectorlen > 0 ? 1 : 0);
512*c76f0793SBaptiste Daroussin 	pos.xdesc = pos.maxdepth + pos.xname + pos.maxname;
513*c76f0793SBaptiste Daroussin 	pos.xdesc += (pos.maxname != 0 ? 1 : 0);
514*c76f0793SBaptiste Daroussin 	pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc);
515*c76f0793SBaptiste Daroussin 
516*c76f0793SBaptiste Daroussin 
517*c76f0793SBaptiste Daroussin 	get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
518*c76f0793SBaptiste Daroussin 	    BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
519*c76f0793SBaptiste Daroussin 
520*c76f0793SBaptiste Daroussin 	if (set_widget_size(conf, rows, cols, &h, &w) != 0)
521*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
522*c76f0793SBaptiste Daroussin 	menu_autosize(conf, rows, cols, &h, &w, text, pos.line, &menurows,
523*c76f0793SBaptiste Daroussin 	    totnitems, bs);
524*c76f0793SBaptiste Daroussin 	if (menu_checksize(h, w, text, menurows, totnitems, bs) != 0)
525*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
526*c76f0793SBaptiste Daroussin 	if (set_widget_position(conf, &y, &x, h, w) != 0)
527*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
528*c76f0793SBaptiste Daroussin 
529*c76f0793SBaptiste Daroussin 	if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
530*c76f0793SBaptiste Daroussin 	    &textpad, &htextpad, text, true) != 0)
531*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
532*c76f0793SBaptiste Daroussin 
533*c76f0793SBaptiste Daroussin 	prefresh(textpad, 0, 0, y + 1, x + 1 + t.texthmargin,
534*c76f0793SBaptiste Daroussin 	    y + h - menurows, x + 1 + w - t.texthmargin);
535*c76f0793SBaptiste Daroussin 
536*c76f0793SBaptiste Daroussin 	menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2,
537*c76f0793SBaptiste Daroussin 	    menurows+2, w-4, LOWERED);
538*c76f0793SBaptiste Daroussin 
539*c76f0793SBaptiste Daroussin 	menupad = newpad(totnitems, pos.line);
540*c76f0793SBaptiste Daroussin 	wbkgd(menupad, t.widgetcolor);
541*c76f0793SBaptiste Daroussin 
542*c76f0793SBaptiste Daroussin 	getfirst_with_default(conf, ngroups, groups, &abs, &g, &rel);
543*c76f0793SBaptiste Daroussin 	ymenupad = 0;
544*c76f0793SBaptiste Daroussin 	for (i=0; i<ngroups; i++) {
545*c76f0793SBaptiste Daroussin 		currmode = getmode(mode, groups[i]);
546*c76f0793SBaptiste Daroussin 		for (j=0; j < (int) groups[i].nitems; j++) {
547*c76f0793SBaptiste Daroussin 			item = &groups[i].items[j];
548*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, ymenupad, *item, currmode,
549*c76f0793SBaptiste Daroussin 			    pos, ymenupad == abs);
550*c76f0793SBaptiste Daroussin 			ymenupad++;
551*c76f0793SBaptiste Daroussin 		}
552*c76f0793SBaptiste Daroussin 	}
553*c76f0793SBaptiste Daroussin 
554*c76f0793SBaptiste Daroussin 	ys = y + h - 5 - menurows + 1;
555*c76f0793SBaptiste Daroussin 	ye = y + h - 5 ;
556*c76f0793SBaptiste Daroussin 	if (conf.menu.align_left || (int)pos.line > w - 6) {
557*c76f0793SBaptiste Daroussin 		xs = x + 3;
558*c76f0793SBaptiste Daroussin 		xe = xs + w - 7;
559*c76f0793SBaptiste Daroussin 	}
560*c76f0793SBaptiste Daroussin 	else { /* center */
561*c76f0793SBaptiste Daroussin 		xs = x + 3 + (w-6)/2 - pos.line/2;
562*c76f0793SBaptiste Daroussin 		xe = xs + w - 5;
563*c76f0793SBaptiste Daroussin 	}
564*c76f0793SBaptiste Daroussin 
565*c76f0793SBaptiste Daroussin 	ymenupad = 0; /* now ymenupad is pminrow for prefresh() */
566*c76f0793SBaptiste Daroussin 	if ((int)(ymenupad + menurows) - 1 < abs)
567*c76f0793SBaptiste Daroussin 		ymenupad = abs - menurows + 1;
568*c76f0793SBaptiste Daroussin 	update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, menurows, ymenupad);
569*c76f0793SBaptiste Daroussin 	wrefresh(menuwin);
570*c76f0793SBaptiste Daroussin 	prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
571*c76f0793SBaptiste Daroussin 
572*c76f0793SBaptiste Daroussin 	draw_buttons(widget, h-2, w, bs, true);
573*c76f0793SBaptiste Daroussin 	wrefresh(widget);
574*c76f0793SBaptiste Daroussin 
575*c76f0793SBaptiste Daroussin 	item = &groups[g].items[rel];
576*c76f0793SBaptiste Daroussin 	currmode = getmode(mode, groups[g]);
577*c76f0793SBaptiste Daroussin 	loop = true;
578*c76f0793SBaptiste Daroussin 	while(loop) {
579*c76f0793SBaptiste Daroussin 		input = getch();
580*c76f0793SBaptiste Daroussin 		switch(input) {
581*c76f0793SBaptiste Daroussin 		case KEY_ENTER:
582*c76f0793SBaptiste Daroussin 		case 10: /* Enter */
583*c76f0793SBaptiste Daroussin 			output = bs.value[bs.curr];
584*c76f0793SBaptiste Daroussin 			if (currmode == MENUMODE)
585*c76f0793SBaptiste Daroussin 				item->on = true;
586*c76f0793SBaptiste Daroussin 			loop = false;
587*c76f0793SBaptiste Daroussin 			break;
588*c76f0793SBaptiste Daroussin 		case 27: /* Esc */
589*c76f0793SBaptiste Daroussin 			output = BSDDIALOG_ESC;
590*c76f0793SBaptiste Daroussin 			loop = false;
591*c76f0793SBaptiste Daroussin 			break;
592*c76f0793SBaptiste Daroussin 		case '\t': /* TAB */
593*c76f0793SBaptiste Daroussin 			bs.curr = (bs.curr + 1) % bs.nbuttons;
594*c76f0793SBaptiste Daroussin 			draw_buttons(widget, h-2, w, bs, true);
595*c76f0793SBaptiste Daroussin 			wrefresh(widget);
596*c76f0793SBaptiste Daroussin 			break;
597*c76f0793SBaptiste Daroussin 		case KEY_LEFT:
598*c76f0793SBaptiste Daroussin 			if (bs.curr > 0) {
599*c76f0793SBaptiste Daroussin 				bs.curr--;
600*c76f0793SBaptiste Daroussin 				draw_buttons(widget, h-2, w, bs, true);
601*c76f0793SBaptiste Daroussin 				wrefresh(widget);
602*c76f0793SBaptiste Daroussin 			}
603*c76f0793SBaptiste Daroussin 			break;
604*c76f0793SBaptiste Daroussin 		case KEY_RIGHT:
605*c76f0793SBaptiste Daroussin 			if (bs.curr < (int) bs.nbuttons - 1) {
606*c76f0793SBaptiste Daroussin 				bs.curr++;
607*c76f0793SBaptiste Daroussin 				draw_buttons(widget, h-2, w, bs, true);
608*c76f0793SBaptiste Daroussin 				wrefresh(widget);
609*c76f0793SBaptiste Daroussin 			}
610*c76f0793SBaptiste Daroussin 			break;
611*c76f0793SBaptiste Daroussin 		case KEY_CTRL('E'): /* add conf.menu.extrahelpkey ? */
612*c76f0793SBaptiste Daroussin 		case KEY_F(1):
613*c76f0793SBaptiste Daroussin 			if (conf.hfile == NULL)
614*c76f0793SBaptiste Daroussin 				break;
615*c76f0793SBaptiste Daroussin 			if (f1help(conf) != 0)
616*c76f0793SBaptiste Daroussin 				return BSDDIALOG_ERROR;
617*c76f0793SBaptiste Daroussin 			/* No break! the terminal size can change */
618*c76f0793SBaptiste Daroussin 		case KEY_RESIZE:
619*c76f0793SBaptiste Daroussin 			hide_widget(y, x, h, w,conf.shadow);
620*c76f0793SBaptiste Daroussin 
621*c76f0793SBaptiste Daroussin 			/*
622*c76f0793SBaptiste Daroussin 			 * Unnecessary, but, when the columns decrease the
623*c76f0793SBaptiste Daroussin 			 * following "refresh" seem not work
624*c76f0793SBaptiste Daroussin 			 */
625*c76f0793SBaptiste Daroussin 			refresh();
626*c76f0793SBaptiste Daroussin 
627*c76f0793SBaptiste Daroussin 			if (set_widget_size(conf, rows, cols, &h, &w) != 0)
628*c76f0793SBaptiste Daroussin 				return BSDDIALOG_ERROR;
629*c76f0793SBaptiste Daroussin 			menurows = automenurows ? 0 : menurows;
630*c76f0793SBaptiste Daroussin 			menu_autosize(conf, rows, cols, &h, &w, text, pos.line,
631*c76f0793SBaptiste Daroussin 			    &menurows, totnitems, bs);
632*c76f0793SBaptiste Daroussin 			if (menu_checksize(h, w, text, menurows, totnitems, bs) != 0)
633*c76f0793SBaptiste Daroussin 				return BSDDIALOG_ERROR;
634*c76f0793SBaptiste Daroussin 			if (set_widget_position(conf, &y, &x, h, w) != 0)
635*c76f0793SBaptiste Daroussin 				return BSDDIALOG_ERROR;
636*c76f0793SBaptiste Daroussin 
637*c76f0793SBaptiste Daroussin 			wclear(shadow);
638*c76f0793SBaptiste Daroussin 			mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
639*c76f0793SBaptiste Daroussin 			wresize(shadow, h, w);
640*c76f0793SBaptiste Daroussin 
641*c76f0793SBaptiste Daroussin 			wclear(widget);
642*c76f0793SBaptiste Daroussin 			mvwin(widget, y, x);
643*c76f0793SBaptiste Daroussin 			wresize(widget, h, w);
644*c76f0793SBaptiste Daroussin 
645*c76f0793SBaptiste Daroussin 			htextpad = 1;
646*c76f0793SBaptiste Daroussin 			wclear(textpad);
647*c76f0793SBaptiste Daroussin 			wresize(textpad, 1, w - HBORDERS - t.texthmargin * 2);
648*c76f0793SBaptiste Daroussin 
649*c76f0793SBaptiste Daroussin 			if(update_widget_withtextpad(conf, shadow, widget, h, w,
650*c76f0793SBaptiste Daroussin 			    RAISED, textpad, &htextpad, text, true) != 0)
651*c76f0793SBaptiste Daroussin 			return BSDDIALOG_ERROR;
652*c76f0793SBaptiste Daroussin 
653*c76f0793SBaptiste Daroussin 			draw_buttons(widget, h-2, w, bs, true);
654*c76f0793SBaptiste Daroussin 			wrefresh(widget);
655*c76f0793SBaptiste Daroussin 
656*c76f0793SBaptiste Daroussin 			prefresh(textpad, 0, 0, y + 1, x + 1 + t.texthmargin,
657*c76f0793SBaptiste Daroussin 			    y + h - menurows, x + 1 + w - t.texthmargin);
658*c76f0793SBaptiste Daroussin 
659*c76f0793SBaptiste Daroussin 			wclear(menuwin);
660*c76f0793SBaptiste Daroussin 			mvwin(menuwin, y + h - 5 - menurows, x + 2);
661*c76f0793SBaptiste Daroussin 			wresize(menuwin,menurows+2, w-4);
662*c76f0793SBaptiste Daroussin 			update_menuwin(conf, menuwin, menurows+2, w-4, totnitems,
663*c76f0793SBaptiste Daroussin 			    menurows, ymenupad);
664*c76f0793SBaptiste Daroussin 			wrefresh(menuwin);
665*c76f0793SBaptiste Daroussin 
666*c76f0793SBaptiste Daroussin 			ys = y + h - 5 - menurows + 1;
667*c76f0793SBaptiste Daroussin 			ye = y + h - 5 ;
668*c76f0793SBaptiste Daroussin 			if (conf.menu.align_left || (int)pos.line > w - 6) {
669*c76f0793SBaptiste Daroussin 				xs = x + 3;
670*c76f0793SBaptiste Daroussin 				xe = xs + w - 7;
671*c76f0793SBaptiste Daroussin 			}
672*c76f0793SBaptiste Daroussin 			else { /* center */
673*c76f0793SBaptiste Daroussin 				xs = x + 3 + (w-6)/2 - pos.line/2;
674*c76f0793SBaptiste Daroussin 				xe = xs + w - 5;
675*c76f0793SBaptiste Daroussin 			}
676*c76f0793SBaptiste Daroussin 
677*c76f0793SBaptiste Daroussin 			if ((int)(ymenupad + menurows) - 1 < abs)
678*c76f0793SBaptiste Daroussin 				ymenupad = abs - menurows + 1;
679*c76f0793SBaptiste Daroussin 			prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
680*c76f0793SBaptiste Daroussin 
681*c76f0793SBaptiste Daroussin 			refresh();
682*c76f0793SBaptiste Daroussin 
683*c76f0793SBaptiste Daroussin 			break;
684*c76f0793SBaptiste Daroussin 		default:
685*c76f0793SBaptiste Daroussin 			for (i = 0; i < (int) bs.nbuttons; i++)
686*c76f0793SBaptiste Daroussin 				if (tolower(input) == tolower((bs.label[i])[0])) {
687*c76f0793SBaptiste Daroussin 					output = bs.value[i];
688*c76f0793SBaptiste Daroussin 					loop = false;
689*c76f0793SBaptiste Daroussin 			}
690*c76f0793SBaptiste Daroussin 
691*c76f0793SBaptiste Daroussin 		}
692*c76f0793SBaptiste Daroussin 
693*c76f0793SBaptiste Daroussin 		if (abs < 0)
694*c76f0793SBaptiste Daroussin 			continue;
695*c76f0793SBaptiste Daroussin 		switch(input) {
696*c76f0793SBaptiste Daroussin 		case KEY_HOME:
697*c76f0793SBaptiste Daroussin 		case KEY_UP:
698*c76f0793SBaptiste Daroussin 		case KEY_PPAGE:
699*c76f0793SBaptiste Daroussin 			if (abs == 0) /* useless, just to save cpu refresh */
700*c76f0793SBaptiste Daroussin 				break;
701*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, abs, *item, currmode, pos, false);
702*c76f0793SBaptiste Daroussin 			if (input == KEY_HOME)
703*c76f0793SBaptiste Daroussin 				getfirst(ngroups, groups, &abs, &g, &rel);
704*c76f0793SBaptiste Daroussin 			else if (input == KEY_UP)
705*c76f0793SBaptiste Daroussin 				getprev(groups, &abs, &g, &rel);
706*c76f0793SBaptiste Daroussin 			else /* input == KEY_PPAGE*/
707*c76f0793SBaptiste Daroussin 				getfastprev(menurows, groups, &abs, &g, &rel);
708*c76f0793SBaptiste Daroussin 			item = &groups[g].items[rel];
709*c76f0793SBaptiste Daroussin 			currmode= getmode(mode, groups[g]);
710*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, abs, *item, currmode, pos, true);
711*c76f0793SBaptiste Daroussin 			if (ymenupad > abs && ymenupad > 0)
712*c76f0793SBaptiste Daroussin 				ymenupad = abs;
713*c76f0793SBaptiste Daroussin 			update_menuwin(conf, menuwin, menurows+2, w-4, totnitems,
714*c76f0793SBaptiste Daroussin 			    menurows, ymenupad);
715*c76f0793SBaptiste Daroussin 			wrefresh(menuwin);
716*c76f0793SBaptiste Daroussin 			prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
717*c76f0793SBaptiste Daroussin 			break;
718*c76f0793SBaptiste Daroussin 		case KEY_END:
719*c76f0793SBaptiste Daroussin 		case KEY_DOWN:
720*c76f0793SBaptiste Daroussin 		case KEY_NPAGE:
721*c76f0793SBaptiste Daroussin 			if (abs == totnitems -1)
722*c76f0793SBaptiste Daroussin 				break; /* useless, just to save cpu refresh */
723*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, abs, *item, currmode, pos, false);
724*c76f0793SBaptiste Daroussin 			if (input == KEY_END)
725*c76f0793SBaptiste Daroussin 				getlast(totnitems, ngroups, groups, &abs, &g, &rel);
726*c76f0793SBaptiste Daroussin 			else if (input == KEY_DOWN)
727*c76f0793SBaptiste Daroussin 				getnext(ngroups, groups, &abs, &g, &rel);
728*c76f0793SBaptiste Daroussin 			else /* input == KEY_NPAGE*/
729*c76f0793SBaptiste Daroussin 				getfastnext(menurows, ngroups, groups, &abs, &g, &rel);
730*c76f0793SBaptiste Daroussin 			item = &groups[g].items[rel];
731*c76f0793SBaptiste Daroussin 			currmode= getmode(mode, groups[g]);
732*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, abs, *item, currmode, pos, true);
733*c76f0793SBaptiste Daroussin 			if ((int)(ymenupad + menurows) <= abs)
734*c76f0793SBaptiste Daroussin 				ymenupad = abs - menurows + 1;
735*c76f0793SBaptiste Daroussin 			update_menuwin(conf, menuwin, menurows+2, w-4, totnitems,
736*c76f0793SBaptiste Daroussin 			    menurows, ymenupad);
737*c76f0793SBaptiste Daroussin 			wrefresh(menuwin);
738*c76f0793SBaptiste Daroussin 			prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
739*c76f0793SBaptiste Daroussin 			break;
740*c76f0793SBaptiste Daroussin 		case ' ': /* Space */
741*c76f0793SBaptiste Daroussin 			if (currmode == MENUMODE)
742*c76f0793SBaptiste Daroussin 				break;
743*c76f0793SBaptiste Daroussin 			else if (currmode == CHECKLISTMODE)
744*c76f0793SBaptiste Daroussin 				item->on = !item->on;
745*c76f0793SBaptiste Daroussin 			else { /* RADIOLISTMODE */
746*c76f0793SBaptiste Daroussin 				if (item->on == true)
747*c76f0793SBaptiste Daroussin 					break;
748*c76f0793SBaptiste Daroussin 				for (i=0; i < (int) groups[g].nitems; i++)
749*c76f0793SBaptiste Daroussin 					if (groups[g].items[i].on == true) {
750*c76f0793SBaptiste Daroussin 						groups[g].items[i].on = false;
751*c76f0793SBaptiste Daroussin 						drawitem(conf, menupad,
752*c76f0793SBaptiste Daroussin 						    abs - rel + i, groups[g].items[i],
753*c76f0793SBaptiste Daroussin 						    currmode, pos, false);
754*c76f0793SBaptiste Daroussin 					}
755*c76f0793SBaptiste Daroussin 				item->on = true;
756*c76f0793SBaptiste Daroussin 			}
757*c76f0793SBaptiste Daroussin 			drawitem(conf, menupad, abs, *item, currmode, pos, true);
758*c76f0793SBaptiste Daroussin 			prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
759*c76f0793SBaptiste Daroussin 		}
760*c76f0793SBaptiste Daroussin 	}
761*c76f0793SBaptiste Daroussin 
762*c76f0793SBaptiste Daroussin 	if (focuslist != NULL)
763*c76f0793SBaptiste Daroussin 		*focuslist = g;
764*c76f0793SBaptiste Daroussin 	if (focusitem !=NULL)
765*c76f0793SBaptiste Daroussin 		*focusitem = rel;
766*c76f0793SBaptiste Daroussin 
767*c76f0793SBaptiste Daroussin 	delwin(menupad);
768*c76f0793SBaptiste Daroussin 	delwin(menuwin);
769*c76f0793SBaptiste Daroussin 	end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
770*c76f0793SBaptiste Daroussin 
771*c76f0793SBaptiste Daroussin 	return output;
772*c76f0793SBaptiste Daroussin }
773*c76f0793SBaptiste Daroussin 
774*c76f0793SBaptiste Daroussin /*
775*c76f0793SBaptiste Daroussin  * API
776*c76f0793SBaptiste Daroussin  */
777*c76f0793SBaptiste Daroussin 
778*c76f0793SBaptiste Daroussin int bsddialog_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
779*c76f0793SBaptiste Daroussin     unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups,
780*c76f0793SBaptiste Daroussin     int *focuslist, int *focusitem)
781*c76f0793SBaptiste Daroussin {
782*c76f0793SBaptiste Daroussin 	int output;
783*c76f0793SBaptiste Daroussin 
784*c76f0793SBaptiste Daroussin 	output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
785*c76f0793SBaptiste Daroussin 	    ngroups, groups, focuslist, focusitem);
786*c76f0793SBaptiste Daroussin 
787*c76f0793SBaptiste Daroussin 	return output;
788*c76f0793SBaptiste Daroussin }
789*c76f0793SBaptiste Daroussin 
790*c76f0793SBaptiste Daroussin int
791*c76f0793SBaptiste Daroussin bsddialog_checklist(struct bsddialog_conf conf, char* text, int rows, int cols,
792*c76f0793SBaptiste Daroussin     unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
793*c76f0793SBaptiste Daroussin     int *focusitem)
794*c76f0793SBaptiste Daroussin {
795*c76f0793SBaptiste Daroussin 	int output;
796*c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
797*c76f0793SBaptiste Daroussin 	    BSDDIALOG_CHECKLIST /* unused */, nitems, items};
798*c76f0793SBaptiste Daroussin 
799*c76f0793SBaptiste Daroussin 	output = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE,
800*c76f0793SBaptiste Daroussin 	    1, &group, NULL, focusitem);
801*c76f0793SBaptiste Daroussin 
802*c76f0793SBaptiste Daroussin 	return output;
803*c76f0793SBaptiste Daroussin }
804*c76f0793SBaptiste Daroussin 
805*c76f0793SBaptiste Daroussin int
806*c76f0793SBaptiste Daroussin bsddialog_menu(struct bsddialog_conf conf, char* text, int rows, int cols,
807*c76f0793SBaptiste Daroussin     unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
808*c76f0793SBaptiste Daroussin     int *focusitem)
809*c76f0793SBaptiste Daroussin {
810*c76f0793SBaptiste Daroussin 	int output;
811*c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
812*c76f0793SBaptiste Daroussin 	    BSDDIALOG_CHECKLIST /* unused */, nitems, items};
813*c76f0793SBaptiste Daroussin 
814*c76f0793SBaptiste Daroussin 	output = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1,
815*c76f0793SBaptiste Daroussin 	    &group, NULL, focusitem);
816*c76f0793SBaptiste Daroussin 
817*c76f0793SBaptiste Daroussin 	return output;
818*c76f0793SBaptiste Daroussin }
819*c76f0793SBaptiste Daroussin 
820*c76f0793SBaptiste Daroussin int
821*c76f0793SBaptiste Daroussin bsddialog_radiolist(struct bsddialog_conf conf, char* text, int rows, int cols,
822*c76f0793SBaptiste Daroussin     unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
823*c76f0793SBaptiste Daroussin     int *focusitem)
824*c76f0793SBaptiste Daroussin {
825*c76f0793SBaptiste Daroussin 	int output;
826*c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
827*c76f0793SBaptiste Daroussin 	    BSDDIALOG_RADIOLIST /* unused */, nitems, items};
828*c76f0793SBaptiste Daroussin 
829*c76f0793SBaptiste Daroussin 	output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
830*c76f0793SBaptiste Daroussin 	    1, &group, NULL, focusitem);
831*c76f0793SBaptiste Daroussin 
832*c76f0793SBaptiste Daroussin 	return output;
833*c76f0793SBaptiste Daroussin }
834*c76f0793SBaptiste Daroussin 
835*c76f0793SBaptiste Daroussin int
836*c76f0793SBaptiste Daroussin bsddialog_treeview(struct bsddialog_conf conf, char* text, int rows, int cols,
837*c76f0793SBaptiste Daroussin     unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
838*c76f0793SBaptiste Daroussin     int *focusitem)
839*c76f0793SBaptiste Daroussin {
840*c76f0793SBaptiste Daroussin 	int output;
841*c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
842*c76f0793SBaptiste Daroussin 	    BSDDIALOG_RADIOLIST /* unused */, nitems, items};
843*c76f0793SBaptiste Daroussin 
844*c76f0793SBaptiste Daroussin 	conf.menu.no_tags = true;
845*c76f0793SBaptiste Daroussin 	conf.menu.align_left = true;
846*c76f0793SBaptiste Daroussin 
847*c76f0793SBaptiste Daroussin 	output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
848*c76f0793SBaptiste Daroussin 	    1, &group, NULL, focusitem);
849*c76f0793SBaptiste Daroussin 
850*c76f0793SBaptiste Daroussin 	return output;
851*c76f0793SBaptiste Daroussin }
852*c76f0793SBaptiste Daroussin 
853*c76f0793SBaptiste Daroussin int
854*c76f0793SBaptiste Daroussin bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
855*c76f0793SBaptiste Daroussin     unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
856*c76f0793SBaptiste Daroussin     int *focusitem)
857*c76f0793SBaptiste Daroussin {
858*c76f0793SBaptiste Daroussin 	WINDOW *widget, *leftwin, *leftpad, *rightwin, *rightpad, *shadow;
859*c76f0793SBaptiste Daroussin 	int output, i, x, y, input;
860*c76f0793SBaptiste Daroussin 	bool loop, buttupdate, padsupdate, startleft;
861*c76f0793SBaptiste Daroussin 	int nlefts, nrights, leftwinx, rightwinx, winsy, padscols, curr;
862*c76f0793SBaptiste Daroussin 	enum side {LEFT, RIGHT} currV;
863*c76f0793SBaptiste Daroussin 	int currH;
864*c76f0793SBaptiste Daroussin 	struct buttons bs;
865*c76f0793SBaptiste Daroussin 	struct lineposition pos = {0,0,0,0,0,0,0,0,0,0};
866*c76f0793SBaptiste Daroussin 
867*c76f0793SBaptiste Daroussin 	startleft = false;
868*c76f0793SBaptiste Daroussin 	for (i=0; i<nitems; i++) {
869*c76f0793SBaptiste Daroussin 		pos.line = MAX(pos.line, strlen(items[i].desc));
870*c76f0793SBaptiste Daroussin 		if (items[i].on == false)
871*c76f0793SBaptiste Daroussin 			startleft = true;
872*c76f0793SBaptiste Daroussin 	}
873*c76f0793SBaptiste Daroussin 
874*c76f0793SBaptiste Daroussin 	if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
875*c76f0793SBaptiste Daroussin 	    true) <0)
876*c76f0793SBaptiste Daroussin 		return -1;
877*c76f0793SBaptiste Daroussin 
878*c76f0793SBaptiste Daroussin 	winsy = y + rows - 5 - menurows;
879*c76f0793SBaptiste Daroussin 	leftwinx = x+2;
880*c76f0793SBaptiste Daroussin 	leftwin = new_boxed_window(conf, winsy, leftwinx, menurows+2, (cols-5)/2,
881*c76f0793SBaptiste Daroussin 	    LOWERED);
882*c76f0793SBaptiste Daroussin 	rightwinx = x + cols - 2 -(cols-5)/2;
883*c76f0793SBaptiste Daroussin 	rightwin = new_boxed_window(conf, winsy, rightwinx, menurows+2,
884*c76f0793SBaptiste Daroussin 	    (cols-5)/2, LOWERED);
885*c76f0793SBaptiste Daroussin 
886*c76f0793SBaptiste Daroussin 	wrefresh(leftwin);
887*c76f0793SBaptiste Daroussin 	wrefresh(rightwin);
888*c76f0793SBaptiste Daroussin 
889*c76f0793SBaptiste Daroussin 	padscols = (cols-5)/2 - 2;
890*c76f0793SBaptiste Daroussin 	leftpad  = newpad(nitems, pos.line);
891*c76f0793SBaptiste Daroussin 	rightpad = newpad(nitems, pos.line);
892*c76f0793SBaptiste Daroussin 	wbkgd(leftpad, t.widgetcolor);
893*c76f0793SBaptiste Daroussin 	wbkgd(rightpad, t.widgetcolor);
894*c76f0793SBaptiste Daroussin 
895*c76f0793SBaptiste Daroussin 	get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
896*c76f0793SBaptiste Daroussin 	    BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
897*c76f0793SBaptiste Daroussin 
898*c76f0793SBaptiste Daroussin 	currH = 0;
899*c76f0793SBaptiste Daroussin 	currV = startleft ? LEFT : RIGHT;
900*c76f0793SBaptiste Daroussin 	loop = buttupdate = padsupdate = true;
901*c76f0793SBaptiste Daroussin 	while(loop) {
902*c76f0793SBaptiste Daroussin 		if (buttupdate) {
903*c76f0793SBaptiste Daroussin 			draw_buttons(widget, rows-2, cols, bs, true);
904*c76f0793SBaptiste Daroussin 			wrefresh(widget);
905*c76f0793SBaptiste Daroussin 			buttupdate = false;
906*c76f0793SBaptiste Daroussin 		}
907*c76f0793SBaptiste Daroussin 
908*c76f0793SBaptiste Daroussin 		if (padsupdate) {
909*c76f0793SBaptiste Daroussin 			werase(leftpad);
910*c76f0793SBaptiste Daroussin 			werase(rightpad);
911*c76f0793SBaptiste Daroussin 			curr = -1;
912*c76f0793SBaptiste Daroussin 			nlefts = nrights = 0;
913*c76f0793SBaptiste Daroussin 			for (i=0; i<nitems; i++) {
914*c76f0793SBaptiste Daroussin 				if (items[i].on == false) {
915*c76f0793SBaptiste Daroussin 					if (currV == LEFT && currH == nlefts)
916*c76f0793SBaptiste Daroussin 						curr = i;
917*c76f0793SBaptiste Daroussin 					drawitem(conf, leftpad, nlefts, items[i],
918*c76f0793SBaptiste Daroussin 					    BUILDLISTMODE, pos, curr == i);
919*c76f0793SBaptiste Daroussin 					nlefts++;
920*c76f0793SBaptiste Daroussin 				} else {
921*c76f0793SBaptiste Daroussin 					if (currV == RIGHT && currH == nrights)
922*c76f0793SBaptiste Daroussin 						curr = i;
923*c76f0793SBaptiste Daroussin 					drawitem(conf, rightpad, nrights, items[i],
924*c76f0793SBaptiste Daroussin 					    BUILDLISTMODE, pos, curr == i);
925*c76f0793SBaptiste Daroussin 					nrights++;
926*c76f0793SBaptiste Daroussin 				}
927*c76f0793SBaptiste Daroussin 			}
928*c76f0793SBaptiste Daroussin 			prefresh(leftpad, 0, 0, winsy+1, leftwinx+1,
929*c76f0793SBaptiste Daroussin 			    winsy+1+menurows, leftwinx + 1 + padscols);
930*c76f0793SBaptiste Daroussin 			prefresh(rightpad, 0, 0, winsy+1, rightwinx+1,
931*c76f0793SBaptiste Daroussin 			    winsy+1+menurows, rightwinx + 1 + padscols);
932*c76f0793SBaptiste Daroussin 			padsupdate = false;
933*c76f0793SBaptiste Daroussin 		}
934*c76f0793SBaptiste Daroussin 
935*c76f0793SBaptiste Daroussin 		input = getch();
936*c76f0793SBaptiste Daroussin 		switch(input) {
937*c76f0793SBaptiste Daroussin 		case 10: // Enter
938*c76f0793SBaptiste Daroussin 			output = bs.value[bs.curr]; // -> buttvalues[selbutton]
939*c76f0793SBaptiste Daroussin 			loop = false;
940*c76f0793SBaptiste Daroussin 			break;
941*c76f0793SBaptiste Daroussin 		case 27: // Esc
942*c76f0793SBaptiste Daroussin 			output = BSDDIALOG_ERROR;
943*c76f0793SBaptiste Daroussin 			loop = false;
944*c76f0793SBaptiste Daroussin 			break;
945*c76f0793SBaptiste Daroussin 		case '\t': // TAB
946*c76f0793SBaptiste Daroussin 			bs.curr = (bs.curr + 1) % bs.nbuttons;
947*c76f0793SBaptiste Daroussin 			buttupdate = true;
948*c76f0793SBaptiste Daroussin 			break;
949*c76f0793SBaptiste Daroussin 		}
950*c76f0793SBaptiste Daroussin 
951*c76f0793SBaptiste Daroussin 		if (nitems <= 0)
952*c76f0793SBaptiste Daroussin 			continue;
953*c76f0793SBaptiste Daroussin 
954*c76f0793SBaptiste Daroussin 		switch(input) {
955*c76f0793SBaptiste Daroussin 		case KEY_LEFT:
956*c76f0793SBaptiste Daroussin 			if (currV == RIGHT && nrights > 0) {
957*c76f0793SBaptiste Daroussin 				currV = LEFT;
958*c76f0793SBaptiste Daroussin 				currH = 0;
959*c76f0793SBaptiste Daroussin 				padsupdate = true;
960*c76f0793SBaptiste Daroussin 			}
961*c76f0793SBaptiste Daroussin 			break;
962*c76f0793SBaptiste Daroussin 		case KEY_RIGHT:
963*c76f0793SBaptiste Daroussin 			if (currV == LEFT && nrights > 0) {
964*c76f0793SBaptiste Daroussin 				currV = RIGHT;
965*c76f0793SBaptiste Daroussin 				currH = 0;
966*c76f0793SBaptiste Daroussin 				padsupdate = true;
967*c76f0793SBaptiste Daroussin 			}
968*c76f0793SBaptiste Daroussin 			break;
969*c76f0793SBaptiste Daroussin 		case KEY_UP:
970*c76f0793SBaptiste Daroussin 			currH = (currH > 0) ? currH - 1 : 0;
971*c76f0793SBaptiste Daroussin 			padsupdate = true;
972*c76f0793SBaptiste Daroussin 			break;
973*c76f0793SBaptiste Daroussin 		case KEY_DOWN:
974*c76f0793SBaptiste Daroussin 			if (currV == LEFT)
975*c76f0793SBaptiste Daroussin 				currH = (currH < nlefts-1) ? currH +1 : currH;
976*c76f0793SBaptiste Daroussin 			else
977*c76f0793SBaptiste Daroussin 				currH = (currH < nrights-1)? currH +1 : currH;
978*c76f0793SBaptiste Daroussin 			padsupdate = true;
979*c76f0793SBaptiste Daroussin 			break;
980*c76f0793SBaptiste Daroussin 		case ' ': // Space
981*c76f0793SBaptiste Daroussin 			items[curr].on = ! items[curr].on;
982*c76f0793SBaptiste Daroussin 			if (currV == LEFT) {
983*c76f0793SBaptiste Daroussin 				if (nlefts > 1)
984*c76f0793SBaptiste Daroussin 					currH = currH > 0 ? currH-1 : 0;
985*c76f0793SBaptiste Daroussin 				else {
986*c76f0793SBaptiste Daroussin 					currH = 0;
987*c76f0793SBaptiste Daroussin 					currV = RIGHT;
988*c76f0793SBaptiste Daroussin 				}
989*c76f0793SBaptiste Daroussin 			} else {
990*c76f0793SBaptiste Daroussin 				if (nrights > 1)
991*c76f0793SBaptiste Daroussin 					currH = currH > 0 ? currH-1 : 0;
992*c76f0793SBaptiste Daroussin 				else {
993*c76f0793SBaptiste Daroussin 					currH = 0;
994*c76f0793SBaptiste Daroussin 					currV = LEFT;
995*c76f0793SBaptiste Daroussin 				}
996*c76f0793SBaptiste Daroussin 			}
997*c76f0793SBaptiste Daroussin 			padsupdate = true;
998*c76f0793SBaptiste Daroussin 			break;
999*c76f0793SBaptiste Daroussin 		default:
1000*c76f0793SBaptiste Daroussin 
1001*c76f0793SBaptiste Daroussin 			break;
1002*c76f0793SBaptiste Daroussin 		}
1003*c76f0793SBaptiste Daroussin 	}
1004*c76f0793SBaptiste Daroussin 
1005*c76f0793SBaptiste Daroussin 	if(focusitem != NULL)
1006*c76f0793SBaptiste Daroussin 		*focusitem = curr;
1007*c76f0793SBaptiste Daroussin 
1008*c76f0793SBaptiste Daroussin 	delwin(leftpad);
1009*c76f0793SBaptiste Daroussin 	delwin(leftwin);
1010*c76f0793SBaptiste Daroussin 	delwin(rightpad);
1011*c76f0793SBaptiste Daroussin 	delwin(rightwin);
1012*c76f0793SBaptiste Daroussin 	end_widget(conf, widget, rows, cols, shadow);
1013*c76f0793SBaptiste Daroussin 
1014*c76f0793SBaptiste Daroussin 	return output;
1015*c76f0793SBaptiste Daroussin }
1016