xref: /freebsd-src/contrib/bsddialog/lib/lib_util.c (revision c76f07938c44264c7ebd400c23f218e561960d23)
1*c76f0793SBaptiste Daroussin /*-
2*c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3*c76f0793SBaptiste Daroussin  *
4*c76f0793SBaptiste Daroussin  * Copyright (c) 2021 Alfonso Sabato Siciliano
5*c76f0793SBaptiste Daroussin  *
6*c76f0793SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7*c76f0793SBaptiste Daroussin  * modification, are permitted provided that the following conditions
8*c76f0793SBaptiste Daroussin  * are met:
9*c76f0793SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10*c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11*c76f0793SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12*c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13*c76f0793SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14*c76f0793SBaptiste Daroussin  *
15*c76f0793SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*c76f0793SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*c76f0793SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*c76f0793SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*c76f0793SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*c76f0793SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*c76f0793SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*c76f0793SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*c76f0793SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*c76f0793SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*c76f0793SBaptiste Daroussin  * SUCH DAMAGE.
26*c76f0793SBaptiste Daroussin  */
27*c76f0793SBaptiste Daroussin 
28*c76f0793SBaptiste Daroussin #include <sys/param.h>
29*c76f0793SBaptiste Daroussin 
30*c76f0793SBaptiste Daroussin #include <stdlib.h>
31*c76f0793SBaptiste Daroussin #include <string.h>
32*c76f0793SBaptiste Daroussin #include <unistd.h>
33*c76f0793SBaptiste Daroussin 
34*c76f0793SBaptiste Daroussin #ifdef PORTNCURSES
35*c76f0793SBaptiste Daroussin #include <ncurses/curses.h>
36*c76f0793SBaptiste Daroussin #else
37*c76f0793SBaptiste Daroussin #include <curses.h>
38*c76f0793SBaptiste Daroussin #endif
39*c76f0793SBaptiste Daroussin 
40*c76f0793SBaptiste Daroussin #include "bsddialog.h"
41*c76f0793SBaptiste Daroussin #include "lib_util.h"
42*c76f0793SBaptiste Daroussin #include "bsddialog_theme.h"
43*c76f0793SBaptiste Daroussin 
44*c76f0793SBaptiste Daroussin extern struct bsddialog_theme t;
45*c76f0793SBaptiste Daroussin 
46*c76f0793SBaptiste Daroussin /* Error buffer */
47*c76f0793SBaptiste Daroussin 
48*c76f0793SBaptiste Daroussin #define ERRBUFLEN 1024
49*c76f0793SBaptiste Daroussin static char errorbuffer[ERRBUFLEN];
50*c76f0793SBaptiste Daroussin 
51*c76f0793SBaptiste Daroussin const char *get_error_string(void)
52*c76f0793SBaptiste Daroussin {
53*c76f0793SBaptiste Daroussin 	return errorbuffer;
54*c76f0793SBaptiste Daroussin }
55*c76f0793SBaptiste Daroussin 
56*c76f0793SBaptiste Daroussin void set_error_string(char *str)
57*c76f0793SBaptiste Daroussin {
58*c76f0793SBaptiste Daroussin 
59*c76f0793SBaptiste Daroussin 	strncpy(errorbuffer, str, ERRBUFLEN-1);
60*c76f0793SBaptiste Daroussin }
61*c76f0793SBaptiste Daroussin 
62*c76f0793SBaptiste Daroussin /* cleaner */
63*c76f0793SBaptiste Daroussin int hide_widget(int y, int x, int h, int w, bool withshadow)
64*c76f0793SBaptiste Daroussin {
65*c76f0793SBaptiste Daroussin 	WINDOW *clear;
66*c76f0793SBaptiste Daroussin 
67*c76f0793SBaptiste Daroussin 	/* no check: y, x, h and w are checked by the builders */
68*c76f0793SBaptiste Daroussin 	if ((clear = newwin(h, w, y + t.shadowrows, x + t.shadowcols)) == NULL)
69*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot hide the widget");
70*c76f0793SBaptiste Daroussin 	wbkgd(clear, t.backgroundcolor);
71*c76f0793SBaptiste Daroussin 
72*c76f0793SBaptiste Daroussin 	if (withshadow)
73*c76f0793SBaptiste Daroussin 		wrefresh(clear);
74*c76f0793SBaptiste Daroussin 
75*c76f0793SBaptiste Daroussin 	mvwin(clear, y, x);
76*c76f0793SBaptiste Daroussin 	wrefresh(clear);
77*c76f0793SBaptiste Daroussin 
78*c76f0793SBaptiste Daroussin 	delwin(clear);
79*c76f0793SBaptiste Daroussin 
80*c76f0793SBaptiste Daroussin 	return 0;
81*c76f0793SBaptiste Daroussin }
82*c76f0793SBaptiste Daroussin 
83*c76f0793SBaptiste Daroussin /* F1 help */
84*c76f0793SBaptiste Daroussin int f1help(struct bsddialog_conf conf)
85*c76f0793SBaptiste Daroussin {
86*c76f0793SBaptiste Daroussin 	char *file = conf.hfile;
87*c76f0793SBaptiste Daroussin 	char *title = conf.title;
88*c76f0793SBaptiste Daroussin 	int output;
89*c76f0793SBaptiste Daroussin 
90*c76f0793SBaptiste Daroussin 	conf.hfile = NULL;
91*c76f0793SBaptiste Daroussin 	conf.clear = true;
92*c76f0793SBaptiste Daroussin 	conf.y = BSDDIALOG_CENTER;
93*c76f0793SBaptiste Daroussin 	conf.x = BSDDIALOG_CENTER;
94*c76f0793SBaptiste Daroussin 	conf.title = "HELP";
95*c76f0793SBaptiste Daroussin 	conf.sleep = 0;
96*c76f0793SBaptiste Daroussin 
97*c76f0793SBaptiste Daroussin 	output = bsddialog_textbox(conf, file, BSDDIALOG_AUTOSIZE,
98*c76f0793SBaptiste Daroussin 	    BSDDIALOG_AUTOSIZE);
99*c76f0793SBaptiste Daroussin 	conf.hfile = file;
100*c76f0793SBaptiste Daroussin 	conf.title = title;
101*c76f0793SBaptiste Daroussin 
102*c76f0793SBaptiste Daroussin 	return output;
103*c76f0793SBaptiste Daroussin }
104*c76f0793SBaptiste Daroussin 
105*c76f0793SBaptiste Daroussin /* Buttons */
106*c76f0793SBaptiste Daroussin void
107*c76f0793SBaptiste Daroussin draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected,
108*c76f0793SBaptiste Daroussin     bool shortkey)
109*c76f0793SBaptiste Daroussin {
110*c76f0793SBaptiste Daroussin 	int i, color_arrows, color_shortkey, color_button;
111*c76f0793SBaptiste Daroussin 
112*c76f0793SBaptiste Daroussin 	if (selected) {
113*c76f0793SBaptiste Daroussin 		color_arrows = t.currbuttdelimcolor;
114*c76f0793SBaptiste Daroussin 		color_shortkey = t.currshortkeycolor;
115*c76f0793SBaptiste Daroussin 		color_button = t.currbuttoncolor;
116*c76f0793SBaptiste Daroussin 	} else {
117*c76f0793SBaptiste Daroussin 		color_arrows = t.buttdelimcolor;
118*c76f0793SBaptiste Daroussin 		color_shortkey = t.shortkeycolor;
119*c76f0793SBaptiste Daroussin 		color_button = t.buttoncolor;
120*c76f0793SBaptiste Daroussin 	}
121*c76f0793SBaptiste Daroussin 
122*c76f0793SBaptiste Daroussin 	wattron(window, color_arrows);
123*c76f0793SBaptiste Daroussin 	mvwaddch(window, y, x, t.buttleftch);
124*c76f0793SBaptiste Daroussin 	wattroff(window, color_arrows);
125*c76f0793SBaptiste Daroussin 	wattron(window, color_button);
126*c76f0793SBaptiste Daroussin 	for(i = 1; i < size - 1; i++)
127*c76f0793SBaptiste Daroussin 		waddch(window, ' ');
128*c76f0793SBaptiste Daroussin 	wattroff(window, color_button);
129*c76f0793SBaptiste Daroussin 	wattron(window, color_arrows);
130*c76f0793SBaptiste Daroussin 	mvwaddch(window, y, x + i, t.buttrightchar);
131*c76f0793SBaptiste Daroussin 	wattroff(window, color_arrows);
132*c76f0793SBaptiste Daroussin 
133*c76f0793SBaptiste Daroussin 	x = x + 1 + ((size - 2 - strlen(text))/2);
134*c76f0793SBaptiste Daroussin 	wattron(window, color_button);
135*c76f0793SBaptiste Daroussin 	mvwaddstr(window, y, x, text);
136*c76f0793SBaptiste Daroussin 	wattroff(window, color_button);
137*c76f0793SBaptiste Daroussin 
138*c76f0793SBaptiste Daroussin 	if (shortkey) {
139*c76f0793SBaptiste Daroussin 		wattron(window, color_shortkey);
140*c76f0793SBaptiste Daroussin 		mvwaddch(window, y, x, text[0]);
141*c76f0793SBaptiste Daroussin 		wattroff(window, color_shortkey);
142*c76f0793SBaptiste Daroussin 	}
143*c76f0793SBaptiste Daroussin }
144*c76f0793SBaptiste Daroussin 
145*c76f0793SBaptiste Daroussin void
146*c76f0793SBaptiste Daroussin draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey)
147*c76f0793SBaptiste Daroussin {
148*c76f0793SBaptiste Daroussin 	int i, x, start_x;
149*c76f0793SBaptiste Daroussin 
150*c76f0793SBaptiste Daroussin 	start_x = bs.sizebutton * bs.nbuttons + (bs.nbuttons - 1) * t.buttonspace;
151*c76f0793SBaptiste Daroussin 	start_x = cols/2 - start_x/2;
152*c76f0793SBaptiste Daroussin 
153*c76f0793SBaptiste Daroussin 	for (i = 0; i < (int) bs.nbuttons; i++) {
154*c76f0793SBaptiste Daroussin 		x = i * (bs.sizebutton + t.buttonspace);
155*c76f0793SBaptiste Daroussin 		draw_button(window, y, start_x + x, bs.sizebutton, bs.label[i],
156*c76f0793SBaptiste Daroussin 		    i == bs.curr, shortkey);
157*c76f0793SBaptiste Daroussin 	}
158*c76f0793SBaptiste Daroussin }
159*c76f0793SBaptiste Daroussin 
160*c76f0793SBaptiste Daroussin void
161*c76f0793SBaptiste Daroussin get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
162*c76f0793SBaptiste Daroussin     char *extralabel, char *nocancellabel, char *helplabel)
163*c76f0793SBaptiste Daroussin {
164*c76f0793SBaptiste Daroussin 	int i;
165*c76f0793SBaptiste Daroussin #define SIZEBUTTON  8
166*c76f0793SBaptiste Daroussin #define DEFAULT_BUTTON_LABEL	LABEL_ok_label
167*c76f0793SBaptiste Daroussin #define DEFAULT_BUTTON_VALUE	BSDDIALOG_YESOK
168*c76f0793SBaptiste Daroussin 
169*c76f0793SBaptiste Daroussin 
170*c76f0793SBaptiste Daroussin 	bs->nbuttons = 0;
171*c76f0793SBaptiste Daroussin 	bs->curr = 0;
172*c76f0793SBaptiste Daroussin 	bs->sizebutton = 0;
173*c76f0793SBaptiste Daroussin 
174*c76f0793SBaptiste Daroussin 	if (yesoklabel != NULL && conf.button.no_ok == false) {
175*c76f0793SBaptiste Daroussin 		bs->label[0] = yesoklabel;
176*c76f0793SBaptiste Daroussin 		bs->value[0] = BSDDIALOG_YESOK;
177*c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
178*c76f0793SBaptiste Daroussin 	}
179*c76f0793SBaptiste Daroussin 
180*c76f0793SBaptiste Daroussin 	if (extralabel != NULL && conf.button.extra_button) {
181*c76f0793SBaptiste Daroussin 		bs->label[bs->nbuttons] = extralabel;
182*c76f0793SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_EXTRA;
183*c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
184*c76f0793SBaptiste Daroussin 	}
185*c76f0793SBaptiste Daroussin 
186*c76f0793SBaptiste Daroussin 	if (nocancellabel != NULL && conf.button.no_cancel == false) {
187*c76f0793SBaptiste Daroussin 		bs->label[bs->nbuttons] = nocancellabel;
188*c76f0793SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_NOCANCEL;
189*c76f0793SBaptiste Daroussin 		if (conf.button.defaultno)
190*c76f0793SBaptiste Daroussin 			bs->curr = bs->nbuttons;
191*c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
192*c76f0793SBaptiste Daroussin 	}
193*c76f0793SBaptiste Daroussin 
194*c76f0793SBaptiste Daroussin 	if (helplabel != NULL && conf.button.help_button) {
195*c76f0793SBaptiste Daroussin 		bs->label[bs->nbuttons] = helplabel;
196*c76f0793SBaptiste Daroussin 		bs->value[bs->nbuttons] = BSDDIALOG_HELP;
197*c76f0793SBaptiste Daroussin 		bs->nbuttons += 1;
198*c76f0793SBaptiste Daroussin 	}
199*c76f0793SBaptiste Daroussin 
200*c76f0793SBaptiste Daroussin 	if (bs->nbuttons == 0) {
201*c76f0793SBaptiste Daroussin 		bs->label[0] = DEFAULT_BUTTON_LABEL;
202*c76f0793SBaptiste Daroussin 		bs->value[0] = DEFAULT_BUTTON_VALUE;
203*c76f0793SBaptiste Daroussin 		bs->nbuttons = 1;
204*c76f0793SBaptiste Daroussin 	}
205*c76f0793SBaptiste Daroussin 
206*c76f0793SBaptiste Daroussin 	if (conf.button.default_label != NULL) {
207*c76f0793SBaptiste Daroussin 		for (i=0; i<(int)bs->nbuttons; i++) {
208*c76f0793SBaptiste Daroussin 			if (strcmp(conf.button.default_label, bs->label[i]) == 0)
209*c76f0793SBaptiste Daroussin 				bs->curr = i;
210*c76f0793SBaptiste Daroussin 		}
211*c76f0793SBaptiste Daroussin 	}
212*c76f0793SBaptiste Daroussin 
213*c76f0793SBaptiste Daroussin 	bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0]));
214*c76f0793SBaptiste Daroussin 	for (i=1; i < (int) bs->nbuttons; i++)
215*c76f0793SBaptiste Daroussin 		bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i]));
216*c76f0793SBaptiste Daroussin 	bs->sizebutton += 2;
217*c76f0793SBaptiste Daroussin }
218*c76f0793SBaptiste Daroussin 
219*c76f0793SBaptiste Daroussin /* Text */
220*c76f0793SBaptiste Daroussin 
221*c76f0793SBaptiste Daroussin // old text, to delete in the future
222*c76f0793SBaptiste Daroussin enum token { TEXT, WS, END };
223*c76f0793SBaptiste Daroussin 
224*c76f0793SBaptiste Daroussin static bool check_set_ncurses_attr(WINDOW *win, char *text)
225*c76f0793SBaptiste Daroussin {
226*c76f0793SBaptiste Daroussin 	bool isattr;
227*c76f0793SBaptiste Daroussin 	int colors[8] = {
228*c76f0793SBaptiste Daroussin 	    COLOR_BLACK,
229*c76f0793SBaptiste Daroussin 	    COLOR_RED,
230*c76f0793SBaptiste Daroussin 	    COLOR_GREEN,
231*c76f0793SBaptiste Daroussin 	    COLOR_YELLOW,
232*c76f0793SBaptiste Daroussin 	    COLOR_BLUE,
233*c76f0793SBaptiste Daroussin 	    COLOR_MAGENTA,
234*c76f0793SBaptiste Daroussin 	    COLOR_CYAN,
235*c76f0793SBaptiste Daroussin 	    COLOR_WHITE
236*c76f0793SBaptiste Daroussin 	};
237*c76f0793SBaptiste Daroussin 
238*c76f0793SBaptiste Daroussin 	if (text[0] == '\0' || text[0] != '\\')
239*c76f0793SBaptiste Daroussin 		return false;
240*c76f0793SBaptiste Daroussin 	if (text[1] == '\0' || text[1] != 'Z')
241*c76f0793SBaptiste Daroussin 		return false;
242*c76f0793SBaptiste Daroussin 	if (text[2] == '\0')
243*c76f0793SBaptiste Daroussin 		return false;
244*c76f0793SBaptiste Daroussin 
245*c76f0793SBaptiste Daroussin 	if ((text[2] - 48) >= 0 && (text[2] - 48) < 8) {
246*c76f0793SBaptiste Daroussin 		// tocheck: import BSD_COLOR
247*c76f0793SBaptiste Daroussin 		// tofix color background
248*c76f0793SBaptiste Daroussin 		wattron(win, COLOR_PAIR(colors[text[2] - 48] * 8 + COLOR_WHITE + 1));
249*c76f0793SBaptiste Daroussin 		return true;
250*c76f0793SBaptiste Daroussin 	}
251*c76f0793SBaptiste Daroussin 
252*c76f0793SBaptiste Daroussin 	isattr = true;
253*c76f0793SBaptiste Daroussin 	switch (text[2]) {
254*c76f0793SBaptiste Daroussin 	case 'n':
255*c76f0793SBaptiste Daroussin 		wattrset(win, A_NORMAL);
256*c76f0793SBaptiste Daroussin 		break;
257*c76f0793SBaptiste Daroussin 	case 'b':
258*c76f0793SBaptiste Daroussin 		wattron(win, A_BOLD);
259*c76f0793SBaptiste Daroussin 		break;
260*c76f0793SBaptiste Daroussin 	case 'B':
261*c76f0793SBaptiste Daroussin 		wattroff(win, A_BOLD);
262*c76f0793SBaptiste Daroussin 		break;
263*c76f0793SBaptiste Daroussin 	case 'r':
264*c76f0793SBaptiste Daroussin 		wattron(win, A_REVERSE);
265*c76f0793SBaptiste Daroussin 		break;
266*c76f0793SBaptiste Daroussin 	case 'R':
267*c76f0793SBaptiste Daroussin 		wattroff(win, A_REVERSE);
268*c76f0793SBaptiste Daroussin 		break;
269*c76f0793SBaptiste Daroussin 	case 'u':
270*c76f0793SBaptiste Daroussin 		wattron(win, A_UNDERLINE);
271*c76f0793SBaptiste Daroussin 		break;
272*c76f0793SBaptiste Daroussin 	case 'U':
273*c76f0793SBaptiste Daroussin 		wattroff(win, A_UNDERLINE);
274*c76f0793SBaptiste Daroussin 		break;
275*c76f0793SBaptiste Daroussin 	default:
276*c76f0793SBaptiste Daroussin 		isattr = false;
277*c76f0793SBaptiste Daroussin 	}
278*c76f0793SBaptiste Daroussin 
279*c76f0793SBaptiste Daroussin 	return isattr;
280*c76f0793SBaptiste Daroussin }
281*c76f0793SBaptiste Daroussin 
282*c76f0793SBaptiste Daroussin static bool isws(int ch)
283*c76f0793SBaptiste Daroussin {
284*c76f0793SBaptiste Daroussin 
285*c76f0793SBaptiste Daroussin 	return (ch == ' ' || ch == '\t' || ch == '\n');
286*c76f0793SBaptiste Daroussin }
287*c76f0793SBaptiste Daroussin 
288*c76f0793SBaptiste Daroussin static int
289*c76f0793SBaptiste Daroussin next_token(char *text, char *valuestr)
290*c76f0793SBaptiste Daroussin {
291*c76f0793SBaptiste Daroussin 	int i, j;
292*c76f0793SBaptiste Daroussin 	enum token tok;
293*c76f0793SBaptiste Daroussin 
294*c76f0793SBaptiste Daroussin 	i = j = 0;
295*c76f0793SBaptiste Daroussin 
296*c76f0793SBaptiste Daroussin 	if (text[0] == '\0')
297*c76f0793SBaptiste Daroussin 		return END;
298*c76f0793SBaptiste Daroussin 
299*c76f0793SBaptiste Daroussin 	while (text[i] != '\0') {
300*c76f0793SBaptiste Daroussin 		if (isws(text[i])) {
301*c76f0793SBaptiste Daroussin 			if (i == 0) {
302*c76f0793SBaptiste Daroussin 				valuestr[0] = text[i];
303*c76f0793SBaptiste Daroussin 				valuestr[1] = '\0';
304*c76f0793SBaptiste Daroussin 				tok = WS;
305*c76f0793SBaptiste Daroussin 			}
306*c76f0793SBaptiste Daroussin 			break;
307*c76f0793SBaptiste Daroussin 		}
308*c76f0793SBaptiste Daroussin 
309*c76f0793SBaptiste Daroussin 		valuestr[j] = text[i];
310*c76f0793SBaptiste Daroussin 		j++;
311*c76f0793SBaptiste Daroussin 		valuestr[j] = '\0';
312*c76f0793SBaptiste Daroussin 		i++;
313*c76f0793SBaptiste Daroussin 		tok = TEXT;
314*c76f0793SBaptiste Daroussin 	}
315*c76f0793SBaptiste Daroussin 
316*c76f0793SBaptiste Daroussin 	return tok;
317*c76f0793SBaptiste Daroussin }
318*c76f0793SBaptiste Daroussin 
319*c76f0793SBaptiste Daroussin static void
320*c76f0793SBaptiste Daroussin print_string(WINDOW *win, int *y, int *x, int minx, int maxx, char *str, bool color)
321*c76f0793SBaptiste Daroussin {
322*c76f0793SBaptiste Daroussin 	int i, j, len, reallen;
323*c76f0793SBaptiste Daroussin 
324*c76f0793SBaptiste Daroussin 	if(strlen(str) == 0)
325*c76f0793SBaptiste Daroussin 		return;
326*c76f0793SBaptiste Daroussin 
327*c76f0793SBaptiste Daroussin 	len = reallen = strlen(str);
328*c76f0793SBaptiste Daroussin 	if (color) {
329*c76f0793SBaptiste Daroussin 		i=0;
330*c76f0793SBaptiste Daroussin 		while (i < len) {
331*c76f0793SBaptiste Daroussin 			if (check_set_ncurses_attr(win, str+i))
332*c76f0793SBaptiste Daroussin 				reallen -= 3;
333*c76f0793SBaptiste Daroussin 			i++;
334*c76f0793SBaptiste Daroussin 		}
335*c76f0793SBaptiste Daroussin 	}
336*c76f0793SBaptiste Daroussin 
337*c76f0793SBaptiste Daroussin 	i = 0;
338*c76f0793SBaptiste Daroussin 	while (i < len) {
339*c76f0793SBaptiste Daroussin 		if (*x + reallen > maxx) {
340*c76f0793SBaptiste Daroussin 			*y = (*x != minx ? *y+1 : *y);
341*c76f0793SBaptiste Daroussin 			*x = minx;
342*c76f0793SBaptiste Daroussin 		}
343*c76f0793SBaptiste Daroussin 		j = *x;
344*c76f0793SBaptiste Daroussin 		while (j < maxx && i < len) {
345*c76f0793SBaptiste Daroussin 			if (color && check_set_ncurses_attr(win, str+i)) {
346*c76f0793SBaptiste Daroussin 				i += 3;
347*c76f0793SBaptiste Daroussin 			} else {
348*c76f0793SBaptiste Daroussin 				mvwaddch(win, *y, j, str[i]);
349*c76f0793SBaptiste Daroussin 				i++;
350*c76f0793SBaptiste Daroussin 				reallen--;
351*c76f0793SBaptiste Daroussin 				j++;
352*c76f0793SBaptiste Daroussin 				*x = j;
353*c76f0793SBaptiste Daroussin 			}
354*c76f0793SBaptiste Daroussin 		}
355*c76f0793SBaptiste Daroussin 	}
356*c76f0793SBaptiste Daroussin }
357*c76f0793SBaptiste Daroussin 
358*c76f0793SBaptiste Daroussin void
359*c76f0793SBaptiste Daroussin print_text(struct bsddialog_conf conf, WINDOW *pad, int starty, int minx, int maxx,
360*c76f0793SBaptiste Daroussin     char *text)
361*c76f0793SBaptiste Daroussin {
362*c76f0793SBaptiste Daroussin 	char *valuestr;
363*c76f0793SBaptiste Daroussin 	int x, y;
364*c76f0793SBaptiste Daroussin 	bool loop;
365*c76f0793SBaptiste Daroussin 	enum token tok;
366*c76f0793SBaptiste Daroussin 
367*c76f0793SBaptiste Daroussin 	valuestr = malloc(strlen(text) + 1);
368*c76f0793SBaptiste Daroussin 
369*c76f0793SBaptiste Daroussin 	x = minx;
370*c76f0793SBaptiste Daroussin 	y = starty;
371*c76f0793SBaptiste Daroussin 	loop = true;
372*c76f0793SBaptiste Daroussin 	while (loop) {
373*c76f0793SBaptiste Daroussin 		tok = next_token(text, valuestr);
374*c76f0793SBaptiste Daroussin 		switch (tok) {
375*c76f0793SBaptiste Daroussin 		case END:
376*c76f0793SBaptiste Daroussin 			loop = false;
377*c76f0793SBaptiste Daroussin 			break;
378*c76f0793SBaptiste Daroussin 		case WS:
379*c76f0793SBaptiste Daroussin 			text += strlen(valuestr);
380*c76f0793SBaptiste Daroussin 			print_string(pad, &y, &x, minx, maxx, valuestr, false /*useless*/);
381*c76f0793SBaptiste Daroussin 			break;
382*c76f0793SBaptiste Daroussin 		case TEXT:
383*c76f0793SBaptiste Daroussin 			text += strlen(valuestr);
384*c76f0793SBaptiste Daroussin 			print_string(pad, &y, &x, minx, maxx, valuestr, conf.text.colors);
385*c76f0793SBaptiste Daroussin 			break;
386*c76f0793SBaptiste Daroussin 		}
387*c76f0793SBaptiste Daroussin 	}
388*c76f0793SBaptiste Daroussin 
389*c76f0793SBaptiste Daroussin 	free(valuestr);
390*c76f0793SBaptiste Daroussin }
391*c76f0793SBaptiste Daroussin 
392*c76f0793SBaptiste Daroussin // new text funcs
393*c76f0793SBaptiste Daroussin 
394*c76f0793SBaptiste Daroussin static bool is_ncurses_attr(char *text)
395*c76f0793SBaptiste Daroussin {
396*c76f0793SBaptiste Daroussin 	bool isattr;
397*c76f0793SBaptiste Daroussin 
398*c76f0793SBaptiste Daroussin 	if (strnlen(text, 3) < 3)
399*c76f0793SBaptiste Daroussin 		return false;
400*c76f0793SBaptiste Daroussin 
401*c76f0793SBaptiste Daroussin 	if (text[0] != '\\' || text[1] != 'Z')
402*c76f0793SBaptiste Daroussin 		return false;
403*c76f0793SBaptiste Daroussin 
404*c76f0793SBaptiste Daroussin 	if ((text[2] - '0') >= 0 && (text[2] - '0') < 8)
405*c76f0793SBaptiste Daroussin 		return true;
406*c76f0793SBaptiste Daroussin 
407*c76f0793SBaptiste Daroussin 	isattr = text[2] == 'n' || text[2] == 'b' || text[2] == 'B' ||
408*c76f0793SBaptiste Daroussin 	    text[2] == 'r' || text[2] == 'R' || text[2] == 'u' ||
409*c76f0793SBaptiste Daroussin 	    text[2] == 'U';
410*c76f0793SBaptiste Daroussin 
411*c76f0793SBaptiste Daroussin 	return isattr;
412*c76f0793SBaptiste Daroussin }
413*c76f0793SBaptiste Daroussin 
414*c76f0793SBaptiste Daroussin static void
415*c76f0793SBaptiste Daroussin print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool color)
416*c76f0793SBaptiste Daroussin {
417*c76f0793SBaptiste Daroussin 	int i, j, len, reallen;
418*c76f0793SBaptiste Daroussin 
419*c76f0793SBaptiste Daroussin 	if(strlen(str) == 0)
420*c76f0793SBaptiste Daroussin 		return;
421*c76f0793SBaptiste Daroussin 
422*c76f0793SBaptiste Daroussin 	len = reallen = strlen(str);
423*c76f0793SBaptiste Daroussin 	if (color) {
424*c76f0793SBaptiste Daroussin 		i=0;
425*c76f0793SBaptiste Daroussin 		while (i < len) {
426*c76f0793SBaptiste Daroussin 			if (is_ncurses_attr(str+i))
427*c76f0793SBaptiste Daroussin 				reallen -= 3;
428*c76f0793SBaptiste Daroussin 			i++;
429*c76f0793SBaptiste Daroussin 		}
430*c76f0793SBaptiste Daroussin 	}
431*c76f0793SBaptiste Daroussin 
432*c76f0793SBaptiste Daroussin 	i = 0;
433*c76f0793SBaptiste Daroussin 	while (i < len) {
434*c76f0793SBaptiste Daroussin 		if (*x + reallen > cols) {
435*c76f0793SBaptiste Daroussin 			*y = (*x != 0 ? *y+1 : *y);
436*c76f0793SBaptiste Daroussin 			if (*y >= *rows) {
437*c76f0793SBaptiste Daroussin 				*rows = *y + 1;
438*c76f0793SBaptiste Daroussin 				wresize(win, *rows, cols);
439*c76f0793SBaptiste Daroussin 			}
440*c76f0793SBaptiste Daroussin 			*x = 0;
441*c76f0793SBaptiste Daroussin 		}
442*c76f0793SBaptiste Daroussin 		j = *x;
443*c76f0793SBaptiste Daroussin 		while (j < cols && i < len) {
444*c76f0793SBaptiste Daroussin 			if (color && check_set_ncurses_attr(win, str+i)) {
445*c76f0793SBaptiste Daroussin 				i += 3;
446*c76f0793SBaptiste Daroussin 			} else {
447*c76f0793SBaptiste Daroussin 				mvwaddch(win, *y, j, str[i]);
448*c76f0793SBaptiste Daroussin 				i++;
449*c76f0793SBaptiste Daroussin 				reallen--;
450*c76f0793SBaptiste Daroussin 				j++;
451*c76f0793SBaptiste Daroussin 				*x = j;
452*c76f0793SBaptiste Daroussin 			}
453*c76f0793SBaptiste Daroussin 		}
454*c76f0793SBaptiste Daroussin 	}
455*c76f0793SBaptiste Daroussin }
456*c76f0793SBaptiste Daroussin 
457*c76f0793SBaptiste Daroussin static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
458*c76f0793SBaptiste Daroussin {
459*c76f0793SBaptiste Daroussin 	int i, j;
460*c76f0793SBaptiste Daroussin 
461*c76f0793SBaptiste Daroussin 	i = j = 0;
462*c76f0793SBaptiste Daroussin 	while (text[i] != '\0') {
463*c76f0793SBaptiste Daroussin 		switch (text[i]) {
464*c76f0793SBaptiste Daroussin 		case '\\':
465*c76f0793SBaptiste Daroussin 			buf[j] = '\\';
466*c76f0793SBaptiste Daroussin 			switch (text[i+1]) {
467*c76f0793SBaptiste Daroussin 			case '\\':
468*c76f0793SBaptiste Daroussin 				i++;
469*c76f0793SBaptiste Daroussin 				break;
470*c76f0793SBaptiste Daroussin 			case 'n':
471*c76f0793SBaptiste Daroussin 				if (conf.text.no_nl_expand) {
472*c76f0793SBaptiste Daroussin 					j++;
473*c76f0793SBaptiste Daroussin 					buf[j] = 'n';
474*c76f0793SBaptiste Daroussin 				} else
475*c76f0793SBaptiste Daroussin 					buf[j] = '\n';
476*c76f0793SBaptiste Daroussin 				i++;
477*c76f0793SBaptiste Daroussin 				break;
478*c76f0793SBaptiste Daroussin 			case 't':
479*c76f0793SBaptiste Daroussin 				if (conf.text.no_collapse) {
480*c76f0793SBaptiste Daroussin 					j++;
481*c76f0793SBaptiste Daroussin 					buf[j] = 't';
482*c76f0793SBaptiste Daroussin 				} else
483*c76f0793SBaptiste Daroussin 					buf[j] = '\t';
484*c76f0793SBaptiste Daroussin 				i++;
485*c76f0793SBaptiste Daroussin 				break;
486*c76f0793SBaptiste Daroussin 			}
487*c76f0793SBaptiste Daroussin 			break;
488*c76f0793SBaptiste Daroussin 		case '\n':
489*c76f0793SBaptiste Daroussin 			buf[j] = conf.text.cr_wrap ? ' ' : '\n';
490*c76f0793SBaptiste Daroussin 			break;
491*c76f0793SBaptiste Daroussin 		case '\t':
492*c76f0793SBaptiste Daroussin 			buf[j] = conf.text.no_collapse ? '\t' : ' ';
493*c76f0793SBaptiste Daroussin 			break;
494*c76f0793SBaptiste Daroussin 		default:
495*c76f0793SBaptiste Daroussin 			buf[j] = text[i];
496*c76f0793SBaptiste Daroussin 		}
497*c76f0793SBaptiste Daroussin 		i++;
498*c76f0793SBaptiste Daroussin 		j += (buf[j] == ' ' && conf.text.trim && j > 0 && buf[j-1] == ' ') ?
499*c76f0793SBaptiste Daroussin 		    0 : 1;
500*c76f0793SBaptiste Daroussin 	}
501*c76f0793SBaptiste Daroussin 	buf[j] = '\0';
502*c76f0793SBaptiste Daroussin }
503*c76f0793SBaptiste Daroussin 
504*c76f0793SBaptiste Daroussin int
505*c76f0793SBaptiste Daroussin get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
506*c76f0793SBaptiste Daroussin     int *maxline, int *nlines)
507*c76f0793SBaptiste Daroussin {
508*c76f0793SBaptiste Daroussin 	char *buf;
509*c76f0793SBaptiste Daroussin 	int i, buflen, wordlen, linelen;
510*c76f0793SBaptiste Daroussin 
511*c76f0793SBaptiste Daroussin 	if ((buf = malloc(strlen(text) + 1)) == NULL)
512*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot building a buffer to find the properties "\
513*c76f0793SBaptiste Daroussin 		    "of the text properties");
514*c76f0793SBaptiste Daroussin 
515*c76f0793SBaptiste Daroussin 	prepare_text(conf, text, buf);
516*c76f0793SBaptiste Daroussin 
517*c76f0793SBaptiste Daroussin 	buflen = strlen(buf) + 1;
518*c76f0793SBaptiste Daroussin 	*maxword = 0;
519*c76f0793SBaptiste Daroussin 	wordlen = 0;
520*c76f0793SBaptiste Daroussin 	for (i=0; i < buflen; i++) {
521*c76f0793SBaptiste Daroussin 		if (buf[i] == '\t' || buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\0')
522*c76f0793SBaptiste Daroussin 			if (wordlen != 0) {
523*c76f0793SBaptiste Daroussin 				*maxword = MAX(*maxword, wordlen);
524*c76f0793SBaptiste Daroussin 				wordlen = 0;
525*c76f0793SBaptiste Daroussin 				continue;
526*c76f0793SBaptiste Daroussin 			}
527*c76f0793SBaptiste Daroussin 		if (conf.text.colors && is_ncurses_attr(buf + i))
528*c76f0793SBaptiste Daroussin 			i += 3;
529*c76f0793SBaptiste Daroussin 		else
530*c76f0793SBaptiste Daroussin 			wordlen++;
531*c76f0793SBaptiste Daroussin 	}
532*c76f0793SBaptiste Daroussin 
533*c76f0793SBaptiste Daroussin 	*maxline = linelen = 0;
534*c76f0793SBaptiste Daroussin 	*nlines = 1;
535*c76f0793SBaptiste Daroussin 	for (i=0; i < buflen; i++) {
536*c76f0793SBaptiste Daroussin 		switch (buf[i]) {
537*c76f0793SBaptiste Daroussin 		case '\n':
538*c76f0793SBaptiste Daroussin 			*nlines = *nlines + 1;
539*c76f0793SBaptiste Daroussin 		case '\0':
540*c76f0793SBaptiste Daroussin 			*maxline = MAX(*maxline, linelen);
541*c76f0793SBaptiste Daroussin 			linelen = 0;
542*c76f0793SBaptiste Daroussin 			break;
543*c76f0793SBaptiste Daroussin 		default:
544*c76f0793SBaptiste Daroussin 			if (conf.text.colors && is_ncurses_attr(buf + i))
545*c76f0793SBaptiste Daroussin 				i += 3;
546*c76f0793SBaptiste Daroussin 			else
547*c76f0793SBaptiste Daroussin 				linelen++;
548*c76f0793SBaptiste Daroussin 		}
549*c76f0793SBaptiste Daroussin 	}
550*c76f0793SBaptiste Daroussin 	if (*nlines == 1 && *maxline == 0)
551*c76f0793SBaptiste Daroussin 		*nlines = 0;
552*c76f0793SBaptiste Daroussin 
553*c76f0793SBaptiste Daroussin 	free(buf);
554*c76f0793SBaptiste Daroussin 
555*c76f0793SBaptiste Daroussin 	return 0;
556*c76f0793SBaptiste Daroussin }
557*c76f0793SBaptiste Daroussin 
558*c76f0793SBaptiste Daroussin static int
559*c76f0793SBaptiste Daroussin print_textpad(struct bsddialog_conf conf, WINDOW *pad, int *rows, int cols, char *text)
560*c76f0793SBaptiste Daroussin {
561*c76f0793SBaptiste Daroussin 	char *buf, *string;
562*c76f0793SBaptiste Daroussin 	int i, j, x, y;
563*c76f0793SBaptiste Daroussin 	bool loop;
564*c76f0793SBaptiste Daroussin 
565*c76f0793SBaptiste Daroussin 	if ((buf = malloc(strlen(text) + 1)) == NULL)
566*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot build (analyze) text");
567*c76f0793SBaptiste Daroussin 
568*c76f0793SBaptiste Daroussin 	prepare_text(conf, text, buf);
569*c76f0793SBaptiste Daroussin 
570*c76f0793SBaptiste Daroussin 	if ((string = malloc(strlen(text) + 1)) == NULL) {
571*c76f0793SBaptiste Daroussin 		free(buf);
572*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Cannot build (analyze) text");
573*c76f0793SBaptiste Daroussin 	}
574*c76f0793SBaptiste Daroussin 	i = j = x = y = 0;
575*c76f0793SBaptiste Daroussin 	loop = true;
576*c76f0793SBaptiste Daroussin 	while (loop) {
577*c76f0793SBaptiste Daroussin 		string[j] = buf[i];
578*c76f0793SBaptiste Daroussin 
579*c76f0793SBaptiste Daroussin 		if (string[j] == '\0' || string[j] == '\n' ||
580*c76f0793SBaptiste Daroussin 		    string[j] == '\t' || string[j] == ' ') {
581*c76f0793SBaptiste Daroussin 			if (j != 0) {
582*c76f0793SBaptiste Daroussin 				string[j] = '\0';
583*c76f0793SBaptiste Daroussin 				print_str(pad, rows, &y, &x, cols, string, conf.text.colors);
584*c76f0793SBaptiste Daroussin 			}
585*c76f0793SBaptiste Daroussin 		}
586*c76f0793SBaptiste Daroussin 
587*c76f0793SBaptiste Daroussin 		switch (buf[i]) {
588*c76f0793SBaptiste Daroussin 		case '\0':
589*c76f0793SBaptiste Daroussin 			loop = false;
590*c76f0793SBaptiste Daroussin 			break;
591*c76f0793SBaptiste Daroussin 		case '\n':
592*c76f0793SBaptiste Daroussin 			j = -1;
593*c76f0793SBaptiste Daroussin 			x = 0;
594*c76f0793SBaptiste Daroussin 			y++;
595*c76f0793SBaptiste Daroussin 			break;
596*c76f0793SBaptiste Daroussin 		case '\t':
597*c76f0793SBaptiste Daroussin 			for (j=0; j<4 /*tablen*/; j++) {
598*c76f0793SBaptiste Daroussin 				x++;
599*c76f0793SBaptiste Daroussin 				if (x >= cols) {
600*c76f0793SBaptiste Daroussin 					x = 0;
601*c76f0793SBaptiste Daroussin 					y++;
602*c76f0793SBaptiste Daroussin 				}
603*c76f0793SBaptiste Daroussin 			}
604*c76f0793SBaptiste Daroussin 			j = -1;
605*c76f0793SBaptiste Daroussin 			break;
606*c76f0793SBaptiste Daroussin 		case ' ':
607*c76f0793SBaptiste Daroussin 			x++;
608*c76f0793SBaptiste Daroussin 			if (x >= cols) {
609*c76f0793SBaptiste Daroussin 				x = 0;
610*c76f0793SBaptiste Daroussin 				y++;
611*c76f0793SBaptiste Daroussin 			}
612*c76f0793SBaptiste Daroussin 			j = -1;
613*c76f0793SBaptiste Daroussin 		}
614*c76f0793SBaptiste Daroussin 
615*c76f0793SBaptiste Daroussin 		if (y >= *rows) { /* check for whitespaces */
616*c76f0793SBaptiste Daroussin 			*rows = y + 1;
617*c76f0793SBaptiste Daroussin 			wresize(pad, *rows, cols);
618*c76f0793SBaptiste Daroussin 		}
619*c76f0793SBaptiste Daroussin 
620*c76f0793SBaptiste Daroussin 		j++;
621*c76f0793SBaptiste Daroussin 		i++;
622*c76f0793SBaptiste Daroussin 	}
623*c76f0793SBaptiste Daroussin 
624*c76f0793SBaptiste Daroussin 	free(string);
625*c76f0793SBaptiste Daroussin 	free(buf);
626*c76f0793SBaptiste Daroussin 
627*c76f0793SBaptiste Daroussin 	return 0;
628*c76f0793SBaptiste Daroussin }
629*c76f0793SBaptiste Daroussin 
630*c76f0793SBaptiste Daroussin /* autosize */
631*c76f0793SBaptiste Daroussin 
632*c76f0793SBaptiste Daroussin /*
633*c76f0793SBaptiste Daroussin  * max y, that is from 0 to LINES - 1 - t.shadowrows,
634*c76f0793SBaptiste Daroussin  * could not be max height but avoids problems with checksize
635*c76f0793SBaptiste Daroussin  */
636*c76f0793SBaptiste Daroussin int widget_max_height(struct bsddialog_conf conf)
637*c76f0793SBaptiste Daroussin {
638*c76f0793SBaptiste Daroussin 	int maxheight;
639*c76f0793SBaptiste Daroussin 
640*c76f0793SBaptiste Daroussin 	if ((maxheight = conf.shadow ? LINES - 1 - t.shadowrows : LINES - 1) <= 0)
641*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Terminal too small, LINES - shadow <= 0");
642*c76f0793SBaptiste Daroussin 
643*c76f0793SBaptiste Daroussin 	if (conf.y > 0)
644*c76f0793SBaptiste Daroussin 		if ((maxheight -= conf.y) <=0)
645*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Terminal too small, LINES - shadow - y <= 0");
646*c76f0793SBaptiste Daroussin 
647*c76f0793SBaptiste Daroussin 	return maxheight;
648*c76f0793SBaptiste Daroussin }
649*c76f0793SBaptiste Daroussin 
650*c76f0793SBaptiste Daroussin /*
651*c76f0793SBaptiste Daroussin  * max x, that is from 0 to COLS - 1 - t.shadowcols,
652*c76f0793SBaptiste Daroussin  *  * could not be max height but avoids problems with checksize
653*c76f0793SBaptiste Daroussin  */
654*c76f0793SBaptiste Daroussin int widget_max_width(struct bsddialog_conf conf)
655*c76f0793SBaptiste Daroussin {
656*c76f0793SBaptiste Daroussin 	int maxwidth;
657*c76f0793SBaptiste Daroussin 
658*c76f0793SBaptiste Daroussin 	if ((maxwidth = conf.shadow ? COLS - 1 - t.shadowcols : COLS - 1)  <= 0)
659*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Terminal too small, COLS - shadow <= 0");
660*c76f0793SBaptiste Daroussin 	if (conf.x > 0)
661*c76f0793SBaptiste Daroussin 		if ((maxwidth -= conf.x) <=0)
662*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Terminal too small, COLS - shadow - x <= 0");
663*c76f0793SBaptiste Daroussin 
664*c76f0793SBaptiste Daroussin 	return maxwidth;
665*c76f0793SBaptiste Daroussin }
666*c76f0793SBaptiste Daroussin 
667*c76f0793SBaptiste Daroussin int
668*c76f0793SBaptiste Daroussin set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w)
669*c76f0793SBaptiste Daroussin {
670*c76f0793SBaptiste Daroussin 	int maxheight, maxwidth;
671*c76f0793SBaptiste Daroussin 
672*c76f0793SBaptiste Daroussin 	if ((maxheight = widget_max_height(conf)) == BSDDIALOG_ERROR)
673*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
674*c76f0793SBaptiste Daroussin 
675*c76f0793SBaptiste Daroussin 	if (rows == BSDDIALOG_FULLSCREEN)
676*c76f0793SBaptiste Daroussin 		*h = maxheight;
677*c76f0793SBaptiste Daroussin 	else if (rows < BSDDIALOG_FULLSCREEN)
678*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative (less than -1) height");
679*c76f0793SBaptiste Daroussin 	else if (rows > BSDDIALOG_AUTOSIZE) {
680*c76f0793SBaptiste Daroussin 		if ((*h = rows) > maxheight)
681*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Height too big (> terminal height - "\
682*c76f0793SBaptiste Daroussin 			    "shadow");
683*c76f0793SBaptiste Daroussin 	}
684*c76f0793SBaptiste Daroussin 	/* rows == AUTOSIZE: each widget has to set its size */
685*c76f0793SBaptiste Daroussin 
686*c76f0793SBaptiste Daroussin 	if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR)
687*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
688*c76f0793SBaptiste Daroussin 
689*c76f0793SBaptiste Daroussin 	if (cols == BSDDIALOG_FULLSCREEN)
690*c76f0793SBaptiste Daroussin 		*w = maxwidth;
691*c76f0793SBaptiste Daroussin 	else if (cols < BSDDIALOG_FULLSCREEN)
692*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative (less than -1) width");
693*c76f0793SBaptiste Daroussin 	else if (cols > BSDDIALOG_AUTOSIZE) {
694*c76f0793SBaptiste Daroussin 		if ((*w = cols) > maxwidth)
695*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Width too big (> terminal width - shadow)");
696*c76f0793SBaptiste Daroussin 	}
697*c76f0793SBaptiste Daroussin 	/* cols == AUTOSIZE: each widget has to set its size */
698*c76f0793SBaptiste Daroussin 
699*c76f0793SBaptiste Daroussin 	return 0;
700*c76f0793SBaptiste Daroussin }
701*c76f0793SBaptiste Daroussin 
702*c76f0793SBaptiste Daroussin int
703*c76f0793SBaptiste Daroussin set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w)
704*c76f0793SBaptiste Daroussin {
705*c76f0793SBaptiste Daroussin 
706*c76f0793SBaptiste Daroussin 	if (conf.y == BSDDIALOG_CENTER)
707*c76f0793SBaptiste Daroussin 		*y = LINES/2 - h/2;
708*c76f0793SBaptiste Daroussin 	else if (conf.y < BSDDIALOG_CENTER)
709*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative begin y (less than -1)");
710*c76f0793SBaptiste Daroussin 	else if (conf.y >= LINES)
711*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Begin Y under the terminal");
712*c76f0793SBaptiste Daroussin 	else
713*c76f0793SBaptiste Daroussin 		*y = conf.y;
714*c76f0793SBaptiste Daroussin 
715*c76f0793SBaptiste Daroussin 	if ((*y + h + (conf.shadow ? (int) t.shadowrows : 0)) > LINES)
716*c76f0793SBaptiste Daroussin 		RETURN_ERROR("The lower of the box under the terminal "\
717*c76f0793SBaptiste Daroussin 		    "(begin Y + height (+ shadow) > terminal lines)");
718*c76f0793SBaptiste Daroussin 
719*c76f0793SBaptiste Daroussin 
720*c76f0793SBaptiste Daroussin 	if (conf.x == BSDDIALOG_CENTER)
721*c76f0793SBaptiste Daroussin 		*x = COLS/2 - w/2;
722*c76f0793SBaptiste Daroussin 	else if (conf.x < BSDDIALOG_CENTER)
723*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Negative begin x (less than -1)");
724*c76f0793SBaptiste Daroussin 	else if (conf.x >= COLS)
725*c76f0793SBaptiste Daroussin 		RETURN_ERROR("Begin X over the right of the terminal");
726*c76f0793SBaptiste Daroussin 	else
727*c76f0793SBaptiste Daroussin 		*x = conf.x;
728*c76f0793SBaptiste Daroussin 
729*c76f0793SBaptiste Daroussin 	if ((*x + w + (conf.shadow ? (int) t.shadowcols : 0)) > COLS)
730*c76f0793SBaptiste Daroussin 		RETURN_ERROR("The right of the box over the terminal "\
731*c76f0793SBaptiste Daroussin 		    "(begin X + width (+ shadow) > terminal cols)");
732*c76f0793SBaptiste Daroussin 
733*c76f0793SBaptiste Daroussin 	return 0;
734*c76f0793SBaptiste Daroussin }
735*c76f0793SBaptiste Daroussin 
736*c76f0793SBaptiste Daroussin /* Widgets builders */
737*c76f0793SBaptiste Daroussin void
738*c76f0793SBaptiste Daroussin draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
739*c76f0793SBaptiste Daroussin     enum elevation elev)
740*c76f0793SBaptiste Daroussin {
741*c76f0793SBaptiste Daroussin 	int leftcolor, rightcolor;
742*c76f0793SBaptiste Daroussin 	int ls, rs, ts, bs, tl, tr, bl, br;
743*c76f0793SBaptiste Daroussin 	int ltee, rtee;
744*c76f0793SBaptiste Daroussin 
745*c76f0793SBaptiste Daroussin 	ls = rs = ACS_VLINE;
746*c76f0793SBaptiste Daroussin 	ts = bs = ACS_HLINE;
747*c76f0793SBaptiste Daroussin 	tl = ACS_ULCORNER;
748*c76f0793SBaptiste Daroussin 	tr = ACS_URCORNER;
749*c76f0793SBaptiste Daroussin 	bl = ACS_LLCORNER;
750*c76f0793SBaptiste Daroussin 	br = ACS_LRCORNER;
751*c76f0793SBaptiste Daroussin 	ltee = ACS_LTEE;
752*c76f0793SBaptiste Daroussin 	rtee = ACS_RTEE;
753*c76f0793SBaptiste Daroussin 
754*c76f0793SBaptiste Daroussin 	if (conf.no_lines == false) {
755*c76f0793SBaptiste Daroussin 		if (conf.ascii_lines) {
756*c76f0793SBaptiste Daroussin 			ls = rs = '|';
757*c76f0793SBaptiste Daroussin 			ts = bs = '-';
758*c76f0793SBaptiste Daroussin 			tl = tr = bl = br = ltee = rtee = '+';
759*c76f0793SBaptiste Daroussin 		}
760*c76f0793SBaptiste Daroussin 		leftcolor  = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
761*c76f0793SBaptiste Daroussin 		rightcolor = elev == RAISED ? t.linelowercolor : t.lineraisecolor;
762*c76f0793SBaptiste Daroussin 		wattron(win, leftcolor);
763*c76f0793SBaptiste Daroussin 		wborder(win, ls, rs, ts, bs, tl, tr, bl, br);
764*c76f0793SBaptiste Daroussin 		wattroff(win, leftcolor);
765*c76f0793SBaptiste Daroussin 
766*c76f0793SBaptiste Daroussin 		wattron(win, rightcolor);
767*c76f0793SBaptiste Daroussin 		mvwaddch(win, 0, cols-1, tr);
768*c76f0793SBaptiste Daroussin 		mvwvline(win, 1, cols-1, rs, rows-2);
769*c76f0793SBaptiste Daroussin 		mvwaddch(win, rows-1, cols-1, br);
770*c76f0793SBaptiste Daroussin 		mvwhline(win, rows-1, 1, bs, cols-2);
771*c76f0793SBaptiste Daroussin 		wattroff(win, rightcolor);
772*c76f0793SBaptiste Daroussin 	}
773*c76f0793SBaptiste Daroussin }
774*c76f0793SBaptiste Daroussin 
775*c76f0793SBaptiste Daroussin WINDOW *
776*c76f0793SBaptiste Daroussin new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
777*c76f0793SBaptiste Daroussin     enum elevation elev)
778*c76f0793SBaptiste Daroussin {
779*c76f0793SBaptiste Daroussin 	WINDOW *win;
780*c76f0793SBaptiste Daroussin 
781*c76f0793SBaptiste Daroussin 	if ((win = newwin(rows, cols, y, x)) == NULL) {
782*c76f0793SBaptiste Daroussin 		set_error_string("Cannot build boxed window");
783*c76f0793SBaptiste Daroussin 		return NULL;
784*c76f0793SBaptiste Daroussin 	}
785*c76f0793SBaptiste Daroussin 
786*c76f0793SBaptiste Daroussin 	wbkgd(win, t.widgetcolor);
787*c76f0793SBaptiste Daroussin 
788*c76f0793SBaptiste Daroussin 	draw_borders(conf, win, rows, cols, elev);
789*c76f0793SBaptiste Daroussin 
790*c76f0793SBaptiste Daroussin 	return win;
791*c76f0793SBaptiste Daroussin }
792*c76f0793SBaptiste Daroussin 
793*c76f0793SBaptiste Daroussin /*
794*c76f0793SBaptiste Daroussin  * `enum elevation elev` could be useless because it should be always RAISED,
795*c76f0793SBaptiste Daroussin  * to check at the end.
796*c76f0793SBaptiste Daroussin  */
797*c76f0793SBaptiste Daroussin static int
798*c76f0793SBaptiste Daroussin draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
799*c76f0793SBaptiste Daroussin     WINDOW *widget, int h, int w, enum elevation elev,
800*c76f0793SBaptiste Daroussin     WINDOW *textpad, int *htextpad, char *text, bool buttons)
801*c76f0793SBaptiste Daroussin {
802*c76f0793SBaptiste Daroussin 	int ts, ltee, rtee;
803*c76f0793SBaptiste Daroussin 	int colorsurroundtitle;
804*c76f0793SBaptiste Daroussin 
805*c76f0793SBaptiste Daroussin 	ts = conf.ascii_lines ? '-' : ACS_HLINE;
806*c76f0793SBaptiste Daroussin 	ltee = conf.ascii_lines ? '+' : ACS_LTEE;
807*c76f0793SBaptiste Daroussin 	rtee = conf.ascii_lines ? '+' : ACS_RTEE;
808*c76f0793SBaptiste Daroussin 	colorsurroundtitle = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
809*c76f0793SBaptiste Daroussin 
810*c76f0793SBaptiste Daroussin 	if (shadow != NULL)
811*c76f0793SBaptiste Daroussin 		wnoutrefresh(shadow);
812*c76f0793SBaptiste Daroussin 
813*c76f0793SBaptiste Daroussin 	// move / resize now or the caller?
814*c76f0793SBaptiste Daroussin 	draw_borders(conf, widget, h, w, elev);
815*c76f0793SBaptiste Daroussin 
816*c76f0793SBaptiste Daroussin 	if (conf.title != NULL) {
817*c76f0793SBaptiste Daroussin 		if (t.surroundtitle && conf.no_lines == false) {
818*c76f0793SBaptiste Daroussin 			wattron(widget, colorsurroundtitle);
819*c76f0793SBaptiste Daroussin 			mvwaddch(widget, 0, w/2 - strlen(conf.title)/2 - 1, rtee);
820*c76f0793SBaptiste Daroussin 			wattroff(widget, colorsurroundtitle);
821*c76f0793SBaptiste Daroussin 		}
822*c76f0793SBaptiste Daroussin 		wattron(widget, t.titlecolor);
823*c76f0793SBaptiste Daroussin 		mvwaddstr(widget, 0, w/2 - strlen(conf.title)/2, conf.title);
824*c76f0793SBaptiste Daroussin 		wattroff(widget, t.titlecolor);
825*c76f0793SBaptiste Daroussin 		if (t.surroundtitle && conf.no_lines == false) {
826*c76f0793SBaptiste Daroussin 			wattron(widget, colorsurroundtitle);
827*c76f0793SBaptiste Daroussin 			waddch(widget, ltee);
828*c76f0793SBaptiste Daroussin 			wattroff(widget, colorsurroundtitle);
829*c76f0793SBaptiste Daroussin 		}
830*c76f0793SBaptiste Daroussin 	}
831*c76f0793SBaptiste Daroussin 
832*c76f0793SBaptiste Daroussin 	if (conf.hline != NULL) {
833*c76f0793SBaptiste Daroussin 		wattron(widget, t.bottomtitlecolor);
834*c76f0793SBaptiste Daroussin 		wmove(widget, h - 1, w/2 - strlen(conf.hline)/2 - 1);
835*c76f0793SBaptiste Daroussin 		waddch(widget, '[');
836*c76f0793SBaptiste Daroussin 		waddstr(widget, conf.hline);
837*c76f0793SBaptiste Daroussin 		waddch(widget, ']');
838*c76f0793SBaptiste Daroussin 		wattroff(widget, t.bottomtitlecolor);
839*c76f0793SBaptiste Daroussin 	}
840*c76f0793SBaptiste Daroussin 
841*c76f0793SBaptiste Daroussin 	if (textpad == NULL && text != NULL) /* no pad, text null for textbox */
842*c76f0793SBaptiste Daroussin 		print_text(conf, widget, 1, 2, w-3, text);
843*c76f0793SBaptiste Daroussin 
844*c76f0793SBaptiste Daroussin 	if (buttons && conf.no_lines == false) {
845*c76f0793SBaptiste Daroussin 		wattron(widget, t.lineraisecolor);
846*c76f0793SBaptiste Daroussin 		mvwaddch(widget, h-3, 0, ltee);
847*c76f0793SBaptiste Daroussin 		mvwhline(widget, h-3, 1, ts, w-2);
848*c76f0793SBaptiste Daroussin 		wattroff(widget, t.lineraisecolor);
849*c76f0793SBaptiste Daroussin 
850*c76f0793SBaptiste Daroussin 		wattron(widget, t.linelowercolor);
851*c76f0793SBaptiste Daroussin 		mvwaddch(widget, h-3, w-1, rtee);
852*c76f0793SBaptiste Daroussin 		wattroff(widget, t.linelowercolor);
853*c76f0793SBaptiste Daroussin 	}
854*c76f0793SBaptiste Daroussin 
855*c76f0793SBaptiste Daroussin 	wnoutrefresh(widget);
856*c76f0793SBaptiste Daroussin 
857*c76f0793SBaptiste Daroussin 	if (textpad == NULL)
858*c76f0793SBaptiste Daroussin 		return 0; /* widget_init() ends */
859*c76f0793SBaptiste Daroussin 
860*c76f0793SBaptiste Daroussin 	if (text != NULL) /* programbox etc */
861*c76f0793SBaptiste Daroussin 		if (print_textpad(conf, textpad, htextpad,
862*c76f0793SBaptiste Daroussin 		    w - HBORDERS - t.texthmargin * 2, text) !=0)
863*c76f0793SBaptiste Daroussin 			return BSDDIALOG_ERROR;
864*c76f0793SBaptiste Daroussin 
865*c76f0793SBaptiste Daroussin 	return 0;
866*c76f0793SBaptiste Daroussin }
867*c76f0793SBaptiste Daroussin 
868*c76f0793SBaptiste Daroussin /*
869*c76f0793SBaptiste Daroussin  * `enum elevation elev` could be useless because it should be always RAISED,
870*c76f0793SBaptiste Daroussin  * to check at the end.
871*c76f0793SBaptiste Daroussin  */
872*c76f0793SBaptiste Daroussin int
873*c76f0793SBaptiste Daroussin update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
874*c76f0793SBaptiste Daroussin     WINDOW *widget, int h, int w, enum elevation elev,
875*c76f0793SBaptiste Daroussin     WINDOW *textpad, int *htextpad, char *text, bool buttons)
876*c76f0793SBaptiste Daroussin {
877*c76f0793SBaptiste Daroussin 	int error;
878*c76f0793SBaptiste Daroussin 
879*c76f0793SBaptiste Daroussin 	/* nothing for now */
880*c76f0793SBaptiste Daroussin 
881*c76f0793SBaptiste Daroussin 	error =  draw_widget_withtextpad(conf, shadow, widget, h, w,
882*c76f0793SBaptiste Daroussin 	    elev, textpad, htextpad, text, buttons);
883*c76f0793SBaptiste Daroussin 
884*c76f0793SBaptiste Daroussin 	return error;
885*c76f0793SBaptiste Daroussin }
886*c76f0793SBaptiste Daroussin 
887*c76f0793SBaptiste Daroussin /*
888*c76f0793SBaptiste Daroussin  * `enum elevation elev` could be useless because it should be always RAISED,
889*c76f0793SBaptiste Daroussin  * to check at the end.
890*c76f0793SBaptiste Daroussin  */
891*c76f0793SBaptiste Daroussin int
892*c76f0793SBaptiste Daroussin new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
893*c76f0793SBaptiste Daroussin     WINDOW **widget, int y, int x, int h, int w, enum elevation elev,
894*c76f0793SBaptiste Daroussin     WINDOW **textpad, int *htextpad, char *text, bool buttons)
895*c76f0793SBaptiste Daroussin {
896*c76f0793SBaptiste Daroussin 	int error;
897*c76f0793SBaptiste Daroussin 
898*c76f0793SBaptiste Daroussin 	if (conf.shadow) {
899*c76f0793SBaptiste Daroussin 		*shadow = newwin(h, w, y + t.shadowrows, x + t.shadowcols);
900*c76f0793SBaptiste Daroussin 		if (*shadow == NULL)
901*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Cannot build shadow");
902*c76f0793SBaptiste Daroussin 		wbkgd(*shadow, t.shadowcolor);
903*c76f0793SBaptiste Daroussin 	}
904*c76f0793SBaptiste Daroussin 
905*c76f0793SBaptiste Daroussin 	if ((*widget = new_boxed_window(conf, y, x, h, w, elev)) == NULL) {
906*c76f0793SBaptiste Daroussin 		if (conf.shadow)
907*c76f0793SBaptiste Daroussin 			delwin(*shadow);
908*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
909*c76f0793SBaptiste Daroussin 	}
910*c76f0793SBaptiste Daroussin 
911*c76f0793SBaptiste Daroussin 	if (textpad == NULL) { /* widget_init() */
912*c76f0793SBaptiste Daroussin 		error =  draw_widget_withtextpad(conf, *shadow, *widget, h, w,
913*c76f0793SBaptiste Daroussin 		    elev, NULL, NULL, text, buttons);
914*c76f0793SBaptiste Daroussin 		return error;
915*c76f0793SBaptiste Daroussin 	}
916*c76f0793SBaptiste Daroussin 
917*c76f0793SBaptiste Daroussin 	if (text != NULL) { /* programbox etc */
918*c76f0793SBaptiste Daroussin 		*htextpad = 1;
919*c76f0793SBaptiste Daroussin 		*textpad = newpad(*htextpad, w - HBORDERS - t.texthmargin * 2);
920*c76f0793SBaptiste Daroussin 		if (*textpad == NULL) {
921*c76f0793SBaptiste Daroussin 			delwin(*textpad);
922*c76f0793SBaptiste Daroussin 			if (conf.shadow)
923*c76f0793SBaptiste Daroussin 				delwin(*shadow);
924*c76f0793SBaptiste Daroussin 			RETURN_ERROR("Cannot build the pad window for text");
925*c76f0793SBaptiste Daroussin 		}
926*c76f0793SBaptiste Daroussin 		wbkgd(*textpad, t.widgetcolor);
927*c76f0793SBaptiste Daroussin 	}
928*c76f0793SBaptiste Daroussin 
929*c76f0793SBaptiste Daroussin 	error =  draw_widget_withtextpad(conf, *shadow, *widget, h, w, elev,
930*c76f0793SBaptiste Daroussin 	    *textpad, htextpad, text, buttons);
931*c76f0793SBaptiste Daroussin 
932*c76f0793SBaptiste Daroussin 	return error;
933*c76f0793SBaptiste Daroussin }
934*c76f0793SBaptiste Daroussin 
935*c76f0793SBaptiste Daroussin int
936*c76f0793SBaptiste Daroussin new_widget(struct bsddialog_conf conf, WINDOW **widget, int *y, int *x,
937*c76f0793SBaptiste Daroussin     char *text, int *h, int *w, WINDOW **shadow, bool buttons)
938*c76f0793SBaptiste Daroussin {
939*c76f0793SBaptiste Daroussin 
940*c76f0793SBaptiste Daroussin 	// to delete (each widget has to check its x,y,h,w)
941*c76f0793SBaptiste Daroussin 	if (*h <= 0)
942*c76f0793SBaptiste Daroussin 		; /* todo */
943*c76f0793SBaptiste Daroussin 
944*c76f0793SBaptiste Daroussin 	if (*w <= 0)
945*c76f0793SBaptiste Daroussin 		; /* todo */
946*c76f0793SBaptiste Daroussin 
947*c76f0793SBaptiste Daroussin 	*y = (conf.y < 0) ? (LINES/2 - *h/2) : conf.y;
948*c76f0793SBaptiste Daroussin 	*x = (conf.x < 0) ? (COLS/2 - *w/2) : conf.x;
949*c76f0793SBaptiste Daroussin 
950*c76f0793SBaptiste Daroussin 	if (new_widget_withtextpad(conf, shadow, widget, *y, *x, *h, *w, RAISED,
951*c76f0793SBaptiste Daroussin 	    NULL, NULL, text, buttons) != 0)
952*c76f0793SBaptiste Daroussin 		return BSDDIALOG_ERROR;
953*c76f0793SBaptiste Daroussin 
954*c76f0793SBaptiste Daroussin 	if (conf.shadow)
955*c76f0793SBaptiste Daroussin 		wrefresh(*shadow);
956*c76f0793SBaptiste Daroussin 
957*c76f0793SBaptiste Daroussin 	wrefresh(*widget);
958*c76f0793SBaptiste Daroussin 
959*c76f0793SBaptiste Daroussin 	return 0;
960*c76f0793SBaptiste Daroussin }
961*c76f0793SBaptiste Daroussin 
962*c76f0793SBaptiste Daroussin void
963*c76f0793SBaptiste Daroussin end_widget_withtextpad(struct bsddialog_conf conf, WINDOW *window, int h, int w,
964*c76f0793SBaptiste Daroussin     WINDOW *textpad, WINDOW *shadow)
965*c76f0793SBaptiste Daroussin {
966*c76f0793SBaptiste Daroussin 	int y, x;
967*c76f0793SBaptiste Daroussin 
968*c76f0793SBaptiste Daroussin 	getbegyx(window, y, x); /* for clear, add y & x to args? */
969*c76f0793SBaptiste Daroussin 
970*c76f0793SBaptiste Daroussin 	if (conf.sleep > 0)
971*c76f0793SBaptiste Daroussin 		sleep(conf.sleep);
972*c76f0793SBaptiste Daroussin 
973*c76f0793SBaptiste Daroussin 	if (textpad != NULL)
974*c76f0793SBaptiste Daroussin 		delwin(textpad);
975*c76f0793SBaptiste Daroussin 
976*c76f0793SBaptiste Daroussin 	delwin(window);
977*c76f0793SBaptiste Daroussin 
978*c76f0793SBaptiste Daroussin 	if (conf.shadow)
979*c76f0793SBaptiste Daroussin 		delwin(shadow);
980*c76f0793SBaptiste Daroussin 
981*c76f0793SBaptiste Daroussin 	if (conf.clear)
982*c76f0793SBaptiste Daroussin 		hide_widget(y, x, h, w, shadow != NULL);
983*c76f0793SBaptiste Daroussin 
984*c76f0793SBaptiste Daroussin 	if (conf.get_height != NULL)
985*c76f0793SBaptiste Daroussin 		*conf.get_height = h;
986*c76f0793SBaptiste Daroussin 	if (conf.get_width != NULL)
987*c76f0793SBaptiste Daroussin 		*conf.get_width = w;
988*c76f0793SBaptiste Daroussin }
989*c76f0793SBaptiste Daroussin 
990*c76f0793SBaptiste Daroussin void
991*c76f0793SBaptiste Daroussin end_widget(struct bsddialog_conf conf, WINDOW *window, int h, int w,
992*c76f0793SBaptiste Daroussin     WINDOW *shadow)
993*c76f0793SBaptiste Daroussin {
994*c76f0793SBaptiste Daroussin 
995*c76f0793SBaptiste Daroussin 	end_widget_withtextpad(conf, window, h, w, NULL, shadow);
996*c76f0793SBaptiste Daroussin }
997