xref: /freebsd-src/contrib/bsddialog/lib/lib_util.c (revision 263660c061ac76d449cbca7bdd0db2ecdfad76d9)
1c76f0793SBaptiste Daroussin /*-
2c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3c76f0793SBaptiste Daroussin  *
4*263660c0SAlfonso Siciliano  * Copyright (c) 2021-2022 Alfonso Sabato Siciliano
5c76f0793SBaptiste Daroussin  *
6c76f0793SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7c76f0793SBaptiste Daroussin  * modification, are permitted provided that the following conditions
8c76f0793SBaptiste Daroussin  * are met:
9c76f0793SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11c76f0793SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13c76f0793SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14c76f0793SBaptiste Daroussin  *
15c76f0793SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c76f0793SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c76f0793SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c76f0793SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c76f0793SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c76f0793SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c76f0793SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c76f0793SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c76f0793SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c76f0793SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c76f0793SBaptiste Daroussin  * SUCH DAMAGE.
26c76f0793SBaptiste Daroussin  */
27c76f0793SBaptiste Daroussin 
28c76f0793SBaptiste Daroussin #include <sys/param.h>
29c76f0793SBaptiste Daroussin 
30*263660c0SAlfonso Siciliano #include <ctype.h>
31*263660c0SAlfonso Siciliano #include <curses.h>
32d93b4d32SBaptiste Daroussin #include <stdlib.h>
33d93b4d32SBaptiste Daroussin #include <string.h>
34d93b4d32SBaptiste Daroussin #include <unistd.h>
35c76f0793SBaptiste Daroussin 
36c76f0793SBaptiste Daroussin #include "bsddialog.h"
37c76f0793SBaptiste Daroussin #include "bsddialog_theme.h"
38*263660c0SAlfonso Siciliano #include "lib_util.h"
39c76f0793SBaptiste Daroussin 
40c76f0793SBaptiste Daroussin extern struct bsddialog_theme t;
41c76f0793SBaptiste Daroussin 
42*263660c0SAlfonso Siciliano #define TABLEN     4    /* Default tab len */
43*263660c0SAlfonso Siciliano #define ERRBUFLEN  1024 /* Error buffer */
44c76f0793SBaptiste Daroussin 
45*263660c0SAlfonso Siciliano /* Error */
46c76f0793SBaptiste Daroussin static char errorbuffer[ERRBUFLEN];
47c76f0793SBaptiste Daroussin 
48c76f0793SBaptiste Daroussin const char *get_error_string(void)
49c76f0793SBaptiste Daroussin {
50*263660c0SAlfonso Siciliano 	return (errorbuffer);
51c76f0793SBaptiste Daroussin }
52c76f0793SBaptiste Daroussin 
53c76f0793SBaptiste Daroussin void set_error_string(char *str)
54c76f0793SBaptiste Daroussin {
55c76f0793SBaptiste Daroussin 	strncpy(errorbuffer, str, ERRBUFLEN-1);
56c76f0793SBaptiste Daroussin }
57c76f0793SBaptiste Daroussin 
58*263660c0SAlfonso Siciliano /* Clear */
59c76f0793SBaptiste Daroussin int hide_widget(int y, int x, int h, int w, bool withshadow)
60c76f0793SBaptiste Daroussin {
61c76f0793SBaptiste Daroussin 	WINDOW *clear;
62c76f0793SBaptiste Daroussin 
63f499134dSBaptiste Daroussin 	if ((clear = newwin(h, w, y + t.shadow.h, x + t.shadow.w)) == NULL)
64c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot hide the widget");
65*263660c0SAlfonso Siciliano 	wbkgd(clear, t.screen.color);
66c76f0793SBaptiste Daroussin 
67c76f0793SBaptiste Daroussin 	if (withshadow)
68c76f0793SBaptiste Daroussin 		wrefresh(clear);
69c76f0793SBaptiste Daroussin 
70c76f0793SBaptiste Daroussin 	mvwin(clear, y, x);
71c76f0793SBaptiste Daroussin 	wrefresh(clear);
72c76f0793SBaptiste Daroussin 
73c76f0793SBaptiste Daroussin 	delwin(clear);
74c76f0793SBaptiste Daroussin 
75*263660c0SAlfonso Siciliano 	return (0);
76c76f0793SBaptiste Daroussin }
77c76f0793SBaptiste Daroussin 
78c76f0793SBaptiste Daroussin /* F1 help */
79f499134dSBaptiste Daroussin int f1help(struct bsddialog_conf *conf)
80c76f0793SBaptiste Daroussin {
81c76f0793SBaptiste Daroussin 	int output;
828c4f4028SBaptiste Daroussin 	struct bsddialog_conf hconf;
83c76f0793SBaptiste Daroussin 
848c4f4028SBaptiste Daroussin 	bsddialog_initconf(&hconf);
858c4f4028SBaptiste Daroussin 	hconf.title           = "HELP";
868c4f4028SBaptiste Daroussin 	hconf.button.ok_label = "EXIT";
878c4f4028SBaptiste Daroussin 	hconf.clear           = true;
888c4f4028SBaptiste Daroussin 	hconf.ascii_lines     = conf->ascii_lines;
898c4f4028SBaptiste Daroussin 	hconf.no_lines        = conf->no_lines;
908c4f4028SBaptiste Daroussin 	hconf.shadow          = conf->shadow;
91*263660c0SAlfonso Siciliano 	hconf.text.highlight  = conf->text.highlight;
92c76f0793SBaptiste Daroussin 
938c4f4028SBaptiste Daroussin 	output = BSDDIALOG_OK;
948c4f4028SBaptiste Daroussin 	if (conf->f1_message != NULL)
958c4f4028SBaptiste Daroussin 		output = bsddialog_msgbox(&hconf, conf->f1_message, 0, 0);
96c76f0793SBaptiste Daroussin 
978c4f4028SBaptiste Daroussin 	if (output != BSDDIALOG_ERROR && conf->f1_file != NULL)
988c4f4028SBaptiste Daroussin 		output = bsddialog_textbox(&hconf, conf->f1_file, 0, 0);
998c4f4028SBaptiste Daroussin 
1008c4f4028SBaptiste Daroussin 	return (output == BSDDIALOG_ERROR ? BSDDIALOG_ERROR : 0);
101c76f0793SBaptiste Daroussin }
102c76f0793SBaptiste Daroussin 
103c76f0793SBaptiste Daroussin /* Buttons */
104*263660c0SAlfonso Siciliano static void
105*263660c0SAlfonso Siciliano draw_button(WINDOW *window, int y, int x, int size, const char *text,
106*263660c0SAlfonso Siciliano     bool selected, bool shortcut)
107c76f0793SBaptiste Daroussin {
108c76f0793SBaptiste Daroussin 	int i, color_arrows, color_shortkey, color_button;
109c76f0793SBaptiste Daroussin 
110c76f0793SBaptiste Daroussin 	if (selected) {
111f499134dSBaptiste Daroussin 		color_arrows = t.button.f_delimcolor;
112f499134dSBaptiste Daroussin 		color_shortkey = t.button.f_shortcutcolor;
113f499134dSBaptiste Daroussin 		color_button = t.button.f_color;
114c76f0793SBaptiste Daroussin 	} else {
115f499134dSBaptiste Daroussin 		color_arrows = t.button.delimcolor;
116f499134dSBaptiste Daroussin 		color_shortkey = t.button.shortcutcolor;
117f499134dSBaptiste Daroussin 		color_button = t.button.color;
118c76f0793SBaptiste Daroussin 	}
119c76f0793SBaptiste Daroussin 
120c76f0793SBaptiste Daroussin 	wattron(window, color_arrows);
121f499134dSBaptiste Daroussin 	mvwaddch(window, y, x, t.button.leftch);
122c76f0793SBaptiste Daroussin 	wattroff(window, color_arrows);
123c76f0793SBaptiste Daroussin 	wattron(window, color_button);
124c76f0793SBaptiste Daroussin 	for (i = 1; i < size - 1; i++)
125c76f0793SBaptiste Daroussin 		waddch(window, ' ');
126c76f0793SBaptiste Daroussin 	wattroff(window, color_button);
127c76f0793SBaptiste Daroussin 	wattron(window, color_arrows);
128f499134dSBaptiste Daroussin 	mvwaddch(window, y, x + i, t.button.rightch);
129c76f0793SBaptiste Daroussin 	wattroff(window, color_arrows);
130c76f0793SBaptiste Daroussin 
131c76f0793SBaptiste Daroussin 	x = x + 1 + ((size - 2 - strlen(text))/2);
132c76f0793SBaptiste Daroussin 	wattron(window, color_button);
133c76f0793SBaptiste Daroussin 	mvwaddstr(window, y, x, text);
134c76f0793SBaptiste Daroussin 	wattroff(window, color_button);
135c76f0793SBaptiste Daroussin 
136*263660c0SAlfonso Siciliano 	if (shortcut) {
137c76f0793SBaptiste Daroussin 		wattron(window, color_shortkey);
138c76f0793SBaptiste Daroussin 		mvwaddch(window, y, x, text[0]);
139c76f0793SBaptiste Daroussin 		wattroff(window, color_shortkey);
140c76f0793SBaptiste Daroussin 	}
141c76f0793SBaptiste Daroussin }
142c76f0793SBaptiste Daroussin 
143c76f0793SBaptiste Daroussin void
144*263660c0SAlfonso Siciliano draw_buttons(WINDOW *window, struct buttons bs, bool shortcut)
145c76f0793SBaptiste Daroussin {
146*263660c0SAlfonso Siciliano 	int i, x, startx, y, rows, cols;
147c76f0793SBaptiste Daroussin 
148*263660c0SAlfonso Siciliano 	getmaxyx(window, rows, cols);
149*263660c0SAlfonso Siciliano 	y = rows - 2;
150*263660c0SAlfonso Siciliano 
151*263660c0SAlfonso Siciliano 	startx = bs.sizebutton * bs.nbuttons + (bs.nbuttons-1) * t.button.space;
152*263660c0SAlfonso Siciliano 	startx = cols/2 - startx/2;
153c76f0793SBaptiste Daroussin 
154c76f0793SBaptiste Daroussin 	for (i = 0; i < (int) bs.nbuttons; i++) {
155f499134dSBaptiste Daroussin 		x = i * (bs.sizebutton + t.button.space);
156*263660c0SAlfonso Siciliano 		draw_button(window, y, startx + x, bs.sizebutton, bs.label[i],
157*263660c0SAlfonso Siciliano 		    i == bs.curr, shortcut);
158c76f0793SBaptiste Daroussin 	}
159c76f0793SBaptiste Daroussin }
160c76f0793SBaptiste Daroussin 
161c76f0793SBaptiste Daroussin void
162f499134dSBaptiste Daroussin get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel,
163*263660c0SAlfonso Siciliano     char *nocancellabel)
164c76f0793SBaptiste Daroussin {
165c76f0793SBaptiste Daroussin 	int i;
166c76f0793SBaptiste Daroussin #define SIZEBUTTON              8
167*263660c0SAlfonso Siciliano #define DEFAULT_BUTTON_LABEL	BUTTON_OK_LABEL
1688c4f4028SBaptiste Daroussin #define DEFAULT_BUTTON_VALUE	BSDDIALOG_OK
169c76f0793SBaptiste Daroussin 
170c76f0793SBaptiste Daroussin 	bs->nbuttons = 0;
171c76f0793SBaptiste Daroussin 	bs->curr = 0;
172c76f0793SBaptiste Daroussin 	bs->sizebutton = 0;
173c76f0793SBaptiste Daroussin 
1748c4f4028SBaptiste Daroussin 	if (yesoklabel != NULL && conf->button.without_ok == false) {
175*263660c0SAlfonso Siciliano 		bs->label[0] = conf->button.ok_label != NULL ?
176*263660c0SAlfonso Siciliano 		    conf->button.ok_label : yesoklabel;
1778c4f4028SBaptiste Daroussin 		bs->value[0] = BSDDIALOG_OK;
178c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
179c76f0793SBaptiste Daroussin 	}
180c76f0793SBaptiste Daroussin 
181*263660c0SAlfonso Siciliano 	if (conf->button.with_extra) {
182*263660c0SAlfonso Siciliano 		bs->label[bs->nbuttons] = conf->button.extra_label != NULL ?
183*263660c0SAlfonso Siciliano 		    conf->button.extra_label : "Extra";
184c76f0793SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_EXTRA;
185c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
186c76f0793SBaptiste Daroussin 	}
187c76f0793SBaptiste Daroussin 
1888c4f4028SBaptiste Daroussin 	if (nocancellabel != NULL && conf->button.without_cancel == false) {
189*263660c0SAlfonso Siciliano 		bs->label[bs->nbuttons] = conf->button.cancel_label ?
190*263660c0SAlfonso Siciliano 		    conf->button.cancel_label : nocancellabel;
1918c4f4028SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_CANCEL;
1928c4f4028SBaptiste Daroussin 		if (conf->button.default_cancel)
193c76f0793SBaptiste Daroussin 			bs->curr = bs->nbuttons;
194c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
195c76f0793SBaptiste Daroussin 	}
196c76f0793SBaptiste Daroussin 
197*263660c0SAlfonso Siciliano 	if (conf->button.with_help) {
198*263660c0SAlfonso Siciliano 		bs->label[bs->nbuttons] = conf->button.help_label != NULL ?
199*263660c0SAlfonso Siciliano 		    conf->button.help_label : "Help";
200c76f0793SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_HELP;
201c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
202c76f0793SBaptiste Daroussin 	}
203c76f0793SBaptiste Daroussin 
204f499134dSBaptiste Daroussin 	if (conf->button.generic1_label != NULL) {
205f499134dSBaptiste Daroussin 		bs->label[bs->nbuttons] = conf->button.generic1_label;
206f499134dSBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_GENERIC1;
207f499134dSBaptiste Daroussin 		bs->nbuttons += 1;
208f499134dSBaptiste Daroussin 	}
209f499134dSBaptiste Daroussin 
210f499134dSBaptiste Daroussin 	if (conf->button.generic2_label != NULL) {
211f499134dSBaptiste Daroussin 		bs->label[bs->nbuttons] = conf->button.generic2_label;
212f499134dSBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_GENERIC2;
213f499134dSBaptiste Daroussin 		bs->nbuttons += 1;
214f499134dSBaptiste Daroussin 	}
215f499134dSBaptiste Daroussin 
216c76f0793SBaptiste Daroussin 	if (bs->nbuttons == 0) {
217c76f0793SBaptiste Daroussin 		bs->label[0] = DEFAULT_BUTTON_LABEL;
218c76f0793SBaptiste Daroussin 		bs->value[0] = DEFAULT_BUTTON_VALUE;
219c76f0793SBaptiste Daroussin 		bs->nbuttons = 1;
220c76f0793SBaptiste Daroussin 	}
221c76f0793SBaptiste Daroussin 
222f499134dSBaptiste Daroussin 	if (conf->button.default_label != NULL) {
223c76f0793SBaptiste Daroussin 		for (i = 0; i < (int)bs->nbuttons; i++) {
224*263660c0SAlfonso Siciliano 			if (strcmp(conf->button.default_label,
225*263660c0SAlfonso Siciliano 			    bs->label[i]) == 0)
226c76f0793SBaptiste Daroussin 				bs->curr = i;
227c76f0793SBaptiste Daroussin 		}
228c76f0793SBaptiste Daroussin 	}
229c76f0793SBaptiste Daroussin 
230c76f0793SBaptiste Daroussin 	bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0]));
231c76f0793SBaptiste Daroussin 	for (i = 1; i < (int)bs->nbuttons; i++)
232c76f0793SBaptiste Daroussin 		bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i]));
233c76f0793SBaptiste Daroussin 	bs->sizebutton += 2;
234c76f0793SBaptiste Daroussin }
235c76f0793SBaptiste Daroussin 
236*263660c0SAlfonso Siciliano bool shortcut_buttons(int key, struct buttons *bs)
237f499134dSBaptiste Daroussin {
238*263660c0SAlfonso Siciliano 	bool match;
239*263660c0SAlfonso Siciliano 	unsigned int i;
240c76f0793SBaptiste Daroussin 
241*263660c0SAlfonso Siciliano 	match = false;
242*263660c0SAlfonso Siciliano 	for (i = 0; i < bs->nbuttons; i++) {
243*263660c0SAlfonso Siciliano 		if (tolower(key) == tolower(bs->label[i][0])) {
244*263660c0SAlfonso Siciliano 			bs->curr = i;
245*263660c0SAlfonso Siciliano 			match = true;
246*263660c0SAlfonso Siciliano 			break;
247*263660c0SAlfonso Siciliano 		}
248*263660c0SAlfonso Siciliano 	}
249*263660c0SAlfonso Siciliano 
250*263660c0SAlfonso Siciliano 	return (match);
251*263660c0SAlfonso Siciliano }
252*263660c0SAlfonso Siciliano 
253*263660c0SAlfonso Siciliano /* Text */
254*263660c0SAlfonso Siciliano static bool is_text_attr(const char *text)
255*263660c0SAlfonso Siciliano {
256f499134dSBaptiste Daroussin 	if (strnlen(text, 3) < 3)
257*263660c0SAlfonso Siciliano 		return (false);
258f499134dSBaptiste Daroussin 
259f499134dSBaptiste Daroussin 	if (text[0] != '\\' || text[1] != 'Z')
260*263660c0SAlfonso Siciliano 		return (false);
261f499134dSBaptiste Daroussin 
262f499134dSBaptiste Daroussin 	return (strchr("nbBrRuU01234567", text[2]) == NULL ? false : true);
263f499134dSBaptiste Daroussin }
264c76f0793SBaptiste Daroussin 
265*263660c0SAlfonso Siciliano static bool check_set_text_attr(WINDOW *win, char *text)
266c76f0793SBaptiste Daroussin {
267*263660c0SAlfonso Siciliano 	if (is_text_attr(text) == false)
268*263660c0SAlfonso Siciliano 		return (false);
269c76f0793SBaptiste Daroussin 
270f499134dSBaptiste Daroussin 	if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) {
2718c4f4028SBaptiste Daroussin 		wattron(win, bsddialog_color(text[2] - '0', COLOR_WHITE, 0));
272*263660c0SAlfonso Siciliano 		return (true);
273c76f0793SBaptiste Daroussin 	}
274c76f0793SBaptiste Daroussin 
275c76f0793SBaptiste Daroussin 	switch (text[2]) {
276c76f0793SBaptiste Daroussin 	case 'n':
277*263660c0SAlfonso Siciliano 		wattron(win, t.dialog.color);
278c76f0793SBaptiste Daroussin 		wattrset(win, A_NORMAL);
279c76f0793SBaptiste Daroussin 		break;
280c76f0793SBaptiste Daroussin 	case 'b':
281c76f0793SBaptiste Daroussin 		wattron(win, A_BOLD);
282c76f0793SBaptiste Daroussin 		break;
283c76f0793SBaptiste Daroussin 	case 'B':
284c76f0793SBaptiste Daroussin 		wattroff(win, A_BOLD);
285c76f0793SBaptiste Daroussin 		break;
286c76f0793SBaptiste Daroussin 	case 'r':
287c76f0793SBaptiste Daroussin 		wattron(win, A_REVERSE);
288c76f0793SBaptiste Daroussin 		break;
289c76f0793SBaptiste Daroussin 	case 'R':
290c76f0793SBaptiste Daroussin 		wattroff(win, A_REVERSE);
291c76f0793SBaptiste Daroussin 		break;
292c76f0793SBaptiste Daroussin 	case 'u':
293c76f0793SBaptiste Daroussin 		wattron(win, A_UNDERLINE);
294c76f0793SBaptiste Daroussin 		break;
295c76f0793SBaptiste Daroussin 	case 'U':
296c76f0793SBaptiste Daroussin 		wattroff(win, A_UNDERLINE);
297c76f0793SBaptiste Daroussin 		break;
298c76f0793SBaptiste Daroussin 	}
299c76f0793SBaptiste Daroussin 
300*263660c0SAlfonso Siciliano 	return (true);
301c76f0793SBaptiste Daroussin }
302c76f0793SBaptiste Daroussin 
303c76f0793SBaptiste Daroussin static void
304*263660c0SAlfonso Siciliano print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str,
305*263660c0SAlfonso Siciliano     bool color)
306c76f0793SBaptiste Daroussin {
307c76f0793SBaptiste Daroussin 	int i, j, len, reallen;
308c76f0793SBaptiste Daroussin 
309c76f0793SBaptiste Daroussin 	len = reallen = strlen(str);
310c76f0793SBaptiste Daroussin 	if (color) {
311c76f0793SBaptiste Daroussin 		i=0;
312c76f0793SBaptiste Daroussin 		while (i < len) {
313*263660c0SAlfonso Siciliano 			if (is_text_attr(str+i))
314c76f0793SBaptiste Daroussin 				reallen -= 3;
315c76f0793SBaptiste Daroussin 			i++;
316c76f0793SBaptiste Daroussin 		}
317c76f0793SBaptiste Daroussin 	}
318c76f0793SBaptiste Daroussin 
319c76f0793SBaptiste Daroussin 	i = 0;
320c76f0793SBaptiste Daroussin 	while (i < len) {
321c76f0793SBaptiste Daroussin 		if (*x + reallen > cols) {
322c76f0793SBaptiste Daroussin 			*y = (*x != 0 ? *y+1 : *y);
323c76f0793SBaptiste Daroussin 			if (*y >= *rows) {
324c76f0793SBaptiste Daroussin 				*rows = *y + 1;
325c76f0793SBaptiste Daroussin 				wresize(win, *rows, cols);
326c76f0793SBaptiste Daroussin 			}
327c76f0793SBaptiste Daroussin 			*x = 0;
328c76f0793SBaptiste Daroussin 		}
329c76f0793SBaptiste Daroussin 		j = *x;
330c76f0793SBaptiste Daroussin 		while (j < cols && i < len) {
331*263660c0SAlfonso Siciliano 			if (color && check_set_text_attr(win, str+i)) {
332c76f0793SBaptiste Daroussin 				i += 3;
333c76f0793SBaptiste Daroussin 			} else {
334c76f0793SBaptiste Daroussin 				mvwaddch(win, *y, j, str[i]);
335c76f0793SBaptiste Daroussin 				i++;
336c76f0793SBaptiste Daroussin 				reallen--;
337c76f0793SBaptiste Daroussin 				j++;
338c76f0793SBaptiste Daroussin 				*x = j;
339c76f0793SBaptiste Daroussin 			}
340c76f0793SBaptiste Daroussin 		}
341c76f0793SBaptiste Daroussin 	}
342c76f0793SBaptiste Daroussin }
343c76f0793SBaptiste Daroussin 
344*263660c0SAlfonso Siciliano static int
345*263660c0SAlfonso Siciliano print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text)
346c76f0793SBaptiste Daroussin {
347c76f0793SBaptiste Daroussin 	bool loop;
348*263660c0SAlfonso Siciliano 	int i, j, z, rows, cols, x, y, tablen;
349*263660c0SAlfonso Siciliano 	char *string;
350c76f0793SBaptiste Daroussin 
3518c4f4028SBaptiste Daroussin 	if ((string = malloc(strlen(text) + 1)) == NULL)
352c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot build (analyze) text");
353c76f0793SBaptiste Daroussin 
354*263660c0SAlfonso Siciliano 	getmaxyx(pad, rows, cols);
355*263660c0SAlfonso Siciliano 	tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen;
356*263660c0SAlfonso Siciliano 
357c76f0793SBaptiste Daroussin 	i = j = x = y = 0;
358c76f0793SBaptiste Daroussin 	loop = true;
359c76f0793SBaptiste Daroussin 	while (loop) {
3608c4f4028SBaptiste Daroussin 		string[j] = text[i];
361c76f0793SBaptiste Daroussin 
362*263660c0SAlfonso Siciliano 		if (strchr("\n\t  ", string[j]) != NULL || string[j] == '\0') {
363c76f0793SBaptiste Daroussin 			string[j] = '\0';
364*263660c0SAlfonso Siciliano 			print_string(pad, &rows, cols, &y, &x, string,
365*263660c0SAlfonso Siciliano 			    conf->text.highlight);
366c76f0793SBaptiste Daroussin 		}
367c76f0793SBaptiste Daroussin 
3688c4f4028SBaptiste Daroussin 		switch (text[i]) {
369c76f0793SBaptiste Daroussin 		case '\0':
370c76f0793SBaptiste Daroussin 			loop = false;
371c76f0793SBaptiste Daroussin 			break;
372c76f0793SBaptiste Daroussin 		case '\n':
373c76f0793SBaptiste Daroussin 			x = 0;
374c76f0793SBaptiste Daroussin 			y++;
375*263660c0SAlfonso Siciliano 			j = -1;
376c76f0793SBaptiste Daroussin 			break;
377c76f0793SBaptiste Daroussin 		case '\t':
378*263660c0SAlfonso Siciliano 			for (z = 0; z < tablen; z++) {
379c76f0793SBaptiste Daroussin 				if (x >= cols) {
380c76f0793SBaptiste Daroussin 					x = 0;
381c76f0793SBaptiste Daroussin 					y++;
382c76f0793SBaptiste Daroussin 				}
383*263660c0SAlfonso Siciliano 				x++;
384c76f0793SBaptiste Daroussin 			}
385c76f0793SBaptiste Daroussin 			j = -1;
386c76f0793SBaptiste Daroussin 			break;
387c76f0793SBaptiste Daroussin 		case ' ':
388c76f0793SBaptiste Daroussin 			x++;
389c76f0793SBaptiste Daroussin 			if (x >= cols) {
390c76f0793SBaptiste Daroussin 				x = 0;
391c76f0793SBaptiste Daroussin 				y++;
392c76f0793SBaptiste Daroussin 			}
393c76f0793SBaptiste Daroussin 			j = -1;
394c76f0793SBaptiste Daroussin 		}
395c76f0793SBaptiste Daroussin 
396*263660c0SAlfonso Siciliano 		if (y >= rows) {
397*263660c0SAlfonso Siciliano 			rows = y + 1;
398*263660c0SAlfonso Siciliano 			wresize(pad, rows, cols);
399c76f0793SBaptiste Daroussin 		}
400c76f0793SBaptiste Daroussin 
401c76f0793SBaptiste Daroussin 		j++;
402c76f0793SBaptiste Daroussin 		i++;
403c76f0793SBaptiste Daroussin 	}
404c76f0793SBaptiste Daroussin 
405c76f0793SBaptiste Daroussin 	free(string);
406c76f0793SBaptiste Daroussin 
407*263660c0SAlfonso Siciliano 	return (0);
408c76f0793SBaptiste Daroussin }
409c76f0793SBaptiste Daroussin 
410*263660c0SAlfonso Siciliano /* Autosize */
411*263660c0SAlfonso Siciliano static int
412*263660c0SAlfonso Siciliano text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows,
413*263660c0SAlfonso Siciliano     int mincols, bool increasecols, int *h, int *w)
414*263660c0SAlfonso Siciliano {
415*263660c0SAlfonso Siciliano 	int i, j, z, x, y;
416*263660c0SAlfonso Siciliano 	int tablen, wordlen, maxwordlen, nword, maxwords, line, maxwidth;
417*263660c0SAlfonso Siciliano 	int *words;
418*263660c0SAlfonso Siciliano #define NL -1
419*263660c0SAlfonso Siciliano #define WS -2
420c76f0793SBaptiste Daroussin 
421*263660c0SAlfonso Siciliano 	maxwords = 1024;
422*263660c0SAlfonso Siciliano 	if ((words = calloc(maxwords, sizeof(int))) == NULL)
423*263660c0SAlfonso Siciliano 		RETURN_ERROR("Cannot alloc memory for text autosize");
424*263660c0SAlfonso Siciliano 
425*263660c0SAlfonso Siciliano 	tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen;
426*263660c0SAlfonso Siciliano 	maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS;
427*263660c0SAlfonso Siciliano 
428*263660c0SAlfonso Siciliano 	nword = 0;
429*263660c0SAlfonso Siciliano 	wordlen = 0;
430*263660c0SAlfonso Siciliano 	maxwordlen = 0;
431*263660c0SAlfonso Siciliano 	i=0;
432*263660c0SAlfonso Siciliano 	while (true) {
433*263660c0SAlfonso Siciliano 		if (conf->text.highlight && is_text_attr(text + i)) {
434*263660c0SAlfonso Siciliano 			i += 3;
435*263660c0SAlfonso Siciliano 			continue;
436*263660c0SAlfonso Siciliano 		}
437*263660c0SAlfonso Siciliano 
438*263660c0SAlfonso Siciliano 		if (nword + tablen >= maxwords) {
439*263660c0SAlfonso Siciliano 			maxwords += 1024;
440*263660c0SAlfonso Siciliano 			if (realloc(words, maxwords * sizeof(int)) == NULL)
441*263660c0SAlfonso Siciliano 				RETURN_ERROR("Cannot realloc memory for text "
442*263660c0SAlfonso Siciliano 				    "autosize");
443*263660c0SAlfonso Siciliano 		}
444*263660c0SAlfonso Siciliano 
445*263660c0SAlfonso Siciliano 		if (text[i] == '\0') {
446*263660c0SAlfonso Siciliano 			words[nword] = wordlen;
447*263660c0SAlfonso Siciliano 			maxwordlen = MAX(wordlen, maxwordlen);
448*263660c0SAlfonso Siciliano 			break;
449*263660c0SAlfonso Siciliano 		}
450*263660c0SAlfonso Siciliano 
451*263660c0SAlfonso Siciliano 		if (strchr("\t\n  ", text[i]) != NULL) {
452*263660c0SAlfonso Siciliano 			maxwordlen = MAX(wordlen, maxwordlen);
453*263660c0SAlfonso Siciliano 
454*263660c0SAlfonso Siciliano 			if (wordlen != 0) {
455*263660c0SAlfonso Siciliano 				words[nword] = wordlen;
456*263660c0SAlfonso Siciliano 				nword++;
457*263660c0SAlfonso Siciliano 				wordlen = 0;
458*263660c0SAlfonso Siciliano 			}
459*263660c0SAlfonso Siciliano 
460*263660c0SAlfonso Siciliano 			if (text[i] == '\t') {
461*263660c0SAlfonso Siciliano 				for (j = 0; j < tablen; j++)
462*263660c0SAlfonso Siciliano 					words[nword + j] = 1;
463*263660c0SAlfonso Siciliano 				nword += tablen;
464*263660c0SAlfonso Siciliano 			} else {
465*263660c0SAlfonso Siciliano 				words[nword] = text[i] == '\n' ? NL : WS;
466*263660c0SAlfonso Siciliano 				nword++;
467*263660c0SAlfonso Siciliano 			}
468*263660c0SAlfonso Siciliano 		}
469*263660c0SAlfonso Siciliano 		else
470*263660c0SAlfonso Siciliano 			wordlen++;
471*263660c0SAlfonso Siciliano 
472*263660c0SAlfonso Siciliano 		i++;
473*263660c0SAlfonso Siciliano 	}
474*263660c0SAlfonso Siciliano 
475*263660c0SAlfonso Siciliano 	if (increasecols) {
476*263660c0SAlfonso Siciliano 		mincols = MAX(mincols, maxwordlen);
477*263660c0SAlfonso Siciliano 		mincols = MAX(mincols,
478*263660c0SAlfonso Siciliano 		    (int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS);
479*263660c0SAlfonso Siciliano 		mincols = MIN(mincols, maxwidth);
480*263660c0SAlfonso Siciliano 	}
481*263660c0SAlfonso Siciliano 
482*263660c0SAlfonso Siciliano 	while (true) {
483*263660c0SAlfonso Siciliano 		x = 0;
484*263660c0SAlfonso Siciliano 		y = 1;
485*263660c0SAlfonso Siciliano 		line=0;
486*263660c0SAlfonso Siciliano 		for (i = 0; i <= nword; i++) {
487*263660c0SAlfonso Siciliano 			if (words[i] == NL) {
488*263660c0SAlfonso Siciliano 				y++;
489*263660c0SAlfonso Siciliano 				x = 0;
490*263660c0SAlfonso Siciliano 			}
491*263660c0SAlfonso Siciliano 			else if (words[i] == WS) {
492*263660c0SAlfonso Siciliano 				x++;
493*263660c0SAlfonso Siciliano 				if (x >= mincols) {
494*263660c0SAlfonso Siciliano 					x = 0;
495*263660c0SAlfonso Siciliano 					y++;
496*263660c0SAlfonso Siciliano 				}
497*263660c0SAlfonso Siciliano 			}
498*263660c0SAlfonso Siciliano 			else {
499*263660c0SAlfonso Siciliano 				if (words[i] + x <= mincols)
500*263660c0SAlfonso Siciliano 					x += words[i];
501*263660c0SAlfonso Siciliano 				else {
502*263660c0SAlfonso Siciliano 					for (z = words[i]; z > 0; ) {
503*263660c0SAlfonso Siciliano 						y++;
504*263660c0SAlfonso Siciliano 						x = MIN(mincols, z);
505*263660c0SAlfonso Siciliano 						z -= x;
506*263660c0SAlfonso Siciliano 					}
507*263660c0SAlfonso Siciliano 				}
508*263660c0SAlfonso Siciliano 			}
509*263660c0SAlfonso Siciliano 			line = MAX(line, x);
510*263660c0SAlfonso Siciliano 		}
511*263660c0SAlfonso Siciliano 
512*263660c0SAlfonso Siciliano 		if (increasecols == false)
513*263660c0SAlfonso Siciliano 			break;
514*263660c0SAlfonso Siciliano 		if (y <= maxrows || mincols >= maxwidth)
515*263660c0SAlfonso Siciliano 			break;
516*263660c0SAlfonso Siciliano 		mincols++;
517*263660c0SAlfonso Siciliano 	}
518*263660c0SAlfonso Siciliano 
519*263660c0SAlfonso Siciliano 	*h = (nword == 0 && words[0] == 0) ? 0 : y;
520*263660c0SAlfonso Siciliano 	*w = MIN(mincols, line); /* wtext can be less than mincols */
521*263660c0SAlfonso Siciliano 
522*263660c0SAlfonso Siciliano 	free(words);
523*263660c0SAlfonso Siciliano 
524*263660c0SAlfonso Siciliano 	return (0);
525*263660c0SAlfonso Siciliano }
526*263660c0SAlfonso Siciliano 
527*263660c0SAlfonso Siciliano int
528*263660c0SAlfonso Siciliano text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text,
529*263660c0SAlfonso Siciliano     struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext)
530*263660c0SAlfonso Siciliano {
531*263660c0SAlfonso Siciliano 	int wbuttons, maxhtext;
532*263660c0SAlfonso Siciliano 	bool changewtext;
533*263660c0SAlfonso Siciliano 
534*263660c0SAlfonso Siciliano 	wbuttons = 0;
535*263660c0SAlfonso Siciliano 	if (bs != NULL) {
536*263660c0SAlfonso Siciliano 		wbuttons = bs->nbuttons * bs->sizebutton;
537*263660c0SAlfonso Siciliano 		if (bs->nbuttons > 0)
538*263660c0SAlfonso Siciliano 			wbuttons += (bs->nbuttons-1) * t.button.space;
539*263660c0SAlfonso Siciliano 	}
540*263660c0SAlfonso Siciliano 
541*263660c0SAlfonso Siciliano 	if (cols == BSDDIALOG_AUTOSIZE) {
542*263660c0SAlfonso Siciliano 		startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS);
543*263660c0SAlfonso Siciliano 		changewtext = true;
544*263660c0SAlfonso Siciliano 	} else if (cols == BSDDIALOG_FULLSCREEN) {
545*263660c0SAlfonso Siciliano 		startwtext = widget_max_width(conf) - VBORDERS - TEXTHMARGINS;
546*263660c0SAlfonso Siciliano 		changewtext = false;
547*263660c0SAlfonso Siciliano 	} else { /* fixed */
548*263660c0SAlfonso Siciliano 		startwtext = cols - VBORDERS - TEXTHMARGINS;
549*263660c0SAlfonso Siciliano 		changewtext = false;
550*263660c0SAlfonso Siciliano 	}
551*263660c0SAlfonso Siciliano 
552*263660c0SAlfonso Siciliano 	if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) {
553*263660c0SAlfonso Siciliano 		maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext;
554*263660c0SAlfonso Siciliano 		if (bs != NULL)
555*263660c0SAlfonso Siciliano 			maxhtext -= 2;
556*263660c0SAlfonso Siciliano 	} else { /* fixed */
557*263660c0SAlfonso Siciliano 		maxhtext = rows - VBORDERS - rowsnotext;
558*263660c0SAlfonso Siciliano 		if (bs != NULL)
559*263660c0SAlfonso Siciliano 			maxhtext -= 2;
560*263660c0SAlfonso Siciliano 	}
561*263660c0SAlfonso Siciliano 
562*263660c0SAlfonso Siciliano 	if (startwtext <= 0 && changewtext)
563*263660c0SAlfonso Siciliano 		startwtext = 1;
564*263660c0SAlfonso Siciliano 	if (maxhtext <= 0 || startwtext <= 0) {
565*263660c0SAlfonso Siciliano 		*htext = *wtext = 0;
566*263660c0SAlfonso Siciliano 		return (0);
567*263660c0SAlfonso Siciliano 	}
568*263660c0SAlfonso Siciliano 
569*263660c0SAlfonso Siciliano 	if (text_autosize(conf, text, maxhtext, startwtext, changewtext,
570*263660c0SAlfonso Siciliano 	    htext, wtext) != 0)
571*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
572*263660c0SAlfonso Siciliano 
573*263660c0SAlfonso Siciliano 	return (0);
574*263660c0SAlfonso Siciliano }
575*263660c0SAlfonso Siciliano 
576f499134dSBaptiste Daroussin int widget_max_height(struct bsddialog_conf *conf)
577c76f0793SBaptiste Daroussin {
578c76f0793SBaptiste Daroussin 	int maxheight;
579c76f0793SBaptiste Daroussin 
580*263660c0SAlfonso Siciliano 	maxheight = conf->shadow ? SCREENLINES - t.shadow.h : SCREENLINES;
581*263660c0SAlfonso Siciliano 	if (maxheight <= 0)
582*263660c0SAlfonso Siciliano 		RETURN_ERROR("Terminal too small, screen lines - shadow <= 0");
583c76f0793SBaptiste Daroussin 
584*263660c0SAlfonso Siciliano 	if (conf->y > 0) {
585*263660c0SAlfonso Siciliano 		maxheight -= conf->y;
586*263660c0SAlfonso Siciliano 		if (maxheight <= 0)
587*263660c0SAlfonso Siciliano 			RETURN_ERROR("Terminal too small, screen lines - "
588*263660c0SAlfonso Siciliano 			    "shadow - y <= 0");
589c76f0793SBaptiste Daroussin 	}
590c76f0793SBaptiste Daroussin 
591*263660c0SAlfonso Siciliano 	return (maxheight);
592*263660c0SAlfonso Siciliano }
593*263660c0SAlfonso Siciliano 
594f499134dSBaptiste Daroussin int widget_max_width(struct bsddialog_conf *conf)
595c76f0793SBaptiste Daroussin {
596c76f0793SBaptiste Daroussin 	int maxwidth;
597c76f0793SBaptiste Daroussin 
598*263660c0SAlfonso Siciliano 	maxwidth = conf->shadow ? SCREENCOLS - t.shadow.w : SCREENCOLS;
599*263660c0SAlfonso Siciliano 	if (maxwidth <= 0)
600*263660c0SAlfonso Siciliano 		RETURN_ERROR("Terminal too small, screen cols - shadow <= 0");
601c76f0793SBaptiste Daroussin 
602*263660c0SAlfonso Siciliano 	if (conf->x > 0) {
603*263660c0SAlfonso Siciliano 		maxwidth -= conf->x;
604*263660c0SAlfonso Siciliano 		if (maxwidth <= 0)
605*263660c0SAlfonso Siciliano 			RETURN_ERROR("Terminal too small, screen cols - shadow "
606*263660c0SAlfonso Siciliano 			    "- x <= 0");
607*263660c0SAlfonso Siciliano 	}
608*263660c0SAlfonso Siciliano 
609*263660c0SAlfonso Siciliano 	return (maxwidth);
610*263660c0SAlfonso Siciliano }
611*263660c0SAlfonso Siciliano 
612*263660c0SAlfonso Siciliano int
613*263660c0SAlfonso Siciliano widget_min_height(struct bsddialog_conf *conf, int htext, int minwidget,
614*263660c0SAlfonso Siciliano     bool withbuttons)
615*263660c0SAlfonso Siciliano {
616*263660c0SAlfonso Siciliano 	int min;
617*263660c0SAlfonso Siciliano 
618*263660c0SAlfonso Siciliano 	min = 0;
619*263660c0SAlfonso Siciliano 
620*263660c0SAlfonso Siciliano 	/* buttons */
621*263660c0SAlfonso Siciliano 	if (withbuttons)
622*263660c0SAlfonso Siciliano 		min += 2; /* buttons and border */
623*263660c0SAlfonso Siciliano 
624*263660c0SAlfonso Siciliano 	/* text */
625*263660c0SAlfonso Siciliano 	min += htext;
626*263660c0SAlfonso Siciliano 
627*263660c0SAlfonso Siciliano 	/* specific widget min height */
628*263660c0SAlfonso Siciliano 	min += minwidget;
629*263660c0SAlfonso Siciliano 
630*263660c0SAlfonso Siciliano 	/* dialog borders */
631*263660c0SAlfonso Siciliano 	min += HBORDERS;
632*263660c0SAlfonso Siciliano 	/* conf.auto_minheight */
633*263660c0SAlfonso Siciliano 	min = MAX(min, (int)conf->auto_minheight);
634*263660c0SAlfonso Siciliano 	/* avoid terminal overflow */
635*263660c0SAlfonso Siciliano 	min = MIN(min, widget_max_height(conf));
636*263660c0SAlfonso Siciliano 
637*263660c0SAlfonso Siciliano 	return (min);
638*263660c0SAlfonso Siciliano }
639*263660c0SAlfonso Siciliano 
640*263660c0SAlfonso Siciliano int
641*263660c0SAlfonso Siciliano widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget,
642*263660c0SAlfonso Siciliano     struct buttons *bs)
643*263660c0SAlfonso Siciliano 
644*263660c0SAlfonso Siciliano {
645*263660c0SAlfonso Siciliano 	int min, delimtitle;
646*263660c0SAlfonso Siciliano 
647*263660c0SAlfonso Siciliano 	min = 0;
648*263660c0SAlfonso Siciliano 
649*263660c0SAlfonso Siciliano 	/* buttons */
650*263660c0SAlfonso Siciliano 	if (bs != NULL) {
651*263660c0SAlfonso Siciliano 		min += bs->nbuttons * bs->sizebutton;
652*263660c0SAlfonso Siciliano 		min += bs->nbuttons > 0 ? (bs->nbuttons-1) * t.button.space : 0;
653*263660c0SAlfonso Siciliano 	}
654*263660c0SAlfonso Siciliano 
655*263660c0SAlfonso Siciliano 	/* text */
656*263660c0SAlfonso Siciliano 	if (wtext > 0)
657*263660c0SAlfonso Siciliano 		min = MAX(min, wtext + TEXTHMARGINS);
658*263660c0SAlfonso Siciliano 
659*263660c0SAlfonso Siciliano 	/* specific widget min width */
660*263660c0SAlfonso Siciliano 	min = MAX(min, minwidget);
661*263660c0SAlfonso Siciliano 
662*263660c0SAlfonso Siciliano 	/* title */
663*263660c0SAlfonso Siciliano 	if (conf->title != NULL) {
664*263660c0SAlfonso Siciliano 		delimtitle = t.dialog.delimtitle ? 2 : 0;
665*263660c0SAlfonso Siciliano 		min = MAX(min, (int)strlen(conf->title) + 2 + delimtitle);
666*263660c0SAlfonso Siciliano 	}
667*263660c0SAlfonso Siciliano 
668*263660c0SAlfonso Siciliano 	/* bottom title */
669*263660c0SAlfonso Siciliano 	if (conf->bottomtitle != NULL)
670*263660c0SAlfonso Siciliano 		min = MAX(min, (int)strlen(conf->bottomtitle) + 4);
671*263660c0SAlfonso Siciliano 
672*263660c0SAlfonso Siciliano 	/* dialog borders */
673*263660c0SAlfonso Siciliano 	min += VBORDERS;
674*263660c0SAlfonso Siciliano 	/* conf.auto_minwidth */
675*263660c0SAlfonso Siciliano 	min = MAX(min, (int)conf->auto_minwidth);
676*263660c0SAlfonso Siciliano 	/* avoid terminal overflow */
677*263660c0SAlfonso Siciliano 	min = MIN(min, widget_max_width(conf));
678*263660c0SAlfonso Siciliano 
679*263660c0SAlfonso Siciliano 	return (min);
680c76f0793SBaptiste Daroussin }
681c76f0793SBaptiste Daroussin 
682c76f0793SBaptiste Daroussin int
683f499134dSBaptiste Daroussin set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
684c76f0793SBaptiste Daroussin {
685c76f0793SBaptiste Daroussin 	int maxheight, maxwidth;
686c76f0793SBaptiste Daroussin 
687c76f0793SBaptiste Daroussin 	if ((maxheight = widget_max_height(conf)) == BSDDIALOG_ERROR)
688*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
689c76f0793SBaptiste Daroussin 
690c76f0793SBaptiste Daroussin 	if (rows == BSDDIALOG_FULLSCREEN)
691c76f0793SBaptiste Daroussin 		*h = maxheight;
692c76f0793SBaptiste Daroussin 	else if (rows < BSDDIALOG_FULLSCREEN)
693c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative (less than -1) height");
694c76f0793SBaptiste Daroussin 	else if (rows > BSDDIALOG_AUTOSIZE) {
695c76f0793SBaptiste Daroussin 		if ((*h = rows) > maxheight)
696*263660c0SAlfonso Siciliano 			RETURN_ERROR("Height too big (> terminal height - "
697*263660c0SAlfonso Siciliano 			    "shadow)");
698c76f0793SBaptiste Daroussin 	}
699c76f0793SBaptiste Daroussin 	/* rows == AUTOSIZE: each widget has to set its size */
700c76f0793SBaptiste Daroussin 
701c76f0793SBaptiste Daroussin 	if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR)
702*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
703c76f0793SBaptiste Daroussin 
704c76f0793SBaptiste Daroussin 	if (cols == BSDDIALOG_FULLSCREEN)
705c76f0793SBaptiste Daroussin 		*w = maxwidth;
706c76f0793SBaptiste Daroussin 	else if (cols < BSDDIALOG_FULLSCREEN)
707c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative (less than -1) width");
708c76f0793SBaptiste Daroussin 	else if (cols > BSDDIALOG_AUTOSIZE) {
709c76f0793SBaptiste Daroussin 		if ((*w = cols) > maxwidth)
710*263660c0SAlfonso Siciliano 			RETURN_ERROR("Width too big (> terminal width - "
711*263660c0SAlfonso Siciliano 			    "shadow)");
712c76f0793SBaptiste Daroussin 	}
713c76f0793SBaptiste Daroussin 	/* cols == AUTOSIZE: each widget has to set its size */
714c76f0793SBaptiste Daroussin 
715*263660c0SAlfonso Siciliano 	return (0);
716c76f0793SBaptiste Daroussin }
717c76f0793SBaptiste Daroussin 
718c76f0793SBaptiste Daroussin int
719f499134dSBaptiste Daroussin set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
720c76f0793SBaptiste Daroussin {
721f499134dSBaptiste Daroussin 	if (conf->y == BSDDIALOG_CENTER)
722*263660c0SAlfonso Siciliano 		*y = SCREENLINES/2 - (h + t.shadow.h)/2;
723f499134dSBaptiste Daroussin 	else if (conf->y < BSDDIALOG_CENTER)
724c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative begin y (less than -1)");
725*263660c0SAlfonso Siciliano 	else if (conf->y >= SCREENLINES)
726c76f0793SBaptiste Daroussin 		RETURN_ERROR("Begin Y under the terminal");
727c76f0793SBaptiste Daroussin 	else
728f499134dSBaptiste Daroussin 		*y = conf->y;
729c76f0793SBaptiste Daroussin 
730*263660c0SAlfonso Siciliano 	if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > SCREENLINES)
731*263660c0SAlfonso Siciliano 		RETURN_ERROR("The lower of the box under the terminal "
732c76f0793SBaptiste Daroussin 		    "(begin Y + height (+ shadow) > terminal lines)");
733c76f0793SBaptiste Daroussin 
734c76f0793SBaptiste Daroussin 
735f499134dSBaptiste Daroussin 	if (conf->x == BSDDIALOG_CENTER)
736*263660c0SAlfonso Siciliano 		*x = SCREENCOLS/2 - (w + t.shadow.w)/2;
737f499134dSBaptiste Daroussin 	else if (conf->x < BSDDIALOG_CENTER)
738c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative begin x (less than -1)");
739*263660c0SAlfonso Siciliano 	else if (conf->x >= SCREENCOLS)
740c76f0793SBaptiste Daroussin 		RETURN_ERROR("Begin X over the right of the terminal");
741c76f0793SBaptiste Daroussin 	else
742f499134dSBaptiste Daroussin 		*x = conf->x;
743c76f0793SBaptiste Daroussin 
744*263660c0SAlfonso Siciliano 	if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > SCREENCOLS)
745*263660c0SAlfonso Siciliano 		RETURN_ERROR("The right of the box over the terminal "
746c76f0793SBaptiste Daroussin 		    "(begin X + width (+ shadow) > terminal cols)");
747c76f0793SBaptiste Daroussin 
748*263660c0SAlfonso Siciliano 	return (0);
749c76f0793SBaptiste Daroussin }
750c76f0793SBaptiste Daroussin 
751c76f0793SBaptiste Daroussin /* Widgets builders */
752c76f0793SBaptiste Daroussin void
753f499134dSBaptiste Daroussin draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
754c76f0793SBaptiste Daroussin     enum elevation elev)
755c76f0793SBaptiste Daroussin {
756c76f0793SBaptiste Daroussin 	int leftcolor, rightcolor;
757*263660c0SAlfonso Siciliano 	int ls, rs, ts, bs, tl, tr, bl, br, ltee, rtee;
758c76f0793SBaptiste Daroussin 
759*263660c0SAlfonso Siciliano 	if (conf->no_lines)
760*263660c0SAlfonso Siciliano 		return;
761*263660c0SAlfonso Siciliano 
762*263660c0SAlfonso Siciliano 	if (conf->ascii_lines) {
763*263660c0SAlfonso Siciliano 		ls = rs = '|';
764*263660c0SAlfonso Siciliano 		ts = bs = '-';
765*263660c0SAlfonso Siciliano 		tl = tr = bl = br = ltee = rtee = '+';
766*263660c0SAlfonso Siciliano 	} else {
767c76f0793SBaptiste Daroussin 		ls = rs = ACS_VLINE;
768c76f0793SBaptiste Daroussin 		ts = bs = ACS_HLINE;
769c76f0793SBaptiste Daroussin 		tl = ACS_ULCORNER;
770c76f0793SBaptiste Daroussin 		tr = ACS_URCORNER;
771c76f0793SBaptiste Daroussin 		bl = ACS_LLCORNER;
772c76f0793SBaptiste Daroussin 		br = ACS_LRCORNER;
773c76f0793SBaptiste Daroussin 		ltee = ACS_LTEE;
774c76f0793SBaptiste Daroussin 		rtee = ACS_RTEE;
775c76f0793SBaptiste Daroussin 	}
776*263660c0SAlfonso Siciliano 
7778c4f4028SBaptiste Daroussin 	leftcolor = elev == RAISED ?
7788c4f4028SBaptiste Daroussin 	    t.dialog.lineraisecolor : t.dialog.linelowercolor;
7798c4f4028SBaptiste Daroussin 	rightcolor = elev == RAISED ?
7808c4f4028SBaptiste Daroussin 	    t.dialog.linelowercolor : t.dialog.lineraisecolor;
781c76f0793SBaptiste Daroussin 	wattron(win, leftcolor);
782c76f0793SBaptiste Daroussin 	wborder(win, ls, rs, ts, bs, tl, tr, bl, br);
783c76f0793SBaptiste Daroussin 	wattroff(win, leftcolor);
784c76f0793SBaptiste Daroussin 
785c76f0793SBaptiste Daroussin 	wattron(win, rightcolor);
786c76f0793SBaptiste Daroussin 	mvwaddch(win, 0, cols-1, tr);
787c76f0793SBaptiste Daroussin 	mvwvline(win, 1, cols-1, rs, rows-2);
788c76f0793SBaptiste Daroussin 	mvwaddch(win, rows-1, cols-1, br);
789c76f0793SBaptiste Daroussin 	mvwhline(win, rows-1, 1, bs, cols-2);
790c76f0793SBaptiste Daroussin 	wattroff(win, rightcolor);
791c76f0793SBaptiste Daroussin }
792c76f0793SBaptiste Daroussin 
793c76f0793SBaptiste Daroussin WINDOW *
794f499134dSBaptiste Daroussin new_boxed_window(struct bsddialog_conf *conf, int y, int x, int rows, int cols,
795c76f0793SBaptiste Daroussin     enum elevation elev)
796c76f0793SBaptiste Daroussin {
797c76f0793SBaptiste Daroussin 	WINDOW *win;
798c76f0793SBaptiste Daroussin 
799c76f0793SBaptiste Daroussin 	if ((win = newwin(rows, cols, y, x)) == NULL) {
800c76f0793SBaptiste Daroussin 		set_error_string("Cannot build boxed window");
801*263660c0SAlfonso Siciliano 		return (NULL);
802c76f0793SBaptiste Daroussin 	}
803c76f0793SBaptiste Daroussin 
8048c4f4028SBaptiste Daroussin 	wbkgd(win, t.dialog.color);
805c76f0793SBaptiste Daroussin 
806c76f0793SBaptiste Daroussin 	draw_borders(conf, win, rows, cols, elev);
807c76f0793SBaptiste Daroussin 
808*263660c0SAlfonso Siciliano 	return (win);
809c76f0793SBaptiste Daroussin }
810c76f0793SBaptiste Daroussin 
811c76f0793SBaptiste Daroussin static int
812*263660c0SAlfonso Siciliano draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
813*263660c0SAlfonso Siciliano     WINDOW *textpad, const char *text, struct buttons *bs, bool shortcutbuttons)
814c76f0793SBaptiste Daroussin {
815*263660c0SAlfonso Siciliano 	int h, w, ts, ltee, rtee;
816c76f0793SBaptiste Daroussin 
817f499134dSBaptiste Daroussin 	ts = conf->ascii_lines ? '-' : ACS_HLINE;
818f499134dSBaptiste Daroussin 	ltee = conf->ascii_lines ? '+' : ACS_LTEE;
819f499134dSBaptiste Daroussin 	rtee = conf->ascii_lines ? '+' : ACS_RTEE;
820*263660c0SAlfonso Siciliano 
821*263660c0SAlfonso Siciliano 	getmaxyx(widget, h, w);
822c76f0793SBaptiste Daroussin 
823c76f0793SBaptiste Daroussin 	if (shadow != NULL)
824c76f0793SBaptiste Daroussin 		wnoutrefresh(shadow);
825c76f0793SBaptiste Daroussin 
826*263660c0SAlfonso Siciliano 	draw_borders(conf, widget, h, w, RAISED);
827c76f0793SBaptiste Daroussin 
828f499134dSBaptiste Daroussin 	if (conf->title != NULL) {
8298c4f4028SBaptiste Daroussin 		if (t.dialog.delimtitle && conf->no_lines == false) {
830*263660c0SAlfonso Siciliano 			wattron(widget, t.dialog.lineraisecolor);
831f499134dSBaptiste Daroussin 			mvwaddch(widget, 0, w/2-strlen(conf->title)/2-1, rtee);
832*263660c0SAlfonso Siciliano 			wattroff(widget, t.dialog.lineraisecolor);
833c76f0793SBaptiste Daroussin 		}
8348c4f4028SBaptiste Daroussin 		wattron(widget, t.dialog.titlecolor);
835f499134dSBaptiste Daroussin 		mvwaddstr(widget, 0, w/2 - strlen(conf->title)/2, conf->title);
8368c4f4028SBaptiste Daroussin 		wattroff(widget, t.dialog.titlecolor);
8378c4f4028SBaptiste Daroussin 		if (t.dialog.delimtitle && conf->no_lines == false) {
838*263660c0SAlfonso Siciliano 			wattron(widget, t.dialog.lineraisecolor);
839c76f0793SBaptiste Daroussin 			waddch(widget, ltee);
840*263660c0SAlfonso Siciliano 			wattroff(widget, t.dialog.lineraisecolor);
841c76f0793SBaptiste Daroussin 		}
842c76f0793SBaptiste Daroussin 	}
843c76f0793SBaptiste Daroussin 
844*263660c0SAlfonso Siciliano 	if (bs != NULL) {
845*263660c0SAlfonso Siciliano 		if (conf->no_lines == false) {
8468c4f4028SBaptiste Daroussin 			wattron(widget, t.dialog.lineraisecolor);
847c76f0793SBaptiste Daroussin 			mvwaddch(widget, h-3, 0, ltee);
848c76f0793SBaptiste Daroussin 			mvwhline(widget, h-3, 1, ts, w-2);
8498c4f4028SBaptiste Daroussin 			wattroff(widget, t.dialog.lineraisecolor);
850c76f0793SBaptiste Daroussin 
8518c4f4028SBaptiste Daroussin 			wattron(widget, t.dialog.linelowercolor);
852c76f0793SBaptiste Daroussin 			mvwaddch(widget, h-3, w-1, rtee);
8538c4f4028SBaptiste Daroussin 			wattroff(widget, t.dialog.linelowercolor);
854c76f0793SBaptiste Daroussin 		}
855*263660c0SAlfonso Siciliano 		draw_buttons(widget, *bs, shortcutbuttons);
856*263660c0SAlfonso Siciliano 	}
857*263660c0SAlfonso Siciliano 
858*263660c0SAlfonso Siciliano 	if (conf->bottomtitle != NULL) {
859*263660c0SAlfonso Siciliano 		wattron(widget, t.dialog.bottomtitlecolor);
860*263660c0SAlfonso Siciliano 		wmove(widget, h - 1, w/2 - strlen(conf->bottomtitle)/2 - 1);
861*263660c0SAlfonso Siciliano 		waddch(widget, ' ');
862*263660c0SAlfonso Siciliano 		waddstr(widget, conf->bottomtitle);
863*263660c0SAlfonso Siciliano 		waddch(widget, ' ');
864*263660c0SAlfonso Siciliano 		wattroff(widget, t.dialog.bottomtitlecolor);
865*263660c0SAlfonso Siciliano 	}
866c76f0793SBaptiste Daroussin 
867c76f0793SBaptiste Daroussin 	wnoutrefresh(widget);
868c76f0793SBaptiste Daroussin 
869*263660c0SAlfonso Siciliano 	if (textpad != NULL && text != NULL) /* textbox */
870*263660c0SAlfonso Siciliano 		if (print_textpad(conf, textpad, text) !=0)
871*263660c0SAlfonso Siciliano 			return (BSDDIALOG_ERROR);
872c76f0793SBaptiste Daroussin 
873*263660c0SAlfonso Siciliano 	return (0);
874c76f0793SBaptiste Daroussin }
875c76f0793SBaptiste Daroussin 
876c76f0793SBaptiste Daroussin int
877*263660c0SAlfonso Siciliano update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
878*263660c0SAlfonso Siciliano     int y, int x, int h, int w, WINDOW *textpad, const char *text,
879*263660c0SAlfonso Siciliano     struct buttons *bs, bool shortcutbuttons)
880c76f0793SBaptiste Daroussin {
881c76f0793SBaptiste Daroussin 	int error;
882c76f0793SBaptiste Daroussin 
883*263660c0SAlfonso Siciliano 	if (shadow != NULL) {
884*263660c0SAlfonso Siciliano 		wclear(shadow);
885*263660c0SAlfonso Siciliano 		mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
886*263660c0SAlfonso Siciliano 		wresize(shadow, h, w);
887c76f0793SBaptiste Daroussin 	}
888c76f0793SBaptiste Daroussin 
889*263660c0SAlfonso Siciliano 	wclear(widget);
890*263660c0SAlfonso Siciliano 	mvwin(widget, y, x);
891*263660c0SAlfonso Siciliano 	wresize(widget, h, w);
892*263660c0SAlfonso Siciliano 
893*263660c0SAlfonso Siciliano 	if (textpad != NULL) {
894*263660c0SAlfonso Siciliano 		wclear(textpad);
895*263660c0SAlfonso Siciliano 		wresize(textpad, 1, w - HBORDERS - TEXTHMARGINS);
896*263660c0SAlfonso Siciliano 	}
897*263660c0SAlfonso Siciliano 
898*263660c0SAlfonso Siciliano 	error = draw_dialog(conf, shadow, widget, textpad, text, bs,
899*263660c0SAlfonso Siciliano 	    shortcutbuttons);
900*263660c0SAlfonso Siciliano 
901*263660c0SAlfonso Siciliano 	return (error);
902*263660c0SAlfonso Siciliano }
903*263660c0SAlfonso Siciliano 
904c76f0793SBaptiste Daroussin int
905*263660c0SAlfonso Siciliano new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y,
906*263660c0SAlfonso Siciliano     int x, int h, int w, WINDOW **textpad, const char *text, struct buttons *bs,
907*263660c0SAlfonso Siciliano     bool shortcutbuttons)
908c76f0793SBaptiste Daroussin {
909c76f0793SBaptiste Daroussin 	int error;
910c76f0793SBaptiste Daroussin 
911f499134dSBaptiste Daroussin 	if (conf->shadow) {
912f499134dSBaptiste Daroussin 		*shadow = newwin(h, w, y + t.shadow.h, x + t.shadow.w);
913c76f0793SBaptiste Daroussin 		if (*shadow == NULL)
914c76f0793SBaptiste Daroussin 			RETURN_ERROR("Cannot build shadow");
915f499134dSBaptiste Daroussin 		wbkgd(*shadow, t.shadow.color);
916c76f0793SBaptiste Daroussin 	}
917c76f0793SBaptiste Daroussin 
918*263660c0SAlfonso Siciliano 	if ((*widget = new_boxed_window(conf, y, x, h, w, RAISED)) == NULL) {
919f499134dSBaptiste Daroussin 		if (conf->shadow)
920c76f0793SBaptiste Daroussin 			delwin(*shadow);
921*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
922c76f0793SBaptiste Daroussin 	}
923c76f0793SBaptiste Daroussin 
924*263660c0SAlfonso Siciliano 	if (textpad != NULL && text != NULL) { /* textbox */
925*263660c0SAlfonso Siciliano 		*textpad = newpad(1, w - HBORDERS - TEXTHMARGINS);
926c76f0793SBaptiste Daroussin 		if (*textpad == NULL) {
927*263660c0SAlfonso Siciliano 			delwin(*widget);
928f499134dSBaptiste Daroussin 			if (conf->shadow)
929c76f0793SBaptiste Daroussin 				delwin(*shadow);
930c76f0793SBaptiste Daroussin 			RETURN_ERROR("Cannot build the pad window for text");
931c76f0793SBaptiste Daroussin 		}
9328c4f4028SBaptiste Daroussin 		wbkgd(*textpad, t.dialog.color);
933c76f0793SBaptiste Daroussin 	}
934c76f0793SBaptiste Daroussin 
935*263660c0SAlfonso Siciliano 	error = draw_dialog(conf, *shadow, *widget,
936*263660c0SAlfonso Siciliano 	    textpad == NULL ? NULL : *textpad, text, bs, shortcutbuttons);
937c76f0793SBaptiste Daroussin 
938*263660c0SAlfonso Siciliano 	return (error);
939c76f0793SBaptiste Daroussin }
940c76f0793SBaptiste Daroussin 
941c76f0793SBaptiste Daroussin void
942*263660c0SAlfonso Siciliano end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget,
943*263660c0SAlfonso Siciliano     WINDOW *textpad)
944c76f0793SBaptiste Daroussin {
945*263660c0SAlfonso Siciliano 	int y, x, h, w;
946c76f0793SBaptiste Daroussin 
947*263660c0SAlfonso Siciliano 	getbegyx(widget, y, x);
948*263660c0SAlfonso Siciliano 	getmaxyx(widget, h, w);
949c76f0793SBaptiste Daroussin 
950f499134dSBaptiste Daroussin 	if (conf->sleep > 0)
951f499134dSBaptiste Daroussin 		sleep(conf->sleep);
952c76f0793SBaptiste Daroussin 
953c76f0793SBaptiste Daroussin 	if (textpad != NULL)
954c76f0793SBaptiste Daroussin 		delwin(textpad);
955c76f0793SBaptiste Daroussin 
956*263660c0SAlfonso Siciliano 	delwin(widget);
957c76f0793SBaptiste Daroussin 
958f499134dSBaptiste Daroussin 	if (conf->shadow)
959c76f0793SBaptiste Daroussin 		delwin(shadow);
960c76f0793SBaptiste Daroussin 
961f499134dSBaptiste Daroussin 	if (conf->clear)
962c76f0793SBaptiste Daroussin 		hide_widget(y, x, h, w, shadow != NULL);
963c76f0793SBaptiste Daroussin 
964f499134dSBaptiste Daroussin 	if (conf->get_height != NULL)
965f499134dSBaptiste Daroussin 		*conf->get_height = h;
966f499134dSBaptiste Daroussin 	if (conf->get_width != NULL)
967f499134dSBaptiste Daroussin 		*conf->get_width = w;
968c76f0793SBaptiste Daroussin }