xref: /freebsd/contrib/bsddialog/lib/menubox.c (revision 61ba55bc)
1c76f0793SBaptiste Daroussin /*-
2c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3c76f0793SBaptiste Daroussin  *
4*61ba55bcSBaptiste Daroussin  * Copyright (c) 2021-2023 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 
28263660c0SAlfonso Siciliano #include <curses.h>
29263660c0SAlfonso Siciliano #include <stdlib.h>
30d93b4d32SBaptiste Daroussin 
31c76f0793SBaptiste Daroussin #include "bsddialog.h"
32c76f0793SBaptiste Daroussin #include "bsddialog_theme.h"
33263660c0SAlfonso Siciliano #include "lib_util.h"
34c76f0793SBaptiste Daroussin 
35c76f0793SBaptiste Daroussin enum menumode {
36c76f0793SBaptiste Daroussin 	CHECKLISTMODE,
37c76f0793SBaptiste Daroussin 	MENUMODE,
38c76f0793SBaptiste Daroussin 	MIXEDLISTMODE,
39c76f0793SBaptiste Daroussin 	RADIOLISTMODE,
40c76f0793SBaptiste Daroussin 	SEPARATORMODE
41c76f0793SBaptiste Daroussin };
42c76f0793SBaptiste Daroussin 
43263660c0SAlfonso Siciliano struct privateitem {
44*61ba55bcSBaptiste Daroussin 	const char *prefix;
45*61ba55bcSBaptiste Daroussin 	bool on;               /* menu changes, not API on */
46*61ba55bcSBaptiste Daroussin 	unsigned int depth;
47*61ba55bcSBaptiste Daroussin 	const char *name;
48*61ba55bcSBaptiste Daroussin 	const char *desc;
49*61ba55bcSBaptiste Daroussin 	const char *bottomdesc;
50*61ba55bcSBaptiste Daroussin 	int group;             /* index menu in menugroup */
51*61ba55bcSBaptiste Daroussin 	int index;             /* real item index inside its menu */
52263660c0SAlfonso Siciliano 	enum menumode type;
53*61ba55bcSBaptiste Daroussin 	wchar_t shortcut;
54263660c0SAlfonso Siciliano };
55c76f0793SBaptiste Daroussin 
56*61ba55bcSBaptiste Daroussin struct privatemenu {
57*61ba55bcSBaptiste Daroussin 	WINDOW *box;              /* only for borders */
58*61ba55bcSBaptiste Daroussin 	WINDOW *pad;              /* pad for the private items */
59*61ba55bcSBaptiste Daroussin 	int ypad;                 /* start pad line */
60*61ba55bcSBaptiste Daroussin 	int ys, ye, xs, xe;       /* pad pos */
61*61ba55bcSBaptiste Daroussin 	unsigned int xselector;   /* [] */
62*61ba55bcSBaptiste Daroussin 	unsigned int xname;       /* real x: xname + item.depth */
63*61ba55bcSBaptiste Daroussin 	unsigned int xdesc;       /* real x: xdesc + item.depth */
64*61ba55bcSBaptiste Daroussin 	unsigned int line;        /* wpad: prefix [] depth name desc */
65*61ba55bcSBaptiste Daroussin 	unsigned int apimenurows;
66*61ba55bcSBaptiste Daroussin 	unsigned int menurows;    /* real menurows after menu_size_position() */
67*61ba55bcSBaptiste Daroussin 	int nitems;               /* total nitems (all groups * all items) */
68*61ba55bcSBaptiste Daroussin 	struct privateitem *pritems;
69*61ba55bcSBaptiste Daroussin 	int sel;                  /* current focus item, can be -1 */
70*61ba55bcSBaptiste Daroussin 	bool hasbottomdesc;
71*61ba55bcSBaptiste Daroussin };
72*61ba55bcSBaptiste Daroussin 
73*61ba55bcSBaptiste Daroussin static enum menumode
getmode(enum menumode mode,struct bsddialog_menugroup group)74*61ba55bcSBaptiste Daroussin getmode(enum menumode mode, struct bsddialog_menugroup group)
75263660c0SAlfonso Siciliano {
76*61ba55bcSBaptiste Daroussin 	if (mode == MIXEDLISTMODE) {
77*61ba55bcSBaptiste Daroussin 		if (group.type == BSDDIALOG_SEPARATOR)
78*61ba55bcSBaptiste Daroussin 			mode = SEPARATORMODE;
79*61ba55bcSBaptiste Daroussin 		else if (group.type == BSDDIALOG_RADIOLIST)
80*61ba55bcSBaptiste Daroussin 			mode = RADIOLISTMODE;
81*61ba55bcSBaptiste Daroussin 		else if (group.type == BSDDIALOG_CHECKLIST)
82*61ba55bcSBaptiste Daroussin 			mode = CHECKLISTMODE;
83*61ba55bcSBaptiste Daroussin 	}
84*61ba55bcSBaptiste Daroussin 
85*61ba55bcSBaptiste Daroussin 	return (mode);
86*61ba55bcSBaptiste Daroussin }
87*61ba55bcSBaptiste Daroussin 
88*61ba55bcSBaptiste Daroussin static int
build_privatemenu(struct bsddialog_conf * conf,struct privatemenu * m,enum menumode mode,unsigned int ngroups,struct bsddialog_menugroup * groups)89*61ba55bcSBaptiste Daroussin build_privatemenu(struct bsddialog_conf *conf, struct privatemenu *m,
90*61ba55bcSBaptiste Daroussin     enum menumode mode, unsigned int ngroups,
91*61ba55bcSBaptiste Daroussin     struct bsddialog_menugroup *groups)
92*61ba55bcSBaptiste Daroussin {
93*61ba55bcSBaptiste Daroussin 	bool onetrue;
94263660c0SAlfonso Siciliano 	int i, j, abs;
95*61ba55bcSBaptiste Daroussin 	unsigned int maxsepstr, maxprefix, selectorlen, maxdepth;
96*61ba55bcSBaptiste Daroussin 	unsigned int maxname, maxdesc;
97*61ba55bcSBaptiste Daroussin 	struct bsddialog_menuitem *item;
98*61ba55bcSBaptiste Daroussin 	struct privateitem *pritem;
99263660c0SAlfonso Siciliano 
100*61ba55bcSBaptiste Daroussin 	/* nitems and fault checks */
101*61ba55bcSBaptiste Daroussin 	CHECK_ARRAY(ngroups, groups);
102*61ba55bcSBaptiste Daroussin 	m->nitems = 0;
103*61ba55bcSBaptiste Daroussin 	for (i = 0; i < (int)ngroups; i++) {
104*61ba55bcSBaptiste Daroussin 		CHECK_ARRAY(groups[i].nitems, groups[i].items);
105*61ba55bcSBaptiste Daroussin 		m->nitems += (int)groups[i].nitems;
106*61ba55bcSBaptiste Daroussin 	}
107c76f0793SBaptiste Daroussin 
108*61ba55bcSBaptiste Daroussin 	/* alloc and set private items */
109*61ba55bcSBaptiste Daroussin 	m->pritems = calloc(m->nitems, sizeof (struct privateitem));
110*61ba55bcSBaptiste Daroussin 	if (m->pritems == NULL)
111*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot allocate memory for internal menu items");
112*61ba55bcSBaptiste Daroussin 	m->hasbottomdesc = false;
113*61ba55bcSBaptiste Daroussin 	abs = 0;
114*61ba55bcSBaptiste Daroussin 	for (i = 0; i < (int)ngroups; i++) {
115*61ba55bcSBaptiste Daroussin 		onetrue = false;
116*61ba55bcSBaptiste Daroussin 		for (j = 0; j < (int)groups[i].nitems; j++) {
117*61ba55bcSBaptiste Daroussin 			item = &groups[i].items[j];
118*61ba55bcSBaptiste Daroussin 			pritem = &m->pritems[abs];
119*61ba55bcSBaptiste Daroussin 
120*61ba55bcSBaptiste Daroussin 			if (getmode(mode, groups[i]) == MENUMODE) {
121*61ba55bcSBaptiste Daroussin 				m->pritems[abs].on = false;
122*61ba55bcSBaptiste Daroussin 			} else if (getmode(mode, groups[i]) == RADIOLISTMODE) {
123*61ba55bcSBaptiste Daroussin 				m->pritems[abs].on = onetrue ? false : item->on;
124*61ba55bcSBaptiste Daroussin 				if (m->pritems[abs].on)
125*61ba55bcSBaptiste Daroussin 					onetrue = true;
126*61ba55bcSBaptiste Daroussin 			} else { /* CHECKLISTMODE */
127*61ba55bcSBaptiste Daroussin 				m->pritems[abs].on = item->on;
128*61ba55bcSBaptiste Daroussin 			}
129*61ba55bcSBaptiste Daroussin 			pritem->group = i;
130*61ba55bcSBaptiste Daroussin 			pritem->index = j;
131*61ba55bcSBaptiste Daroussin 			pritem->type = getmode(mode, groups[i]);
132*61ba55bcSBaptiste Daroussin 
133*61ba55bcSBaptiste Daroussin 			pritem->prefix = CHECK_STR(item->prefix);
134*61ba55bcSBaptiste Daroussin 			pritem->depth = item->depth;
135*61ba55bcSBaptiste Daroussin 			pritem->name = CHECK_STR(item->name);
136*61ba55bcSBaptiste Daroussin 			pritem->desc = CHECK_STR(item->desc);
137*61ba55bcSBaptiste Daroussin 			pritem->bottomdesc = CHECK_STR(item->bottomdesc);
138*61ba55bcSBaptiste Daroussin 			if (item->bottomdesc != NULL)
139*61ba55bcSBaptiste Daroussin 				m->hasbottomdesc = true;
140*61ba55bcSBaptiste Daroussin 
141*61ba55bcSBaptiste Daroussin 			mbtowc(&pritem->shortcut, conf->menu.no_name ?
142*61ba55bcSBaptiste Daroussin 			    pritem->desc : pritem->name, MB_CUR_MAX);
143*61ba55bcSBaptiste Daroussin 
144*61ba55bcSBaptiste Daroussin 			abs++;
145*61ba55bcSBaptiste Daroussin 		}
146*61ba55bcSBaptiste Daroussin 	}
147*61ba55bcSBaptiste Daroussin 
148*61ba55bcSBaptiste Daroussin 	/* positions */
149*61ba55bcSBaptiste Daroussin 	m->xselector = m->xname = m->xdesc = m->line = 0;
150*61ba55bcSBaptiste Daroussin 	maxsepstr = maxprefix = selectorlen = maxdepth = maxname = maxdesc = 0;
151*61ba55bcSBaptiste Daroussin 	for (i = 0; i < m->nitems; i++) {
152*61ba55bcSBaptiste Daroussin 		if (m->pritems[i].type == RADIOLISTMODE ||
153*61ba55bcSBaptiste Daroussin 		    m->pritems[i].type == CHECKLISTMODE)
154*61ba55bcSBaptiste Daroussin 			selectorlen = 4;
155*61ba55bcSBaptiste Daroussin 
156*61ba55bcSBaptiste Daroussin 		if (m->pritems[i].type == SEPARATORMODE) {
157*61ba55bcSBaptiste Daroussin 			maxsepstr = MAX(maxsepstr,
158*61ba55bcSBaptiste Daroussin 			    strcols(m->pritems[i].name) +
159*61ba55bcSBaptiste Daroussin 			    strcols(m->pritems[i].desc));
160c76f0793SBaptiste Daroussin 			continue;
161c76f0793SBaptiste Daroussin 		}
162263660c0SAlfonso Siciliano 
163*61ba55bcSBaptiste Daroussin 		maxprefix = MAX(maxprefix, strcols(m->pritems[i].prefix));
164*61ba55bcSBaptiste Daroussin 		maxdepth  = MAX(maxdepth, m->pritems[i].depth);
165*61ba55bcSBaptiste Daroussin 		maxname   = MAX(maxname, strcols(m->pritems[i].name));
166*61ba55bcSBaptiste Daroussin 		maxdesc   = MAX(maxdesc, strcols(m->pritems[i].desc));
167c76f0793SBaptiste Daroussin 	}
168*61ba55bcSBaptiste Daroussin 	maxname = conf->menu.no_name ? 0 : maxname;
169*61ba55bcSBaptiste Daroussin 	maxdesc = conf->menu.no_desc ? 0 : maxdesc;
170*61ba55bcSBaptiste Daroussin 
171*61ba55bcSBaptiste Daroussin 	m->xselector = maxprefix + (maxprefix != 0 ? 1 : 0);
172*61ba55bcSBaptiste Daroussin 	m->xname = m->xselector + selectorlen;
173*61ba55bcSBaptiste Daroussin 	m->xdesc = maxdepth + m->xname + maxname;
174*61ba55bcSBaptiste Daroussin 	m->xdesc += (maxname != 0 ? 1 : 0);
175*61ba55bcSBaptiste Daroussin 	m->line = MAX(maxsepstr + 3, m->xdesc + maxdesc);
176*61ba55bcSBaptiste Daroussin 
177*61ba55bcSBaptiste Daroussin 	return (0);
178*61ba55bcSBaptiste Daroussin }
179*61ba55bcSBaptiste Daroussin 
180*61ba55bcSBaptiste Daroussin static void
set_return_on(struct privatemenu * m,struct bsddialog_menugroup * groups)181*61ba55bcSBaptiste Daroussin set_return_on(struct privatemenu *m, struct bsddialog_menugroup *groups)
182*61ba55bcSBaptiste Daroussin {
183*61ba55bcSBaptiste Daroussin 	int i;
184*61ba55bcSBaptiste Daroussin 	struct privateitem *pritem;
185*61ba55bcSBaptiste Daroussin 
186*61ba55bcSBaptiste Daroussin 	for(i = 0; i < m->nitems; i++) {
187*61ba55bcSBaptiste Daroussin 		if (m->pritems[i].type == SEPARATORMODE)
188*61ba55bcSBaptiste Daroussin 			continue;
189*61ba55bcSBaptiste Daroussin 		pritem = &m->pritems[i];
190*61ba55bcSBaptiste Daroussin 		groups[pritem->group].items[pritem->index].on = pritem->on;
191c76f0793SBaptiste Daroussin 	}
192c76f0793SBaptiste Daroussin }
193c76f0793SBaptiste Daroussin 
getprev(struct privateitem * pritems,int abs)194263660c0SAlfonso Siciliano static int getprev(struct privateitem *pritems, int abs)
195c76f0793SBaptiste Daroussin {
196263660c0SAlfonso Siciliano 	int i;
197c76f0793SBaptiste Daroussin 
198263660c0SAlfonso Siciliano 	for (i = abs - 1; i >= 0; i--) {
199263660c0SAlfonso Siciliano 		if (pritems[i].type == SEPARATORMODE)
200c76f0793SBaptiste Daroussin 			continue;
201263660c0SAlfonso Siciliano 		return (i);
202c76f0793SBaptiste Daroussin 	}
203c76f0793SBaptiste Daroussin 
204263660c0SAlfonso Siciliano 	return (abs);
205263660c0SAlfonso Siciliano }
206263660c0SAlfonso Siciliano 
getnext(int npritems,struct privateitem * pritems,int abs)207263660c0SAlfonso Siciliano static int getnext(int npritems, struct privateitem *pritems, int abs)
208c76f0793SBaptiste Daroussin {
209263660c0SAlfonso Siciliano 	int i;
210c76f0793SBaptiste Daroussin 
211263660c0SAlfonso Siciliano 	for (i = abs + 1; i < npritems; i++) {
212263660c0SAlfonso Siciliano 		if (pritems[i].type == SEPARATORMODE)
213c76f0793SBaptiste Daroussin 			continue;
214263660c0SAlfonso Siciliano 		return (i);
215c76f0793SBaptiste Daroussin 	}
216c76f0793SBaptiste Daroussin 
217263660c0SAlfonso Siciliano 	return (abs);
218263660c0SAlfonso Siciliano }
219263660c0SAlfonso Siciliano 
220263660c0SAlfonso Siciliano static int
getfirst_with_default(int npritems,struct privateitem * pritems,int ngroups,struct bsddialog_menugroup * groups,int * focusgroup,int * focusitem)221263660c0SAlfonso Siciliano getfirst_with_default(int npritems, struct privateitem *pritems, int ngroups,
222263660c0SAlfonso Siciliano     struct bsddialog_menugroup *groups, int *focusgroup, int *focusitem)
223263660c0SAlfonso Siciliano {
224263660c0SAlfonso Siciliano 	int i, abs;
225263660c0SAlfonso Siciliano 
226263660c0SAlfonso Siciliano 	if ((abs =  getnext(npritems, pritems, -1)) < 0)
227263660c0SAlfonso Siciliano 		return (abs);
228263660c0SAlfonso Siciliano 
229263660c0SAlfonso Siciliano 	if (focusgroup == NULL || focusitem == NULL)
230263660c0SAlfonso Siciliano 		return (abs);
231263660c0SAlfonso Siciliano 	if (*focusgroup < 0 || *focusgroup >= ngroups)
232263660c0SAlfonso Siciliano 		return (abs);
233263660c0SAlfonso Siciliano 	if (groups[*focusgroup].type == BSDDIALOG_SEPARATOR)
234263660c0SAlfonso Siciliano 		return (abs);
235263660c0SAlfonso Siciliano 	if (*focusitem < 0 || *focusitem >= (int)groups[*focusgroup].nitems)
236263660c0SAlfonso Siciliano 		return (abs);
237263660c0SAlfonso Siciliano 
238263660c0SAlfonso Siciliano 	for (i = abs; i < npritems; i++) {
239263660c0SAlfonso Siciliano 		if (pritems[i].group == *focusgroup &&
240263660c0SAlfonso Siciliano 		    pritems[i].index == *focusitem)
241263660c0SAlfonso Siciliano 			return (i);
242263660c0SAlfonso Siciliano 	}
243263660c0SAlfonso Siciliano 
244263660c0SAlfonso Siciliano 	return (abs);
245263660c0SAlfonso Siciliano }
246263660c0SAlfonso Siciliano 
247263660c0SAlfonso Siciliano static int
getfastnext(int menurows,int npritems,struct privateitem * pritems,int abs)248263660c0SAlfonso Siciliano getfastnext(int menurows, int npritems, struct privateitem *pritems, int abs)
249c76f0793SBaptiste Daroussin {
250c76f0793SBaptiste Daroussin 	int a, start, i;
251c76f0793SBaptiste Daroussin 
252263660c0SAlfonso Siciliano 	start = abs;
253c76f0793SBaptiste Daroussin 	i = menurows;
254c76f0793SBaptiste Daroussin 	do {
255263660c0SAlfonso Siciliano 		a = abs;
256263660c0SAlfonso Siciliano 		abs = getnext(npritems, pritems, abs);
257c76f0793SBaptiste Daroussin 		i--;
258263660c0SAlfonso Siciliano 	} while (abs != a && abs < start + menurows && i > 0);
259263660c0SAlfonso Siciliano 
260263660c0SAlfonso Siciliano 	return (abs);
261c76f0793SBaptiste Daroussin }
262c76f0793SBaptiste Daroussin 
263263660c0SAlfonso Siciliano static int
getfastprev(int menurows,struct privateitem * pritems,int abs)264263660c0SAlfonso Siciliano getfastprev(int menurows, struct privateitem *pritems, int abs)
265c76f0793SBaptiste Daroussin {
266c76f0793SBaptiste Daroussin 	int a, start, i;
267c76f0793SBaptiste Daroussin 
268263660c0SAlfonso Siciliano 	start = abs;
269c76f0793SBaptiste Daroussin 	i = menurows;
270c76f0793SBaptiste Daroussin 	do {
271263660c0SAlfonso Siciliano 		a = abs;
272263660c0SAlfonso Siciliano 		abs = getprev(pritems, abs);
273c76f0793SBaptiste Daroussin 		i--;
274263660c0SAlfonso Siciliano 	} while (abs != a && abs > start - menurows && i > 0);
275263660c0SAlfonso Siciliano 
276263660c0SAlfonso Siciliano 	return (abs);
277c76f0793SBaptiste Daroussin }
278c76f0793SBaptiste Daroussin 
279263660c0SAlfonso Siciliano static int
getnextshortcut(int npritems,struct privateitem * pritems,int abs,wint_t key)280*61ba55bcSBaptiste Daroussin getnextshortcut(int npritems, struct privateitem *pritems, int abs, wint_t key)
2818c4f4028SBaptiste Daroussin {
282b319d934SAlfonso S. Siciliano 	int i, next;
2838c4f4028SBaptiste Daroussin 
284263660c0SAlfonso Siciliano 	next = -1;
285263660c0SAlfonso Siciliano 	for (i = 0; i < npritems; i++) {
286263660c0SAlfonso Siciliano 		if (pritems[i].type == SEPARATORMODE)
2878c4f4028SBaptiste Daroussin 			continue;
288*61ba55bcSBaptiste Daroussin 		if (pritems[i].shortcut == (wchar_t)key) {
289263660c0SAlfonso Siciliano 			if (i > abs)
290263660c0SAlfonso Siciliano 				return (i);
291263660c0SAlfonso Siciliano 			if (i < abs && next == -1)
292263660c0SAlfonso Siciliano 				next = i;
2938c4f4028SBaptiste Daroussin 		}
2948c4f4028SBaptiste Daroussin 	}
2958c4f4028SBaptiste Daroussin 
296263660c0SAlfonso Siciliano 	return (next != -1 ? next : abs);
2978c4f4028SBaptiste Daroussin }
2988c4f4028SBaptiste Daroussin 
drawseparators(struct bsddialog_conf * conf,struct privatemenu * m)299*61ba55bcSBaptiste Daroussin static void drawseparators(struct bsddialog_conf *conf, struct privatemenu *m)
300c76f0793SBaptiste Daroussin {
301*61ba55bcSBaptiste Daroussin 	int i, linech, realw, labellen;
302bce40c02SAlfonso S. Siciliano 	const char *desc, *name;
303263660c0SAlfonso Siciliano 
304*61ba55bcSBaptiste Daroussin 	for (i = 0; i < m->nitems; i++) {
305*61ba55bcSBaptiste Daroussin 		if (m->pritems[i].type != SEPARATORMODE)
306bce40c02SAlfonso S. Siciliano 			continue;
307f499134dSBaptiste Daroussin 		if (conf->no_lines == false) {
308*61ba55bcSBaptiste Daroussin 			wattron(m->pad, t.menu.desccolor);
309f499134dSBaptiste Daroussin 			linech = conf->ascii_lines ? '-' : ACS_HLINE;
310*61ba55bcSBaptiste Daroussin 			mvwhline(m->pad, i, 0, linech, m->line);
311*61ba55bcSBaptiste Daroussin 			wattroff(m->pad, t.menu.desccolor);
312c76f0793SBaptiste Daroussin 		}
313*61ba55bcSBaptiste Daroussin 		name = m->pritems[i].name;
314*61ba55bcSBaptiste Daroussin 		desc = m->pritems[i].desc;
315*61ba55bcSBaptiste Daroussin 		realw = m->xe - m->xs;
316b319d934SAlfonso S. Siciliano 		labellen = strcols(name) + strcols(desc) + 1;
317*61ba55bcSBaptiste Daroussin 		wmove(m->pad, i, (labellen < realw) ? realw/2 - labellen/2 : 0);
318*61ba55bcSBaptiste Daroussin 		wattron(m->pad, t.menu.sepnamecolor);
319*61ba55bcSBaptiste Daroussin 		waddstr(m->pad, name);
320*61ba55bcSBaptiste Daroussin 		wattroff(m->pad, t.menu.sepnamecolor);
321b319d934SAlfonso S. Siciliano 		if (strcols(name) > 0 && strcols(desc) > 0)
322*61ba55bcSBaptiste Daroussin 			waddch(m->pad, ' ');
323*61ba55bcSBaptiste Daroussin 		wattron(m->pad, t.menu.sepdesccolor);
324*61ba55bcSBaptiste Daroussin 		waddstr(m->pad, desc);
325*61ba55bcSBaptiste Daroussin 		wattroff(m->pad, t.menu.sepdesccolor);
326bce40c02SAlfonso S. Siciliano 	}
327c76f0793SBaptiste Daroussin }
328c76f0793SBaptiste Daroussin 
329bce40c02SAlfonso S. Siciliano static void
drawitem(struct bsddialog_conf * conf,struct privatemenu * m,int y,bool focus)330*61ba55bcSBaptiste Daroussin drawitem(struct bsddialog_conf *conf, struct privatemenu *m, int y, bool focus)
331bce40c02SAlfonso S. Siciliano {
332bce40c02SAlfonso S. Siciliano 	int colordesc, colorname, colorshortcut;
333*61ba55bcSBaptiste Daroussin 	struct privateitem *pritem;
334bce40c02SAlfonso S. Siciliano 
335*61ba55bcSBaptiste Daroussin 	pritem = &m->pritems[y];
336bce40c02SAlfonso S. Siciliano 
337c76f0793SBaptiste Daroussin 	/* prefix */
338*61ba55bcSBaptiste Daroussin 	wattron(m->pad, focus ? t.menu.f_prefixcolor : t.menu.prefixcolor);
339*61ba55bcSBaptiste Daroussin 	mvwaddstr(m->pad, y, 0, pritem->prefix);
340*61ba55bcSBaptiste Daroussin 	wattroff(m->pad, focus ? t.menu.f_prefixcolor : t.menu.prefixcolor);
341c76f0793SBaptiste Daroussin 
342c76f0793SBaptiste Daroussin 	/* selector */
343*61ba55bcSBaptiste Daroussin 	wmove(m->pad, y, m->xselector);
344*61ba55bcSBaptiste Daroussin 	wattron(m->pad, focus ? t.menu.f_selectorcolor : t.menu.selectorcolor);
345bce40c02SAlfonso S. Siciliano 	if (pritem->type == CHECKLISTMODE)
346*61ba55bcSBaptiste Daroussin 		wprintw(m->pad, "[%c]", pritem->on ? 'X' : ' ');
347bce40c02SAlfonso S. Siciliano 	if (pritem->type == RADIOLISTMODE)
348*61ba55bcSBaptiste Daroussin 		wprintw(m->pad, "(%c)", pritem->on ? '*' : ' ');
349*61ba55bcSBaptiste Daroussin 	wattroff(m->pad, focus ? t.menu.f_selectorcolor : t.menu.selectorcolor);
350c76f0793SBaptiste Daroussin 
351c76f0793SBaptiste Daroussin 	/* name */
352263660c0SAlfonso Siciliano 	colorname = focus ? t.menu.f_namecolor : t.menu.namecolor;
353263660c0SAlfonso Siciliano 	if (conf->menu.no_name == false) {
354*61ba55bcSBaptiste Daroussin 		wattron(m->pad, colorname);
355*61ba55bcSBaptiste Daroussin 		mvwaddstr(m->pad, y, m->xname + pritem->depth, pritem->name);
356*61ba55bcSBaptiste Daroussin 		wattroff(m->pad, colorname);
357c76f0793SBaptiste Daroussin 	}
358c76f0793SBaptiste Daroussin 
359c76f0793SBaptiste Daroussin 	/* description */
3608c4f4028SBaptiste Daroussin 	if (conf->menu.no_name)
361263660c0SAlfonso Siciliano 		colordesc = focus ? t.menu.f_namecolor : t.menu.namecolor;
3628c4f4028SBaptiste Daroussin 	else
363263660c0SAlfonso Siciliano 		colordesc = focus ? t.menu.f_desccolor : t.menu.desccolor;
364263660c0SAlfonso Siciliano 
365263660c0SAlfonso Siciliano 	if (conf->menu.no_desc == false) {
366*61ba55bcSBaptiste Daroussin 		wattron(m->pad, colordesc);
367f499134dSBaptiste Daroussin 		if (conf->menu.no_name)
368*61ba55bcSBaptiste Daroussin 			mvwaddstr(m->pad, y, m->xname + pritem->depth,
369*61ba55bcSBaptiste Daroussin 			    pritem->desc);
370c76f0793SBaptiste Daroussin 		else
371*61ba55bcSBaptiste Daroussin 			mvwaddstr(m->pad, y, m->xdesc, pritem->desc);
372*61ba55bcSBaptiste Daroussin 		wattroff(m->pad, colordesc);
373c76f0793SBaptiste Daroussin 	}
374c76f0793SBaptiste Daroussin 
3758c4f4028SBaptiste Daroussin 	/* shortcut */
376263660c0SAlfonso Siciliano 	if (conf->menu.shortcut_buttons == false) {
377263660c0SAlfonso Siciliano 		colorshortcut = focus ?
378263660c0SAlfonso Siciliano 		    t.menu.f_shortcutcolor : t.menu.shortcutcolor;
379*61ba55bcSBaptiste Daroussin 		wattron(m->pad, colorshortcut);
380*61ba55bcSBaptiste Daroussin 		mvwaddwch(m->pad, y, m->xname + pritem->depth, pritem->shortcut);
381*61ba55bcSBaptiste Daroussin 		wattroff(m->pad, colorshortcut);
3828c4f4028SBaptiste Daroussin 	}
3838c4f4028SBaptiste Daroussin 
3848c4f4028SBaptiste Daroussin 	/* bottom description */
385*61ba55bcSBaptiste Daroussin 	if (m->hasbottomdesc) {
386263660c0SAlfonso Siciliano 		move(SCREENLINES - 1, 2);
387c76f0793SBaptiste Daroussin 		clrtoeol();
388*61ba55bcSBaptiste Daroussin 		if (focus) {
389b319d934SAlfonso S. Siciliano 			attron(t.menu.bottomdesccolor);
390*61ba55bcSBaptiste Daroussin 			addstr(pritem->bottomdesc);
391b319d934SAlfonso S. Siciliano 			attroff(t.menu.bottomdesccolor);
392c76f0793SBaptiste Daroussin 			refresh();
393c76f0793SBaptiste Daroussin 		}
394c76f0793SBaptiste Daroussin 	}
395*61ba55bcSBaptiste Daroussin }
396c76f0793SBaptiste Daroussin 
update_menubox(struct bsddialog_conf * conf,struct privatemenu * m)397*61ba55bcSBaptiste Daroussin static void update_menubox(struct bsddialog_conf *conf, struct privatemenu *m)
398b319d934SAlfonso S. Siciliano {
399*61ba55bcSBaptiste Daroussin 	int h, w;
400b319d934SAlfonso S. Siciliano 
401*61ba55bcSBaptiste Daroussin 	draw_borders(conf, m->box, LOWERED);
402*61ba55bcSBaptiste Daroussin 	getmaxyx(m->box, h, w);
403*61ba55bcSBaptiste Daroussin 
404*61ba55bcSBaptiste Daroussin 	if (m->nitems > (int)m->menurows) {
405*61ba55bcSBaptiste Daroussin 		wattron(m->box, t.dialog.arrowcolor);
406*61ba55bcSBaptiste Daroussin 		if (m->ypad > 0)
407*61ba55bcSBaptiste Daroussin 			mvwhline(m->box, 0, 2,
408b319d934SAlfonso S. Siciliano 			    conf->ascii_lines ? '^' : ACS_UARROW, 3);
409b319d934SAlfonso S. Siciliano 
410*61ba55bcSBaptiste Daroussin 		if ((m->ypad + (int)m->menurows) < m->nitems)
411*61ba55bcSBaptiste Daroussin 			mvwhline(m->box, h-1, 2,
412b319d934SAlfonso S. Siciliano 			    conf->ascii_lines ? 'v' : ACS_DARROW, 3);
413b319d934SAlfonso S. Siciliano 
414*61ba55bcSBaptiste Daroussin 		mvwprintw(m->box, h-1, w-6, "%3d%%",
415*61ba55bcSBaptiste Daroussin 		    100 * (m->ypad + m->menurows) / m->nitems);
416*61ba55bcSBaptiste Daroussin 		wattroff(m->box, t.dialog.arrowcolor);
417b319d934SAlfonso S. Siciliano 	}
418b319d934SAlfonso S. Siciliano }
419b319d934SAlfonso S. Siciliano 
menu_size_position(struct dialog * d,struct privatemenu * m)420*61ba55bcSBaptiste Daroussin static int menu_size_position(struct dialog *d, struct privatemenu *m)
421c76f0793SBaptiste Daroussin {
422*61ba55bcSBaptiste Daroussin 	int htext, hmenu;
423c76f0793SBaptiste Daroussin 
424*61ba55bcSBaptiste Daroussin 	if (set_widget_size(d->conf, d->rows, d->cols, &d->h, &d->w) != 0)
425263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
426c76f0793SBaptiste Daroussin 
427*61ba55bcSBaptiste Daroussin 	hmenu = (int)(m->menurows == BSDDIALOG_AUTOSIZE) ?
428*61ba55bcSBaptiste Daroussin 	    (int)m->nitems : (int)m->menurows;
429*61ba55bcSBaptiste Daroussin 	hmenu += 2; /* menu borders */
430*61ba55bcSBaptiste Daroussin 	/*
431*61ba55bcSBaptiste Daroussin 	 * algo 1: notext = 1 (grows vertically).
432*61ba55bcSBaptiste Daroussin 	 * algo 2: notext = hmenu (grows horizontally, better for little term).
433*61ba55bcSBaptiste Daroussin 	 */
434*61ba55bcSBaptiste Daroussin 	if (set_widget_autosize(d->conf, d->rows, d->cols, &d->h, &d->w,
435*61ba55bcSBaptiste Daroussin 	    d->text, &htext, &d->bs, hmenu, m->line + 4) != 0)
436*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
437*61ba55bcSBaptiste Daroussin 	/* avoid menurows overflow and menurows becomes "at most menurows" */
438*61ba55bcSBaptiste Daroussin 	if (d->h - BORDERS - htext - HBUTTONS <= 2 /* menuborders */)
439*61ba55bcSBaptiste Daroussin 		m->menurows = (m->nitems > 0) ? 1 : 0; /* widget_checksize() */
440b319d934SAlfonso S. Siciliano 	else
441*61ba55bcSBaptiste Daroussin 		m->menurows = MIN(d->h - BORDERS - htext - HBUTTONS, hmenu) - 2;
442263660c0SAlfonso Siciliano 
443*61ba55bcSBaptiste Daroussin 	/*
444*61ba55bcSBaptiste Daroussin 	 * no minw=linelen to avoid big menu fault, then some col can be
445*61ba55bcSBaptiste Daroussin 	 * hidden (example portconfig www/apache24).
446*61ba55bcSBaptiste Daroussin 	 */
447*61ba55bcSBaptiste Daroussin 	if (widget_checksize(d->h, d->w, &d->bs,
448*61ba55bcSBaptiste Daroussin 	    2 /* border box */ + MIN(m->menurows, 1), 0) != 0)
449*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
450*61ba55bcSBaptiste Daroussin 
451*61ba55bcSBaptiste Daroussin 	if (set_widget_position(d->conf, &d->y, &d->x, d->h, d->w) != 0)
452*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
45384823cc7SAlfonso S. Siciliano 
454263660c0SAlfonso Siciliano 	return (0);
455c76f0793SBaptiste Daroussin }
456c76f0793SBaptiste Daroussin 
mixedlist_redraw(struct dialog * d,struct privatemenu * m)457*61ba55bcSBaptiste Daroussin static int mixedlist_redraw(struct dialog *d, struct privatemenu *m)
458c76f0793SBaptiste Daroussin {
459*61ba55bcSBaptiste Daroussin 	if (d->built) {
460*61ba55bcSBaptiste Daroussin 		hide_dialog(d);
461*61ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
462*61ba55bcSBaptiste Daroussin 	}
463*61ba55bcSBaptiste Daroussin 	m->menurows = m->apimenurows;
464*61ba55bcSBaptiste Daroussin 	if (menu_size_position(d, m) != 0)
465*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
466*61ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
467*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
468*61ba55bcSBaptiste Daroussin 	if (d->built)
469*61ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
470*61ba55bcSBaptiste Daroussin 	TEXTPAD(d, 2/*bmenu*/ + m->menurows + HBUTTONS);
471c76f0793SBaptiste Daroussin 
472*61ba55bcSBaptiste Daroussin 	/* selected item in view*/
473*61ba55bcSBaptiste Daroussin 	if (m->ypad > m->sel && m->ypad > 0)
474*61ba55bcSBaptiste Daroussin 		m->ypad = m->sel;
475*61ba55bcSBaptiste Daroussin 	if ((int)(m->ypad + m->menurows) <= m->sel)
476*61ba55bcSBaptiste Daroussin 		m->ypad = m->sel - m->menurows + 1;
477*61ba55bcSBaptiste Daroussin 	/* lower pad after a terminal expansion */
478*61ba55bcSBaptiste Daroussin 	if (m->ypad > 0 && (m->nitems - m->ypad) < (int)m->menurows)
479*61ba55bcSBaptiste Daroussin 		m->ypad = m->nitems - m->menurows;
480c76f0793SBaptiste Daroussin 
481*61ba55bcSBaptiste Daroussin 	update_box(d->conf, m->box, d->y + d->h - 5 - m->menurows, d->x + 2,
482*61ba55bcSBaptiste Daroussin 	    m->menurows+2, d->w-4, LOWERED);
483*61ba55bcSBaptiste Daroussin 	update_menubox(d->conf, m);
484*61ba55bcSBaptiste Daroussin 	wnoutrefresh(m->box);
485c76f0793SBaptiste Daroussin 
486*61ba55bcSBaptiste Daroussin 	m->ys = d->y + d->h - 5 - m->menurows + 1;
487*61ba55bcSBaptiste Daroussin 	m->ye = d->y + d->h - 5 ;
488*61ba55bcSBaptiste Daroussin 	if (d->conf->menu.align_left || (int)m->line > d->w - 6) {
489*61ba55bcSBaptiste Daroussin 		m->xs = d->x + 3;
490*61ba55bcSBaptiste Daroussin 		m->xe = m->xs + d->w - 7;
491*61ba55bcSBaptiste Daroussin 	} else { /* center */
492*61ba55bcSBaptiste Daroussin 		m->xs = d->x + 3 + (d->w-6)/2 - m->line/2;
493*61ba55bcSBaptiste Daroussin 		m->xe = m->xs + d->w - 5;
494*61ba55bcSBaptiste Daroussin 	}
495*61ba55bcSBaptiste Daroussin 	drawseparators(d->conf, m); /* uses xe - xs */
496*61ba55bcSBaptiste Daroussin 	pnoutrefresh(m->pad, m->ypad, 0, m->ys, m->xs, m->ye, m->xe);
497c76f0793SBaptiste Daroussin 
498263660c0SAlfonso Siciliano 	return (0);
499c76f0793SBaptiste Daroussin }
500c76f0793SBaptiste Daroussin 
501c76f0793SBaptiste Daroussin static int
do_mixedlist(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int menurows,enum menumode mode,unsigned int ngroups,struct bsddialog_menugroup * groups,int * focuslist,int * focusitem)502263660c0SAlfonso Siciliano do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
503263660c0SAlfonso Siciliano     unsigned int menurows, enum menumode mode, unsigned int ngroups,
504c76f0793SBaptiste Daroussin     struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
505c76f0793SBaptiste Daroussin {
506*61ba55bcSBaptiste Daroussin 	bool loop, changeitem;
507*61ba55bcSBaptiste Daroussin 	int i, next, retval;
508b319d934SAlfonso S. Siciliano 	wint_t input;
509*61ba55bcSBaptiste Daroussin 	struct privatemenu m;
510*61ba55bcSBaptiste Daroussin 	struct dialog d;
511c76f0793SBaptiste Daroussin 
512*61ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
513263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
514*61ba55bcSBaptiste Daroussin 	set_buttons(&d, conf->menu.shortcut_buttons, OK_LABEL, CANCEL_LABEL);
515*61ba55bcSBaptiste Daroussin 	if (d.conf->menu.no_name && d.conf->menu.no_desc)
516*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Both conf.menu.no_name and conf.menu.no_desc");
517*61ba55bcSBaptiste Daroussin 
518*61ba55bcSBaptiste Daroussin 	if (build_privatemenu(conf, &m, mode, ngroups, groups) != 0)
519263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
520c76f0793SBaptiste Daroussin 
521*61ba55bcSBaptiste Daroussin 	if ((m.box = newwin(1, 1, 1, 1)) == NULL)
522*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW box menu");
523*61ba55bcSBaptiste Daroussin 	wbkgd(m.box, t.dialog.color);
524*61ba55bcSBaptiste Daroussin 	m.pad = newpad(m.nitems, m.line);
525*61ba55bcSBaptiste Daroussin 	wbkgd(m.pad, t.dialog.color);
526c76f0793SBaptiste Daroussin 
527*61ba55bcSBaptiste Daroussin 	for (i = 0; i < m.nitems; i++)
528*61ba55bcSBaptiste Daroussin 		drawitem(conf, &m, i, false);
529*61ba55bcSBaptiste Daroussin 	m.sel = getfirst_with_default(m.nitems, m.pritems, ngroups, groups,
530263660c0SAlfonso Siciliano 	    focuslist, focusitem);
531*61ba55bcSBaptiste Daroussin 	if (m.sel >= 0)
532*61ba55bcSBaptiste Daroussin 		drawitem(d.conf, &m, m.sel, true);
533*61ba55bcSBaptiste Daroussin 	m.ypad = 0;
534*61ba55bcSBaptiste Daroussin 	m.apimenurows = menurows;
535*61ba55bcSBaptiste Daroussin 	if (mixedlist_redraw(&d, &m) != 0)
536*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
537c76f0793SBaptiste Daroussin 
538*61ba55bcSBaptiste Daroussin 	changeitem = false;
539c76f0793SBaptiste Daroussin 	loop = true;
540c76f0793SBaptiste Daroussin 	while (loop) {
541*61ba55bcSBaptiste Daroussin 		doupdate();
542b319d934SAlfonso S. Siciliano 		if (get_wch(&input) == ERR)
543b319d934SAlfonso S. Siciliano 			continue;
544c76f0793SBaptiste Daroussin 		switch(input) {
545c76f0793SBaptiste Daroussin 		case KEY_ENTER:
546c76f0793SBaptiste Daroussin 		case 10: /* Enter */
547*61ba55bcSBaptiste Daroussin 			retval = BUTTONVALUE(d.bs);
548*61ba55bcSBaptiste Daroussin 			if (m.sel >= 0 && m.pritems[m.sel].type == MENUMODE)
549*61ba55bcSBaptiste Daroussin 				m.pritems[m.sel].on = true;
550c76f0793SBaptiste Daroussin 			loop = false;
551c76f0793SBaptiste Daroussin 			break;
552c76f0793SBaptiste Daroussin 		case 27: /* Esc */
553263660c0SAlfonso Siciliano 			if (conf->key.enable_esc) {
554b319d934SAlfonso S. Siciliano 				retval = BSDDIALOG_ESC;
555*61ba55bcSBaptiste Daroussin 				if (m.sel >= 0 &&
556*61ba55bcSBaptiste Daroussin 				   m.pritems[m.sel].type == MENUMODE)
557*61ba55bcSBaptiste Daroussin 					m.pritems[m.sel].on = true;
558c76f0793SBaptiste Daroussin 				loop = false;
559263660c0SAlfonso Siciliano 			}
560c76f0793SBaptiste Daroussin 			break;
561c76f0793SBaptiste Daroussin 		case '\t': /* TAB */
562*61ba55bcSBaptiste Daroussin 		case KEY_RIGHT:
563*61ba55bcSBaptiste Daroussin 			d.bs.curr = (d.bs.curr + 1) % d.bs.nbuttons;
564*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
565c76f0793SBaptiste Daroussin 			break;
566c76f0793SBaptiste Daroussin 		case KEY_LEFT:
567*61ba55bcSBaptiste Daroussin 			d.bs.curr--;
568*61ba55bcSBaptiste Daroussin 			if (d.bs.curr < 0)
569*61ba55bcSBaptiste Daroussin 				 d.bs.curr = d.bs.nbuttons - 1;
570*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
571c76f0793SBaptiste Daroussin 			break;
572c76f0793SBaptiste Daroussin 		case KEY_F(1):
573bce40c02SAlfonso S. Siciliano 			if (conf->key.f1_file == NULL &&
574bce40c02SAlfonso S. Siciliano 			    conf->key.f1_message == NULL)
575c76f0793SBaptiste Daroussin 				break;
576*61ba55bcSBaptiste Daroussin 			if (f1help_dialog(conf) != 0)
577263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
578*61ba55bcSBaptiste Daroussin 			if (mixedlist_redraw(&d, &m) != 0)
579*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
580*61ba55bcSBaptiste Daroussin 			break;
581c76f0793SBaptiste Daroussin 		case KEY_RESIZE:
582*61ba55bcSBaptiste Daroussin 			if (mixedlist_redraw(&d, &m) != 0)
583263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
584c76f0793SBaptiste Daroussin 			break;
585c76f0793SBaptiste Daroussin 		}
586c76f0793SBaptiste Daroussin 
587*61ba55bcSBaptiste Daroussin 		if (m.sel < 0)
588c76f0793SBaptiste Daroussin 			continue;
589c76f0793SBaptiste Daroussin 		switch(input) {
590c76f0793SBaptiste Daroussin 		case KEY_HOME:
591*61ba55bcSBaptiste Daroussin 			next = getnext(m.nitems, m.pritems, -1);
592*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
593c76f0793SBaptiste Daroussin 			break;
594263660c0SAlfonso Siciliano 		case KEY_UP:
595*61ba55bcSBaptiste Daroussin 			next = getprev(m.pritems, m.sel);
596*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
597263660c0SAlfonso Siciliano 			break;
598263660c0SAlfonso Siciliano 		case KEY_PPAGE:
599*61ba55bcSBaptiste Daroussin 			next = getfastprev(m.menurows, m.pritems, m.sel);
600*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
601c76f0793SBaptiste Daroussin 			break;
602c76f0793SBaptiste Daroussin 		case KEY_END:
603*61ba55bcSBaptiste Daroussin 			next = getprev(m.pritems, m.nitems);
604*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
605263660c0SAlfonso Siciliano 			break;
606c76f0793SBaptiste Daroussin 		case KEY_DOWN:
607*61ba55bcSBaptiste Daroussin 			next = getnext(m.nitems, m.pritems, m.sel);
608*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
609263660c0SAlfonso Siciliano 			break;
610c76f0793SBaptiste Daroussin 		case KEY_NPAGE:
611*61ba55bcSBaptiste Daroussin 			next = getfastnext(m.menurows, m.nitems, m.pritems, m.sel);
612*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
613c76f0793SBaptiste Daroussin 			break;
614c76f0793SBaptiste Daroussin 		case ' ': /* Space */
615*61ba55bcSBaptiste Daroussin 			if (m.pritems[m.sel].type == MENUMODE) {
616*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
617*61ba55bcSBaptiste Daroussin 				m.pritems[m.sel].on = true;
61884823cc7SAlfonso S. Siciliano 				loop = false;
619*61ba55bcSBaptiste Daroussin 			} else if (m.pritems[m.sel].type == CHECKLISTMODE) {
620*61ba55bcSBaptiste Daroussin 				m.pritems[m.sel].on = !m.pritems[m.sel].on;
62184823cc7SAlfonso S. Siciliano 			} else { /* RADIOLISTMODE */
622*61ba55bcSBaptiste Daroussin 				for (i = m.sel - m.pritems[m.sel].index;
623*61ba55bcSBaptiste Daroussin 				    i < m.nitems &&
624*61ba55bcSBaptiste Daroussin 				    m.pritems[i].group == m.pritems[m.sel].group;
625263660c0SAlfonso Siciliano 				    i++) {
626*61ba55bcSBaptiste Daroussin 					if (i != m.sel && m.pritems[i].on) {
627*61ba55bcSBaptiste Daroussin 						m.pritems[i].on = false;
628*61ba55bcSBaptiste Daroussin 						drawitem(conf, &m, i, false);
629c76f0793SBaptiste Daroussin 					}
630c76f0793SBaptiste Daroussin 				}
631*61ba55bcSBaptiste Daroussin 				m.pritems[m.sel].on = !m.pritems[m.sel].on;
632263660c0SAlfonso Siciliano 			}
633*61ba55bcSBaptiste Daroussin 			drawitem(conf, &m, m.sel, true);
634*61ba55bcSBaptiste Daroussin 			pnoutrefresh(m.pad, m.ypad, 0, m.ys, m.xs, m.ye, m.xe);
635263660c0SAlfonso Siciliano 			break;
6368c4f4028SBaptiste Daroussin 		default:
637*61ba55bcSBaptiste Daroussin 			if (conf->menu.shortcut_buttons) {
638*61ba55bcSBaptiste Daroussin 				if (shortcut_buttons(input, &d.bs)) {
639*61ba55bcSBaptiste Daroussin 					DRAW_BUTTONS(d);
640*61ba55bcSBaptiste Daroussin 					doupdate();
641*61ba55bcSBaptiste Daroussin 					retval = BUTTONVALUE(d.bs);
642*61ba55bcSBaptiste Daroussin 					if (m.pritems[m.sel].type == MENUMODE)
643*61ba55bcSBaptiste Daroussin 						m.pritems[m.sel].on = true;
6448c4f4028SBaptiste Daroussin 					loop = false;
6458c4f4028SBaptiste Daroussin 				}
6468c4f4028SBaptiste Daroussin 				break;
6478c4f4028SBaptiste Daroussin 			}
6488c4f4028SBaptiste Daroussin 
649263660c0SAlfonso Siciliano 			/* shourtcut items */
650*61ba55bcSBaptiste Daroussin 			next = getnextshortcut(m.nitems, m.pritems, m.sel,
651263660c0SAlfonso Siciliano 			    input);
652*61ba55bcSBaptiste Daroussin 			changeitem = next != m.sel;
653*61ba55bcSBaptiste Daroussin 		} /* end switch get_wch() */
654263660c0SAlfonso Siciliano 
655*61ba55bcSBaptiste Daroussin 		if (changeitem) {
656*61ba55bcSBaptiste Daroussin 			drawitem(conf, &m, m.sel, false);
657*61ba55bcSBaptiste Daroussin 			m.sel = next;
658*61ba55bcSBaptiste Daroussin 			drawitem(conf, &m, m.sel, true);
659*61ba55bcSBaptiste Daroussin 			if (m.ypad > m.sel && m.ypad > 0)
660*61ba55bcSBaptiste Daroussin 				m.ypad = m.sel;
661*61ba55bcSBaptiste Daroussin 			if ((int)(m.ypad + m.menurows) <= m.sel)
662*61ba55bcSBaptiste Daroussin 				m.ypad = m.sel - m.menurows + 1;
663*61ba55bcSBaptiste Daroussin 			update_menubox(conf, &m);
664*61ba55bcSBaptiste Daroussin 			wnoutrefresh(m.box);
665*61ba55bcSBaptiste Daroussin 			pnoutrefresh(m.pad, m.ypad, 0, m.ys, m.xs, m.ye, m.xe);
666*61ba55bcSBaptiste Daroussin 			changeitem = false;
667c76f0793SBaptiste Daroussin 		}
668*61ba55bcSBaptiste Daroussin 	} /* end while(loop) */
669*61ba55bcSBaptiste Daroussin 
670*61ba55bcSBaptiste Daroussin 	set_return_on(&m, groups);
671c76f0793SBaptiste Daroussin 
672c76f0793SBaptiste Daroussin 	if (focuslist != NULL)
673*61ba55bcSBaptiste Daroussin 		*focuslist = m.sel < 0 ? -1 : m.pritems[m.sel].group;
674c76f0793SBaptiste Daroussin 	if (focusitem !=NULL)
675*61ba55bcSBaptiste Daroussin 		*focusitem = m.sel < 0 ? -1 : m.pritems[m.sel].index;
676c76f0793SBaptiste Daroussin 
677*61ba55bcSBaptiste Daroussin 	if (m.hasbottomdesc && conf->clear) {
678*61ba55bcSBaptiste Daroussin 		move(SCREENLINES - 1, 2);
679*61ba55bcSBaptiste Daroussin 		clrtoeol();
680*61ba55bcSBaptiste Daroussin 	}
681*61ba55bcSBaptiste Daroussin 	delwin(m.pad);
682*61ba55bcSBaptiste Daroussin 	delwin(m.box);
683*61ba55bcSBaptiste Daroussin 	end_dialog(&d);
684*61ba55bcSBaptiste Daroussin 	free(m.pritems);
685c76f0793SBaptiste Daroussin 
686b319d934SAlfonso S. Siciliano 	return (retval);
687c76f0793SBaptiste Daroussin }
688c76f0793SBaptiste Daroussin 
689263660c0SAlfonso Siciliano /* API */
690263660c0SAlfonso Siciliano int
bsddialog_mixedlist(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int menurows,unsigned int ngroups,struct bsddialog_menugroup * groups,int * focuslist,int * focusitem)691263660c0SAlfonso Siciliano bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows,
692263660c0SAlfonso Siciliano     int cols, unsigned int menurows, unsigned int ngroups,
693263660c0SAlfonso Siciliano     struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
694c76f0793SBaptiste Daroussin {
695b319d934SAlfonso S. Siciliano 	int retval;
696c76f0793SBaptiste Daroussin 
697b319d934SAlfonso S. Siciliano 	retval = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE,
698c76f0793SBaptiste Daroussin 	    ngroups, groups, focuslist, focusitem);
699c76f0793SBaptiste Daroussin 
700b319d934SAlfonso S. Siciliano 	return (retval);
701c76f0793SBaptiste Daroussin }
702c76f0793SBaptiste Daroussin 
703c76f0793SBaptiste Daroussin int
bsddialog_checklist(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int menurows,unsigned int nitems,struct bsddialog_menuitem * items,int * focusitem)704263660c0SAlfonso Siciliano bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
705263660c0SAlfonso Siciliano     int cols, unsigned int menurows, unsigned int nitems,
706263660c0SAlfonso Siciliano     struct bsddialog_menuitem *items, int *focusitem)
707c76f0793SBaptiste Daroussin {
708b319d934SAlfonso S. Siciliano 	int retval, focuslist = 0;
709c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
710*61ba55bcSBaptiste Daroussin 	    BSDDIALOG_CHECKLIST /* unused */, nitems, items, 0};
711c76f0793SBaptiste Daroussin 
712*61ba55bcSBaptiste Daroussin 	CHECK_ARRAY(nitems, items); /* efficiency, avoid do_mixedlist() */
713b319d934SAlfonso S. Siciliano 	retval = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE,
714263660c0SAlfonso Siciliano 	    1, &group, &focuslist, focusitem);
715c76f0793SBaptiste Daroussin 
716b319d934SAlfonso S. Siciliano 	return (retval);
717c76f0793SBaptiste Daroussin }
718c76f0793SBaptiste Daroussin 
719c76f0793SBaptiste Daroussin int
bsddialog_menu(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int menurows,unsigned int nitems,struct bsddialog_menuitem * items,int * focusitem)720263660c0SAlfonso Siciliano bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows,
721263660c0SAlfonso Siciliano     int cols, unsigned int menurows, unsigned int nitems,
722263660c0SAlfonso Siciliano     struct bsddialog_menuitem *items, int *focusitem)
723c76f0793SBaptiste Daroussin {
724b319d934SAlfonso S. Siciliano 	int retval, focuslist = 0;
725c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
726*61ba55bcSBaptiste Daroussin 	    BSDDIALOG_CHECKLIST /* unused */, nitems, items, 0};
727c76f0793SBaptiste Daroussin 
728*61ba55bcSBaptiste Daroussin 	CHECK_ARRAY(nitems, items); /* efficiency, avoid do_mixedlist() */
729b319d934SAlfonso S. Siciliano 	retval = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1,
730263660c0SAlfonso Siciliano 	    &group, &focuslist, focusitem);
731c76f0793SBaptiste Daroussin 
732b319d934SAlfonso S. Siciliano 	return (retval);
733c76f0793SBaptiste Daroussin }
734c76f0793SBaptiste Daroussin 
735c76f0793SBaptiste Daroussin int
bsddialog_radiolist(struct bsddialog_conf * conf,const char * text,int rows,int cols,unsigned int menurows,unsigned int nitems,struct bsddialog_menuitem * items,int * focusitem)736263660c0SAlfonso Siciliano bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows,
737263660c0SAlfonso Siciliano     int cols, unsigned int menurows, unsigned int nitems,
738263660c0SAlfonso Siciliano     struct bsddialog_menuitem *items, int *focusitem)
739c76f0793SBaptiste Daroussin {
740b319d934SAlfonso S. Siciliano 	int retval, focuslist = 0;
741c76f0793SBaptiste Daroussin 	struct bsddialog_menugroup group = {
742*61ba55bcSBaptiste Daroussin 	    BSDDIALOG_RADIOLIST /* unused */, nitems, items, 0};
743c76f0793SBaptiste Daroussin 
744*61ba55bcSBaptiste Daroussin 	CHECK_ARRAY(nitems, items); /* efficiency, avoid do_mixedlist() */
745b319d934SAlfonso S. Siciliano 	retval = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
746263660c0SAlfonso Siciliano 	    1, &group, &focuslist, focusitem);
747c76f0793SBaptiste Daroussin 
748b319d934SAlfonso S. Siciliano 	return (retval);
749c76f0793SBaptiste Daroussin }
750