xref: /freebsd/contrib/dialog/util.c (revision 4c8945a06b01a5c8122cdeb402af36bb46a06acc)
1*4c8945a0SNathan Whitehorn /*
2*4c8945a0SNathan Whitehorn  *  $Id: util.c,v 1.201 2010/04/28 21:12:42 tom Exp $
3*4c8945a0SNathan Whitehorn  *
4*4c8945a0SNathan Whitehorn  *  util.c -- miscellaneous utilities for dialog
5*4c8945a0SNathan Whitehorn  *
6*4c8945a0SNathan Whitehorn  *  Copyright 2000-2008,2010	Thomas E. Dickey
7*4c8945a0SNathan Whitehorn  *
8*4c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
9*4c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
10*4c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
11*4c8945a0SNathan Whitehorn  *
12*4c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
13*4c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14*4c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*4c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
16*4c8945a0SNathan Whitehorn  *
17*4c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
18*4c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
19*4c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
20*4c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
21*4c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
22*4c8945a0SNathan Whitehorn  *
23*4c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors
24*4c8945a0SNathan Whitehorn  *	Savio Lam (lam836@cs.cuhk.hk)
25*4c8945a0SNathan Whitehorn  */
26*4c8945a0SNathan Whitehorn 
27*4c8945a0SNathan Whitehorn #include <dialog.h>
28*4c8945a0SNathan Whitehorn #include <dlg_keys.h>
29*4c8945a0SNathan Whitehorn 
30*4c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
31*4c8945a0SNathan Whitehorn #if defined(HAVE_NCURSESW_TERM_H)
32*4c8945a0SNathan Whitehorn #include <ncursesw/term.h>
33*4c8945a0SNathan Whitehorn #elif defined(HAVE_NCURSES_TERM_H)
34*4c8945a0SNathan Whitehorn #include <ncurses/term.h>
35*4c8945a0SNathan Whitehorn #else
36*4c8945a0SNathan Whitehorn #include <term.h>
37*4c8945a0SNathan Whitehorn #endif
38*4c8945a0SNathan Whitehorn #endif
39*4c8945a0SNathan Whitehorn 
40*4c8945a0SNathan Whitehorn /* globals */
41*4c8945a0SNathan Whitehorn DIALOG_STATE dialog_state;
42*4c8945a0SNathan Whitehorn DIALOG_VARS dialog_vars;
43*4c8945a0SNathan Whitehorn 
44*4c8945a0SNathan Whitehorn #define concat(a,b) a##b
45*4c8945a0SNathan Whitehorn 
46*4c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
47*4c8945a0SNathan Whitehorn #define RC_DATA(name,comment) , #name "_color", comment " color"
48*4c8945a0SNathan Whitehorn #else
49*4c8945a0SNathan Whitehorn #define RC_DATA(name,comment)	/*nothing */
50*4c8945a0SNathan Whitehorn #endif
51*4c8945a0SNathan Whitehorn 
52*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
53*4c8945a0SNathan Whitehorn #include <dlg_colors.h>
54*4c8945a0SNathan Whitehorn #define COLOR_DATA(upr) , \
55*4c8945a0SNathan Whitehorn 	concat(DLGC_FG_,upr), \
56*4c8945a0SNathan Whitehorn 	concat(DLGC_BG_,upr), \
57*4c8945a0SNathan Whitehorn 	concat(DLGC_HL_,upr)
58*4c8945a0SNathan Whitehorn #else
59*4c8945a0SNathan Whitehorn #define COLOR_DATA(upr)		/*nothing */
60*4c8945a0SNathan Whitehorn #endif
61*4c8945a0SNathan Whitehorn 
62*4c8945a0SNathan Whitehorn #define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }
63*4c8945a0SNathan Whitehorn 
64*4c8945a0SNathan Whitehorn /*
65*4c8945a0SNathan Whitehorn  * Table of color and attribute values, default is for mono display.
66*4c8945a0SNathan Whitehorn  */
67*4c8945a0SNathan Whitehorn /* *INDENT-OFF* */
68*4c8945a0SNathan Whitehorn DIALOG_COLORS dlg_color_table[] =
69*4c8945a0SNathan Whitehorn {
70*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SCREEN,			screen, "Screen"),
71*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SHADOW,			shadow, "Shadow"),
72*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DIALOG,			dialog, "Dialog box"),
73*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TITLE,			title, "Dialog box title"),
74*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	BORDER,			border, "Dialog box border"),
75*4c8945a0SNathan Whitehorn     DATA(A_BOLD,	BUTTON_ACTIVE,		button_active, "Active button"),
76*4c8945a0SNathan Whitehorn     DATA(A_DIM,		BUTTON_INACTIVE,	button_inactive, "Inactive button"),
77*4c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_ACTIVE,	button_key_active, "Active button key"),
78*4c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_INACTIVE,	button_key_inactive, "Inactive button key"),
79*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_ACTIVE,	button_label_active, "Active button label"),
80*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_INACTIVE,	button_label_inactive, "Inactive button label"),
81*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX,		inputbox, "Input box"),
82*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX_BORDER,	inputbox_border, "Input box border"),
83*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX,		searchbox, "Search box"),
84*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_TITLE,	searchbox_title, "Search box title"),
85*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_BORDER,	searchbox_border, "Search box border"),
86*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	POSITION_INDICATOR,	position_indicator, "File position indicator"),
87*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX,		menubox, "Menu box"),
88*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX_BORDER,		menubox_border, "Menu box border"),
89*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	ITEM,			item, "Item"),
90*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEM_SELECTED,		item_selected, "Selected item"),
91*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG,			tag, "Tag"),
92*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG_SELECTED,		tag_selected, "Selected tag"),
93*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	TAG_KEY,		tag_key, "Tag key"),
94*4c8945a0SNathan Whitehorn     DATA(A_BOLD,	TAG_KEY_SELECTED,	tag_key_selected, "Selected tag key"),
95*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK,			check, "Check box"),
96*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK_SELECTED,		check_selected, "Selected check box"),
97*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	UARROW,			uarrow, "Up arrow"),
98*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DARROW,			darrow, "Down arrow"),
99*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEMHELP,		itemhelp, "Item help-text"),
100*4c8945a0SNathan Whitehorn     DATA(A_BOLD,	FORM_ACTIVE_TEXT,	form_active_text, "Active form text"),
101*4c8945a0SNathan Whitehorn     DATA(A_REVERSE,	FORM_TEXT,		form_text, "Form text"),
102*4c8945a0SNathan Whitehorn     DATA(A_NORMAL,	FORM_ITEM_READONLY,	form_item_readonly, "Readonly form item")
103*4c8945a0SNathan Whitehorn };
104*4c8945a0SNathan Whitehorn /* *INDENT-ON* */
105*4c8945a0SNathan Whitehorn 
106*4c8945a0SNathan Whitehorn /*
107*4c8945a0SNathan Whitehorn  * Display background title if it exists ...
108*4c8945a0SNathan Whitehorn  */
109*4c8945a0SNathan Whitehorn void
110*4c8945a0SNathan Whitehorn dlg_put_backtitle(void)
111*4c8945a0SNathan Whitehorn {
112*4c8945a0SNathan Whitehorn     int i;
113*4c8945a0SNathan Whitehorn 
114*4c8945a0SNathan Whitehorn     if (dialog_vars.backtitle != NULL) {
115*4c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
116*4c8945a0SNathan Whitehorn 	int backwidth = dlg_count_columns(dialog_vars.backtitle);
117*4c8945a0SNathan Whitehorn 
118*4c8945a0SNathan Whitehorn 	wattrset(stdscr, screen_attr);
119*4c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 0, 1);
120*4c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);
121*4c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - backwidth; i++)
122*4c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, ' ');
123*4c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 1, 1);
124*4c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - 2; i++)
125*4c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, dlg_boxchar(ACS_HLINE));
126*4c8945a0SNathan Whitehorn     }
127*4c8945a0SNathan Whitehorn 
128*4c8945a0SNathan Whitehorn     (void) wnoutrefresh(stdscr);
129*4c8945a0SNathan Whitehorn }
130*4c8945a0SNathan Whitehorn 
131*4c8945a0SNathan Whitehorn /*
132*4c8945a0SNathan Whitehorn  * Set window to attribute 'attr'.  There are more efficient ways to do this,
133*4c8945a0SNathan Whitehorn  * but will not work on older/buggy ncurses versions.
134*4c8945a0SNathan Whitehorn  */
135*4c8945a0SNathan Whitehorn void
136*4c8945a0SNathan Whitehorn dlg_attr_clear(WINDOW *win, int height, int width, chtype attr)
137*4c8945a0SNathan Whitehorn {
138*4c8945a0SNathan Whitehorn     int i, j;
139*4c8945a0SNathan Whitehorn 
140*4c8945a0SNathan Whitehorn     wattrset(win, attr);
141*4c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
142*4c8945a0SNathan Whitehorn 	(void) wmove(win, i, 0);
143*4c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
144*4c8945a0SNathan Whitehorn 	    (void) waddch(win, ' ');
145*4c8945a0SNathan Whitehorn     }
146*4c8945a0SNathan Whitehorn     (void) touchwin(win);
147*4c8945a0SNathan Whitehorn }
148*4c8945a0SNathan Whitehorn 
149*4c8945a0SNathan Whitehorn void
150*4c8945a0SNathan Whitehorn dlg_clear(void)
151*4c8945a0SNathan Whitehorn {
152*4c8945a0SNathan Whitehorn     dlg_attr_clear(stdscr, LINES, COLS, screen_attr);
153*4c8945a0SNathan Whitehorn }
154*4c8945a0SNathan Whitehorn 
155*4c8945a0SNathan Whitehorn #define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)
156*4c8945a0SNathan Whitehorn 
157*4c8945a0SNathan Whitehorn #define TTY_DEVICE "/dev/tty"
158*4c8945a0SNathan Whitehorn 
159*4c8945a0SNathan Whitehorn /*
160*4c8945a0SNathan Whitehorn  * If $DIALOG_TTY exists, allow the program to try to open the terminal
161*4c8945a0SNathan Whitehorn  * directly when stdout is redirected.  By default we require the "--stdout"
162*4c8945a0SNathan Whitehorn  * option to be given, but some scripts were written making use of the
163*4c8945a0SNathan Whitehorn  * behavior of dialog which tried opening the terminal anyway.
164*4c8945a0SNathan Whitehorn  */
165*4c8945a0SNathan Whitehorn static char *
166*4c8945a0SNathan Whitehorn dialog_tty(void)
167*4c8945a0SNathan Whitehorn {
168*4c8945a0SNathan Whitehorn     char *result = getenv("DIALOG_TTY");
169*4c8945a0SNathan Whitehorn     if (result != 0 && atoi(result) == 0)
170*4c8945a0SNathan Whitehorn 	result = 0;
171*4c8945a0SNathan Whitehorn     return result;
172*4c8945a0SNathan Whitehorn }
173*4c8945a0SNathan Whitehorn 
174*4c8945a0SNathan Whitehorn /*
175*4c8945a0SNathan Whitehorn  * Open the terminal directly.  If one of stdin, stdout or stderr really points
176*4c8945a0SNathan Whitehorn  * to a tty, use it.  Otherwise give up and open /dev/tty.
177*4c8945a0SNathan Whitehorn  */
178*4c8945a0SNathan Whitehorn static int
179*4c8945a0SNathan Whitehorn open_terminal(char **result, int mode)
180*4c8945a0SNathan Whitehorn {
181*4c8945a0SNathan Whitehorn     const char *device = TTY_DEVICE;
182*4c8945a0SNathan Whitehorn     if (!isatty(fileno(stderr))
183*4c8945a0SNathan Whitehorn 	|| (device = ttyname(fileno(stderr))) == 0) {
184*4c8945a0SNathan Whitehorn 	if (!isatty(fileno(stdout))
185*4c8945a0SNathan Whitehorn 	    || (device = ttyname(fileno(stdout))) == 0) {
186*4c8945a0SNathan Whitehorn 	    if (!isatty(fileno(stdin))
187*4c8945a0SNathan Whitehorn 		|| (device = ttyname(fileno(stdin))) == 0) {
188*4c8945a0SNathan Whitehorn 		device = TTY_DEVICE;
189*4c8945a0SNathan Whitehorn 	    }
190*4c8945a0SNathan Whitehorn 	}
191*4c8945a0SNathan Whitehorn     }
192*4c8945a0SNathan Whitehorn     *result = dlg_strclone(device);
193*4c8945a0SNathan Whitehorn     return open(device, mode);
194*4c8945a0SNathan Whitehorn }
195*4c8945a0SNathan Whitehorn 
196*4c8945a0SNathan Whitehorn /*
197*4c8945a0SNathan Whitehorn  * Do some initialization for dialog.
198*4c8945a0SNathan Whitehorn  *
199*4c8945a0SNathan Whitehorn  * 'input' is the real tty input of dialog.  Usually it is stdin, but if
200*4c8945a0SNathan Whitehorn  * --input-fd option is used, it may be anything.
201*4c8945a0SNathan Whitehorn  *
202*4c8945a0SNathan Whitehorn  * 'output' is where dialog will send its result.  Usually it is stderr, but
203*4c8945a0SNathan Whitehorn  * if --stdout or --output-fd is used, it may be anything.  We are concerned
204*4c8945a0SNathan Whitehorn  * mainly with the case where it happens to be the same as stdout.
205*4c8945a0SNathan Whitehorn  */
206*4c8945a0SNathan Whitehorn void
207*4c8945a0SNathan Whitehorn init_dialog(FILE *input, FILE *output)
208*4c8945a0SNathan Whitehorn {
209*4c8945a0SNathan Whitehorn     int fd1, fd2;
210*4c8945a0SNathan Whitehorn     char *device = 0;
211*4c8945a0SNathan Whitehorn 
212*4c8945a0SNathan Whitehorn     dialog_state.output = output;
213*4c8945a0SNathan Whitehorn     dialog_state.tab_len = TAB_LEN;
214*4c8945a0SNathan Whitehorn     dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;
215*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
216*4c8945a0SNathan Whitehorn     dialog_state.use_colors = USE_COLORS;	/* use colors by default? */
217*4c8945a0SNathan Whitehorn     dialog_state.use_shadow = USE_SHADOW;	/* shadow dialog boxes by default? */
218*4c8945a0SNathan Whitehorn #endif
219*4c8945a0SNathan Whitehorn 
220*4c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
221*4c8945a0SNathan Whitehorn     if (dlg_parse_rc() == -1)	/* Read the configuration file */
222*4c8945a0SNathan Whitehorn 	dlg_exiterr("init_dialog: dlg_parse_rc");
223*4c8945a0SNathan Whitehorn #endif
224*4c8945a0SNathan Whitehorn 
225*4c8945a0SNathan Whitehorn     /*
226*4c8945a0SNathan Whitehorn      * Some widgets (such as gauge) may read from the standard input.  Pipes
227*4c8945a0SNathan Whitehorn      * only connect stdout/stdin, so there is not much choice.  But reading a
228*4c8945a0SNathan Whitehorn      * pipe would get in the way of curses' normal reading stdin for getch.
229*4c8945a0SNathan Whitehorn      *
230*4c8945a0SNathan Whitehorn      * As in the --stdout (see below), reopening the terminal does not always
231*4c8945a0SNathan Whitehorn      * work properly.  dialog provides a --pipe-fd option for this purpose.  We
232*4c8945a0SNathan Whitehorn      * test that case first (differing fileno's for input/stdin).  If the
233*4c8945a0SNathan Whitehorn      * fileno's are equal, but we're not reading from a tty, see if we can open
234*4c8945a0SNathan Whitehorn      * /dev/tty.
235*4c8945a0SNathan Whitehorn      */
236*4c8945a0SNathan Whitehorn     dialog_state.pipe_input = stdin;
237*4c8945a0SNathan Whitehorn     if (fileno(input) != fileno(stdin)) {
238*4c8945a0SNathan Whitehorn 	if ((fd1 = dup(fileno(input))) >= 0
239*4c8945a0SNathan Whitehorn 	    && (fd2 = dup(fileno(stdin))) >= 0) {
240*4c8945a0SNathan Whitehorn 	    (void) dup2(fileno(input), fileno(stdin));
241*4c8945a0SNathan Whitehorn 	    dialog_state.pipe_input = fdopen(fd2, "r");
242*4c8945a0SNathan Whitehorn 	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */
243*4c8945a0SNathan Whitehorn 		(void) dup2(fileno(stdin), 0);
244*4c8945a0SNathan Whitehorn 	} else
245*4c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-input");
246*4c8945a0SNathan Whitehorn     } else if (!isatty(fileno(stdin))) {
247*4c8945a0SNathan Whitehorn 	if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0
248*4c8945a0SNathan Whitehorn 	    && (fd2 = dup(fileno(stdin))) >= 0) {
249*4c8945a0SNathan Whitehorn 	    dialog_state.pipe_input = fdopen(fd2, "r");
250*4c8945a0SNathan Whitehorn 	    if (freopen(device, "r", stdin) == 0)
251*4c8945a0SNathan Whitehorn 		dlg_exiterr("cannot open tty-input");
252*4c8945a0SNathan Whitehorn 	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */
253*4c8945a0SNathan Whitehorn 		(void) dup2(fileno(stdin), 0);
254*4c8945a0SNathan Whitehorn 	}
255*4c8945a0SNathan Whitehorn 	free(device);
256*4c8945a0SNathan Whitehorn     }
257*4c8945a0SNathan Whitehorn 
258*4c8945a0SNathan Whitehorn     /*
259*4c8945a0SNathan Whitehorn      * If stdout is not a tty and dialog is called with the --stdout option, we
260*4c8945a0SNathan Whitehorn      * have to provide for a way to write to the screen.
261*4c8945a0SNathan Whitehorn      *
262*4c8945a0SNathan Whitehorn      * The curses library normally writes its output to stdout, leaving stderr
263*4c8945a0SNathan Whitehorn      * free for scripting.  Scripts are simpler when stdout is redirected.  The
264*4c8945a0SNathan Whitehorn      * newterm function is useful; it allows us to specify where the output
265*4c8945a0SNathan Whitehorn      * goes.  Reopening the terminal is not portable since several
266*4c8945a0SNathan Whitehorn      * configurations do not allow this to work properly:
267*4c8945a0SNathan Whitehorn      *
268*4c8945a0SNathan Whitehorn      * a) some getty implementations (and possibly broken tty drivers, e.g., on
269*4c8945a0SNathan Whitehorn      *    HPUX 10 and 11) cause stdin to act as if it is still in cooked mode
270*4c8945a0SNathan Whitehorn      *    even though results from ioctl's state that it is successfully
271*4c8945a0SNathan Whitehorn      *    altered to raw mode.  Broken is the proper term.
272*4c8945a0SNathan Whitehorn      *
273*4c8945a0SNathan Whitehorn      * b) the user may not have permissions on the device, e.g., if one su's
274*4c8945a0SNathan Whitehorn      *    from the login user to another non-privileged user.
275*4c8945a0SNathan Whitehorn      */
276*4c8945a0SNathan Whitehorn     if (!isatty(fileno(stdout))
277*4c8945a0SNathan Whitehorn 	&& (fileno(stdout) == fileno(output) || dialog_tty())) {
278*4c8945a0SNathan Whitehorn 	if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0
279*4c8945a0SNathan Whitehorn 	    && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {
280*4c8945a0SNathan Whitehorn 	    if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {
281*4c8945a0SNathan Whitehorn 		dlg_exiterr("cannot initialize curses");
282*4c8945a0SNathan Whitehorn 	    }
283*4c8945a0SNathan Whitehorn 	    free(device);
284*4c8945a0SNathan Whitehorn 	} else {
285*4c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-output");
286*4c8945a0SNathan Whitehorn 	}
287*4c8945a0SNathan Whitehorn     } else {
288*4c8945a0SNathan Whitehorn 	dialog_state.screen_output = stdout;
289*4c8945a0SNathan Whitehorn 	(void) initscr();
290*4c8945a0SNathan Whitehorn     }
291*4c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
292*4c8945a0SNathan Whitehorn     /*
293*4c8945a0SNathan Whitehorn      * Cancel xterm's alternate-screen mode.
294*4c8945a0SNathan Whitehorn      */
295*4c8945a0SNathan Whitehorn     if (!dialog_vars.keep_tite
296*4c8945a0SNathan Whitehorn 	&& (dialog_state.screen_output != stdout
297*4c8945a0SNathan Whitehorn 	    || isatty(fileno(dialog_state.screen_output)))
298*4c8945a0SNathan Whitehorn 	&& key_mouse != 0	/* xterm and kindred */
299*4c8945a0SNathan Whitehorn 	&& isprivate(enter_ca_mode)
300*4c8945a0SNathan Whitehorn 	&& isprivate(exit_ca_mode)) {
301*4c8945a0SNathan Whitehorn 	/*
302*4c8945a0SNathan Whitehorn 	 * initscr() or newterm() already did putp(enter_ca_mode) as a side
303*4c8945a0SNathan Whitehorn 	 * effect of initializing the screen.  It would be nice to not even
304*4c8945a0SNathan Whitehorn 	 * do that, but we do not really have access to the correct copy of
305*4c8945a0SNathan Whitehorn 	 * the terminfo description until those functions have been invoked.
306*4c8945a0SNathan Whitehorn 	 */
307*4c8945a0SNathan Whitehorn 	(void) putp(exit_ca_mode);
308*4c8945a0SNathan Whitehorn 	(void) putp(clear_screen);
309*4c8945a0SNathan Whitehorn 	/*
310*4c8945a0SNathan Whitehorn 	 * Prevent ncurses from switching "back" to the normal screen when
311*4c8945a0SNathan Whitehorn 	 * exiting from dialog.  That would move the cursor to the original
312*4c8945a0SNathan Whitehorn 	 * location saved in xterm.  Normally curses sets the cursor position
313*4c8945a0SNathan Whitehorn 	 * to the first line after the display, but the alternate screen
314*4c8945a0SNathan Whitehorn 	 * switching is done after that point.
315*4c8945a0SNathan Whitehorn 	 *
316*4c8945a0SNathan Whitehorn 	 * Cancelling the strings altogether also works around the buggy
317*4c8945a0SNathan Whitehorn 	 * implementation of alternate-screen in rxvt, etc., which clear
318*4c8945a0SNathan Whitehorn 	 * more of the display than they should.
319*4c8945a0SNathan Whitehorn 	 */
320*4c8945a0SNathan Whitehorn 	enter_ca_mode = 0;
321*4c8945a0SNathan Whitehorn 	exit_ca_mode = 0;
322*4c8945a0SNathan Whitehorn     }
323*4c8945a0SNathan Whitehorn #endif
324*4c8945a0SNathan Whitehorn #ifdef HAVE_FLUSHINP
325*4c8945a0SNathan Whitehorn     (void) flushinp();
326*4c8945a0SNathan Whitehorn #endif
327*4c8945a0SNathan Whitehorn     (void) keypad(stdscr, TRUE);
328*4c8945a0SNathan Whitehorn     (void) cbreak();
329*4c8945a0SNathan Whitehorn     (void) noecho();
330*4c8945a0SNathan Whitehorn     mouse_open();
331*4c8945a0SNathan Whitehorn     dialog_state.screen_initialized = TRUE;
332*4c8945a0SNathan Whitehorn 
333*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
334*4c8945a0SNathan Whitehorn     if (dialog_state.use_colors || dialog_state.use_shadow)
335*4c8945a0SNathan Whitehorn 	dlg_color_setup();	/* Set up colors */
336*4c8945a0SNathan Whitehorn #endif
337*4c8945a0SNathan Whitehorn 
338*4c8945a0SNathan Whitehorn     /* Set screen to screen attribute */
339*4c8945a0SNathan Whitehorn     dlg_clear();
340*4c8945a0SNathan Whitehorn }
341*4c8945a0SNathan Whitehorn 
342*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
343*4c8945a0SNathan Whitehorn static int defined_colors = 1;	/* pair-0 is reserved */
344*4c8945a0SNathan Whitehorn /*
345*4c8945a0SNathan Whitehorn  * Setup for color display
346*4c8945a0SNathan Whitehorn  */
347*4c8945a0SNathan Whitehorn void
348*4c8945a0SNathan Whitehorn dlg_color_setup(void)
349*4c8945a0SNathan Whitehorn {
350*4c8945a0SNathan Whitehorn     unsigned i;
351*4c8945a0SNathan Whitehorn 
352*4c8945a0SNathan Whitehorn     if (has_colors()) {		/* Terminal supports color? */
353*4c8945a0SNathan Whitehorn 	(void) start_color();
354*4c8945a0SNathan Whitehorn 
355*4c8945a0SNathan Whitehorn #if defined(HAVE_USE_DEFAULT_COLORS)
356*4c8945a0SNathan Whitehorn 	use_default_colors();
357*4c8945a0SNathan Whitehorn #endif
358*4c8945a0SNathan Whitehorn 
359*4c8945a0SNathan Whitehorn #if defined(__NetBSD__) && defined(_CURSES_)
360*4c8945a0SNathan Whitehorn #define C_ATTR(x,y) (((x) != 0 ? A_BOLD :  0) | COLOR_PAIR((y)))
361*4c8945a0SNathan Whitehorn 	/* work around bug in NetBSD curses */
362*4c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
363*4c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
364*4c8945a0SNathan Whitehorn 
365*4c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
366*4c8945a0SNathan Whitehorn 	    (void) init_pair(i + 1,
367*4c8945a0SNathan Whitehorn 			     dlg_color_table[i].fg,
368*4c8945a0SNathan Whitehorn 			     dlg_color_table[i].bg);
369*4c8945a0SNathan Whitehorn 
370*4c8945a0SNathan Whitehorn 	    /* Setup color attributes */
371*4c8945a0SNathan Whitehorn 	    dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);
372*4c8945a0SNathan Whitehorn 	}
373*4c8945a0SNathan Whitehorn 	defined_colors = i + 1;
374*4c8945a0SNathan Whitehorn #else
375*4c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
376*4c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
377*4c8945a0SNathan Whitehorn 
378*4c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
379*4c8945a0SNathan Whitehorn 	    chtype color = dlg_color_pair(dlg_color_table[i].fg,
380*4c8945a0SNathan Whitehorn 					  dlg_color_table[i].bg);
381*4c8945a0SNathan Whitehorn 
382*4c8945a0SNathan Whitehorn 	    /* Setup color attributes */
383*4c8945a0SNathan Whitehorn 	    dlg_color_table[i].atr = ((dlg_color_table[i].hilite
384*4c8945a0SNathan Whitehorn 				       ? A_BOLD
385*4c8945a0SNathan Whitehorn 				       : 0)
386*4c8945a0SNathan Whitehorn 				      | color);
387*4c8945a0SNathan Whitehorn 	}
388*4c8945a0SNathan Whitehorn #endif
389*4c8945a0SNathan Whitehorn     } else {
390*4c8945a0SNathan Whitehorn 	dialog_state.use_colors = FALSE;
391*4c8945a0SNathan Whitehorn 	dialog_state.use_shadow = FALSE;
392*4c8945a0SNathan Whitehorn     }
393*4c8945a0SNathan Whitehorn }
394*4c8945a0SNathan Whitehorn 
395*4c8945a0SNathan Whitehorn int
396*4c8945a0SNathan Whitehorn dlg_color_count(void)
397*4c8945a0SNathan Whitehorn {
398*4c8945a0SNathan Whitehorn     return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]);
399*4c8945a0SNathan Whitehorn }
400*4c8945a0SNathan Whitehorn 
401*4c8945a0SNathan Whitehorn /*
402*4c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
403*4c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
404*4c8945a0SNathan Whitehorn  * window's defined background.
405*4c8945a0SNathan Whitehorn  */
406*4c8945a0SNathan Whitehorn chtype
407*4c8945a0SNathan Whitehorn dlg_color_pair(int foreground, int background)
408*4c8945a0SNathan Whitehorn {
409*4c8945a0SNathan Whitehorn     chtype result = 0;
410*4c8945a0SNathan Whitehorn     int pair;
411*4c8945a0SNathan Whitehorn     short fg, bg;
412*4c8945a0SNathan Whitehorn     bool found = FALSE;
413*4c8945a0SNathan Whitehorn 
414*4c8945a0SNathan Whitehorn     for (pair = 1; pair < defined_colors; ++pair) {
415*4c8945a0SNathan Whitehorn 	if (pair_content((short) pair, &fg, &bg) != ERR
416*4c8945a0SNathan Whitehorn 	    && fg == foreground
417*4c8945a0SNathan Whitehorn 	    && bg == background) {
418*4c8945a0SNathan Whitehorn 	    result = (chtype) COLOR_PAIR(pair);
419*4c8945a0SNathan Whitehorn 	    found = TRUE;
420*4c8945a0SNathan Whitehorn 	    break;
421*4c8945a0SNathan Whitehorn 	}
422*4c8945a0SNathan Whitehorn     }
423*4c8945a0SNathan Whitehorn     if (!found && (defined_colors + 1) < COLOR_PAIRS) {
424*4c8945a0SNathan Whitehorn 	pair = defined_colors++;
425*4c8945a0SNathan Whitehorn 	(void) init_pair((short) pair, (short) foreground, (short) background);
426*4c8945a0SNathan Whitehorn 	result = (chtype) COLOR_PAIR(pair);
427*4c8945a0SNathan Whitehorn     }
428*4c8945a0SNathan Whitehorn     return result;
429*4c8945a0SNathan Whitehorn }
430*4c8945a0SNathan Whitehorn 
431*4c8945a0SNathan Whitehorn /*
432*4c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
433*4c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
434*4c8945a0SNathan Whitehorn  * window's defined background.
435*4c8945a0SNathan Whitehorn  */
436*4c8945a0SNathan Whitehorn static chtype
437*4c8945a0SNathan Whitehorn define_color(WINDOW *win, int foreground)
438*4c8945a0SNathan Whitehorn {
439*4c8945a0SNathan Whitehorn     chtype attrs = getattrs(win);
440*4c8945a0SNathan Whitehorn     int pair;
441*4c8945a0SNathan Whitehorn     short fg, bg, background;
442*4c8945a0SNathan Whitehorn 
443*4c8945a0SNathan Whitehorn     if ((pair = PAIR_NUMBER(attrs)) != 0
444*4c8945a0SNathan Whitehorn 	&& pair_content((short) pair, &fg, &bg) != ERR) {
445*4c8945a0SNathan Whitehorn 	background = bg;
446*4c8945a0SNathan Whitehorn     } else {
447*4c8945a0SNathan Whitehorn 	background = COLOR_BLACK;
448*4c8945a0SNathan Whitehorn     }
449*4c8945a0SNathan Whitehorn     return dlg_color_pair(foreground, background);
450*4c8945a0SNathan Whitehorn }
451*4c8945a0SNathan Whitehorn #endif
452*4c8945a0SNathan Whitehorn 
453*4c8945a0SNathan Whitehorn /*
454*4c8945a0SNathan Whitehorn  * End using dialog functions.
455*4c8945a0SNathan Whitehorn  */
456*4c8945a0SNathan Whitehorn void
457*4c8945a0SNathan Whitehorn end_dialog(void)
458*4c8945a0SNathan Whitehorn {
459*4c8945a0SNathan Whitehorn     if (dialog_state.screen_initialized) {
460*4c8945a0SNathan Whitehorn 	dialog_state.screen_initialized = FALSE;
461*4c8945a0SNathan Whitehorn 	mouse_close();
462*4c8945a0SNathan Whitehorn 	(void) endwin();
463*4c8945a0SNathan Whitehorn 	(void) fflush(stdout);
464*4c8945a0SNathan Whitehorn     }
465*4c8945a0SNathan Whitehorn }
466*4c8945a0SNathan Whitehorn 
467*4c8945a0SNathan Whitehorn #define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))
468*4c8945a0SNathan Whitehorn 
469*4c8945a0SNathan Whitehorn static int
470*4c8945a0SNathan Whitehorn centered(int width, const char *string)
471*4c8945a0SNathan Whitehorn {
472*4c8945a0SNathan Whitehorn     int len = dlg_count_columns(string);
473*4c8945a0SNathan Whitehorn     int left;
474*4c8945a0SNathan Whitehorn     int hide = 0;
475*4c8945a0SNathan Whitehorn     int n;
476*4c8945a0SNathan Whitehorn 
477*4c8945a0SNathan Whitehorn     if (dialog_vars.colors) {
478*4c8945a0SNathan Whitehorn 	for (n = 0; n < len; ++n) {
479*4c8945a0SNathan Whitehorn 	    if (isOurEscape(string + n)) {
480*4c8945a0SNathan Whitehorn 		hide += 3;
481*4c8945a0SNathan Whitehorn 	    }
482*4c8945a0SNathan Whitehorn 	}
483*4c8945a0SNathan Whitehorn     }
484*4c8945a0SNathan Whitehorn     left = (width - (len - hide)) / 2 - 1;
485*4c8945a0SNathan Whitehorn     if (left < 0)
486*4c8945a0SNathan Whitehorn 	left = 0;
487*4c8945a0SNathan Whitehorn     return left;
488*4c8945a0SNathan Whitehorn }
489*4c8945a0SNathan Whitehorn 
490*4c8945a0SNathan Whitehorn /*
491*4c8945a0SNathan Whitehorn  * Print up to 'cols' columns from 'text', optionally rendering our escape
492*4c8945a0SNathan Whitehorn  * sequence for attributes and color.
493*4c8945a0SNathan Whitehorn  */
494*4c8945a0SNathan Whitehorn void
495*4c8945a0SNathan Whitehorn dlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr)
496*4c8945a0SNathan Whitehorn {
497*4c8945a0SNathan Whitehorn     int y_origin, x_origin;
498*4c8945a0SNathan Whitehorn     int y_before, x_before = 0;
499*4c8945a0SNathan Whitehorn     int y_after, x_after;
500*4c8945a0SNathan Whitehorn     int tabbed = 0;
501*4c8945a0SNathan Whitehorn     bool thisTab;
502*4c8945a0SNathan Whitehorn     bool ended = FALSE;
503*4c8945a0SNathan Whitehorn     chtype useattr;
504*4c8945a0SNathan Whitehorn 
505*4c8945a0SNathan Whitehorn     getyx(win, y_origin, x_origin);
506*4c8945a0SNathan Whitehorn     while (cols > 0 && (*txt != '\0')) {
507*4c8945a0SNathan Whitehorn 	if (dialog_vars.colors) {
508*4c8945a0SNathan Whitehorn 	    while (isOurEscape(txt)) {
509*4c8945a0SNathan Whitehorn 		int code;
510*4c8945a0SNathan Whitehorn 
511*4c8945a0SNathan Whitehorn 		txt += 2;
512*4c8945a0SNathan Whitehorn 		switch (code = CharOf(*txt)) {
513*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
514*4c8945a0SNathan Whitehorn 		case '0':
515*4c8945a0SNathan Whitehorn 		case '1':
516*4c8945a0SNathan Whitehorn 		case '2':
517*4c8945a0SNathan Whitehorn 		case '3':
518*4c8945a0SNathan Whitehorn 		case '4':
519*4c8945a0SNathan Whitehorn 		case '5':
520*4c8945a0SNathan Whitehorn 		case '6':
521*4c8945a0SNathan Whitehorn 		case '7':
522*4c8945a0SNathan Whitehorn 		    *attr &= ~A_COLOR;
523*4c8945a0SNathan Whitehorn 		    *attr |= define_color(win, code - '0');
524*4c8945a0SNathan Whitehorn 		    break;
525*4c8945a0SNathan Whitehorn #endif
526*4c8945a0SNathan Whitehorn 		case 'B':
527*4c8945a0SNathan Whitehorn 		    *attr &= ~A_BOLD;
528*4c8945a0SNathan Whitehorn 		    break;
529*4c8945a0SNathan Whitehorn 		case 'b':
530*4c8945a0SNathan Whitehorn 		    *attr |= A_BOLD;
531*4c8945a0SNathan Whitehorn 		    break;
532*4c8945a0SNathan Whitehorn 		case 'R':
533*4c8945a0SNathan Whitehorn 		    *attr &= ~A_REVERSE;
534*4c8945a0SNathan Whitehorn 		    break;
535*4c8945a0SNathan Whitehorn 		case 'r':
536*4c8945a0SNathan Whitehorn 		    *attr |= A_REVERSE;
537*4c8945a0SNathan Whitehorn 		    break;
538*4c8945a0SNathan Whitehorn 		case 'U':
539*4c8945a0SNathan Whitehorn 		    *attr &= ~A_UNDERLINE;
540*4c8945a0SNathan Whitehorn 		    break;
541*4c8945a0SNathan Whitehorn 		case 'u':
542*4c8945a0SNathan Whitehorn 		    *attr |= A_UNDERLINE;
543*4c8945a0SNathan Whitehorn 		    break;
544*4c8945a0SNathan Whitehorn 		case 'n':
545*4c8945a0SNathan Whitehorn 		    *attr = A_NORMAL;
546*4c8945a0SNathan Whitehorn 		    break;
547*4c8945a0SNathan Whitehorn 		}
548*4c8945a0SNathan Whitehorn 		++txt;
549*4c8945a0SNathan Whitehorn 	    }
550*4c8945a0SNathan Whitehorn 	}
551*4c8945a0SNathan Whitehorn 	if (ended || *txt == '\n' || *txt == '\0')
552*4c8945a0SNathan Whitehorn 	    break;
553*4c8945a0SNathan Whitehorn 	useattr = (*attr) & A_ATTRIBUTES;
554*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
555*4c8945a0SNathan Whitehorn 	/*
556*4c8945a0SNathan Whitehorn 	 * Prevent this from making text invisible when the foreground and
557*4c8945a0SNathan Whitehorn 	 * background colors happen to be the same, and there's no bold
558*4c8945a0SNathan Whitehorn 	 * attribute.
559*4c8945a0SNathan Whitehorn 	 */
560*4c8945a0SNathan Whitehorn 	if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) {
561*4c8945a0SNathan Whitehorn 	    short pair = (short) PAIR_NUMBER(useattr);
562*4c8945a0SNathan Whitehorn 	    short fg, bg;
563*4c8945a0SNathan Whitehorn 	    if (pair_content(pair, &fg, &bg) != ERR
564*4c8945a0SNathan Whitehorn 		&& fg == bg) {
565*4c8945a0SNathan Whitehorn 		useattr &= ~A_COLOR;
566*4c8945a0SNathan Whitehorn 		useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK)
567*4c8945a0SNathan Whitehorn 					       ? COLOR_WHITE
568*4c8945a0SNathan Whitehorn 					       : COLOR_BLACK));
569*4c8945a0SNathan Whitehorn 	    }
570*4c8945a0SNathan Whitehorn 	}
571*4c8945a0SNathan Whitehorn #endif
572*4c8945a0SNathan Whitehorn 	/*
573*4c8945a0SNathan Whitehorn 	 * Write the character, using curses to tell exactly how wide it
574*4c8945a0SNathan Whitehorn 	 * is.  If it is a tab, discount that, since the caller thinks
575*4c8945a0SNathan Whitehorn 	 * tabs are nonprinting, and curses will expand tabs to one or
576*4c8945a0SNathan Whitehorn 	 * more blanks.
577*4c8945a0SNathan Whitehorn 	 */
578*4c8945a0SNathan Whitehorn 	thisTab = (CharOf(*txt) == TAB);
579*4c8945a0SNathan Whitehorn 	if (thisTab)
580*4c8945a0SNathan Whitehorn 	    getyx(win, y_before, x_before);
581*4c8945a0SNathan Whitehorn 	(void) waddch(win, CharOf(*txt++) | useattr);
582*4c8945a0SNathan Whitehorn 	getyx(win, y_after, x_after);
583*4c8945a0SNathan Whitehorn 	if (thisTab && (y_after == y_origin))
584*4c8945a0SNathan Whitehorn 	    tabbed += (x_after - x_before);
585*4c8945a0SNathan Whitehorn 	if (y_after != y_origin || x_after >= cols + tabbed + x_origin) {
586*4c8945a0SNathan Whitehorn 	    ended = TRUE;
587*4c8945a0SNathan Whitehorn 	}
588*4c8945a0SNathan Whitehorn     }
589*4c8945a0SNathan Whitehorn }
590*4c8945a0SNathan Whitehorn 
591*4c8945a0SNathan Whitehorn /*
592*4c8945a0SNathan Whitehorn  * Print one line of the prompt in the window within the limits of the
593*4c8945a0SNathan Whitehorn  * specified right margin.  The line will end on a word boundary and a pointer
594*4c8945a0SNathan Whitehorn  * to the start of the next line is returned, or a NULL pointer if the end of
595*4c8945a0SNathan Whitehorn  * *prompt is reached.
596*4c8945a0SNathan Whitehorn  */
597*4c8945a0SNathan Whitehorn const char *
598*4c8945a0SNathan Whitehorn dlg_print_line(WINDOW *win,
599*4c8945a0SNathan Whitehorn 	       chtype *attr,
600*4c8945a0SNathan Whitehorn 	       const char *prompt,
601*4c8945a0SNathan Whitehorn 	       int lm, int rm, int *x)
602*4c8945a0SNathan Whitehorn {
603*4c8945a0SNathan Whitehorn     const char *wrap_ptr = prompt;
604*4c8945a0SNathan Whitehorn     const char *test_ptr = prompt;
605*4c8945a0SNathan Whitehorn     const int *cols = dlg_index_columns(prompt);
606*4c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(prompt);
607*4c8945a0SNathan Whitehorn     int wrap_inx = 0;
608*4c8945a0SNathan Whitehorn     int test_inx = 0;
609*4c8945a0SNathan Whitehorn     int cur_x = lm;
610*4c8945a0SNathan Whitehorn     int hidden = 0;
611*4c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(prompt);
612*4c8945a0SNathan Whitehorn     int n;
613*4c8945a0SNathan Whitehorn     int tabbed = 0;
614*4c8945a0SNathan Whitehorn 
615*4c8945a0SNathan Whitehorn     *x = 1;
616*4c8945a0SNathan Whitehorn 
617*4c8945a0SNathan Whitehorn     /*
618*4c8945a0SNathan Whitehorn      * Set *test_ptr to the end of the line or the right margin (rm), whichever
619*4c8945a0SNathan Whitehorn      * is less, and set wrap_ptr to the end of the last word in the line.
620*4c8945a0SNathan Whitehorn      */
621*4c8945a0SNathan Whitehorn     for (n = 0; n < limit; ++n) {
622*4c8945a0SNathan Whitehorn 	test_ptr = prompt + indx[test_inx];
623*4c8945a0SNathan Whitehorn 	if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden))
624*4c8945a0SNathan Whitehorn 	    break;
625*4c8945a0SNathan Whitehorn 	if (*test_ptr == TAB && n == 0) {
626*4c8945a0SNathan Whitehorn 	    tabbed = 8;		/* workaround for leading tabs */
627*4c8945a0SNathan Whitehorn 	} else if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') {
628*4c8945a0SNathan Whitehorn 	    wrap_inx = n;
629*4c8945a0SNathan Whitehorn 	    *x = cur_x;
630*4c8945a0SNathan Whitehorn 	} else if (isOurEscape(test_ptr)) {
631*4c8945a0SNathan Whitehorn 	    hidden += 3;
632*4c8945a0SNathan Whitehorn 	    n += 2;
633*4c8945a0SNathan Whitehorn 	}
634*4c8945a0SNathan Whitehorn 	cur_x = lm + tabbed + cols[n + 1];
635*4c8945a0SNathan Whitehorn 	if (cur_x > (rm + hidden))
636*4c8945a0SNathan Whitehorn 	    break;
637*4c8945a0SNathan Whitehorn 	test_inx = n + 1;
638*4c8945a0SNathan Whitehorn     }
639*4c8945a0SNathan Whitehorn 
640*4c8945a0SNathan Whitehorn     /*
641*4c8945a0SNathan Whitehorn      * If the line doesn't reach the right margin in the middle of a word, then
642*4c8945a0SNathan Whitehorn      * we don't have to wrap it at the end of the previous word.
643*4c8945a0SNathan Whitehorn      */
644*4c8945a0SNathan Whitehorn     test_ptr = prompt + indx[test_inx];
645*4c8945a0SNathan Whitehorn     if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') {
646*4c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
647*4c8945a0SNathan Whitehorn 	while (wrap_inx > 0 && prompt[indx[wrap_inx - 1]] == ' ') {
648*4c8945a0SNathan Whitehorn 	    wrap_inx--;
649*4c8945a0SNathan Whitehorn 	}
650*4c8945a0SNathan Whitehorn 	*x = lm + indx[wrap_inx];
651*4c8945a0SNathan Whitehorn     } else if (*x == 1 && cur_x >= rm) {
652*4c8945a0SNathan Whitehorn 	/*
653*4c8945a0SNathan Whitehorn 	 * If the line has no spaces, then wrap it anyway at the right margin
654*4c8945a0SNathan Whitehorn 	 */
655*4c8945a0SNathan Whitehorn 	*x = rm;
656*4c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
657*4c8945a0SNathan Whitehorn     }
658*4c8945a0SNathan Whitehorn     wrap_ptr = prompt + indx[wrap_inx];
659*4c8945a0SNathan Whitehorn 
660*4c8945a0SNathan Whitehorn     /*
661*4c8945a0SNathan Whitehorn      * Print the line if we have a window pointer.  Otherwise this routine
662*4c8945a0SNathan Whitehorn      * is just being called for sizing the window.
663*4c8945a0SNathan Whitehorn      */
664*4c8945a0SNathan Whitehorn     if (win) {
665*4c8945a0SNathan Whitehorn 	dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr);
666*4c8945a0SNathan Whitehorn     }
667*4c8945a0SNathan Whitehorn 
668*4c8945a0SNathan Whitehorn     /* *x tells the calling function how long the line was */
669*4c8945a0SNathan Whitehorn     if (*x == 1)
670*4c8945a0SNathan Whitehorn 	*x = rm;
671*4c8945a0SNathan Whitehorn 
672*4c8945a0SNathan Whitehorn     /* Find the start of the next line and return a pointer to it */
673*4c8945a0SNathan Whitehorn     test_ptr = wrap_ptr;
674*4c8945a0SNathan Whitehorn     while (*test_ptr == ' ')
675*4c8945a0SNathan Whitehorn 	test_ptr++;
676*4c8945a0SNathan Whitehorn     if (*test_ptr == '\n')
677*4c8945a0SNathan Whitehorn 	test_ptr++;
678*4c8945a0SNathan Whitehorn     return (test_ptr);
679*4c8945a0SNathan Whitehorn }
680*4c8945a0SNathan Whitehorn 
681*4c8945a0SNathan Whitehorn static void
682*4c8945a0SNathan Whitehorn justify_text(WINDOW *win,
683*4c8945a0SNathan Whitehorn 	     const char *prompt,
684*4c8945a0SNathan Whitehorn 	     int limit_y,
685*4c8945a0SNathan Whitehorn 	     int limit_x,
686*4c8945a0SNathan Whitehorn 	     int *high, int *wide)
687*4c8945a0SNathan Whitehorn {
688*4c8945a0SNathan Whitehorn     chtype attr = A_NORMAL;
689*4c8945a0SNathan Whitehorn     int x = (2 * MARGIN);
690*4c8945a0SNathan Whitehorn     int y = MARGIN;
691*4c8945a0SNathan Whitehorn     int max_x = 2;
692*4c8945a0SNathan Whitehorn     int lm = (2 * MARGIN);	/* left margin (box-border plus a space) */
693*4c8945a0SNathan Whitehorn     int rm = limit_x;		/* right margin */
694*4c8945a0SNathan Whitehorn     int bm = limit_y;		/* bottom margin */
695*4c8945a0SNathan Whitehorn     int last_y = 0, last_x = 0;
696*4c8945a0SNathan Whitehorn 
697*4c8945a0SNathan Whitehorn     if (win) {
698*4c8945a0SNathan Whitehorn 	rm -= (2 * MARGIN);
699*4c8945a0SNathan Whitehorn 	bm -= (2 * MARGIN);
700*4c8945a0SNathan Whitehorn     }
701*4c8945a0SNathan Whitehorn     if (prompt == 0)
702*4c8945a0SNathan Whitehorn 	prompt = "";
703*4c8945a0SNathan Whitehorn 
704*4c8945a0SNathan Whitehorn     if (win != 0)
705*4c8945a0SNathan Whitehorn 	getyx(win, last_y, last_x);
706*4c8945a0SNathan Whitehorn     while (y <= bm && *prompt) {
707*4c8945a0SNathan Whitehorn 	x = lm;
708*4c8945a0SNathan Whitehorn 
709*4c8945a0SNathan Whitehorn 	if (*prompt == '\n') {
710*4c8945a0SNathan Whitehorn 	    while (*prompt == '\n' && y < bm) {
711*4c8945a0SNathan Whitehorn 		if (*(prompt + 1) != '\0') {
712*4c8945a0SNathan Whitehorn 		    ++y;
713*4c8945a0SNathan Whitehorn 		    if (win != 0)
714*4c8945a0SNathan Whitehorn 			(void) wmove(win, y, lm);
715*4c8945a0SNathan Whitehorn 		}
716*4c8945a0SNathan Whitehorn 		prompt++;
717*4c8945a0SNathan Whitehorn 	    }
718*4c8945a0SNathan Whitehorn 	} else if (win != 0)
719*4c8945a0SNathan Whitehorn 	    (void) wmove(win, y, lm);
720*4c8945a0SNathan Whitehorn 
721*4c8945a0SNathan Whitehorn 	if (*prompt) {
722*4c8945a0SNathan Whitehorn 	    prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x);
723*4c8945a0SNathan Whitehorn 	    if (win != 0)
724*4c8945a0SNathan Whitehorn 		getyx(win, last_y, last_x);
725*4c8945a0SNathan Whitehorn 	}
726*4c8945a0SNathan Whitehorn 	if (*prompt) {
727*4c8945a0SNathan Whitehorn 	    ++y;
728*4c8945a0SNathan Whitehorn 	    if (win != 0)
729*4c8945a0SNathan Whitehorn 		(void) wmove(win, y, lm);
730*4c8945a0SNathan Whitehorn 	}
731*4c8945a0SNathan Whitehorn 	max_x = MAX(max_x, x);
732*4c8945a0SNathan Whitehorn     }
733*4c8945a0SNathan Whitehorn     /* Move back to the last position after drawing prompt, for msgbox. */
734*4c8945a0SNathan Whitehorn     if (win != 0)
735*4c8945a0SNathan Whitehorn 	(void) wmove(win, last_y, last_x);
736*4c8945a0SNathan Whitehorn 
737*4c8945a0SNathan Whitehorn     /* Set the final height and width for the calling function */
738*4c8945a0SNathan Whitehorn     if (high != 0)
739*4c8945a0SNathan Whitehorn 	*high = y;
740*4c8945a0SNathan Whitehorn     if (wide != 0)
741*4c8945a0SNathan Whitehorn 	*wide = max_x;
742*4c8945a0SNathan Whitehorn }
743*4c8945a0SNathan Whitehorn 
744*4c8945a0SNathan Whitehorn /*
745*4c8945a0SNathan Whitehorn  * Print a string of text in a window, automatically wrap around to the next
746*4c8945a0SNathan Whitehorn  * line if the string is too long to fit on one line.  Note that the string may
747*4c8945a0SNathan Whitehorn  * contain embedded newlines.
748*4c8945a0SNathan Whitehorn  */
749*4c8945a0SNathan Whitehorn void
750*4c8945a0SNathan Whitehorn dlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width)
751*4c8945a0SNathan Whitehorn {
752*4c8945a0SNathan Whitehorn     justify_text(win, prompt,
753*4c8945a0SNathan Whitehorn 		 height,
754*4c8945a0SNathan Whitehorn 		 width,
755*4c8945a0SNathan Whitehorn 		 (int *) 0, (int *) 0);
756*4c8945a0SNathan Whitehorn }
757*4c8945a0SNathan Whitehorn 
758*4c8945a0SNathan Whitehorn /*
759*4c8945a0SNathan Whitehorn  * Display the message in a scrollable window.  Actually the way it works is
760*4c8945a0SNathan Whitehorn  * that we create a "tall" window of the proper width, let the text wrap within
761*4c8945a0SNathan Whitehorn  * that, and copy a slice of the result to the dialog.
762*4c8945a0SNathan Whitehorn  *
763*4c8945a0SNathan Whitehorn  * It works for ncurses.  Other curses implementations show only blanks (Tru64)
764*4c8945a0SNathan Whitehorn  * or garbage (NetBSD).
765*4c8945a0SNathan Whitehorn  */
766*4c8945a0SNathan Whitehorn int
767*4c8945a0SNathan Whitehorn dlg_print_scrolled(WINDOW *win,
768*4c8945a0SNathan Whitehorn 		   const char *prompt,
769*4c8945a0SNathan Whitehorn 		   int offset,
770*4c8945a0SNathan Whitehorn 		   int height,
771*4c8945a0SNathan Whitehorn 		   int width,
772*4c8945a0SNathan Whitehorn 		   int pauseopt)
773*4c8945a0SNathan Whitehorn {
774*4c8945a0SNathan Whitehorn     int oldy, oldx;
775*4c8945a0SNathan Whitehorn     int last = 0;
776*4c8945a0SNathan Whitehorn 
777*4c8945a0SNathan Whitehorn     getyx(win, oldy, oldx);
778*4c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
779*4c8945a0SNathan Whitehorn     if (pauseopt) {
780*4c8945a0SNathan Whitehorn 	int wide = width - (2 * MARGIN);
781*4c8945a0SNathan Whitehorn 	int high = LINES;
782*4c8945a0SNathan Whitehorn 	int y, x;
783*4c8945a0SNathan Whitehorn 	int len;
784*4c8945a0SNathan Whitehorn 	int percent;
785*4c8945a0SNathan Whitehorn 	WINDOW *dummy;
786*4c8945a0SNathan Whitehorn 	char buffer[5];
787*4c8945a0SNathan Whitehorn 
788*4c8945a0SNathan Whitehorn #if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417
789*4c8945a0SNathan Whitehorn 	/*
790*4c8945a0SNathan Whitehorn 	 * If we're not limited by the screensize, allow text to possibly be
791*4c8945a0SNathan Whitehorn 	 * one character per line.
792*4c8945a0SNathan Whitehorn 	 */
793*4c8945a0SNathan Whitehorn 	if ((len = dlg_count_columns(prompt)) > high)
794*4c8945a0SNathan Whitehorn 	    high = len;
795*4c8945a0SNathan Whitehorn #endif
796*4c8945a0SNathan Whitehorn 	dummy = newwin(high, width, 0, 0);
797*4c8945a0SNathan Whitehorn 	wbkgdset(dummy, dialog_attr | ' ');
798*4c8945a0SNathan Whitehorn 	wattrset(dummy, dialog_attr);
799*4c8945a0SNathan Whitehorn 	werase(dummy);
800*4c8945a0SNathan Whitehorn 	dlg_print_autowrap(dummy, prompt, high, width);
801*4c8945a0SNathan Whitehorn 	getyx(dummy, y, x);
802*4c8945a0SNathan Whitehorn 
803*4c8945a0SNathan Whitehorn 	copywin(dummy,		/* srcwin */
804*4c8945a0SNathan Whitehorn 		win,		/* dstwin */
805*4c8945a0SNathan Whitehorn 		offset + MARGIN,	/* sminrow */
806*4c8945a0SNathan Whitehorn 		MARGIN,		/* smincol */
807*4c8945a0SNathan Whitehorn 		MARGIN,		/* dminrow */
808*4c8945a0SNathan Whitehorn 		MARGIN,		/* dmincol */
809*4c8945a0SNathan Whitehorn 		height,		/* dmaxrow */
810*4c8945a0SNathan Whitehorn 		wide,		/* dmaxcol */
811*4c8945a0SNathan Whitehorn 		FALSE);
812*4c8945a0SNathan Whitehorn 
813*4c8945a0SNathan Whitehorn 	delwin(dummy);
814*4c8945a0SNathan Whitehorn 
815*4c8945a0SNathan Whitehorn 	/* if the text is incomplete, or we have scrolled, show the percentage */
816*4c8945a0SNathan Whitehorn 	if (y > 0 && wide > 4) {
817*4c8945a0SNathan Whitehorn 	    percent = (int) ((height + offset) * 100.0 / y);
818*4c8945a0SNathan Whitehorn 	    if (percent < 0)
819*4c8945a0SNathan Whitehorn 		percent = 0;
820*4c8945a0SNathan Whitehorn 	    if (percent > 100)
821*4c8945a0SNathan Whitehorn 		percent = 100;
822*4c8945a0SNathan Whitehorn 	    if (offset != 0 || percent != 100) {
823*4c8945a0SNathan Whitehorn 		(void) wattrset(win, position_indicator_attr);
824*4c8945a0SNathan Whitehorn 		(void) wmove(win, MARGIN + height, wide - 4);
825*4c8945a0SNathan Whitehorn 		(void) sprintf(buffer, "%d%%", percent);
826*4c8945a0SNathan Whitehorn 		(void) waddstr(win, buffer);
827*4c8945a0SNathan Whitehorn 		if ((len = (int) strlen(buffer)) < 4) {
828*4c8945a0SNathan Whitehorn 		    wattrset(win, border_attr);
829*4c8945a0SNathan Whitehorn 		    whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
830*4c8945a0SNathan Whitehorn 		}
831*4c8945a0SNathan Whitehorn 	    }
832*4c8945a0SNathan Whitehorn 	}
833*4c8945a0SNathan Whitehorn 	last = (y - height);
834*4c8945a0SNathan Whitehorn     } else
835*4c8945a0SNathan Whitehorn #endif
836*4c8945a0SNathan Whitehorn     {
837*4c8945a0SNathan Whitehorn 	(void) offset;
838*4c8945a0SNathan Whitehorn 	wattrset(win, dialog_attr);
839*4c8945a0SNathan Whitehorn 	dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
840*4c8945a0SNathan Whitehorn 	last = 0;
841*4c8945a0SNathan Whitehorn     }
842*4c8945a0SNathan Whitehorn     wmove(win, oldy, oldx);
843*4c8945a0SNathan Whitehorn     return last;
844*4c8945a0SNathan Whitehorn }
845*4c8945a0SNathan Whitehorn 
846*4c8945a0SNathan Whitehorn int
847*4c8945a0SNathan Whitehorn dlg_check_scrolled(int key, int last, int page, bool * show, int *offset)
848*4c8945a0SNathan Whitehorn {
849*4c8945a0SNathan Whitehorn     int code = 0;
850*4c8945a0SNathan Whitehorn 
851*4c8945a0SNathan Whitehorn     *show = FALSE;
852*4c8945a0SNathan Whitehorn 
853*4c8945a0SNathan Whitehorn     switch (key) {
854*4c8945a0SNathan Whitehorn     case DLGK_PAGE_FIRST:
855*4c8945a0SNathan Whitehorn 	if (*offset > 0) {
856*4c8945a0SNathan Whitehorn 	    *offset = 0;
857*4c8945a0SNathan Whitehorn 	    *show = TRUE;
858*4c8945a0SNathan Whitehorn 	}
859*4c8945a0SNathan Whitehorn 	break;
860*4c8945a0SNathan Whitehorn     case DLGK_PAGE_LAST:
861*4c8945a0SNathan Whitehorn 	if (*offset < last) {
862*4c8945a0SNathan Whitehorn 	    *offset = last;
863*4c8945a0SNathan Whitehorn 	    *show = TRUE;
864*4c8945a0SNathan Whitehorn 	}
865*4c8945a0SNathan Whitehorn 	break;
866*4c8945a0SNathan Whitehorn     case DLGK_GRID_UP:
867*4c8945a0SNathan Whitehorn 	if (*offset > 0) {
868*4c8945a0SNathan Whitehorn 	    --(*offset);
869*4c8945a0SNathan Whitehorn 	    *show = TRUE;
870*4c8945a0SNathan Whitehorn 	}
871*4c8945a0SNathan Whitehorn 	break;
872*4c8945a0SNathan Whitehorn     case DLGK_GRID_DOWN:
873*4c8945a0SNathan Whitehorn 	if (*offset < last) {
874*4c8945a0SNathan Whitehorn 	    ++(*offset);
875*4c8945a0SNathan Whitehorn 	    *show = TRUE;
876*4c8945a0SNathan Whitehorn 	}
877*4c8945a0SNathan Whitehorn 	break;
878*4c8945a0SNathan Whitehorn     case DLGK_PAGE_PREV:
879*4c8945a0SNathan Whitehorn 	if (*offset > 0) {
880*4c8945a0SNathan Whitehorn 	    *offset -= page;
881*4c8945a0SNathan Whitehorn 	    if (*offset < 0)
882*4c8945a0SNathan Whitehorn 		*offset = 0;
883*4c8945a0SNathan Whitehorn 	    *show = TRUE;
884*4c8945a0SNathan Whitehorn 	}
885*4c8945a0SNathan Whitehorn 	break;
886*4c8945a0SNathan Whitehorn     case DLGK_PAGE_NEXT:
887*4c8945a0SNathan Whitehorn 	if (*offset < last) {
888*4c8945a0SNathan Whitehorn 	    *offset += page;
889*4c8945a0SNathan Whitehorn 	    if (*offset > last)
890*4c8945a0SNathan Whitehorn 		*offset = last;
891*4c8945a0SNathan Whitehorn 	    *show = TRUE;
892*4c8945a0SNathan Whitehorn 	}
893*4c8945a0SNathan Whitehorn 	break;
894*4c8945a0SNathan Whitehorn     default:
895*4c8945a0SNathan Whitehorn 	code = -1;
896*4c8945a0SNathan Whitehorn 	break;
897*4c8945a0SNathan Whitehorn     }
898*4c8945a0SNathan Whitehorn     return code;
899*4c8945a0SNathan Whitehorn }
900*4c8945a0SNathan Whitehorn 
901*4c8945a0SNathan Whitehorn /*
902*4c8945a0SNathan Whitehorn  * Calculate the window size for preformatted text.  This will calculate box
903*4c8945a0SNathan Whitehorn  * dimensions that are at or close to the specified aspect ratio for the prompt
904*4c8945a0SNathan Whitehorn  * string with all spaces and newlines preserved and additional newlines added
905*4c8945a0SNathan Whitehorn  * as necessary.
906*4c8945a0SNathan Whitehorn  */
907*4c8945a0SNathan Whitehorn static void
908*4c8945a0SNathan Whitehorn auto_size_preformatted(const char *prompt, int *height, int *width)
909*4c8945a0SNathan Whitehorn {
910*4c8945a0SNathan Whitehorn     int high = 0, wide = 0;
911*4c8945a0SNathan Whitehorn     float car;			/* Calculated Aspect Ratio */
912*4c8945a0SNathan Whitehorn     float diff;
913*4c8945a0SNathan Whitehorn     int max_y = SLINES - 1;
914*4c8945a0SNathan Whitehorn     int max_x = SCOLS - 2;
915*4c8945a0SNathan Whitehorn     int max_width = max_x;
916*4c8945a0SNathan Whitehorn     int ar = dialog_state.aspect_ratio;
917*4c8945a0SNathan Whitehorn 
918*4c8945a0SNathan Whitehorn     /* Get the initial dimensions */
919*4c8945a0SNathan Whitehorn     justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
920*4c8945a0SNathan Whitehorn     car = (float) (wide / high);
921*4c8945a0SNathan Whitehorn 
922*4c8945a0SNathan Whitehorn     /*
923*4c8945a0SNathan Whitehorn      * If the aspect ratio is greater than it should be, then decrease the
924*4c8945a0SNathan Whitehorn      * width proportionately.
925*4c8945a0SNathan Whitehorn      */
926*4c8945a0SNathan Whitehorn     if (car > ar) {
927*4c8945a0SNathan Whitehorn 	diff = car / (float) ar;
928*4c8945a0SNathan Whitehorn 	max_x = (int) ((float) wide / diff + 4);
929*4c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
930*4c8945a0SNathan Whitehorn 	car = (float) wide / (float) high;
931*4c8945a0SNathan Whitehorn     }
932*4c8945a0SNathan Whitehorn 
933*4c8945a0SNathan Whitehorn     /*
934*4c8945a0SNathan Whitehorn      * If the aspect ratio is too small after decreasing the width, then
935*4c8945a0SNathan Whitehorn      * incrementally increase the width until the aspect ratio is equal to or
936*4c8945a0SNathan Whitehorn      * greater than the specified aspect ratio.
937*4c8945a0SNathan Whitehorn      */
938*4c8945a0SNathan Whitehorn     while (car < ar && max_x < max_width) {
939*4c8945a0SNathan Whitehorn 	max_x += 4;
940*4c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
941*4c8945a0SNathan Whitehorn 	car = (float) (wide / high);
942*4c8945a0SNathan Whitehorn     }
943*4c8945a0SNathan Whitehorn 
944*4c8945a0SNathan Whitehorn     *height = high;
945*4c8945a0SNathan Whitehorn     *width = wide;
946*4c8945a0SNathan Whitehorn }
947*4c8945a0SNathan Whitehorn 
948*4c8945a0SNathan Whitehorn /*
949*4c8945a0SNathan Whitehorn  * Find the length of the longest "word" in the given string.  By setting the
950*4c8945a0SNathan Whitehorn  * widget width at least this long, we can avoid splitting a word on the
951*4c8945a0SNathan Whitehorn  * margin.
952*4c8945a0SNathan Whitehorn  */
953*4c8945a0SNathan Whitehorn static int
954*4c8945a0SNathan Whitehorn longest_word(const char *string)
955*4c8945a0SNathan Whitehorn {
956*4c8945a0SNathan Whitehorn     int length, result = 0;
957*4c8945a0SNathan Whitehorn 
958*4c8945a0SNathan Whitehorn     while (*string != '\0') {
959*4c8945a0SNathan Whitehorn 	length = 0;
960*4c8945a0SNathan Whitehorn 	while (*string != '\0' && !isspace(UCH(*string))) {
961*4c8945a0SNathan Whitehorn 	    length++;
962*4c8945a0SNathan Whitehorn 	    string++;
963*4c8945a0SNathan Whitehorn 	}
964*4c8945a0SNathan Whitehorn 	result = MAX(result, length);
965*4c8945a0SNathan Whitehorn 	if (*string != '\0')
966*4c8945a0SNathan Whitehorn 	    string++;
967*4c8945a0SNathan Whitehorn     }
968*4c8945a0SNathan Whitehorn     return result;
969*4c8945a0SNathan Whitehorn }
970*4c8945a0SNathan Whitehorn 
971*4c8945a0SNathan Whitehorn /*
972*4c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
973*4c8945a0SNathan Whitehorn  * if (height or width == 0), justify and return actual limits.
974*4c8945a0SNathan Whitehorn  */
975*4c8945a0SNathan Whitehorn static void
976*4c8945a0SNathan Whitehorn real_auto_size(const char *title,
977*4c8945a0SNathan Whitehorn 	       const char *prompt,
978*4c8945a0SNathan Whitehorn 	       int *height, int *width,
979*4c8945a0SNathan Whitehorn 	       int boxlines, int mincols)
980*4c8945a0SNathan Whitehorn {
981*4c8945a0SNathan Whitehorn     int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2);
982*4c8945a0SNathan Whitehorn     int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1);
983*4c8945a0SNathan Whitehorn     int title_length = title ? dlg_count_columns(title) : 0;
984*4c8945a0SNathan Whitehorn     int nc = 4;
985*4c8945a0SNathan Whitehorn     int high;
986*4c8945a0SNathan Whitehorn     int wide;
987*4c8945a0SNathan Whitehorn     int save_high = *height;
988*4c8945a0SNathan Whitehorn     int save_wide = *width;
989*4c8945a0SNathan Whitehorn 
990*4c8945a0SNathan Whitehorn     if (prompt == 0) {
991*4c8945a0SNathan Whitehorn 	if (*height == 0)
992*4c8945a0SNathan Whitehorn 	    *height = -1;
993*4c8945a0SNathan Whitehorn 	if (*width == 0)
994*4c8945a0SNathan Whitehorn 	    *width = -1;
995*4c8945a0SNathan Whitehorn     }
996*4c8945a0SNathan Whitehorn 
997*4c8945a0SNathan Whitehorn     if (*height > 0) {
998*4c8945a0SNathan Whitehorn 	high = *height;
999*4c8945a0SNathan Whitehorn     } else {
1000*4c8945a0SNathan Whitehorn 	high = SLINES - y;
1001*4c8945a0SNathan Whitehorn     }
1002*4c8945a0SNathan Whitehorn 
1003*4c8945a0SNathan Whitehorn     if (*width > 0) {
1004*4c8945a0SNathan Whitehorn 	wide = *width;
1005*4c8945a0SNathan Whitehorn     } else if (prompt != 0) {
1006*4c8945a0SNathan Whitehorn 	wide = MAX(title_length, mincols);
1007*4c8945a0SNathan Whitehorn 	if (strchr(prompt, '\n') == 0) {
1008*4c8945a0SNathan Whitehorn 	    double val = dialog_state.aspect_ratio * dlg_count_columns(prompt);
1009*4c8945a0SNathan Whitehorn 	    double xxx = sqrt(val);
1010*4c8945a0SNathan Whitehorn 	    int tmp = (int) xxx;
1011*4c8945a0SNathan Whitehorn 	    wide = MAX(wide, tmp);
1012*4c8945a0SNathan Whitehorn 	    wide = MAX(wide, longest_word(prompt));
1013*4c8945a0SNathan Whitehorn 	    justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1014*4c8945a0SNathan Whitehorn 	} else {
1015*4c8945a0SNathan Whitehorn 	    auto_size_preformatted(prompt, height, width);
1016*4c8945a0SNathan Whitehorn 	}
1017*4c8945a0SNathan Whitehorn     } else {
1018*4c8945a0SNathan Whitehorn 	wide = SCOLS - x;
1019*4c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1020*4c8945a0SNathan Whitehorn     }
1021*4c8945a0SNathan Whitehorn 
1022*4c8945a0SNathan Whitehorn     if (*width < title_length) {
1023*4c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, high, title_length, height, width);
1024*4c8945a0SNathan Whitehorn 	*width = title_length;
1025*4c8945a0SNathan Whitehorn     }
1026*4c8945a0SNathan Whitehorn 
1027*4c8945a0SNathan Whitehorn     if (*width < mincols && save_wide == 0)
1028*4c8945a0SNathan Whitehorn 	*width = mincols;
1029*4c8945a0SNathan Whitehorn     if (prompt != 0) {
1030*4c8945a0SNathan Whitehorn 	*width += nc;
1031*4c8945a0SNathan Whitehorn 	*height += boxlines + 2;
1032*4c8945a0SNathan Whitehorn     }
1033*4c8945a0SNathan Whitehorn     if (save_high > 0)
1034*4c8945a0SNathan Whitehorn 	*height = save_high;
1035*4c8945a0SNathan Whitehorn     if (save_wide > 0)
1036*4c8945a0SNathan Whitehorn 	*width = save_wide;
1037*4c8945a0SNathan Whitehorn }
1038*4c8945a0SNathan Whitehorn 
1039*4c8945a0SNathan Whitehorn /* End of real_auto_size() */
1040*4c8945a0SNathan Whitehorn 
1041*4c8945a0SNathan Whitehorn void
1042*4c8945a0SNathan Whitehorn dlg_auto_size(const char *title,
1043*4c8945a0SNathan Whitehorn 	      const char *prompt,
1044*4c8945a0SNathan Whitehorn 	      int *height,
1045*4c8945a0SNathan Whitehorn 	      int *width,
1046*4c8945a0SNathan Whitehorn 	      int boxlines,
1047*4c8945a0SNathan Whitehorn 	      int mincols)
1048*4c8945a0SNathan Whitehorn {
1049*4c8945a0SNathan Whitehorn     real_auto_size(title, prompt, height, width, boxlines, mincols);
1050*4c8945a0SNathan Whitehorn 
1051*4c8945a0SNathan Whitehorn     if (*width > SCOLS) {
1052*4c8945a0SNathan Whitehorn 	(*height)++;
1053*4c8945a0SNathan Whitehorn 	*width = SCOLS;
1054*4c8945a0SNathan Whitehorn     }
1055*4c8945a0SNathan Whitehorn 
1056*4c8945a0SNathan Whitehorn     if (*height > SLINES)
1057*4c8945a0SNathan Whitehorn 	*height = SLINES;
1058*4c8945a0SNathan Whitehorn }
1059*4c8945a0SNathan Whitehorn 
1060*4c8945a0SNathan Whitehorn /*
1061*4c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
1062*4c8945a0SNathan Whitehorn  * if (height or width == 0)
1063*4c8945a0SNathan Whitehorn  *    height=MIN(SLINES, num.lines in fd+n);
1064*4c8945a0SNathan Whitehorn  *    width=MIN(SCOLS, MAX(longer line+n, mincols));
1065*4c8945a0SNathan Whitehorn  */
1066*4c8945a0SNathan Whitehorn void
1067*4c8945a0SNathan Whitehorn dlg_auto_sizefile(const char *title,
1068*4c8945a0SNathan Whitehorn 		  const char *file,
1069*4c8945a0SNathan Whitehorn 		  int *height,
1070*4c8945a0SNathan Whitehorn 		  int *width,
1071*4c8945a0SNathan Whitehorn 		  int boxlines,
1072*4c8945a0SNathan Whitehorn 		  int mincols)
1073*4c8945a0SNathan Whitehorn {
1074*4c8945a0SNathan Whitehorn     int count = 0;
1075*4c8945a0SNathan Whitehorn     int len = title ? dlg_count_columns(title) : 0;
1076*4c8945a0SNathan Whitehorn     int nc = 4;
1077*4c8945a0SNathan Whitehorn     int numlines = 2;
1078*4c8945a0SNathan Whitehorn     long offset;
1079*4c8945a0SNathan Whitehorn     int ch;
1080*4c8945a0SNathan Whitehorn     FILE *fd;
1081*4c8945a0SNathan Whitehorn 
1082*4c8945a0SNathan Whitehorn     /* Open input file for reading */
1083*4c8945a0SNathan Whitehorn     if ((fd = fopen(file, "rb")) == NULL)
1084*4c8945a0SNathan Whitehorn 	dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file);
1085*4c8945a0SNathan Whitehorn 
1086*4c8945a0SNathan Whitehorn     if ((*height == -1) || (*width == -1)) {
1087*4c8945a0SNathan Whitehorn 	*height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1088*4c8945a0SNathan Whitehorn 	*width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
1089*4c8945a0SNathan Whitehorn     }
1090*4c8945a0SNathan Whitehorn     if ((*height != 0) && (*width != 0)) {
1091*4c8945a0SNathan Whitehorn 	(void) fclose(fd);
1092*4c8945a0SNathan Whitehorn 	if (*width > SCOLS)
1093*4c8945a0SNathan Whitehorn 	    *width = SCOLS;
1094*4c8945a0SNathan Whitehorn 	if (*height > SLINES)
1095*4c8945a0SNathan Whitehorn 	    *height = SLINES;
1096*4c8945a0SNathan Whitehorn 	return;
1097*4c8945a0SNathan Whitehorn     }
1098*4c8945a0SNathan Whitehorn 
1099*4c8945a0SNathan Whitehorn     while (!feof(fd)) {
1100*4c8945a0SNathan Whitehorn 	offset = 0;
1101*4c8945a0SNathan Whitehorn 	while (((ch = getc(fd)) != '\n') && !feof(fd))
1102*4c8945a0SNathan Whitehorn 	    if ((ch == TAB) && (dialog_vars.tab_correct))
1103*4c8945a0SNathan Whitehorn 		offset += dialog_state.tab_len - (offset % dialog_state.tab_len);
1104*4c8945a0SNathan Whitehorn 	    else
1105*4c8945a0SNathan Whitehorn 		offset++;
1106*4c8945a0SNathan Whitehorn 
1107*4c8945a0SNathan Whitehorn 	if (offset > len)
1108*4c8945a0SNathan Whitehorn 	    len = offset;
1109*4c8945a0SNathan Whitehorn 
1110*4c8945a0SNathan Whitehorn 	count++;
1111*4c8945a0SNathan Whitehorn     }
1112*4c8945a0SNathan Whitehorn 
1113*4c8945a0SNathan Whitehorn     /* now 'count' has the number of lines of fd and 'len' the max lenght */
1114*4c8945a0SNathan Whitehorn 
1115*4c8945a0SNathan Whitehorn     *height = MIN(SLINES, count + numlines + boxlines);
1116*4c8945a0SNathan Whitehorn     *width = MIN(SCOLS, MAX((len + nc), mincols));
1117*4c8945a0SNathan Whitehorn     /* here width and height can be maximized if > SCOLS|SLINES because
1118*4c8945a0SNathan Whitehorn        textbox-like widgets don't put all <file> on the screen.
1119*4c8945a0SNathan Whitehorn        Msgbox-like widget instead have to put all <text> correctly. */
1120*4c8945a0SNathan Whitehorn 
1121*4c8945a0SNathan Whitehorn     (void) fclose(fd);
1122*4c8945a0SNathan Whitehorn }
1123*4c8945a0SNathan Whitehorn 
1124*4c8945a0SNathan Whitehorn /*
1125*4c8945a0SNathan Whitehorn  * Draw a rectangular box with line drawing characters.
1126*4c8945a0SNathan Whitehorn  *
1127*4c8945a0SNathan Whitehorn  * borderchar is used to color the upper/left edges.
1128*4c8945a0SNathan Whitehorn  *
1129*4c8945a0SNathan Whitehorn  * boxchar is used to color the right/lower edges.  It also is fill-color used
1130*4c8945a0SNathan Whitehorn  * for the box contents.
1131*4c8945a0SNathan Whitehorn  *
1132*4c8945a0SNathan Whitehorn  * Normally, if you are drawing a scrollable box, use menubox_border_attr for
1133*4c8945a0SNathan Whitehorn  * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn
1134*4c8945a0SNathan Whitehorn  * with menubox_attr at the top, and menubox_border_attr at the bottom.  That
1135*4c8945a0SNathan Whitehorn  * also (given the default color choices) produces a recessed effect.
1136*4c8945a0SNathan Whitehorn  *
1137*4c8945a0SNathan Whitehorn  * If you want a raised effect (and are not going to use the scroll-arrows),
1138*4c8945a0SNathan Whitehorn  * reverse this choice.
1139*4c8945a0SNathan Whitehorn  */
1140*4c8945a0SNathan Whitehorn void
1141*4c8945a0SNathan Whitehorn dlg_draw_box(WINDOW *win, int y, int x, int height, int width,
1142*4c8945a0SNathan Whitehorn 	     chtype boxchar, chtype borderchar)
1143*4c8945a0SNathan Whitehorn {
1144*4c8945a0SNathan Whitehorn     int i, j;
1145*4c8945a0SNathan Whitehorn     chtype save = getattrs(win);
1146*4c8945a0SNathan Whitehorn 
1147*4c8945a0SNathan Whitehorn     wattrset(win, 0);
1148*4c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
1149*4c8945a0SNathan Whitehorn 	(void) wmove(win, y + i, x);
1150*4c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
1151*4c8945a0SNathan Whitehorn 	    if (!i && !j)
1152*4c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER));
1153*4c8945a0SNathan Whitehorn 	    else if (i == height - 1 && !j)
1154*4c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER));
1155*4c8945a0SNathan Whitehorn 	    else if (!i && j == width - 1)
1156*4c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | dlg_boxchar(ACS_URCORNER));
1157*4c8945a0SNathan Whitehorn 	    else if (i == height - 1 && j == width - 1)
1158*4c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | dlg_boxchar(ACS_LRCORNER));
1159*4c8945a0SNathan Whitehorn 	    else if (!i)
1160*4c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE));
1161*4c8945a0SNathan Whitehorn 	    else if (i == height - 1)
1162*4c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | dlg_boxchar(ACS_HLINE));
1163*4c8945a0SNathan Whitehorn 	    else if (!j)
1164*4c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE));
1165*4c8945a0SNathan Whitehorn 	    else if (j == width - 1)
1166*4c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | dlg_boxchar(ACS_VLINE));
1167*4c8945a0SNathan Whitehorn 	    else
1168*4c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | ' ');
1169*4c8945a0SNathan Whitehorn     }
1170*4c8945a0SNathan Whitehorn     wattrset(win, save);
1171*4c8945a0SNathan Whitehorn }
1172*4c8945a0SNathan Whitehorn 
1173*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1174*4c8945a0SNathan Whitehorn /*
1175*4c8945a0SNathan Whitehorn  * Draw a shadow on the parent window corresponding to the right- and
1176*4c8945a0SNathan Whitehorn  * bottom-edge of the child window, to give a 3-dimensional look.
1177*4c8945a0SNathan Whitehorn  */
1178*4c8945a0SNathan Whitehorn static void
1179*4c8945a0SNathan Whitehorn draw_childs_shadow(WINDOW *parent, WINDOW *child)
1180*4c8945a0SNathan Whitehorn {
1181*4c8945a0SNathan Whitehorn     if (has_colors()) {		/* Whether terminal supports color? */
1182*4c8945a0SNathan Whitehorn 	chtype save = getattrs(parent);
1183*4c8945a0SNathan Whitehorn 
1184*4c8945a0SNathan Whitehorn 	dlg_draw_shadow(parent,
1185*4c8945a0SNathan Whitehorn 			getbegy(child) - getbegy(parent),
1186*4c8945a0SNathan Whitehorn 			getbegx(child) - getbegx(parent),
1187*4c8945a0SNathan Whitehorn 			getmaxy(child),
1188*4c8945a0SNathan Whitehorn 			getmaxx(child));
1189*4c8945a0SNathan Whitehorn 	wattrset(parent, save);
1190*4c8945a0SNathan Whitehorn     }
1191*4c8945a0SNathan Whitehorn }
1192*4c8945a0SNathan Whitehorn 
1193*4c8945a0SNathan Whitehorn /*
1194*4c8945a0SNathan Whitehorn  * Draw shadows along the right and bottom edge to give a more 3D look
1195*4c8945a0SNathan Whitehorn  * to the boxes
1196*4c8945a0SNathan Whitehorn  */
1197*4c8945a0SNathan Whitehorn void
1198*4c8945a0SNathan Whitehorn dlg_draw_shadow(WINDOW *win, int y, int x, int height, int width)
1199*4c8945a0SNathan Whitehorn {
1200*4c8945a0SNathan Whitehorn     int i, j;
1201*4c8945a0SNathan Whitehorn 
1202*4c8945a0SNathan Whitehorn     if (has_colors()) {		/* Whether terminal supports color? */
1203*4c8945a0SNathan Whitehorn 	wattrset(win, shadow_attr);
1204*4c8945a0SNathan Whitehorn 	for (i = 0; i < SHADOW_ROWS; ++i) {
1205*4c8945a0SNathan Whitehorn 	    for (j = 0; j < width; ++j) {
1206*4c8945a0SNathan Whitehorn 		if (wmove(win, i + y + height, j + x + SHADOW_COLS) != ERR) {
1207*4c8945a0SNathan Whitehorn 		    (void) waddch(win, winch(win) & (chtype) (~A_COLOR));
1208*4c8945a0SNathan Whitehorn 		}
1209*4c8945a0SNathan Whitehorn 	    }
1210*4c8945a0SNathan Whitehorn 	}
1211*4c8945a0SNathan Whitehorn 	for (i = 0; i < height; i++) {
1212*4c8945a0SNathan Whitehorn 	    for (j = 0; j < SHADOW_COLS; ++j) {
1213*4c8945a0SNathan Whitehorn 		if (wmove(win, i + y + SHADOW_ROWS, j + x + width) != ERR) {
1214*4c8945a0SNathan Whitehorn 		    (void) waddch(win, winch(win) & (chtype) (~A_COLOR));
1215*4c8945a0SNathan Whitehorn 		}
1216*4c8945a0SNathan Whitehorn 	    }
1217*4c8945a0SNathan Whitehorn 	}
1218*4c8945a0SNathan Whitehorn 	(void) wnoutrefresh(win);
1219*4c8945a0SNathan Whitehorn     }
1220*4c8945a0SNathan Whitehorn }
1221*4c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
1222*4c8945a0SNathan Whitehorn 
1223*4c8945a0SNathan Whitehorn /*
1224*4c8945a0SNathan Whitehorn  * Allow shell scripts to remap the exit codes so they can distinguish ESC
1225*4c8945a0SNathan Whitehorn  * from ERROR.
1226*4c8945a0SNathan Whitehorn  */
1227*4c8945a0SNathan Whitehorn void
1228*4c8945a0SNathan Whitehorn dlg_exit(int code)
1229*4c8945a0SNathan Whitehorn {
1230*4c8945a0SNathan Whitehorn     /* *INDENT-OFF* */
1231*4c8945a0SNathan Whitehorn     static const struct {
1232*4c8945a0SNathan Whitehorn 	int code;
1233*4c8945a0SNathan Whitehorn 	const char *name;
1234*4c8945a0SNathan Whitehorn     } table[] = {
1235*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_CANCEL, 	"DIALOG_CANCEL" },
1236*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_ERROR,  	"DIALOG_ERROR" },
1237*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_ESC,	   	"DIALOG_ESC" },
1238*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_EXTRA,  	"DIALOG_EXTRA" },
1239*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_HELP,   	"DIALOG_HELP" },
1240*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_OK,	   	"DIALOG_OK" },
1241*4c8945a0SNathan Whitehorn 	{ DLG_EXIT_ITEM_HELP,	"DIALOG_ITEM_HELP" },
1242*4c8945a0SNathan Whitehorn     };
1243*4c8945a0SNathan Whitehorn     /* *INDENT-ON* */
1244*4c8945a0SNathan Whitehorn 
1245*4c8945a0SNathan Whitehorn     unsigned n;
1246*4c8945a0SNathan Whitehorn     char *name;
1247*4c8945a0SNathan Whitehorn     char *temp;
1248*4c8945a0SNathan Whitehorn     long value;
1249*4c8945a0SNathan Whitehorn     bool overridden = FALSE;
1250*4c8945a0SNathan Whitehorn 
1251*4c8945a0SNathan Whitehorn   retry:
1252*4c8945a0SNathan Whitehorn     for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) {
1253*4c8945a0SNathan Whitehorn 	if (table[n].code == code) {
1254*4c8945a0SNathan Whitehorn 	    if ((name = getenv(table[n].name)) != 0) {
1255*4c8945a0SNathan Whitehorn 		value = strtol(name, &temp, 0);
1256*4c8945a0SNathan Whitehorn 		if (temp != 0 && temp != name && *temp == '\0') {
1257*4c8945a0SNathan Whitehorn 		    code = value;
1258*4c8945a0SNathan Whitehorn 		    overridden = TRUE;
1259*4c8945a0SNathan Whitehorn 		}
1260*4c8945a0SNathan Whitehorn 	    }
1261*4c8945a0SNathan Whitehorn 	    break;
1262*4c8945a0SNathan Whitehorn 	}
1263*4c8945a0SNathan Whitehorn     }
1264*4c8945a0SNathan Whitehorn 
1265*4c8945a0SNathan Whitehorn     /*
1266*4c8945a0SNathan Whitehorn      * Prior to 2004/12/19, a widget using --item-help would exit with "OK"
1267*4c8945a0SNathan Whitehorn      * if the help button were selected.  Now we want to exit with "HELP",
1268*4c8945a0SNathan Whitehorn      * but allow the environment variable to override.
1269*4c8945a0SNathan Whitehorn      */
1270*4c8945a0SNathan Whitehorn     if (code == DLG_EXIT_ITEM_HELP && !overridden) {
1271*4c8945a0SNathan Whitehorn 	code = DLG_EXIT_HELP;
1272*4c8945a0SNathan Whitehorn 	goto retry;
1273*4c8945a0SNathan Whitehorn     }
1274*4c8945a0SNathan Whitehorn #ifdef NO_LEAKS
1275*4c8945a0SNathan Whitehorn     _dlg_inputstr_leaks();
1276*4c8945a0SNathan Whitehorn #if defined(NCURSES_VERSION) && defined(HAVE__NC_FREE_AND_EXIT)
1277*4c8945a0SNathan Whitehorn     _nc_free_and_exit(code);
1278*4c8945a0SNathan Whitehorn #endif
1279*4c8945a0SNathan Whitehorn #endif
1280*4c8945a0SNathan Whitehorn 
1281*4c8945a0SNathan Whitehorn     if (dialog_state.input == stdin) {
1282*4c8945a0SNathan Whitehorn 	exit(code);
1283*4c8945a0SNathan Whitehorn     } else {
1284*4c8945a0SNathan Whitehorn 	/*
1285*4c8945a0SNathan Whitehorn 	 * Just in case of using --input-fd option, do not
1286*4c8945a0SNathan Whitehorn 	 * call atexit functions of ncurses which may hang.
1287*4c8945a0SNathan Whitehorn 	 */
1288*4c8945a0SNathan Whitehorn 	if (dialog_state.input) {
1289*4c8945a0SNathan Whitehorn 	    fclose(dialog_state.input);
1290*4c8945a0SNathan Whitehorn 	    dialog_state.input = 0;
1291*4c8945a0SNathan Whitehorn 	}
1292*4c8945a0SNathan Whitehorn 	if (dialog_state.pipe_input) {
1293*4c8945a0SNathan Whitehorn 	    if (dialog_state.pipe_input != stdin) {
1294*4c8945a0SNathan Whitehorn 		fclose(dialog_state.pipe_input);
1295*4c8945a0SNathan Whitehorn 		dialog_state.pipe_input = 0;
1296*4c8945a0SNathan Whitehorn 	    }
1297*4c8945a0SNathan Whitehorn 	}
1298*4c8945a0SNathan Whitehorn 	_exit(code);
1299*4c8945a0SNathan Whitehorn     }
1300*4c8945a0SNathan Whitehorn }
1301*4c8945a0SNathan Whitehorn 
1302*4c8945a0SNathan Whitehorn /* quit program killing all tailbg */
1303*4c8945a0SNathan Whitehorn void
1304*4c8945a0SNathan Whitehorn dlg_exiterr(const char *fmt,...)
1305*4c8945a0SNathan Whitehorn {
1306*4c8945a0SNathan Whitehorn     int retval;
1307*4c8945a0SNathan Whitehorn     va_list ap;
1308*4c8945a0SNathan Whitehorn 
1309*4c8945a0SNathan Whitehorn     end_dialog();
1310*4c8945a0SNathan Whitehorn 
1311*4c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
1312*4c8945a0SNathan Whitehorn     va_start(ap, fmt);
1313*4c8945a0SNathan Whitehorn     (void) vfprintf(stderr, fmt, ap);
1314*4c8945a0SNathan Whitehorn     va_end(ap);
1315*4c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
1316*4c8945a0SNathan Whitehorn 
1317*4c8945a0SNathan Whitehorn     dlg_killall_bg(&retval);
1318*4c8945a0SNathan Whitehorn 
1319*4c8945a0SNathan Whitehorn     (void) fflush(stderr);
1320*4c8945a0SNathan Whitehorn     (void) fflush(stdout);
1321*4c8945a0SNathan Whitehorn     dlg_exit(DLG_EXIT_ERROR);
1322*4c8945a0SNathan Whitehorn }
1323*4c8945a0SNathan Whitehorn 
1324*4c8945a0SNathan Whitehorn void
1325*4c8945a0SNathan Whitehorn dlg_beeping(void)
1326*4c8945a0SNathan Whitehorn {
1327*4c8945a0SNathan Whitehorn     if (dialog_vars.beep_signal) {
1328*4c8945a0SNathan Whitehorn 	(void) beep();
1329*4c8945a0SNathan Whitehorn 	dialog_vars.beep_signal = 0;
1330*4c8945a0SNathan Whitehorn     }
1331*4c8945a0SNathan Whitehorn }
1332*4c8945a0SNathan Whitehorn 
1333*4c8945a0SNathan Whitehorn void
1334*4c8945a0SNathan Whitehorn dlg_print_size(int height, int width)
1335*4c8945a0SNathan Whitehorn {
1336*4c8945a0SNathan Whitehorn     if (dialog_vars.print_siz)
1337*4c8945a0SNathan Whitehorn 	fprintf(dialog_state.output, "Size: %d, %d\n", height, width);
1338*4c8945a0SNathan Whitehorn }
1339*4c8945a0SNathan Whitehorn 
1340*4c8945a0SNathan Whitehorn void
1341*4c8945a0SNathan Whitehorn dlg_ctl_size(int height, int width)
1342*4c8945a0SNathan Whitehorn {
1343*4c8945a0SNathan Whitehorn     if (dialog_vars.size_err) {
1344*4c8945a0SNathan Whitehorn 	if ((width > COLS) || (height > LINES)) {
1345*4c8945a0SNathan Whitehorn 	    dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1346*4c8945a0SNathan Whitehorn 			height, width, LINES, COLS);
1347*4c8945a0SNathan Whitehorn 	}
1348*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1349*4c8945a0SNathan Whitehorn 	else if ((dialog_state.use_shadow)
1350*4c8945a0SNathan Whitehorn 		 && ((width > SCOLS || height > SLINES))) {
1351*4c8945a0SNathan Whitehorn 	    if ((width <= COLS) && (height <= LINES)) {
1352*4c8945a0SNathan Whitehorn 		/* try again, without shadows */
1353*4c8945a0SNathan Whitehorn 		dialog_state.use_shadow = 0;
1354*4c8945a0SNathan Whitehorn 	    } else {
1355*4c8945a0SNathan Whitehorn 		dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1356*4c8945a0SNathan Whitehorn 			    height, width, SLINES, SCOLS);
1357*4c8945a0SNathan Whitehorn 	    }
1358*4c8945a0SNathan Whitehorn 	}
1359*4c8945a0SNathan Whitehorn #endif
1360*4c8945a0SNathan Whitehorn     }
1361*4c8945a0SNathan Whitehorn }
1362*4c8945a0SNathan Whitehorn 
1363*4c8945a0SNathan Whitehorn /*
1364*4c8945a0SNathan Whitehorn  * If the --tab-correct was not selected, convert tabs to single spaces.
1365*4c8945a0SNathan Whitehorn  */
1366*4c8945a0SNathan Whitehorn void
1367*4c8945a0SNathan Whitehorn dlg_tab_correct_str(char *prompt)
1368*4c8945a0SNathan Whitehorn {
1369*4c8945a0SNathan Whitehorn     char *ptr;
1370*4c8945a0SNathan Whitehorn 
1371*4c8945a0SNathan Whitehorn     if (dialog_vars.tab_correct) {
1372*4c8945a0SNathan Whitehorn 	while ((ptr = strchr(prompt, TAB)) != NULL) {
1373*4c8945a0SNathan Whitehorn 	    *ptr = ' ';
1374*4c8945a0SNathan Whitehorn 	    prompt = ptr;
1375*4c8945a0SNathan Whitehorn 	}
1376*4c8945a0SNathan Whitehorn     }
1377*4c8945a0SNathan Whitehorn }
1378*4c8945a0SNathan Whitehorn 
1379*4c8945a0SNathan Whitehorn void
1380*4c8945a0SNathan Whitehorn dlg_calc_listh(int *height, int *list_height, int item_no)
1381*4c8945a0SNathan Whitehorn {
1382*4c8945a0SNathan Whitehorn     /* calculate new height and list_height */
1383*4c8945a0SNathan Whitehorn     int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1384*4c8945a0SNathan Whitehorn     if (rows - (*height) > 0) {
1385*4c8945a0SNathan Whitehorn 	if (rows - (*height) > item_no)
1386*4c8945a0SNathan Whitehorn 	    *list_height = item_no;
1387*4c8945a0SNathan Whitehorn 	else
1388*4c8945a0SNathan Whitehorn 	    *list_height = rows - (*height);
1389*4c8945a0SNathan Whitehorn     }
1390*4c8945a0SNathan Whitehorn     (*height) += (*list_height);
1391*4c8945a0SNathan Whitehorn }
1392*4c8945a0SNathan Whitehorn 
1393*4c8945a0SNathan Whitehorn /* obsolete */
1394*4c8945a0SNathan Whitehorn int
1395*4c8945a0SNathan Whitehorn dlg_calc_listw(int item_no, char **items, int group)
1396*4c8945a0SNathan Whitehorn {
1397*4c8945a0SNathan Whitehorn     int n, i, len1 = 0, len2 = 0;
1398*4c8945a0SNathan Whitehorn     for (i = 0; i < (item_no * group); i += group) {
1399*4c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i])) > len1)
1400*4c8945a0SNathan Whitehorn 	    len1 = n;
1401*4c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i + 1])) > len2)
1402*4c8945a0SNathan Whitehorn 	    len2 = n;
1403*4c8945a0SNathan Whitehorn     }
1404*4c8945a0SNathan Whitehorn     return len1 + len2;
1405*4c8945a0SNathan Whitehorn }
1406*4c8945a0SNathan Whitehorn 
1407*4c8945a0SNathan Whitehorn int
1408*4c8945a0SNathan Whitehorn dlg_calc_list_width(int item_no, DIALOG_LISTITEM * items)
1409*4c8945a0SNathan Whitehorn {
1410*4c8945a0SNathan Whitehorn     int n, i, len1 = 0, len2 = 0;
1411*4c8945a0SNathan Whitehorn     for (i = 0; i < item_no; ++i) {
1412*4c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i].name)) > len1)
1413*4c8945a0SNathan Whitehorn 	    len1 = n;
1414*4c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i].text)) > len2)
1415*4c8945a0SNathan Whitehorn 	    len2 = n;
1416*4c8945a0SNathan Whitehorn     }
1417*4c8945a0SNathan Whitehorn     return len1 + len2;
1418*4c8945a0SNathan Whitehorn }
1419*4c8945a0SNathan Whitehorn 
1420*4c8945a0SNathan Whitehorn char *
1421*4c8945a0SNathan Whitehorn dlg_strempty(void)
1422*4c8945a0SNathan Whitehorn {
1423*4c8945a0SNathan Whitehorn     static char empty[] = "";
1424*4c8945a0SNathan Whitehorn     return empty;
1425*4c8945a0SNathan Whitehorn }
1426*4c8945a0SNathan Whitehorn 
1427*4c8945a0SNathan Whitehorn char *
1428*4c8945a0SNathan Whitehorn dlg_strclone(const char *cprompt)
1429*4c8945a0SNathan Whitehorn {
1430*4c8945a0SNathan Whitehorn     char *prompt = dlg_malloc(char, strlen(cprompt) + 1);
1431*4c8945a0SNathan Whitehorn     assert_ptr(prompt, "dlg_strclone");
1432*4c8945a0SNathan Whitehorn     strcpy(prompt, cprompt);
1433*4c8945a0SNathan Whitehorn     return prompt;
1434*4c8945a0SNathan Whitehorn }
1435*4c8945a0SNathan Whitehorn 
1436*4c8945a0SNathan Whitehorn chtype
1437*4c8945a0SNathan Whitehorn dlg_asciibox(chtype ch)
1438*4c8945a0SNathan Whitehorn {
1439*4c8945a0SNathan Whitehorn     chtype result = 0;
1440*4c8945a0SNathan Whitehorn 
1441*4c8945a0SNathan Whitehorn     if (ch == ACS_ULCORNER)
1442*4c8945a0SNathan Whitehorn 	result = '+';
1443*4c8945a0SNathan Whitehorn     else if (ch == ACS_LLCORNER)
1444*4c8945a0SNathan Whitehorn 	result = '+';
1445*4c8945a0SNathan Whitehorn     else if (ch == ACS_URCORNER)
1446*4c8945a0SNathan Whitehorn 	result = '+';
1447*4c8945a0SNathan Whitehorn     else if (ch == ACS_LRCORNER)
1448*4c8945a0SNathan Whitehorn 	result = '+';
1449*4c8945a0SNathan Whitehorn     else if (ch == ACS_HLINE)
1450*4c8945a0SNathan Whitehorn 	result = '-';
1451*4c8945a0SNathan Whitehorn     else if (ch == ACS_VLINE)
1452*4c8945a0SNathan Whitehorn 	result = '|';
1453*4c8945a0SNathan Whitehorn     else if (ch == ACS_LTEE)
1454*4c8945a0SNathan Whitehorn 	result = '+';
1455*4c8945a0SNathan Whitehorn     else if (ch == ACS_RTEE)
1456*4c8945a0SNathan Whitehorn 	result = '+';
1457*4c8945a0SNathan Whitehorn     else if (ch == ACS_UARROW)
1458*4c8945a0SNathan Whitehorn 	result = '^';
1459*4c8945a0SNathan Whitehorn     else if (ch == ACS_DARROW)
1460*4c8945a0SNathan Whitehorn 	result = 'v';
1461*4c8945a0SNathan Whitehorn 
1462*4c8945a0SNathan Whitehorn     return result;
1463*4c8945a0SNathan Whitehorn }
1464*4c8945a0SNathan Whitehorn 
1465*4c8945a0SNathan Whitehorn chtype
1466*4c8945a0SNathan Whitehorn dlg_boxchar(chtype ch)
1467*4c8945a0SNathan Whitehorn {
1468*4c8945a0SNathan Whitehorn     chtype result = dlg_asciibox(ch);
1469*4c8945a0SNathan Whitehorn 
1470*4c8945a0SNathan Whitehorn     if (result != 0) {
1471*4c8945a0SNathan Whitehorn 	if (dialog_vars.ascii_lines)
1472*4c8945a0SNathan Whitehorn 	    ch = result;
1473*4c8945a0SNathan Whitehorn 	else if (dialog_vars.no_lines)
1474*4c8945a0SNathan Whitehorn 	    ch = ' ';
1475*4c8945a0SNathan Whitehorn     }
1476*4c8945a0SNathan Whitehorn     return ch;
1477*4c8945a0SNathan Whitehorn }
1478*4c8945a0SNathan Whitehorn 
1479*4c8945a0SNathan Whitehorn int
1480*4c8945a0SNathan Whitehorn dlg_box_x_ordinate(int width)
1481*4c8945a0SNathan Whitehorn {
1482*4c8945a0SNathan Whitehorn     int x;
1483*4c8945a0SNathan Whitehorn 
1484*4c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
1485*4c8945a0SNathan Whitehorn 	x = dialog_vars.begin_x;
1486*4c8945a0SNathan Whitehorn     } else {
1487*4c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
1488*4c8945a0SNathan Whitehorn 	x = (SCOLS - width) / 2;
1489*4c8945a0SNathan Whitehorn     }
1490*4c8945a0SNathan Whitehorn     return x;
1491*4c8945a0SNathan Whitehorn }
1492*4c8945a0SNathan Whitehorn 
1493*4c8945a0SNathan Whitehorn int
1494*4c8945a0SNathan Whitehorn dlg_box_y_ordinate(int height)
1495*4c8945a0SNathan Whitehorn {
1496*4c8945a0SNathan Whitehorn     int y;
1497*4c8945a0SNathan Whitehorn 
1498*4c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
1499*4c8945a0SNathan Whitehorn 	y = dialog_vars.begin_y;
1500*4c8945a0SNathan Whitehorn     } else {
1501*4c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
1502*4c8945a0SNathan Whitehorn 	y = (SLINES - height) / 2;
1503*4c8945a0SNathan Whitehorn     }
1504*4c8945a0SNathan Whitehorn     return y;
1505*4c8945a0SNathan Whitehorn }
1506*4c8945a0SNathan Whitehorn 
1507*4c8945a0SNathan Whitehorn void
1508*4c8945a0SNathan Whitehorn dlg_draw_title(WINDOW *win, const char *title)
1509*4c8945a0SNathan Whitehorn {
1510*4c8945a0SNathan Whitehorn     if (title != NULL) {
1511*4c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
1512*4c8945a0SNathan Whitehorn 	chtype save = getattrs(win);
1513*4c8945a0SNathan Whitehorn 	int x = centered(getmaxx(win), title);
1514*4c8945a0SNathan Whitehorn 
1515*4c8945a0SNathan Whitehorn 	wattrset(win, title_attr);
1516*4c8945a0SNathan Whitehorn 	wmove(win, 0, x);
1517*4c8945a0SNathan Whitehorn 	dlg_print_text(win, title, getmaxx(win) - x, &attr);
1518*4c8945a0SNathan Whitehorn 	wattrset(win, save);
1519*4c8945a0SNathan Whitehorn     }
1520*4c8945a0SNathan Whitehorn }
1521*4c8945a0SNathan Whitehorn 
1522*4c8945a0SNathan Whitehorn void
1523*4c8945a0SNathan Whitehorn dlg_draw_bottom_box(WINDOW *win)
1524*4c8945a0SNathan Whitehorn {
1525*4c8945a0SNathan Whitehorn     int width = getmaxx(win);
1526*4c8945a0SNathan Whitehorn     int height = getmaxy(win);
1527*4c8945a0SNathan Whitehorn     int i;
1528*4c8945a0SNathan Whitehorn 
1529*4c8945a0SNathan Whitehorn     wattrset(win, border_attr);
1530*4c8945a0SNathan Whitehorn     (void) wmove(win, height - 3, 0);
1531*4c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_LTEE));
1532*4c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
1533*4c8945a0SNathan Whitehorn 	(void) waddch(win, dlg_boxchar(ACS_HLINE));
1534*4c8945a0SNathan Whitehorn     wattrset(win, dialog_attr);
1535*4c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_RTEE));
1536*4c8945a0SNathan Whitehorn     (void) wmove(win, height - 2, 1);
1537*4c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
1538*4c8945a0SNathan Whitehorn 	(void) waddch(win, ' ');
1539*4c8945a0SNathan Whitehorn }
1540*4c8945a0SNathan Whitehorn 
1541*4c8945a0SNathan Whitehorn /*
1542*4c8945a0SNathan Whitehorn  * Remove a window, repainting everything else.  This would be simpler if we
1543*4c8945a0SNathan Whitehorn  * used the panel library, but that is not _always_ available.
1544*4c8945a0SNathan Whitehorn  */
1545*4c8945a0SNathan Whitehorn void
1546*4c8945a0SNathan Whitehorn dlg_del_window(WINDOW *win)
1547*4c8945a0SNathan Whitehorn {
1548*4c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p, *q, *r;
1549*4c8945a0SNathan Whitehorn 
1550*4c8945a0SNathan Whitehorn     /*
1551*4c8945a0SNathan Whitehorn      * If --keep-window was set, do not delete/repaint the windows.
1552*4c8945a0SNathan Whitehorn      */
1553*4c8945a0SNathan Whitehorn     if (dialog_vars.keep_window)
1554*4c8945a0SNathan Whitehorn 	return;
1555*4c8945a0SNathan Whitehorn 
1556*4c8945a0SNathan Whitehorn     /* Leave the main window untouched if there are no background windows.
1557*4c8945a0SNathan Whitehorn      * We do this so the current window will not be cleared on exit, allowing
1558*4c8945a0SNathan Whitehorn      * things like the infobox demo to run without flicker.
1559*4c8945a0SNathan Whitehorn      */
1560*4c8945a0SNathan Whitehorn     if (dialog_state.getc_callbacks != 0) {
1561*4c8945a0SNathan Whitehorn 	touchwin(stdscr);
1562*4c8945a0SNathan Whitehorn 	wnoutrefresh(stdscr);
1563*4c8945a0SNathan Whitehorn     }
1564*4c8945a0SNathan Whitehorn 
1565*4c8945a0SNathan Whitehorn     for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) {
1566*4c8945a0SNathan Whitehorn 	if (p->normal == win) {
1567*4c8945a0SNathan Whitehorn 	    q = p;		/* found a match - should be only one */
1568*4c8945a0SNathan Whitehorn 	    if (r == 0) {
1569*4c8945a0SNathan Whitehorn 		dialog_state.all_windows = p->next;
1570*4c8945a0SNathan Whitehorn 	    } else {
1571*4c8945a0SNathan Whitehorn 		r->next = p->next;
1572*4c8945a0SNathan Whitehorn 	    }
1573*4c8945a0SNathan Whitehorn 	} else {
1574*4c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
1575*4c8945a0SNathan Whitehorn 		touchwin(p->shadow);
1576*4c8945a0SNathan Whitehorn 		wnoutrefresh(p->shadow);
1577*4c8945a0SNathan Whitehorn 	    }
1578*4c8945a0SNathan Whitehorn 	    touchwin(p->normal);
1579*4c8945a0SNathan Whitehorn 	    wnoutrefresh(p->normal);
1580*4c8945a0SNathan Whitehorn 	}
1581*4c8945a0SNathan Whitehorn     }
1582*4c8945a0SNathan Whitehorn 
1583*4c8945a0SNathan Whitehorn     if (q) {
1584*4c8945a0SNathan Whitehorn 	delwin(q->normal);
1585*4c8945a0SNathan Whitehorn 	dlg_unregister_window(q->normal);
1586*4c8945a0SNathan Whitehorn 	free(q);
1587*4c8945a0SNathan Whitehorn     }
1588*4c8945a0SNathan Whitehorn     doupdate();
1589*4c8945a0SNathan Whitehorn }
1590*4c8945a0SNathan Whitehorn 
1591*4c8945a0SNathan Whitehorn /*
1592*4c8945a0SNathan Whitehorn  * Create a window, optionally with a shadow.
1593*4c8945a0SNathan Whitehorn  */
1594*4c8945a0SNathan Whitehorn WINDOW *
1595*4c8945a0SNathan Whitehorn dlg_new_window(int height, int width, int y, int x)
1596*4c8945a0SNathan Whitehorn {
1597*4c8945a0SNathan Whitehorn     WINDOW *win;
1598*4c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
1599*4c8945a0SNathan Whitehorn 
1600*4c8945a0SNathan Whitehorn     if ((win = newwin(height, width, y, x)) == 0) {
1601*4c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
1602*4c8945a0SNathan Whitehorn 		    y, x, height, width);
1603*4c8945a0SNathan Whitehorn     }
1604*4c8945a0SNathan Whitehorn     p->next = dialog_state.all_windows;
1605*4c8945a0SNathan Whitehorn     p->normal = win;
1606*4c8945a0SNathan Whitehorn     dialog_state.all_windows = p;
1607*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1608*4c8945a0SNathan Whitehorn     if (dialog_state.use_shadow) {
1609*4c8945a0SNathan Whitehorn 	draw_childs_shadow(p->shadow = stdscr, win);
1610*4c8945a0SNathan Whitehorn     }
1611*4c8945a0SNathan Whitehorn #endif
1612*4c8945a0SNathan Whitehorn 
1613*4c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
1614*4c8945a0SNathan Whitehorn     return win;
1615*4c8945a0SNathan Whitehorn }
1616*4c8945a0SNathan Whitehorn 
1617*4c8945a0SNathan Whitehorn WINDOW *
1618*4c8945a0SNathan Whitehorn dlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x)
1619*4c8945a0SNathan Whitehorn {
1620*4c8945a0SNathan Whitehorn     WINDOW *win;
1621*4c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
1622*4c8945a0SNathan Whitehorn 
1623*4c8945a0SNathan Whitehorn     (void) parent;
1624*4c8945a0SNathan Whitehorn     if ((win = newwin(height, width, y, x)) == 0) {
1625*4c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
1626*4c8945a0SNathan Whitehorn 		    y, x, height, width);
1627*4c8945a0SNathan Whitehorn     }
1628*4c8945a0SNathan Whitehorn     p->next = dialog_state.all_windows;
1629*4c8945a0SNathan Whitehorn     p->normal = win;
1630*4c8945a0SNathan Whitehorn     dialog_state.all_windows = p;
1631*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1632*4c8945a0SNathan Whitehorn     if (dialog_state.use_shadow) {
1633*4c8945a0SNathan Whitehorn 	draw_childs_shadow(p->shadow = parent, win);
1634*4c8945a0SNathan Whitehorn     }
1635*4c8945a0SNathan Whitehorn #endif
1636*4c8945a0SNathan Whitehorn 
1637*4c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
1638*4c8945a0SNathan Whitehorn     return win;
1639*4c8945a0SNathan Whitehorn }
1640*4c8945a0SNathan Whitehorn 
1641*4c8945a0SNathan Whitehorn /*
1642*4c8945a0SNathan Whitehorn  * Move/Resize a window, optionally with a shadow.
1643*4c8945a0SNathan Whitehorn  */
1644*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
1645*4c8945a0SNathan Whitehorn void
1646*4c8945a0SNathan Whitehorn dlg_move_window(WINDOW *win, int height, int width, int y, int x)
1647*4c8945a0SNathan Whitehorn {
1648*4c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p, *q;
1649*4c8945a0SNathan Whitehorn 
1650*4c8945a0SNathan Whitehorn     if (win != 0) {
1651*4c8945a0SNathan Whitehorn 	dlg_ctl_size(height, width);
1652*4c8945a0SNathan Whitehorn 
1653*4c8945a0SNathan Whitehorn 	for (p = dialog_state.all_windows; p != 0; p = q) {
1654*4c8945a0SNathan Whitehorn 	    q = p->next;
1655*4c8945a0SNathan Whitehorn 	    if (p->normal == win) {
1656*4c8945a0SNathan Whitehorn 		break;
1657*4c8945a0SNathan Whitehorn 	    }
1658*4c8945a0SNathan Whitehorn 	}
1659*4c8945a0SNathan Whitehorn 
1660*4c8945a0SNathan Whitehorn 	if (p != 0) {
1661*4c8945a0SNathan Whitehorn 	    (void) wresize(win, height, width);
1662*4c8945a0SNathan Whitehorn 	    (void) mvwin(win, y, x);
1663*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1664*4c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
1665*4c8945a0SNathan Whitehorn 		if (dialog_state.use_shadow) {
1666*4c8945a0SNathan Whitehorn 		    (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS);
1667*4c8945a0SNathan Whitehorn 		} else {
1668*4c8945a0SNathan Whitehorn 		    p->shadow = 0;
1669*4c8945a0SNathan Whitehorn 		}
1670*4c8945a0SNathan Whitehorn 	    }
1671*4c8945a0SNathan Whitehorn #endif
1672*4c8945a0SNathan Whitehorn 	    (void) refresh();
1673*4c8945a0SNathan Whitehorn 
1674*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1675*4c8945a0SNathan Whitehorn 	    if (p->shadow)
1676*4c8945a0SNathan Whitehorn 		draw_childs_shadow(p->shadow, win);
1677*4c8945a0SNathan Whitehorn #endif
1678*4c8945a0SNathan Whitehorn 	}
1679*4c8945a0SNathan Whitehorn     }
1680*4c8945a0SNathan Whitehorn }
1681*4c8945a0SNathan Whitehorn #endif /* KEY_RESIZE */
1682*4c8945a0SNathan Whitehorn 
1683*4c8945a0SNathan Whitehorn WINDOW *
1684*4c8945a0SNathan Whitehorn dlg_sub_window(WINDOW *parent, int height, int width, int y, int x)
1685*4c8945a0SNathan Whitehorn {
1686*4c8945a0SNathan Whitehorn     WINDOW *win;
1687*4c8945a0SNathan Whitehorn 
1688*4c8945a0SNathan Whitehorn     if ((win = subwin(parent, height, width, y, x)) == 0) {
1689*4c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n",
1690*4c8945a0SNathan Whitehorn 		    y, x, height, width);
1691*4c8945a0SNathan Whitehorn     }
1692*4c8945a0SNathan Whitehorn 
1693*4c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
1694*4c8945a0SNathan Whitehorn     return win;
1695*4c8945a0SNathan Whitehorn }
1696*4c8945a0SNathan Whitehorn 
1697*4c8945a0SNathan Whitehorn /* obsolete */
1698*4c8945a0SNathan Whitehorn int
1699*4c8945a0SNathan Whitehorn dlg_default_item(char **items, int llen)
1700*4c8945a0SNathan Whitehorn {
1701*4c8945a0SNathan Whitehorn     int result = 0;
1702*4c8945a0SNathan Whitehorn 
1703*4c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
1704*4c8945a0SNathan Whitehorn 	int count = 0;
1705*4c8945a0SNathan Whitehorn 	while (*items != 0) {
1706*4c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, *items)) {
1707*4c8945a0SNathan Whitehorn 		result = count;
1708*4c8945a0SNathan Whitehorn 		break;
1709*4c8945a0SNathan Whitehorn 	    }
1710*4c8945a0SNathan Whitehorn 	    items += llen;
1711*4c8945a0SNathan Whitehorn 	    count++;
1712*4c8945a0SNathan Whitehorn 	}
1713*4c8945a0SNathan Whitehorn     }
1714*4c8945a0SNathan Whitehorn     return result;
1715*4c8945a0SNathan Whitehorn }
1716*4c8945a0SNathan Whitehorn 
1717*4c8945a0SNathan Whitehorn int
1718*4c8945a0SNathan Whitehorn dlg_default_listitem(DIALOG_LISTITEM * items)
1719*4c8945a0SNathan Whitehorn {
1720*4c8945a0SNathan Whitehorn     int result = 0;
1721*4c8945a0SNathan Whitehorn 
1722*4c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
1723*4c8945a0SNathan Whitehorn 	int count = 0;
1724*4c8945a0SNathan Whitehorn 	while (items->name != 0) {
1725*4c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, items->name)) {
1726*4c8945a0SNathan Whitehorn 		result = count;
1727*4c8945a0SNathan Whitehorn 		break;
1728*4c8945a0SNathan Whitehorn 	    }
1729*4c8945a0SNathan Whitehorn 	    ++items;
1730*4c8945a0SNathan Whitehorn 	    count++;
1731*4c8945a0SNathan Whitehorn 	}
1732*4c8945a0SNathan Whitehorn     }
1733*4c8945a0SNathan Whitehorn     return result;
1734*4c8945a0SNathan Whitehorn }
1735*4c8945a0SNathan Whitehorn 
1736*4c8945a0SNathan Whitehorn /*
1737*4c8945a0SNathan Whitehorn  * Draw the string for item_help
1738*4c8945a0SNathan Whitehorn  */
1739*4c8945a0SNathan Whitehorn void
1740*4c8945a0SNathan Whitehorn dlg_item_help(const char *txt)
1741*4c8945a0SNathan Whitehorn {
1742*4c8945a0SNathan Whitehorn     if (USE_ITEM_HELP(txt)) {
1743*4c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
1744*4c8945a0SNathan Whitehorn 	int y, x;
1745*4c8945a0SNathan Whitehorn 
1746*4c8945a0SNathan Whitehorn 	wattrset(stdscr, itemhelp_attr);
1747*4c8945a0SNathan Whitehorn 	(void) wmove(stdscr, LINES - 1, 0);
1748*4c8945a0SNathan Whitehorn 	(void) wclrtoeol(stdscr);
1749*4c8945a0SNathan Whitehorn 	(void) addch(' ');
1750*4c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, txt, COLS - 1, &attr);
1751*4c8945a0SNathan Whitehorn 	if (itemhelp_attr & A_COLOR) {
1752*4c8945a0SNathan Whitehorn 	    /* fill the remainder of the line with the window's attributes */
1753*4c8945a0SNathan Whitehorn 	    getyx(stdscr, y, x);
1754*4c8945a0SNathan Whitehorn 	    while (x < COLS) {
1755*4c8945a0SNathan Whitehorn 		(void) addch(' ');
1756*4c8945a0SNathan Whitehorn 		++x;
1757*4c8945a0SNathan Whitehorn 	    }
1758*4c8945a0SNathan Whitehorn 	}
1759*4c8945a0SNathan Whitehorn 	(void) wnoutrefresh(stdscr);
1760*4c8945a0SNathan Whitehorn     }
1761*4c8945a0SNathan Whitehorn }
1762*4c8945a0SNathan Whitehorn 
1763*4c8945a0SNathan Whitehorn #ifndef HAVE_STRCASECMP
1764*4c8945a0SNathan Whitehorn int
1765*4c8945a0SNathan Whitehorn dlg_strcmp(const char *a, const char *b)
1766*4c8945a0SNathan Whitehorn {
1767*4c8945a0SNathan Whitehorn     int ac, bc, cmp;
1768*4c8945a0SNathan Whitehorn 
1769*4c8945a0SNathan Whitehorn     for (;;) {
1770*4c8945a0SNathan Whitehorn 	ac = UCH(*a++);
1771*4c8945a0SNathan Whitehorn 	bc = UCH(*b++);
1772*4c8945a0SNathan Whitehorn 	if (isalpha(ac) && islower(ac))
1773*4c8945a0SNathan Whitehorn 	    ac = _toupper(ac);
1774*4c8945a0SNathan Whitehorn 	if (isalpha(bc) && islower(bc))
1775*4c8945a0SNathan Whitehorn 	    bc = _toupper(bc);
1776*4c8945a0SNathan Whitehorn 	cmp = ac - bc;
1777*4c8945a0SNathan Whitehorn 	if (ac == 0 || bc == 0 || cmp != 0)
1778*4c8945a0SNathan Whitehorn 	    break;
1779*4c8945a0SNathan Whitehorn     }
1780*4c8945a0SNathan Whitehorn     return cmp;
1781*4c8945a0SNathan Whitehorn }
1782*4c8945a0SNathan Whitehorn #endif
1783*4c8945a0SNathan Whitehorn 
1784*4c8945a0SNathan Whitehorn /*
1785*4c8945a0SNathan Whitehorn  * Returns true if 'dst' points to a blank which follows another blank which
1786*4c8945a0SNathan Whitehorn  * is not a leading blank on a line.
1787*4c8945a0SNathan Whitehorn  */
1788*4c8945a0SNathan Whitehorn static bool
1789*4c8945a0SNathan Whitehorn trim_blank(char *base, char *dst)
1790*4c8945a0SNathan Whitehorn {
1791*4c8945a0SNathan Whitehorn     int count = 0;
1792*4c8945a0SNathan Whitehorn 
1793*4c8945a0SNathan Whitehorn     while (dst-- != base) {
1794*4c8945a0SNathan Whitehorn 	if (*dst == '\n') {
1795*4c8945a0SNathan Whitehorn 	    return FALSE;
1796*4c8945a0SNathan Whitehorn 	} else if (*dst != ' ') {
1797*4c8945a0SNathan Whitehorn 	    return (count > 1);
1798*4c8945a0SNathan Whitehorn 	} else {
1799*4c8945a0SNathan Whitehorn 	    count++;
1800*4c8945a0SNathan Whitehorn 	}
1801*4c8945a0SNathan Whitehorn     }
1802*4c8945a0SNathan Whitehorn     return FALSE;
1803*4c8945a0SNathan Whitehorn }
1804*4c8945a0SNathan Whitehorn 
1805*4c8945a0SNathan Whitehorn /*
1806*4c8945a0SNathan Whitehorn  * Change embedded "\n" substrings to '\n' characters and tabs to single
1807*4c8945a0SNathan Whitehorn  * spaces.  If there are no "\n"s, it will strip all extra spaces, for
1808*4c8945a0SNathan Whitehorn  * justification.  If it has "\n"'s, it will preserve extra spaces.  If cr_wrap
1809*4c8945a0SNathan Whitehorn  * is set, it will preserve '\n's.
1810*4c8945a0SNathan Whitehorn  */
1811*4c8945a0SNathan Whitehorn void
1812*4c8945a0SNathan Whitehorn dlg_trim_string(char *s)
1813*4c8945a0SNathan Whitehorn {
1814*4c8945a0SNathan Whitehorn     char *base = s;
1815*4c8945a0SNathan Whitehorn     char *p1;
1816*4c8945a0SNathan Whitehorn     char *p = s;
1817*4c8945a0SNathan Whitehorn     int has_newlines = (strstr(s, "\\n") != 0);
1818*4c8945a0SNathan Whitehorn 
1819*4c8945a0SNathan Whitehorn     while (*p != '\0') {
1820*4c8945a0SNathan Whitehorn 	if (*p == TAB && !dialog_vars.nocollapse)
1821*4c8945a0SNathan Whitehorn 	    *p = ' ';
1822*4c8945a0SNathan Whitehorn 
1823*4c8945a0SNathan Whitehorn 	if (has_newlines) {	/* If prompt contains "\n" strings */
1824*4c8945a0SNathan Whitehorn 	    if (*p == '\\' && *(p + 1) == 'n') {
1825*4c8945a0SNathan Whitehorn 		*s++ = '\n';
1826*4c8945a0SNathan Whitehorn 		p += 2;
1827*4c8945a0SNathan Whitehorn 		p1 = p;
1828*4c8945a0SNathan Whitehorn 		/*
1829*4c8945a0SNathan Whitehorn 		 * Handle end of lines intelligently.  If '\n' follows "\n"
1830*4c8945a0SNathan Whitehorn 		 * then ignore the '\n'.  This eliminates the need to escape
1831*4c8945a0SNathan Whitehorn 		 * the '\n' character (no need to use "\n\").
1832*4c8945a0SNathan Whitehorn 		 */
1833*4c8945a0SNathan Whitehorn 		while (*p1 == ' ')
1834*4c8945a0SNathan Whitehorn 		    p1++;
1835*4c8945a0SNathan Whitehorn 		if (*p1 == '\n')
1836*4c8945a0SNathan Whitehorn 		    p = p1 + 1;
1837*4c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
1838*4c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
1839*4c8945a0SNathan Whitehorn 		    *s++ = *p++;
1840*4c8945a0SNathan Whitehorn 		else {
1841*4c8945a0SNathan Whitehorn 		    /* Replace the '\n' with a space if cr_wrap is not set */
1842*4c8945a0SNathan Whitehorn 		    if (!trim_blank(base, s))
1843*4c8945a0SNathan Whitehorn 			*s++ = ' ';
1844*4c8945a0SNathan Whitehorn 		    p++;
1845*4c8945a0SNathan Whitehorn 		}
1846*4c8945a0SNathan Whitehorn 	    } else		/* If *p != '\n' */
1847*4c8945a0SNathan Whitehorn 		*s++ = *p++;
1848*4c8945a0SNathan Whitehorn 	} else if (dialog_vars.trim_whitespace) {
1849*4c8945a0SNathan Whitehorn 	    if (*p == ' ') {
1850*4c8945a0SNathan Whitehorn 		if (*(s - 1) != ' ') {
1851*4c8945a0SNathan Whitehorn 		    *s++ = ' ';
1852*4c8945a0SNathan Whitehorn 		    p++;
1853*4c8945a0SNathan Whitehorn 		} else
1854*4c8945a0SNathan Whitehorn 		    p++;
1855*4c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
1856*4c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
1857*4c8945a0SNathan Whitehorn 		    *s++ = *p++;
1858*4c8945a0SNathan Whitehorn 		else if (*(s - 1) != ' ') {
1859*4c8945a0SNathan Whitehorn 		    /* Strip '\n's if cr_wrap is not set. */
1860*4c8945a0SNathan Whitehorn 		    *s++ = ' ';
1861*4c8945a0SNathan Whitehorn 		    p++;
1862*4c8945a0SNathan Whitehorn 		} else
1863*4c8945a0SNathan Whitehorn 		    p++;
1864*4c8945a0SNathan Whitehorn 	    } else
1865*4c8945a0SNathan Whitehorn 		*s++ = *p++;
1866*4c8945a0SNathan Whitehorn 	} else {		/* If there are no "\n" strings */
1867*4c8945a0SNathan Whitehorn 	    if (*p == ' ' && !dialog_vars.nocollapse) {
1868*4c8945a0SNathan Whitehorn 		if (!trim_blank(base, s))
1869*4c8945a0SNathan Whitehorn 		    *s++ = *p;
1870*4c8945a0SNathan Whitehorn 		p++;
1871*4c8945a0SNathan Whitehorn 	    } else
1872*4c8945a0SNathan Whitehorn 		*s++ = *p++;
1873*4c8945a0SNathan Whitehorn 	}
1874*4c8945a0SNathan Whitehorn     }
1875*4c8945a0SNathan Whitehorn 
1876*4c8945a0SNathan Whitehorn     *s = '\0';
1877*4c8945a0SNathan Whitehorn }
1878*4c8945a0SNathan Whitehorn 
1879*4c8945a0SNathan Whitehorn void
1880*4c8945a0SNathan Whitehorn dlg_set_focus(WINDOW *parent, WINDOW *win)
1881*4c8945a0SNathan Whitehorn {
1882*4c8945a0SNathan Whitehorn     if (win != 0) {
1883*4c8945a0SNathan Whitehorn 	(void) wmove(parent,
1884*4c8945a0SNathan Whitehorn 		     getpary(win) + getcury(win),
1885*4c8945a0SNathan Whitehorn 		     getparx(win) + getcurx(win));
1886*4c8945a0SNathan Whitehorn 	(void) wnoutrefresh(win);
1887*4c8945a0SNathan Whitehorn 	(void) doupdate();
1888*4c8945a0SNathan Whitehorn     }
1889*4c8945a0SNathan Whitehorn }
1890*4c8945a0SNathan Whitehorn 
1891*4c8945a0SNathan Whitehorn /*
1892*4c8945a0SNathan Whitehorn  * Returns the nominal maximum buffer size.
1893*4c8945a0SNathan Whitehorn  */
1894*4c8945a0SNathan Whitehorn int
1895*4c8945a0SNathan Whitehorn dlg_max_input(int max_len)
1896*4c8945a0SNathan Whitehorn {
1897*4c8945a0SNathan Whitehorn     if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN)
1898*4c8945a0SNathan Whitehorn 	max_len = dialog_vars.max_input;
1899*4c8945a0SNathan Whitehorn 
1900*4c8945a0SNathan Whitehorn     return max_len;
1901*4c8945a0SNathan Whitehorn }
1902*4c8945a0SNathan Whitehorn 
1903*4c8945a0SNathan Whitehorn /*
1904*4c8945a0SNathan Whitehorn  * Free storage used for the result buffer.
1905*4c8945a0SNathan Whitehorn  */
1906*4c8945a0SNathan Whitehorn void
1907*4c8945a0SNathan Whitehorn dlg_clr_result(void)
1908*4c8945a0SNathan Whitehorn {
1909*4c8945a0SNathan Whitehorn     if (dialog_vars.input_length) {
1910*4c8945a0SNathan Whitehorn 	dialog_vars.input_length = 0;
1911*4c8945a0SNathan Whitehorn 	if (dialog_vars.input_result)
1912*4c8945a0SNathan Whitehorn 	    free(dialog_vars.input_result);
1913*4c8945a0SNathan Whitehorn     }
1914*4c8945a0SNathan Whitehorn     dialog_vars.input_result = 0;
1915*4c8945a0SNathan Whitehorn }
1916*4c8945a0SNathan Whitehorn 
1917*4c8945a0SNathan Whitehorn /*
1918*4c8945a0SNathan Whitehorn  * Setup a fixed-buffer for the result.
1919*4c8945a0SNathan Whitehorn  */
1920*4c8945a0SNathan Whitehorn char *
1921*4c8945a0SNathan Whitehorn dlg_set_result(const char *string)
1922*4c8945a0SNathan Whitehorn {
1923*4c8945a0SNathan Whitehorn     unsigned need = string ? strlen(string) + 1 : 0;
1924*4c8945a0SNathan Whitehorn 
1925*4c8945a0SNathan Whitehorn     /* inputstr.c needs a fixed buffer */
1926*4c8945a0SNathan Whitehorn     if (need < MAX_LEN)
1927*4c8945a0SNathan Whitehorn 	need = MAX_LEN;
1928*4c8945a0SNathan Whitehorn 
1929*4c8945a0SNathan Whitehorn     /*
1930*4c8945a0SNathan Whitehorn      * If the buffer is not big enough, allocate a new one.
1931*4c8945a0SNathan Whitehorn      */
1932*4c8945a0SNathan Whitehorn     if (dialog_vars.input_length != 0
1933*4c8945a0SNathan Whitehorn 	|| dialog_vars.input_result == 0
1934*4c8945a0SNathan Whitehorn 	|| need > MAX_LEN) {
1935*4c8945a0SNathan Whitehorn 
1936*4c8945a0SNathan Whitehorn 	dlg_clr_result();
1937*4c8945a0SNathan Whitehorn 
1938*4c8945a0SNathan Whitehorn 	dialog_vars.input_length = need;
1939*4c8945a0SNathan Whitehorn 	dialog_vars.input_result = dlg_malloc(char, need);
1940*4c8945a0SNathan Whitehorn 	assert_ptr(dialog_vars.input_result, "dlg_set_result");
1941*4c8945a0SNathan Whitehorn     }
1942*4c8945a0SNathan Whitehorn 
1943*4c8945a0SNathan Whitehorn     strcpy(dialog_vars.input_result, string ? string : "");
1944*4c8945a0SNathan Whitehorn 
1945*4c8945a0SNathan Whitehorn     return dialog_vars.input_result;
1946*4c8945a0SNathan Whitehorn }
1947*4c8945a0SNathan Whitehorn 
1948*4c8945a0SNathan Whitehorn /*
1949*4c8945a0SNathan Whitehorn  * Accumulate results in dynamically allocated buffer.
1950*4c8945a0SNathan Whitehorn  * If input_length is zero, it is a MAX_LEN buffer belonging to the caller.
1951*4c8945a0SNathan Whitehorn  */
1952*4c8945a0SNathan Whitehorn void
1953*4c8945a0SNathan Whitehorn dlg_add_result(const char *string)
1954*4c8945a0SNathan Whitehorn {
1955*4c8945a0SNathan Whitehorn     unsigned have = (dialog_vars.input_result
1956*4c8945a0SNathan Whitehorn 		     ? strlen(dialog_vars.input_result)
1957*4c8945a0SNathan Whitehorn 		     : 0);
1958*4c8945a0SNathan Whitehorn     unsigned want = strlen(string) + 1 + have;
1959*4c8945a0SNathan Whitehorn 
1960*4c8945a0SNathan Whitehorn     if ((want >= MAX_LEN)
1961*4c8945a0SNathan Whitehorn 	|| (dialog_vars.input_length != 0)
1962*4c8945a0SNathan Whitehorn 	|| (dialog_vars.input_result == 0)) {
1963*4c8945a0SNathan Whitehorn 
1964*4c8945a0SNathan Whitehorn 	if (dialog_vars.input_length == 0
1965*4c8945a0SNathan Whitehorn 	    || dialog_vars.input_result == 0) {
1966*4c8945a0SNathan Whitehorn 
1967*4c8945a0SNathan Whitehorn 	    char *save = dialog_vars.input_result;
1968*4c8945a0SNathan Whitehorn 
1969*4c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
1970*4c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length);
1971*4c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result malloc");
1972*4c8945a0SNathan Whitehorn 	    dialog_vars.input_result[0] = 0;
1973*4c8945a0SNathan Whitehorn 	    if (save != 0)
1974*4c8945a0SNathan Whitehorn 		strcpy(dialog_vars.input_result, save);
1975*4c8945a0SNathan Whitehorn 	} else if (want >= dialog_vars.input_length) {
1976*4c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
1977*4c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_realloc(char,
1978*4c8945a0SNathan Whitehorn 						   dialog_vars.input_length,
1979*4c8945a0SNathan Whitehorn 						   dialog_vars.input_result);
1980*4c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result realloc");
1981*4c8945a0SNathan Whitehorn 	}
1982*4c8945a0SNathan Whitehorn     }
1983*4c8945a0SNathan Whitehorn     strcat(dialog_vars.input_result, string);
1984*4c8945a0SNathan Whitehorn }
1985*4c8945a0SNathan Whitehorn 
1986*4c8945a0SNathan Whitehorn /*
1987*4c8945a0SNathan Whitehorn  * These are characters that (aside from the quote-delimiter) will have to
1988*4c8945a0SNathan Whitehorn  * be escaped in a single- or double-quoted string.
1989*4c8945a0SNathan Whitehorn  */
1990*4c8945a0SNathan Whitehorn #define FIX_SINGLE "\n\\"
1991*4c8945a0SNathan Whitehorn #define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>"
1992*4c8945a0SNathan Whitehorn 
1993*4c8945a0SNathan Whitehorn /*
1994*4c8945a0SNathan Whitehorn  * Returns the quote-delimiter.
1995*4c8945a0SNathan Whitehorn  */
1996*4c8945a0SNathan Whitehorn static const char *
1997*4c8945a0SNathan Whitehorn quote_delimiter(void)
1998*4c8945a0SNathan Whitehorn {
1999*4c8945a0SNathan Whitehorn     return dialog_vars.single_quoted ? "'" : "\"";
2000*4c8945a0SNathan Whitehorn }
2001*4c8945a0SNathan Whitehorn 
2002*4c8945a0SNathan Whitehorn /*
2003*4c8945a0SNathan Whitehorn  * Returns true if we should quote the given string.
2004*4c8945a0SNathan Whitehorn  */
2005*4c8945a0SNathan Whitehorn static bool
2006*4c8945a0SNathan Whitehorn must_quote(char *string)
2007*4c8945a0SNathan Whitehorn {
2008*4c8945a0SNathan Whitehorn     bool code = FALSE;
2009*4c8945a0SNathan Whitehorn 
2010*4c8945a0SNathan Whitehorn     if (*string != '\0') {
2011*4c8945a0SNathan Whitehorn 	unsigned len = strlen(string);
2012*4c8945a0SNathan Whitehorn 	if (strcspn(string, quote_delimiter()) != len)
2013*4c8945a0SNathan Whitehorn 	    code = TRUE;
2014*4c8945a0SNathan Whitehorn 	else if (strcspn(string, "\n\t ") != len)
2015*4c8945a0SNathan Whitehorn 	    code = TRUE;
2016*4c8945a0SNathan Whitehorn 	else
2017*4c8945a0SNathan Whitehorn 	    code = (strcspn(string, FIX_DOUBLE) != len);
2018*4c8945a0SNathan Whitehorn     } else {
2019*4c8945a0SNathan Whitehorn 	code = TRUE;
2020*4c8945a0SNathan Whitehorn     }
2021*4c8945a0SNathan Whitehorn 
2022*4c8945a0SNathan Whitehorn     return code;
2023*4c8945a0SNathan Whitehorn }
2024*4c8945a0SNathan Whitehorn 
2025*4c8945a0SNathan Whitehorn /*
2026*4c8945a0SNathan Whitehorn  * Add a quoted string to the result buffer.
2027*4c8945a0SNathan Whitehorn  */
2028*4c8945a0SNathan Whitehorn void
2029*4c8945a0SNathan Whitehorn dlg_add_quoted(char *string)
2030*4c8945a0SNathan Whitehorn {
2031*4c8945a0SNathan Whitehorn     char temp[2];
2032*4c8945a0SNathan Whitehorn     const char *my_quote = quote_delimiter();
2033*4c8945a0SNathan Whitehorn     const char *must_fix = (dialog_vars.single_quoted
2034*4c8945a0SNathan Whitehorn 			    ? FIX_SINGLE
2035*4c8945a0SNathan Whitehorn 			    : FIX_DOUBLE);
2036*4c8945a0SNathan Whitehorn 
2037*4c8945a0SNathan Whitehorn     if (dialog_vars.quoted || must_quote(string)) {
2038*4c8945a0SNathan Whitehorn 	temp[1] = '\0';
2039*4c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
2040*4c8945a0SNathan Whitehorn 	while (*string != '\0') {
2041*4c8945a0SNathan Whitehorn 	    temp[0] = *string++;
2042*4c8945a0SNathan Whitehorn 	    if (strchr(my_quote, *temp) || strchr(must_fix, *temp))
2043*4c8945a0SNathan Whitehorn 		dlg_add_result("\\");
2044*4c8945a0SNathan Whitehorn 	    dlg_add_result(temp);
2045*4c8945a0SNathan Whitehorn 	}
2046*4c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
2047*4c8945a0SNathan Whitehorn     } else {
2048*4c8945a0SNathan Whitehorn 	dlg_add_result(string);
2049*4c8945a0SNathan Whitehorn     }
2050*4c8945a0SNathan Whitehorn }
2051*4c8945a0SNathan Whitehorn 
2052*4c8945a0SNathan Whitehorn /*
2053*4c8945a0SNathan Whitehorn  * When adding a result, make that depend on whether "--quoted" is used.
2054*4c8945a0SNathan Whitehorn  */
2055*4c8945a0SNathan Whitehorn void
2056*4c8945a0SNathan Whitehorn dlg_add_string(char *string)
2057*4c8945a0SNathan Whitehorn {
2058*4c8945a0SNathan Whitehorn     if (dialog_vars.quoted) {
2059*4c8945a0SNathan Whitehorn 	dlg_add_quoted(string);
2060*4c8945a0SNathan Whitehorn     } else {
2061*4c8945a0SNathan Whitehorn 	dlg_add_result(string);
2062*4c8945a0SNathan Whitehorn     }
2063*4c8945a0SNathan Whitehorn }
2064*4c8945a0SNathan Whitehorn 
2065*4c8945a0SNathan Whitehorn bool
2066*4c8945a0SNathan Whitehorn dlg_need_separator(void)
2067*4c8945a0SNathan Whitehorn {
2068*4c8945a0SNathan Whitehorn     bool result = FALSE;
2069*4c8945a0SNathan Whitehorn 
2070*4c8945a0SNathan Whitehorn     if (dialog_vars.output_separator) {
2071*4c8945a0SNathan Whitehorn 	result = TRUE;
2072*4c8945a0SNathan Whitehorn     } else if (dialog_vars.input_result && *(dialog_vars.input_result)) {
2073*4c8945a0SNathan Whitehorn 	result = TRUE;
2074*4c8945a0SNathan Whitehorn     }
2075*4c8945a0SNathan Whitehorn     return result;
2076*4c8945a0SNathan Whitehorn }
2077*4c8945a0SNathan Whitehorn 
2078*4c8945a0SNathan Whitehorn void
2079*4c8945a0SNathan Whitehorn dlg_add_separator(void)
2080*4c8945a0SNathan Whitehorn {
2081*4c8945a0SNathan Whitehorn     const char *separator = (dialog_vars.separate_output) ? "\n" : " ";
2082*4c8945a0SNathan Whitehorn 
2083*4c8945a0SNathan Whitehorn     if (dialog_vars.output_separator)
2084*4c8945a0SNathan Whitehorn 	separator = dialog_vars.output_separator;
2085*4c8945a0SNathan Whitehorn 
2086*4c8945a0SNathan Whitehorn     dlg_add_result(separator);
2087*4c8945a0SNathan Whitehorn }
2088*4c8945a0SNathan Whitehorn 
2089*4c8945a0SNathan Whitehorn /*
2090*4c8945a0SNathan Whitehorn  * Some widgets support only one value of a given variable - save/restore the
2091*4c8945a0SNathan Whitehorn  * global dialog_vars so we can override it consistently.
2092*4c8945a0SNathan Whitehorn  */
2093*4c8945a0SNathan Whitehorn void
2094*4c8945a0SNathan Whitehorn dlg_save_vars(DIALOG_VARS * vars)
2095*4c8945a0SNathan Whitehorn {
2096*4c8945a0SNathan Whitehorn     *vars = dialog_vars;
2097*4c8945a0SNathan Whitehorn }
2098*4c8945a0SNathan Whitehorn 
2099*4c8945a0SNathan Whitehorn void
2100*4c8945a0SNathan Whitehorn dlg_restore_vars(DIALOG_VARS * vars)
2101*4c8945a0SNathan Whitehorn {
2102*4c8945a0SNathan Whitehorn     dialog_vars = *vars;
2103*4c8945a0SNathan Whitehorn }
2104*4c8945a0SNathan Whitehorn 
2105*4c8945a0SNathan Whitehorn /*
2106*4c8945a0SNathan Whitehorn  * Called each time a widget is invoked which may do output, increment a count.
2107*4c8945a0SNathan Whitehorn  */
2108*4c8945a0SNathan Whitehorn void
2109*4c8945a0SNathan Whitehorn dlg_does_output(void)
2110*4c8945a0SNathan Whitehorn {
2111*4c8945a0SNathan Whitehorn     dialog_state.output_count += 1;
2112*4c8945a0SNathan Whitehorn }
2113*4c8945a0SNathan Whitehorn 
2114*4c8945a0SNathan Whitehorn /*
2115*4c8945a0SNathan Whitehorn  * Compatibility for different versions of curses.
2116*4c8945a0SNathan Whitehorn  */
2117*4c8945a0SNathan Whitehorn #if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY))
2118*4c8945a0SNathan Whitehorn int
2119*4c8945a0SNathan Whitehorn getbegx(WINDOW *win)
2120*4c8945a0SNathan Whitehorn {
2121*4c8945a0SNathan Whitehorn     int y, x;
2122*4c8945a0SNathan Whitehorn     getbegyx(win, y, x);
2123*4c8945a0SNathan Whitehorn     return x;
2124*4c8945a0SNathan Whitehorn }
2125*4c8945a0SNathan Whitehorn int
2126*4c8945a0SNathan Whitehorn getbegy(WINDOW *win)
2127*4c8945a0SNathan Whitehorn {
2128*4c8945a0SNathan Whitehorn     int y, x;
2129*4c8945a0SNathan Whitehorn     getbegyx(win, y, x);
2130*4c8945a0SNathan Whitehorn     return y;
2131*4c8945a0SNathan Whitehorn }
2132*4c8945a0SNathan Whitehorn #endif
2133*4c8945a0SNathan Whitehorn 
2134*4c8945a0SNathan Whitehorn #if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY))
2135*4c8945a0SNathan Whitehorn int
2136*4c8945a0SNathan Whitehorn getcurx(WINDOW *win)
2137*4c8945a0SNathan Whitehorn {
2138*4c8945a0SNathan Whitehorn     int y, x;
2139*4c8945a0SNathan Whitehorn     getyx(win, y, x);
2140*4c8945a0SNathan Whitehorn     return x;
2141*4c8945a0SNathan Whitehorn }
2142*4c8945a0SNathan Whitehorn int
2143*4c8945a0SNathan Whitehorn getcury(WINDOW *win)
2144*4c8945a0SNathan Whitehorn {
2145*4c8945a0SNathan Whitehorn     int y, x;
2146*4c8945a0SNathan Whitehorn     getyx(win, y, x);
2147*4c8945a0SNathan Whitehorn     return y;
2148*4c8945a0SNathan Whitehorn }
2149*4c8945a0SNathan Whitehorn #endif
2150*4c8945a0SNathan Whitehorn 
2151*4c8945a0SNathan Whitehorn #if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY))
2152*4c8945a0SNathan Whitehorn int
2153*4c8945a0SNathan Whitehorn getmaxx(WINDOW *win)
2154*4c8945a0SNathan Whitehorn {
2155*4c8945a0SNathan Whitehorn     int y, x;
2156*4c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
2157*4c8945a0SNathan Whitehorn     return x;
2158*4c8945a0SNathan Whitehorn }
2159*4c8945a0SNathan Whitehorn int
2160*4c8945a0SNathan Whitehorn getmaxy(WINDOW *win)
2161*4c8945a0SNathan Whitehorn {
2162*4c8945a0SNathan Whitehorn     int y, x;
2163*4c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
2164*4c8945a0SNathan Whitehorn     return y;
2165*4c8945a0SNathan Whitehorn }
2166*4c8945a0SNathan Whitehorn #endif
2167*4c8945a0SNathan Whitehorn 
2168*4c8945a0SNathan Whitehorn #if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY))
2169*4c8945a0SNathan Whitehorn int
2170*4c8945a0SNathan Whitehorn getparx(WINDOW *win)
2171*4c8945a0SNathan Whitehorn {
2172*4c8945a0SNathan Whitehorn     int y, x;
2173*4c8945a0SNathan Whitehorn     getparyx(win, y, x);
2174*4c8945a0SNathan Whitehorn     return x;
2175*4c8945a0SNathan Whitehorn }
2176*4c8945a0SNathan Whitehorn int
2177*4c8945a0SNathan Whitehorn getpary(WINDOW *win)
2178*4c8945a0SNathan Whitehorn {
2179*4c8945a0SNathan Whitehorn     int y, x;
2180*4c8945a0SNathan Whitehorn     getparyx(win, y, x);
2181*4c8945a0SNathan Whitehorn     return y;
2182*4c8945a0SNathan Whitehorn }
2183*4c8945a0SNathan Whitehorn #endif
2184