1217309Snwhitehorn/*
2255852Sdteske *  $Id: util.c,v 1.258 2013/09/22 00:41:40 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  util.c -- miscellaneous utilities for dialog
5217309Snwhitehorn *
6251843Sbapt *  Copyright 2000-2012,2013	Thomas E. Dickey
7217309Snwhitehorn *
8217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
9217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License, version 2.1
10217309Snwhitehorn *  as published by the Free Software Foundation.
11217309Snwhitehorn *
12217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
13217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
14217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15217309Snwhitehorn *  Lesser General Public License for more details.
16217309Snwhitehorn *
17217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
18217309Snwhitehorn *  License along with this program; if not, write to
19217309Snwhitehorn *	Free Software Foundation, Inc.
20217309Snwhitehorn *	51 Franklin St., Fifth Floor
21217309Snwhitehorn *	Boston, MA 02110, USA.
22217309Snwhitehorn *
23217309Snwhitehorn *  An earlier version of this program lists as authors
24217309Snwhitehorn *	Savio Lam (lam836@cs.cuhk.hk)
25217309Snwhitehorn */
26217309Snwhitehorn
27217309Snwhitehorn#include <dialog.h>
28217309Snwhitehorn#include <dlg_keys.h>
29217309Snwhitehorn
30251843Sbapt#ifdef HAVE_SETLOCALE
31251843Sbapt#include <locale.h>
32251843Sbapt#endif
33251843Sbapt
34251843Sbapt#ifdef NEED_WCHAR_H
35251843Sbapt#include <wchar.h>
36251843Sbapt#endif
37251843Sbapt
38217309Snwhitehorn#ifdef NCURSES_VERSION
39217309Snwhitehorn#if defined(HAVE_NCURSESW_TERM_H)
40217309Snwhitehorn#include <ncursesw/term.h>
41217309Snwhitehorn#elif defined(HAVE_NCURSES_TERM_H)
42217309Snwhitehorn#include <ncurses/term.h>
43217309Snwhitehorn#else
44217309Snwhitehorn#include <term.h>
45217309Snwhitehorn#endif
46217309Snwhitehorn#endif
47217309Snwhitehorn
48224014Snwhitehorn#if defined(HAVE_WCHGAT)
49224014Snwhitehorn#  if defined(NCURSES_VERSION_PATCH)
50224014Snwhitehorn#    if NCURSES_VERSION_PATCH >= 20060715
51224014Snwhitehorn#      define USE_WCHGAT 1
52224014Snwhitehorn#    else
53224014Snwhitehorn#      define USE_WCHGAT 0
54224014Snwhitehorn#    endif
55224014Snwhitehorn#  else
56224014Snwhitehorn#    define USE_WCHGAT 1
57224014Snwhitehorn#  endif
58224014Snwhitehorn#else
59224014Snwhitehorn#  define USE_WCHGAT 0
60224014Snwhitehorn#endif
61224014Snwhitehorn
62217309Snwhitehorn/* globals */
63217309SnwhitehornDIALOG_STATE dialog_state;
64217309SnwhitehornDIALOG_VARS dialog_vars;
65217309Snwhitehorn
66251843Sbapt#if !(defined(HAVE_WGETPARENT) && defined(HAVE_WINDOW__PARENT))
67251843Sbapt#define NEED_WGETPARENT 1
68251843Sbapt#else
69251843Sbapt#undef NEED_WGETPARENT
70251843Sbapt#endif
71251843Sbapt
72217309Snwhitehorn#define concat(a,b) a##b
73217309Snwhitehorn
74217309Snwhitehorn#ifdef HAVE_RC_FILE
75217309Snwhitehorn#define RC_DATA(name,comment) , #name "_color", comment " color"
76217309Snwhitehorn#else
77217309Snwhitehorn#define RC_DATA(name,comment)	/*nothing */
78217309Snwhitehorn#endif
79217309Snwhitehorn
80217309Snwhitehorn#ifdef HAVE_COLOR
81217309Snwhitehorn#include <dlg_colors.h>
82217309Snwhitehorn#define COLOR_DATA(upr) , \
83217309Snwhitehorn	concat(DLGC_FG_,upr), \
84217309Snwhitehorn	concat(DLGC_BG_,upr), \
85217309Snwhitehorn	concat(DLGC_HL_,upr)
86217309Snwhitehorn#else
87217309Snwhitehorn#define COLOR_DATA(upr)		/*nothing */
88217309Snwhitehorn#endif
89217309Snwhitehorn
90217309Snwhitehorn#define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }
91217309Snwhitehorn
92224014Snwhitehorn#define UseShadow(dw) ((dw) != 0 && (dw)->normal != 0 && (dw)->shadow != 0)
93224014Snwhitehorn
94217309Snwhitehorn/*
95217309Snwhitehorn * Table of color and attribute values, default is for mono display.
96251843Sbapt * The order matches the DIALOG_ATR() values.
97217309Snwhitehorn */
98217309Snwhitehorn/* *INDENT-OFF* */
99217309SnwhitehornDIALOG_COLORS dlg_color_table[] =
100217309Snwhitehorn{
101217309Snwhitehorn    DATA(A_NORMAL,	SCREEN,			screen, "Screen"),
102217309Snwhitehorn    DATA(A_NORMAL,	SHADOW,			shadow, "Shadow"),
103217309Snwhitehorn    DATA(A_REVERSE,	DIALOG,			dialog, "Dialog box"),
104217309Snwhitehorn    DATA(A_REVERSE,	TITLE,			title, "Dialog box title"),
105217309Snwhitehorn    DATA(A_REVERSE,	BORDER,			border, "Dialog box border"),
106217309Snwhitehorn    DATA(A_BOLD,	BUTTON_ACTIVE,		button_active, "Active button"),
107217309Snwhitehorn    DATA(A_DIM,		BUTTON_INACTIVE,	button_inactive, "Inactive button"),
108217309Snwhitehorn    DATA(A_UNDERLINE,	BUTTON_KEY_ACTIVE,	button_key_active, "Active button key"),
109217309Snwhitehorn    DATA(A_UNDERLINE,	BUTTON_KEY_INACTIVE,	button_key_inactive, "Inactive button key"),
110217309Snwhitehorn    DATA(A_NORMAL,	BUTTON_LABEL_ACTIVE,	button_label_active, "Active button label"),
111217309Snwhitehorn    DATA(A_NORMAL,	BUTTON_LABEL_INACTIVE,	button_label_inactive, "Inactive button label"),
112217309Snwhitehorn    DATA(A_REVERSE,	INPUTBOX,		inputbox, "Input box"),
113217309Snwhitehorn    DATA(A_REVERSE,	INPUTBOX_BORDER,	inputbox_border, "Input box border"),
114217309Snwhitehorn    DATA(A_REVERSE,	SEARCHBOX,		searchbox, "Search box"),
115217309Snwhitehorn    DATA(A_REVERSE,	SEARCHBOX_TITLE,	searchbox_title, "Search box title"),
116217309Snwhitehorn    DATA(A_REVERSE,	SEARCHBOX_BORDER,	searchbox_border, "Search box border"),
117217309Snwhitehorn    DATA(A_REVERSE,	POSITION_INDICATOR,	position_indicator, "File position indicator"),
118217309Snwhitehorn    DATA(A_REVERSE,	MENUBOX,		menubox, "Menu box"),
119217309Snwhitehorn    DATA(A_REVERSE,	MENUBOX_BORDER,		menubox_border, "Menu box border"),
120217309Snwhitehorn    DATA(A_REVERSE,	ITEM,			item, "Item"),
121217309Snwhitehorn    DATA(A_NORMAL,	ITEM_SELECTED,		item_selected, "Selected item"),
122217309Snwhitehorn    DATA(A_REVERSE,	TAG,			tag, "Tag"),
123217309Snwhitehorn    DATA(A_REVERSE,	TAG_SELECTED,		tag_selected, "Selected tag"),
124217309Snwhitehorn    DATA(A_NORMAL,	TAG_KEY,		tag_key, "Tag key"),
125217309Snwhitehorn    DATA(A_BOLD,	TAG_KEY_SELECTED,	tag_key_selected, "Selected tag key"),
126217309Snwhitehorn    DATA(A_REVERSE,	CHECK,			check, "Check box"),
127217309Snwhitehorn    DATA(A_REVERSE,	CHECK_SELECTED,		check_selected, "Selected check box"),
128217309Snwhitehorn    DATA(A_REVERSE,	UARROW,			uarrow, "Up arrow"),
129217309Snwhitehorn    DATA(A_REVERSE,	DARROW,			darrow, "Down arrow"),
130217309Snwhitehorn    DATA(A_NORMAL,	ITEMHELP,		itemhelp, "Item help-text"),
131217309Snwhitehorn    DATA(A_BOLD,	FORM_ACTIVE_TEXT,	form_active_text, "Active form text"),
132217309Snwhitehorn    DATA(A_REVERSE,	FORM_TEXT,		form_text, "Form text"),
133220749Snwhitehorn    DATA(A_NORMAL,	FORM_ITEM_READONLY,	form_item_readonly, "Readonly form item"),
134251843Sbapt    DATA(A_REVERSE,	GAUGE,			gauge, "Dialog box gauge"),
135251843Sbapt    DATA(A_REVERSE,	BORDER2,		border2, "Dialog box border2"),
136251843Sbapt    DATA(A_REVERSE,	INPUTBOX_BORDER2,	inputbox_border2, "Input box border2"),
137251843Sbapt    DATA(A_REVERSE,	SEARCHBOX_BORDER2,	searchbox_border2, "Search box border2"),
138251843Sbapt    DATA(A_REVERSE,	MENUBOX_BORDER2,	menubox_border2, "Menu box border2")
139217309Snwhitehorn};
140217309Snwhitehorn/* *INDENT-ON* */
141217309Snwhitehorn
142217309Snwhitehorn/*
143251843Sbapt * Maintain a list of subwindows so that we can delete them to cleanup.
144251843Sbapt * More important, this provides a fallback when wgetparent() is not available.
145251843Sbapt */
146251843Sbaptstatic void
147251843Sbaptadd_subwindow(WINDOW *parent, WINDOW *child)
148251843Sbapt{
149251843Sbapt    DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
150251843Sbapt
151251843Sbapt    if (p != 0) {
152251843Sbapt	p->normal = parent;
153251843Sbapt	p->shadow = child;
154251843Sbapt	p->next = dialog_state.all_subwindows;
155251843Sbapt	dialog_state.all_subwindows = p;
156251843Sbapt    }
157251843Sbapt}
158251843Sbapt
159251843Sbaptstatic void
160251843Sbaptdel_subwindows(WINDOW *parent)
161251843Sbapt{
162251843Sbapt    DIALOG_WINDOWS *p = dialog_state.all_subwindows;
163251843Sbapt    DIALOG_WINDOWS *q = 0;
164251843Sbapt    DIALOG_WINDOWS *r;
165251843Sbapt
166251843Sbapt    while (p != 0) {
167251843Sbapt	if (p->normal == parent) {
168251843Sbapt	    delwin(p->shadow);
169251843Sbapt	    r = p->next;
170251843Sbapt	    if (q == 0) {
171251843Sbapt		dialog_state.all_subwindows = r;
172251843Sbapt	    } else {
173251843Sbapt		q->next = r;
174251843Sbapt	    }
175251843Sbapt	    free(p);
176251843Sbapt	    p = r;
177251843Sbapt	} else {
178251843Sbapt	    q = p;
179251843Sbapt	    p = p->next;
180251843Sbapt	}
181251843Sbapt    }
182251843Sbapt}
183251843Sbapt
184251843Sbapt/*
185217309Snwhitehorn * Display background title if it exists ...
186217309Snwhitehorn */
187217309Snwhitehornvoid
188217309Snwhitehorndlg_put_backtitle(void)
189217309Snwhitehorn{
190217309Snwhitehorn    int i;
191217309Snwhitehorn
192217309Snwhitehorn    if (dialog_vars.backtitle != NULL) {
193217309Snwhitehorn	chtype attr = A_NORMAL;
194217309Snwhitehorn	int backwidth = dlg_count_columns(dialog_vars.backtitle);
195217309Snwhitehorn
196251843Sbapt	(void) wattrset(stdscr, screen_attr);
197217309Snwhitehorn	(void) wmove(stdscr, 0, 1);
198217309Snwhitehorn	dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);
199217309Snwhitehorn	for (i = 0; i < COLS - backwidth; i++)
200217309Snwhitehorn	    (void) waddch(stdscr, ' ');
201217309Snwhitehorn	(void) wmove(stdscr, 1, 1);
202217309Snwhitehorn	for (i = 0; i < COLS - 2; i++)
203217309Snwhitehorn	    (void) waddch(stdscr, dlg_boxchar(ACS_HLINE));
204217309Snwhitehorn    }
205217309Snwhitehorn
206217309Snwhitehorn    (void) wnoutrefresh(stdscr);
207217309Snwhitehorn}
208217309Snwhitehorn
209217309Snwhitehorn/*
210217309Snwhitehorn * Set window to attribute 'attr'.  There are more efficient ways to do this,
211217309Snwhitehorn * but will not work on older/buggy ncurses versions.
212217309Snwhitehorn */
213217309Snwhitehornvoid
214217309Snwhitehorndlg_attr_clear(WINDOW *win, int height, int width, chtype attr)
215217309Snwhitehorn{
216217309Snwhitehorn    int i, j;
217217309Snwhitehorn
218251843Sbapt    (void) wattrset(win, attr);
219217309Snwhitehorn    for (i = 0; i < height; i++) {
220217309Snwhitehorn	(void) wmove(win, i, 0);
221217309Snwhitehorn	for (j = 0; j < width; j++)
222217309Snwhitehorn	    (void) waddch(win, ' ');
223217309Snwhitehorn    }
224217309Snwhitehorn    (void) touchwin(win);
225217309Snwhitehorn}
226217309Snwhitehorn
227217309Snwhitehornvoid
228217309Snwhitehorndlg_clear(void)
229217309Snwhitehorn{
230217309Snwhitehorn    dlg_attr_clear(stdscr, LINES, COLS, screen_attr);
231217309Snwhitehorn}
232217309Snwhitehorn
233217309Snwhitehorn#define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)
234217309Snwhitehorn
235217309Snwhitehorn#define TTY_DEVICE "/dev/tty"
236217309Snwhitehorn
237217309Snwhitehorn/*
238217309Snwhitehorn * If $DIALOG_TTY exists, allow the program to try to open the terminal
239217309Snwhitehorn * directly when stdout is redirected.  By default we require the "--stdout"
240217309Snwhitehorn * option to be given, but some scripts were written making use of the
241217309Snwhitehorn * behavior of dialog which tried opening the terminal anyway.
242217309Snwhitehorn */
243217309Snwhitehornstatic char *
244217309Snwhitehorndialog_tty(void)
245217309Snwhitehorn{
246217309Snwhitehorn    char *result = getenv("DIALOG_TTY");
247217309Snwhitehorn    if (result != 0 && atoi(result) == 0)
248217309Snwhitehorn	result = 0;
249217309Snwhitehorn    return result;
250217309Snwhitehorn}
251217309Snwhitehorn
252217309Snwhitehorn/*
253217309Snwhitehorn * Open the terminal directly.  If one of stdin, stdout or stderr really points
254217309Snwhitehorn * to a tty, use it.  Otherwise give up and open /dev/tty.
255217309Snwhitehorn */
256217309Snwhitehornstatic int
257217309Snwhitehornopen_terminal(char **result, int mode)
258217309Snwhitehorn{
259217309Snwhitehorn    const char *device = TTY_DEVICE;
260217309Snwhitehorn    if (!isatty(fileno(stderr))
261217309Snwhitehorn	|| (device = ttyname(fileno(stderr))) == 0) {
262217309Snwhitehorn	if (!isatty(fileno(stdout))
263217309Snwhitehorn	    || (device = ttyname(fileno(stdout))) == 0) {
264217309Snwhitehorn	    if (!isatty(fileno(stdin))
265217309Snwhitehorn		|| (device = ttyname(fileno(stdin))) == 0) {
266217309Snwhitehorn		device = TTY_DEVICE;
267217309Snwhitehorn	    }
268217309Snwhitehorn	}
269217309Snwhitehorn    }
270217309Snwhitehorn    *result = dlg_strclone(device);
271217309Snwhitehorn    return open(device, mode);
272217309Snwhitehorn}
273217309Snwhitehorn
274251843Sbapt#ifdef NCURSES_VERSION
275251843Sbaptstatic int
276251843Sbaptmy_putc(int ch)
277251843Sbapt{
278251843Sbapt    char buffer[2];
279251843Sbapt    int fd = fileno(dialog_state.screen_output);
280251843Sbapt
281251843Sbapt    buffer[0] = (char) ch;
282251843Sbapt    return (int) write(fd, buffer, (size_t) 1);
283251843Sbapt}
284251843Sbapt#endif
285251843Sbapt
286217309Snwhitehorn/*
287217309Snwhitehorn * Do some initialization for dialog.
288217309Snwhitehorn *
289217309Snwhitehorn * 'input' is the real tty input of dialog.  Usually it is stdin, but if
290217309Snwhitehorn * --input-fd option is used, it may be anything.
291217309Snwhitehorn *
292217309Snwhitehorn * 'output' is where dialog will send its result.  Usually it is stderr, but
293217309Snwhitehorn * if --stdout or --output-fd is used, it may be anything.  We are concerned
294217309Snwhitehorn * mainly with the case where it happens to be the same as stdout.
295217309Snwhitehorn */
296217309Snwhitehornvoid
297217309Snwhitehorninit_dialog(FILE *input, FILE *output)
298217309Snwhitehorn{
299217309Snwhitehorn    int fd1, fd2;
300217309Snwhitehorn    char *device = 0;
301217309Snwhitehorn
302251843Sbapt    setlocale(LC_ALL, "");
303251843Sbapt
304217309Snwhitehorn    dialog_state.output = output;
305217309Snwhitehorn    dialog_state.tab_len = TAB_LEN;
306217309Snwhitehorn    dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;
307217309Snwhitehorn#ifdef HAVE_COLOR
308217309Snwhitehorn    dialog_state.use_colors = USE_COLORS;	/* use colors by default? */
309217309Snwhitehorn    dialog_state.use_shadow = USE_SHADOW;	/* shadow dialog boxes by default? */
310217309Snwhitehorn#endif
311217309Snwhitehorn
312217309Snwhitehorn#ifdef HAVE_RC_FILE
313217309Snwhitehorn    if (dlg_parse_rc() == -1)	/* Read the configuration file */
314217309Snwhitehorn	dlg_exiterr("init_dialog: dlg_parse_rc");
315217309Snwhitehorn#endif
316217309Snwhitehorn
317217309Snwhitehorn    /*
318217309Snwhitehorn     * Some widgets (such as gauge) may read from the standard input.  Pipes
319217309Snwhitehorn     * only connect stdout/stdin, so there is not much choice.  But reading a
320217309Snwhitehorn     * pipe would get in the way of curses' normal reading stdin for getch.
321217309Snwhitehorn     *
322217309Snwhitehorn     * As in the --stdout (see below), reopening the terminal does not always
323217309Snwhitehorn     * work properly.  dialog provides a --pipe-fd option for this purpose.  We
324217309Snwhitehorn     * test that case first (differing fileno's for input/stdin).  If the
325217309Snwhitehorn     * fileno's are equal, but we're not reading from a tty, see if we can open
326217309Snwhitehorn     * /dev/tty.
327217309Snwhitehorn     */
328217309Snwhitehorn    dialog_state.pipe_input = stdin;
329217309Snwhitehorn    if (fileno(input) != fileno(stdin)) {
330244850Snwhitehorn	if ((fd1 = dup(fileno(input))) >= 0
331217309Snwhitehorn	    && (fd2 = dup(fileno(stdin))) >= 0) {
332217309Snwhitehorn	    (void) dup2(fileno(input), fileno(stdin));
333217309Snwhitehorn	    dialog_state.pipe_input = fdopen(fd2, "r");
334217309Snwhitehorn	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */
335217309Snwhitehorn		(void) dup2(fileno(stdin), 0);
336251843Sbapt	} else {
337217309Snwhitehorn	    dlg_exiterr("cannot open tty-input");
338251843Sbapt	}
339251843Sbapt	close(fd1);
340217309Snwhitehorn    } else if (!isatty(fileno(stdin))) {
341251843Sbapt	if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0) {
342251843Sbapt	    if ((fd2 = dup(fileno(stdin))) >= 0) {
343251843Sbapt		dialog_state.pipe_input = fdopen(fd2, "r");
344251843Sbapt		if (freopen(device, "r", stdin) == 0)
345251843Sbapt		    dlg_exiterr("cannot open tty-input");
346251843Sbapt		if (fileno(stdin) != 0)		/* some functions may read fd #0 */
347251843Sbapt		    (void) dup2(fileno(stdin), 0);
348251843Sbapt	    }
349251843Sbapt	    close(fd1);
350217309Snwhitehorn	}
351217309Snwhitehorn	free(device);
352217309Snwhitehorn    }
353217309Snwhitehorn
354217309Snwhitehorn    /*
355217309Snwhitehorn     * If stdout is not a tty and dialog is called with the --stdout option, we
356217309Snwhitehorn     * have to provide for a way to write to the screen.
357217309Snwhitehorn     *
358217309Snwhitehorn     * The curses library normally writes its output to stdout, leaving stderr
359217309Snwhitehorn     * free for scripting.  Scripts are simpler when stdout is redirected.  The
360217309Snwhitehorn     * newterm function is useful; it allows us to specify where the output
361217309Snwhitehorn     * goes.  Reopening the terminal is not portable since several
362217309Snwhitehorn     * configurations do not allow this to work properly:
363217309Snwhitehorn     *
364217309Snwhitehorn     * a) some getty implementations (and possibly broken tty drivers, e.g., on
365217309Snwhitehorn     *    HPUX 10 and 11) cause stdin to act as if it is still in cooked mode
366217309Snwhitehorn     *    even though results from ioctl's state that it is successfully
367217309Snwhitehorn     *    altered to raw mode.  Broken is the proper term.
368217309Snwhitehorn     *
369217309Snwhitehorn     * b) the user may not have permissions on the device, e.g., if one su's
370217309Snwhitehorn     *    from the login user to another non-privileged user.
371217309Snwhitehorn     */
372217309Snwhitehorn    if (!isatty(fileno(stdout))
373217309Snwhitehorn	&& (fileno(stdout) == fileno(output) || dialog_tty())) {
374217309Snwhitehorn	if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0
375217309Snwhitehorn	    && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {
376217309Snwhitehorn	    if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {
377217309Snwhitehorn		dlg_exiterr("cannot initialize curses");
378217309Snwhitehorn	    }
379217309Snwhitehorn	    free(device);
380217309Snwhitehorn	} else {
381217309Snwhitehorn	    dlg_exiterr("cannot open tty-output");
382217309Snwhitehorn	}
383217309Snwhitehorn    } else {
384217309Snwhitehorn	dialog_state.screen_output = stdout;
385217309Snwhitehorn	(void) initscr();
386217309Snwhitehorn    }
387217309Snwhitehorn#ifdef NCURSES_VERSION
388217309Snwhitehorn    /*
389217309Snwhitehorn     * Cancel xterm's alternate-screen mode.
390217309Snwhitehorn     */
391217309Snwhitehorn    if (!dialog_vars.keep_tite
392251843Sbapt	&& (fileno(dialog_state.screen_output) != fileno(stdout)
393217309Snwhitehorn	    || isatty(fileno(dialog_state.screen_output)))
394217309Snwhitehorn	&& key_mouse != 0	/* xterm and kindred */
395217309Snwhitehorn	&& isprivate(enter_ca_mode)
396217309Snwhitehorn	&& isprivate(exit_ca_mode)) {
397217309Snwhitehorn	/*
398251843Sbapt	 * initscr() or newterm() already wrote enter_ca_mode as a side
399217309Snwhitehorn	 * effect of initializing the screen.  It would be nice to not even
400217309Snwhitehorn	 * do that, but we do not really have access to the correct copy of
401217309Snwhitehorn	 * the terminfo description until those functions have been invoked.
402217309Snwhitehorn	 */
403251843Sbapt	(void) refresh();
404251843Sbapt	(void) tputs(exit_ca_mode, 0, my_putc);
405251843Sbapt	(void) tputs(clear_screen, 0, my_putc);
406217309Snwhitehorn	/*
407217309Snwhitehorn	 * Prevent ncurses from switching "back" to the normal screen when
408217309Snwhitehorn	 * exiting from dialog.  That would move the cursor to the original
409217309Snwhitehorn	 * location saved in xterm.  Normally curses sets the cursor position
410217309Snwhitehorn	 * to the first line after the display, but the alternate screen
411217309Snwhitehorn	 * switching is done after that point.
412217309Snwhitehorn	 *
413217309Snwhitehorn	 * Cancelling the strings altogether also works around the buggy
414217309Snwhitehorn	 * implementation of alternate-screen in rxvt, etc., which clear
415217309Snwhitehorn	 * more of the display than they should.
416217309Snwhitehorn	 */
417217309Snwhitehorn	enter_ca_mode = 0;
418217309Snwhitehorn	exit_ca_mode = 0;
419217309Snwhitehorn    }
420217309Snwhitehorn#endif
421217309Snwhitehorn#ifdef HAVE_FLUSHINP
422217309Snwhitehorn    (void) flushinp();
423217309Snwhitehorn#endif
424217309Snwhitehorn    (void) keypad(stdscr, TRUE);
425217309Snwhitehorn    (void) cbreak();
426217309Snwhitehorn    (void) noecho();
427220749Snwhitehorn
428220749Snwhitehorn    if (!dialog_state.no_mouse) {
429220749Snwhitehorn	mouse_open();
430220749Snwhitehorn    }
431220749Snwhitehorn
432217309Snwhitehorn    dialog_state.screen_initialized = TRUE;
433217309Snwhitehorn
434217309Snwhitehorn#ifdef HAVE_COLOR
435217309Snwhitehorn    if (dialog_state.use_colors || dialog_state.use_shadow)
436217309Snwhitehorn	dlg_color_setup();	/* Set up colors */
437217309Snwhitehorn#endif
438217309Snwhitehorn
439217309Snwhitehorn    /* Set screen to screen attribute */
440217309Snwhitehorn    dlg_clear();
441217309Snwhitehorn}
442217309Snwhitehorn
443217309Snwhitehorn#ifdef HAVE_COLOR
444217309Snwhitehornstatic int defined_colors = 1;	/* pair-0 is reserved */
445217309Snwhitehorn/*
446217309Snwhitehorn * Setup for color display
447217309Snwhitehorn */
448217309Snwhitehornvoid
449217309Snwhitehorndlg_color_setup(void)
450217309Snwhitehorn{
451217309Snwhitehorn    unsigned i;
452217309Snwhitehorn
453217309Snwhitehorn    if (has_colors()) {		/* Terminal supports color? */
454217309Snwhitehorn	(void) start_color();
455217309Snwhitehorn
456217309Snwhitehorn#if defined(HAVE_USE_DEFAULT_COLORS)
457217309Snwhitehorn	use_default_colors();
458217309Snwhitehorn#endif
459217309Snwhitehorn
460217309Snwhitehorn#if defined(__NetBSD__) && defined(_CURSES_)
461217309Snwhitehorn#define C_ATTR(x,y) (((x) != 0 ? A_BOLD :  0) | COLOR_PAIR((y)))
462217309Snwhitehorn	/* work around bug in NetBSD curses */
463217309Snwhitehorn	for (i = 0; i < sizeof(dlg_color_table) /
464217309Snwhitehorn	     sizeof(dlg_color_table[0]); i++) {
465217309Snwhitehorn
466217309Snwhitehorn	    /* Initialize color pairs */
467217309Snwhitehorn	    (void) init_pair(i + 1,
468217309Snwhitehorn			     dlg_color_table[i].fg,
469217309Snwhitehorn			     dlg_color_table[i].bg);
470217309Snwhitehorn
471217309Snwhitehorn	    /* Setup color attributes */
472217309Snwhitehorn	    dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);
473217309Snwhitehorn	}
474217309Snwhitehorn	defined_colors = i + 1;
475217309Snwhitehorn#else
476217309Snwhitehorn	for (i = 0; i < sizeof(dlg_color_table) /
477217309Snwhitehorn	     sizeof(dlg_color_table[0]); i++) {
478217309Snwhitehorn
479217309Snwhitehorn	    /* Initialize color pairs */
480217309Snwhitehorn	    chtype color = dlg_color_pair(dlg_color_table[i].fg,
481217309Snwhitehorn					  dlg_color_table[i].bg);
482217309Snwhitehorn
483217309Snwhitehorn	    /* Setup color attributes */
484217309Snwhitehorn	    dlg_color_table[i].atr = ((dlg_color_table[i].hilite
485217309Snwhitehorn				       ? A_BOLD
486217309Snwhitehorn				       : 0)
487217309Snwhitehorn				      | color);
488217309Snwhitehorn	}
489217309Snwhitehorn#endif
490217309Snwhitehorn    } else {
491217309Snwhitehorn	dialog_state.use_colors = FALSE;
492217309Snwhitehorn	dialog_state.use_shadow = FALSE;
493217309Snwhitehorn    }
494217309Snwhitehorn}
495217309Snwhitehorn
496217309Snwhitehornint
497217309Snwhitehorndlg_color_count(void)
498217309Snwhitehorn{
499217309Snwhitehorn    return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]);
500217309Snwhitehorn}
501217309Snwhitehorn
502217309Snwhitehorn/*
503220749Snwhitehorn * Wrapper for getattrs(), or the more cumbersome X/Open wattr_get().
504220749Snwhitehorn */
505220749Snwhitehornchtype
506220749Snwhitehorndlg_get_attrs(WINDOW *win)
507220749Snwhitehorn{
508220749Snwhitehorn    chtype result;
509220749Snwhitehorn#ifdef HAVE_GETATTRS
510224014Snwhitehorn    result = (chtype) getattrs(win);
511220749Snwhitehorn#else
512220749Snwhitehorn    attr_t my_result;
513220749Snwhitehorn    short my_pair;
514220749Snwhitehorn    wattr_get(win, &my_result, &my_pair, NULL);
515220749Snwhitehorn    result = my_result;
516220749Snwhitehorn#endif
517220749Snwhitehorn    return result;
518220749Snwhitehorn}
519220749Snwhitehorn
520220749Snwhitehorn/*
521217309Snwhitehorn * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
522217309Snwhitehorn * have (or can) define a pair with the given color as foreground on the
523217309Snwhitehorn * window's defined background.
524217309Snwhitehorn */
525217309Snwhitehornchtype
526217309Snwhitehorndlg_color_pair(int foreground, int background)
527217309Snwhitehorn{
528217309Snwhitehorn    chtype result = 0;
529217309Snwhitehorn    int pair;
530217309Snwhitehorn    short fg, bg;
531217309Snwhitehorn    bool found = FALSE;
532217309Snwhitehorn
533217309Snwhitehorn    for (pair = 1; pair < defined_colors; ++pair) {
534217309Snwhitehorn	if (pair_content((short) pair, &fg, &bg) != ERR
535217309Snwhitehorn	    && fg == foreground
536217309Snwhitehorn	    && bg == background) {
537217309Snwhitehorn	    result = (chtype) COLOR_PAIR(pair);
538217309Snwhitehorn	    found = TRUE;
539217309Snwhitehorn	    break;
540217309Snwhitehorn	}
541217309Snwhitehorn    }
542217309Snwhitehorn    if (!found && (defined_colors + 1) < COLOR_PAIRS) {
543217309Snwhitehorn	pair = defined_colors++;
544217309Snwhitehorn	(void) init_pair((short) pair, (short) foreground, (short) background);
545217309Snwhitehorn	result = (chtype) COLOR_PAIR(pair);
546217309Snwhitehorn    }
547217309Snwhitehorn    return result;
548217309Snwhitehorn}
549217309Snwhitehorn
550217309Snwhitehorn/*
551217309Snwhitehorn * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
552217309Snwhitehorn * have (or can) define a pair with the given color as foreground on the
553217309Snwhitehorn * window's defined background.
554217309Snwhitehorn */
555217309Snwhitehornstatic chtype
556217309Snwhitehorndefine_color(WINDOW *win, int foreground)
557217309Snwhitehorn{
558220749Snwhitehorn    chtype attrs = dlg_get_attrs(win);
559217309Snwhitehorn    int pair;
560217309Snwhitehorn    short fg, bg, background;
561217309Snwhitehorn
562217309Snwhitehorn    if ((pair = PAIR_NUMBER(attrs)) != 0
563217309Snwhitehorn	&& pair_content((short) pair, &fg, &bg) != ERR) {
564217309Snwhitehorn	background = bg;
565217309Snwhitehorn    } else {
566217309Snwhitehorn	background = COLOR_BLACK;
567217309Snwhitehorn    }
568217309Snwhitehorn    return dlg_color_pair(foreground, background);
569217309Snwhitehorn}
570217309Snwhitehorn#endif
571217309Snwhitehorn
572217309Snwhitehorn/*
573217309Snwhitehorn * End using dialog functions.
574217309Snwhitehorn */
575217309Snwhitehornvoid
576217309Snwhitehornend_dialog(void)
577217309Snwhitehorn{
578217309Snwhitehorn    if (dialog_state.screen_initialized) {
579217309Snwhitehorn	dialog_state.screen_initialized = FALSE;
580217309Snwhitehorn	mouse_close();
581217309Snwhitehorn	(void) endwin();
582217309Snwhitehorn	(void) fflush(stdout);
583217309Snwhitehorn    }
584217309Snwhitehorn}
585217309Snwhitehorn
586224014Snwhitehorn#define ESCAPE_LEN 3
587217309Snwhitehorn#define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))
588217309Snwhitehorn
589251843Sbaptint
590251843Sbaptdlg_count_real_columns(const char *text)
591251843Sbapt{
592255852Sdteske    int result = 0;
593255852Sdteske    if (*text) {
594255852Sdteske	result = dlg_count_columns(text);
595255852Sdteske	if (result && dialog_vars.colors) {
596255852Sdteske	    int hidden = 0;
597255852Sdteske	    while (*text) {
598255852Sdteske		if (dialog_vars.colors && isOurEscape(text)) {
599255852Sdteske		    hidden += ESCAPE_LEN;
600255852Sdteske		    text += ESCAPE_LEN;
601255852Sdteske		} else {
602255852Sdteske		    ++text;
603255852Sdteske		}
604251843Sbapt	    }
605255852Sdteske	    result -= hidden;
606251843Sbapt	}
607251843Sbapt    }
608251843Sbapt    return result;
609251843Sbapt}
610251843Sbapt
611217309Snwhitehornstatic int
612217309Snwhitehorncentered(int width, const char *string)
613217309Snwhitehorn{
614251843Sbapt    int need = dlg_count_real_columns(string);
615217309Snwhitehorn    int left;
616217309Snwhitehorn
617251843Sbapt    left = (width - need) / 2 - 1;
618217309Snwhitehorn    if (left < 0)
619217309Snwhitehorn	left = 0;
620217309Snwhitehorn    return left;
621217309Snwhitehorn}
622217309Snwhitehorn
623220749Snwhitehorn#ifdef USE_WIDE_CURSES
624220749Snwhitehornstatic bool
625220749Snwhitehornis_combining(const char *txt, int *combined)
626220749Snwhitehorn{
627220749Snwhitehorn    bool result = FALSE;
628220749Snwhitehorn
629220749Snwhitehorn    if (*combined == 0) {
630220749Snwhitehorn	if (UCH(*txt) >= 128) {
631220749Snwhitehorn	    wchar_t wch;
632220749Snwhitehorn	    mbstate_t state;
633220749Snwhitehorn	    size_t given = strlen(txt);
634220749Snwhitehorn	    size_t len;
635220749Snwhitehorn
636220749Snwhitehorn	    memset(&state, 0, sizeof(state));
637220749Snwhitehorn	    len = mbrtowc(&wch, txt, given, &state);
638220749Snwhitehorn	    if ((int) len > 0 && wcwidth(wch) == 0) {
639220749Snwhitehorn		*combined = (int) len - 1;
640220749Snwhitehorn		result = TRUE;
641220749Snwhitehorn	    }
642220749Snwhitehorn	}
643220749Snwhitehorn    } else {
644220749Snwhitehorn	result = TRUE;
645220749Snwhitehorn	*combined -= 1;
646220749Snwhitehorn    }
647220749Snwhitehorn    return result;
648220749Snwhitehorn}
649220749Snwhitehorn#endif
650220749Snwhitehorn
651217309Snwhitehorn/*
652251843Sbapt * Print the name (tag) or text from a DIALOG_LISTITEM, highlighting the
653251843Sbapt * first character if selected.
654251843Sbapt */
655251843Sbaptvoid
656251843Sbaptdlg_print_listitem(WINDOW *win,
657251843Sbapt		   const char *text,
658251843Sbapt		   int climit,
659251843Sbapt		   bool first,
660251843Sbapt		   int selected)
661251843Sbapt{
662251843Sbapt    chtype attr = A_NORMAL;
663251843Sbapt    int limit;
664251843Sbapt    const int *cols;
665251843Sbapt    chtype attrs[4];
666251843Sbapt
667251843Sbapt    if (text == 0)
668251843Sbapt	text = "";
669251843Sbapt
670251843Sbapt    if (first) {
671251843Sbapt	const int *indx = dlg_index_wchars(text);
672251843Sbapt	attrs[3] = tag_key_selected_attr;
673251843Sbapt	attrs[2] = tag_key_attr;
674251843Sbapt	attrs[1] = tag_selected_attr;
675251843Sbapt	attrs[0] = tag_attr;
676251843Sbapt
677251843Sbapt	(void) wattrset(win, selected ? attrs[3] : attrs[2]);
678251843Sbapt	(void) waddnstr(win, text, indx[1]);
679251843Sbapt
680251843Sbapt	if ((int) strlen(text) > indx[1]) {
681251843Sbapt	    limit = dlg_limit_columns(text, climit, 1);
682251843Sbapt	    if (limit > 1) {
683251843Sbapt		(void) wattrset(win, selected ? attrs[1] : attrs[0]);
684251843Sbapt		(void) waddnstr(win,
685251843Sbapt				text + indx[1],
686251843Sbapt				indx[limit] - indx[1]);
687251843Sbapt	    }
688251843Sbapt	}
689251843Sbapt    } else {
690251843Sbapt	attrs[1] = item_selected_attr;
691251843Sbapt	attrs[0] = item_attr;
692251843Sbapt
693251843Sbapt	cols = dlg_index_columns(text);
694251843Sbapt	limit = dlg_limit_columns(text, climit, 0);
695251843Sbapt
696251843Sbapt	if (limit > 0) {
697251843Sbapt	    (void) wattrset(win, selected ? attrs[1] : attrs[0]);
698251843Sbapt	    dlg_print_text(win, text, cols[limit], &attr);
699251843Sbapt	}
700251843Sbapt    }
701251843Sbapt}
702251843Sbapt
703251843Sbapt/*
704217309Snwhitehorn * Print up to 'cols' columns from 'text', optionally rendering our escape
705217309Snwhitehorn * sequence for attributes and color.
706217309Snwhitehorn */
707217309Snwhitehornvoid
708217309Snwhitehorndlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr)
709217309Snwhitehorn{
710217309Snwhitehorn    int y_origin, x_origin;
711217309Snwhitehorn    int y_before, x_before = 0;
712217309Snwhitehorn    int y_after, x_after;
713217309Snwhitehorn    int tabbed = 0;
714217309Snwhitehorn    bool thisTab;
715217309Snwhitehorn    bool ended = FALSE;
716217309Snwhitehorn    chtype useattr;
717220749Snwhitehorn#ifdef USE_WIDE_CURSES
718220749Snwhitehorn    int combined = 0;
719220749Snwhitehorn#endif
720217309Snwhitehorn
721217309Snwhitehorn    getyx(win, y_origin, x_origin);
722217309Snwhitehorn    while (cols > 0 && (*txt != '\0')) {
723217309Snwhitehorn	if (dialog_vars.colors) {
724217309Snwhitehorn	    while (isOurEscape(txt)) {
725217309Snwhitehorn		int code;
726217309Snwhitehorn
727217309Snwhitehorn		txt += 2;
728217309Snwhitehorn		switch (code = CharOf(*txt)) {
729217309Snwhitehorn#ifdef HAVE_COLOR
730217309Snwhitehorn		case '0':
731217309Snwhitehorn		case '1':
732217309Snwhitehorn		case '2':
733217309Snwhitehorn		case '3':
734217309Snwhitehorn		case '4':
735217309Snwhitehorn		case '5':
736217309Snwhitehorn		case '6':
737217309Snwhitehorn		case '7':
738217309Snwhitehorn		    *attr &= ~A_COLOR;
739217309Snwhitehorn		    *attr |= define_color(win, code - '0');
740217309Snwhitehorn		    break;
741217309Snwhitehorn#endif
742217309Snwhitehorn		case 'B':
743217309Snwhitehorn		    *attr &= ~A_BOLD;
744217309Snwhitehorn		    break;
745217309Snwhitehorn		case 'b':
746217309Snwhitehorn		    *attr |= A_BOLD;
747217309Snwhitehorn		    break;
748217309Snwhitehorn		case 'R':
749217309Snwhitehorn		    *attr &= ~A_REVERSE;
750217309Snwhitehorn		    break;
751217309Snwhitehorn		case 'r':
752217309Snwhitehorn		    *attr |= A_REVERSE;
753217309Snwhitehorn		    break;
754217309Snwhitehorn		case 'U':
755217309Snwhitehorn		    *attr &= ~A_UNDERLINE;
756217309Snwhitehorn		    break;
757217309Snwhitehorn		case 'u':
758217309Snwhitehorn		    *attr |= A_UNDERLINE;
759217309Snwhitehorn		    break;
760217309Snwhitehorn		case 'n':
761217309Snwhitehorn		    *attr = A_NORMAL;
762217309Snwhitehorn		    break;
763217309Snwhitehorn		}
764217309Snwhitehorn		++txt;
765217309Snwhitehorn	    }
766217309Snwhitehorn	}
767217309Snwhitehorn	if (ended || *txt == '\n' || *txt == '\0')
768217309Snwhitehorn	    break;
769217309Snwhitehorn	useattr = (*attr) & A_ATTRIBUTES;
770217309Snwhitehorn#ifdef HAVE_COLOR
771217309Snwhitehorn	/*
772217309Snwhitehorn	 * Prevent this from making text invisible when the foreground and
773217309Snwhitehorn	 * background colors happen to be the same, and there's no bold
774217309Snwhitehorn	 * attribute.
775217309Snwhitehorn	 */
776217309Snwhitehorn	if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) {
777217309Snwhitehorn	    short pair = (short) PAIR_NUMBER(useattr);
778217309Snwhitehorn	    short fg, bg;
779217309Snwhitehorn	    if (pair_content(pair, &fg, &bg) != ERR
780217309Snwhitehorn		&& fg == bg) {
781217309Snwhitehorn		useattr &= ~A_COLOR;
782217309Snwhitehorn		useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK)
783217309Snwhitehorn					       ? COLOR_WHITE
784217309Snwhitehorn					       : COLOR_BLACK));
785217309Snwhitehorn	    }
786217309Snwhitehorn	}
787217309Snwhitehorn#endif
788217309Snwhitehorn	/*
789217309Snwhitehorn	 * Write the character, using curses to tell exactly how wide it
790217309Snwhitehorn	 * is.  If it is a tab, discount that, since the caller thinks
791217309Snwhitehorn	 * tabs are nonprinting, and curses will expand tabs to one or
792217309Snwhitehorn	 * more blanks.
793217309Snwhitehorn	 */
794217309Snwhitehorn	thisTab = (CharOf(*txt) == TAB);
795251843Sbapt	if (thisTab) {
796217309Snwhitehorn	    getyx(win, y_before, x_before);
797251843Sbapt	    (void) y_before;
798251843Sbapt	}
799217309Snwhitehorn	(void) waddch(win, CharOf(*txt++) | useattr);
800217309Snwhitehorn	getyx(win, y_after, x_after);
801217309Snwhitehorn	if (thisTab && (y_after == y_origin))
802217309Snwhitehorn	    tabbed += (x_after - x_before);
803220749Snwhitehorn	if ((y_after != y_origin) ||
804220749Snwhitehorn	    (x_after >= (cols + tabbed + x_origin)
805220749Snwhitehorn#ifdef USE_WIDE_CURSES
806220749Snwhitehorn	     && !is_combining(txt, &combined)
807220749Snwhitehorn#endif
808220749Snwhitehorn	    )) {
809217309Snwhitehorn	    ended = TRUE;
810217309Snwhitehorn	}
811217309Snwhitehorn    }
812217309Snwhitehorn}
813217309Snwhitehorn
814217309Snwhitehorn/*
815217309Snwhitehorn * Print one line of the prompt in the window within the limits of the
816217309Snwhitehorn * specified right margin.  The line will end on a word boundary and a pointer
817217309Snwhitehorn * to the start of the next line is returned, or a NULL pointer if the end of
818217309Snwhitehorn * *prompt is reached.
819217309Snwhitehorn */
820217309Snwhitehornconst char *
821217309Snwhitehorndlg_print_line(WINDOW *win,
822217309Snwhitehorn	       chtype *attr,
823217309Snwhitehorn	       const char *prompt,
824217309Snwhitehorn	       int lm, int rm, int *x)
825217309Snwhitehorn{
826251843Sbapt    const char *wrap_ptr;
827251843Sbapt    const char *test_ptr;
828224014Snwhitehorn    const char *hide_ptr = 0;
829217309Snwhitehorn    const int *cols = dlg_index_columns(prompt);
830217309Snwhitehorn    const int *indx = dlg_index_wchars(prompt);
831217309Snwhitehorn    int wrap_inx = 0;
832217309Snwhitehorn    int test_inx = 0;
833217309Snwhitehorn    int cur_x = lm;
834217309Snwhitehorn    int hidden = 0;
835217309Snwhitehorn    int limit = dlg_count_wchars(prompt);
836217309Snwhitehorn    int n;
837217309Snwhitehorn    int tabbed = 0;
838217309Snwhitehorn
839217309Snwhitehorn    *x = 1;
840217309Snwhitehorn
841217309Snwhitehorn    /*
842217309Snwhitehorn     * Set *test_ptr to the end of the line or the right margin (rm), whichever
843217309Snwhitehorn     * is less, and set wrap_ptr to the end of the last word in the line.
844217309Snwhitehorn     */
845217309Snwhitehorn    for (n = 0; n < limit; ++n) {
846217309Snwhitehorn	test_ptr = prompt + indx[test_inx];
847217309Snwhitehorn	if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden))
848217309Snwhitehorn	    break;
849217309Snwhitehorn	if (*test_ptr == TAB && n == 0) {
850217309Snwhitehorn	    tabbed = 8;		/* workaround for leading tabs */
851217309Snwhitehorn	} else if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') {
852217309Snwhitehorn	    wrap_inx = n;
853217309Snwhitehorn	    *x = cur_x;
854251843Sbapt	} else if (dialog_vars.colors && isOurEscape(test_ptr)) {
855224014Snwhitehorn	    hide_ptr = test_ptr;
856224014Snwhitehorn	    hidden += ESCAPE_LEN;
857224014Snwhitehorn	    n += (ESCAPE_LEN - 1);
858217309Snwhitehorn	}
859217309Snwhitehorn	cur_x = lm + tabbed + cols[n + 1];
860217309Snwhitehorn	if (cur_x > (rm + hidden))
861217309Snwhitehorn	    break;
862217309Snwhitehorn	test_inx = n + 1;
863217309Snwhitehorn    }
864217309Snwhitehorn
865217309Snwhitehorn    /*
866217309Snwhitehorn     * If the line doesn't reach the right margin in the middle of a word, then
867217309Snwhitehorn     * we don't have to wrap it at the end of the previous word.
868217309Snwhitehorn     */
869217309Snwhitehorn    test_ptr = prompt + indx[test_inx];
870217309Snwhitehorn    if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') {
871217309Snwhitehorn	wrap_inx = test_inx;
872217309Snwhitehorn	while (wrap_inx > 0 && prompt[indx[wrap_inx - 1]] == ' ') {
873217309Snwhitehorn	    wrap_inx--;
874217309Snwhitehorn	}
875217309Snwhitehorn	*x = lm + indx[wrap_inx];
876217309Snwhitehorn    } else if (*x == 1 && cur_x >= rm) {
877217309Snwhitehorn	/*
878217309Snwhitehorn	 * If the line has no spaces, then wrap it anyway at the right margin
879217309Snwhitehorn	 */
880217309Snwhitehorn	*x = rm;
881217309Snwhitehorn	wrap_inx = test_inx;
882217309Snwhitehorn    }
883217309Snwhitehorn    wrap_ptr = prompt + indx[wrap_inx];
884220749Snwhitehorn#ifdef USE_WIDE_CURSES
885220749Snwhitehorn    if (UCH(*wrap_ptr) >= 128) {
886220749Snwhitehorn	int combined = 0;
887220749Snwhitehorn	while (is_combining(wrap_ptr, &combined)) {
888220749Snwhitehorn	    ++wrap_ptr;
889220749Snwhitehorn	}
890220749Snwhitehorn    }
891220749Snwhitehorn#endif
892217309Snwhitehorn
893217309Snwhitehorn    /*
894224014Snwhitehorn     * If we found hidden text past the last point that we will display,
895224014Snwhitehorn     * discount that from the displayed length.
896224014Snwhitehorn     */
897224014Snwhitehorn    if ((hide_ptr != 0) && (hide_ptr >= wrap_ptr)) {
898224014Snwhitehorn	hidden -= ESCAPE_LEN;
899224014Snwhitehorn	test_ptr = wrap_ptr;
900224014Snwhitehorn	while (test_ptr < wrap_ptr) {
901251843Sbapt	    if (dialog_vars.colors && isOurEscape(test_ptr)) {
902224014Snwhitehorn		hidden -= ESCAPE_LEN;
903224014Snwhitehorn		test_ptr += ESCAPE_LEN;
904224014Snwhitehorn	    } else {
905224014Snwhitehorn		++test_ptr;
906224014Snwhitehorn	    }
907224014Snwhitehorn	}
908224014Snwhitehorn    }
909224014Snwhitehorn
910224014Snwhitehorn    /*
911217309Snwhitehorn     * Print the line if we have a window pointer.  Otherwise this routine
912217309Snwhitehorn     * is just being called for sizing the window.
913217309Snwhitehorn     */
914217309Snwhitehorn    if (win) {
915217309Snwhitehorn	dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr);
916217309Snwhitehorn    }
917217309Snwhitehorn
918217309Snwhitehorn    /* *x tells the calling function how long the line was */
919217309Snwhitehorn    if (*x == 1)
920217309Snwhitehorn	*x = rm;
921217309Snwhitehorn
922224014Snwhitehorn    *x -= hidden;
923224014Snwhitehorn
924217309Snwhitehorn    /* Find the start of the next line and return a pointer to it */
925217309Snwhitehorn    test_ptr = wrap_ptr;
926217309Snwhitehorn    while (*test_ptr == ' ')
927217309Snwhitehorn	test_ptr++;
928217309Snwhitehorn    if (*test_ptr == '\n')
929217309Snwhitehorn	test_ptr++;
930255852Sdteske    dlg_finish_string(prompt);
931217309Snwhitehorn    return (test_ptr);
932217309Snwhitehorn}
933217309Snwhitehorn
934217309Snwhitehornstatic void
935217309Snwhitehornjustify_text(WINDOW *win,
936217309Snwhitehorn	     const char *prompt,
937217309Snwhitehorn	     int limit_y,
938217309Snwhitehorn	     int limit_x,
939217309Snwhitehorn	     int *high, int *wide)
940217309Snwhitehorn{
941217309Snwhitehorn    chtype attr = A_NORMAL;
942217309Snwhitehorn    int x = (2 * MARGIN);
943217309Snwhitehorn    int y = MARGIN;
944217309Snwhitehorn    int max_x = 2;
945217309Snwhitehorn    int lm = (2 * MARGIN);	/* left margin (box-border plus a space) */
946217309Snwhitehorn    int rm = limit_x;		/* right margin */
947217309Snwhitehorn    int bm = limit_y;		/* bottom margin */
948217309Snwhitehorn    int last_y = 0, last_x = 0;
949217309Snwhitehorn
950217309Snwhitehorn    if (win) {
951217309Snwhitehorn	rm -= (2 * MARGIN);
952217309Snwhitehorn	bm -= (2 * MARGIN);
953217309Snwhitehorn    }
954217309Snwhitehorn    if (prompt == 0)
955217309Snwhitehorn	prompt = "";
956217309Snwhitehorn
957217309Snwhitehorn    if (win != 0)
958217309Snwhitehorn	getyx(win, last_y, last_x);
959217309Snwhitehorn    while (y <= bm && *prompt) {
960217309Snwhitehorn	x = lm;
961217309Snwhitehorn
962217309Snwhitehorn	if (*prompt == '\n') {
963217309Snwhitehorn	    while (*prompt == '\n' && y < bm) {
964217309Snwhitehorn		if (*(prompt + 1) != '\0') {
965217309Snwhitehorn		    ++y;
966217309Snwhitehorn		    if (win != 0)
967217309Snwhitehorn			(void) wmove(win, y, lm);
968217309Snwhitehorn		}
969217309Snwhitehorn		prompt++;
970217309Snwhitehorn	    }
971217309Snwhitehorn	} else if (win != 0)
972217309Snwhitehorn	    (void) wmove(win, y, lm);
973217309Snwhitehorn
974217309Snwhitehorn	if (*prompt) {
975217309Snwhitehorn	    prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x);
976217309Snwhitehorn	    if (win != 0)
977217309Snwhitehorn		getyx(win, last_y, last_x);
978217309Snwhitehorn	}
979217309Snwhitehorn	if (*prompt) {
980217309Snwhitehorn	    ++y;
981217309Snwhitehorn	    if (win != 0)
982217309Snwhitehorn		(void) wmove(win, y, lm);
983217309Snwhitehorn	}
984217309Snwhitehorn	max_x = MAX(max_x, x);
985217309Snwhitehorn    }
986217309Snwhitehorn    /* Move back to the last position after drawing prompt, for msgbox. */
987217309Snwhitehorn    if (win != 0)
988217309Snwhitehorn	(void) wmove(win, last_y, last_x);
989217309Snwhitehorn
990217309Snwhitehorn    /* Set the final height and width for the calling function */
991217309Snwhitehorn    if (high != 0)
992217309Snwhitehorn	*high = y;
993217309Snwhitehorn    if (wide != 0)
994217309Snwhitehorn	*wide = max_x;
995217309Snwhitehorn}
996217309Snwhitehorn
997217309Snwhitehorn/*
998217309Snwhitehorn * Print a string of text in a window, automatically wrap around to the next
999217309Snwhitehorn * line if the string is too long to fit on one line.  Note that the string may
1000217309Snwhitehorn * contain embedded newlines.
1001217309Snwhitehorn */
1002217309Snwhitehornvoid
1003217309Snwhitehorndlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width)
1004217309Snwhitehorn{
1005217309Snwhitehorn    justify_text(win, prompt,
1006217309Snwhitehorn		 height,
1007217309Snwhitehorn		 width,
1008217309Snwhitehorn		 (int *) 0, (int *) 0);
1009217309Snwhitehorn}
1010217309Snwhitehorn
1011217309Snwhitehorn/*
1012217309Snwhitehorn * Display the message in a scrollable window.  Actually the way it works is
1013217309Snwhitehorn * that we create a "tall" window of the proper width, let the text wrap within
1014217309Snwhitehorn * that, and copy a slice of the result to the dialog.
1015217309Snwhitehorn *
1016217309Snwhitehorn * It works for ncurses.  Other curses implementations show only blanks (Tru64)
1017217309Snwhitehorn * or garbage (NetBSD).
1018217309Snwhitehorn */
1019217309Snwhitehornint
1020217309Snwhitehorndlg_print_scrolled(WINDOW *win,
1021217309Snwhitehorn		   const char *prompt,
1022217309Snwhitehorn		   int offset,
1023217309Snwhitehorn		   int height,
1024217309Snwhitehorn		   int width,
1025217309Snwhitehorn		   int pauseopt)
1026217309Snwhitehorn{
1027217309Snwhitehorn    int oldy, oldx;
1028217309Snwhitehorn    int last = 0;
1029217309Snwhitehorn
1030220749Snwhitehorn    (void) pauseopt;		/* used only for ncurses */
1031220749Snwhitehorn
1032217309Snwhitehorn    getyx(win, oldy, oldx);
1033217309Snwhitehorn#ifdef NCURSES_VERSION
1034217309Snwhitehorn    if (pauseopt) {
1035217309Snwhitehorn	int wide = width - (2 * MARGIN);
1036217309Snwhitehorn	int high = LINES;
1037217309Snwhitehorn	int y, x;
1038217309Snwhitehorn	int len;
1039217309Snwhitehorn	int percent;
1040217309Snwhitehorn	WINDOW *dummy;
1041217309Snwhitehorn	char buffer[5];
1042217309Snwhitehorn
1043217309Snwhitehorn#if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417
1044217309Snwhitehorn	/*
1045217309Snwhitehorn	 * If we're not limited by the screensize, allow text to possibly be
1046217309Snwhitehorn	 * one character per line.
1047217309Snwhitehorn	 */
1048217309Snwhitehorn	if ((len = dlg_count_columns(prompt)) > high)
1049217309Snwhitehorn	    high = len;
1050217309Snwhitehorn#endif
1051217309Snwhitehorn	dummy = newwin(high, width, 0, 0);
1052224014Snwhitehorn	if (dummy == 0) {
1053251843Sbapt	    (void) wattrset(win, dialog_attr);
1054224014Snwhitehorn	    dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
1055224014Snwhitehorn	    last = 0;
1056224014Snwhitehorn	} else {
1057224014Snwhitehorn	    wbkgdset(dummy, dialog_attr | ' ');
1058251843Sbapt	    (void) wattrset(dummy, dialog_attr);
1059224014Snwhitehorn	    werase(dummy);
1060224014Snwhitehorn	    dlg_print_autowrap(dummy, prompt, high, width);
1061224014Snwhitehorn	    getyx(dummy, y, x);
1062251843Sbapt	    (void) x;
1063217309Snwhitehorn
1064224014Snwhitehorn	    copywin(dummy,	/* srcwin */
1065224014Snwhitehorn		    win,	/* dstwin */
1066224014Snwhitehorn		    offset + MARGIN,	/* sminrow */
1067224014Snwhitehorn		    MARGIN,	/* smincol */
1068224014Snwhitehorn		    MARGIN,	/* dminrow */
1069224014Snwhitehorn		    MARGIN,	/* dmincol */
1070224014Snwhitehorn		    height,	/* dmaxrow */
1071224014Snwhitehorn		    wide,	/* dmaxcol */
1072224014Snwhitehorn		    FALSE);
1073217309Snwhitehorn
1074224014Snwhitehorn	    delwin(dummy);
1075217309Snwhitehorn
1076224014Snwhitehorn	    /* if the text is incomplete, or we have scrolled, show the percentage */
1077224014Snwhitehorn	    if (y > 0 && wide > 4) {
1078224014Snwhitehorn		percent = (int) ((height + offset) * 100.0 / y);
1079224014Snwhitehorn		if (percent < 0)
1080224014Snwhitehorn		    percent = 0;
1081224014Snwhitehorn		if (percent > 100)
1082224014Snwhitehorn		    percent = 100;
1083224014Snwhitehorn		if (offset != 0 || percent != 100) {
1084224014Snwhitehorn		    (void) wattrset(win, position_indicator_attr);
1085224014Snwhitehorn		    (void) wmove(win, MARGIN + height, wide - 4);
1086224014Snwhitehorn		    (void) sprintf(buffer, "%d%%", percent);
1087224014Snwhitehorn		    (void) waddstr(win, buffer);
1088224014Snwhitehorn		    if ((len = (int) strlen(buffer)) < 4) {
1089251843Sbapt			(void) wattrset(win, border_attr);
1090224014Snwhitehorn			whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
1091224014Snwhitehorn		    }
1092217309Snwhitehorn		}
1093217309Snwhitehorn	    }
1094224014Snwhitehorn	    last = (y - height);
1095217309Snwhitehorn	}
1096217309Snwhitehorn    } else
1097217309Snwhitehorn#endif
1098217309Snwhitehorn    {
1099217309Snwhitehorn	(void) offset;
1100251843Sbapt	(void) wattrset(win, dialog_attr);
1101217309Snwhitehorn	dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
1102217309Snwhitehorn	last = 0;
1103217309Snwhitehorn    }
1104217309Snwhitehorn    wmove(win, oldy, oldx);
1105217309Snwhitehorn    return last;
1106217309Snwhitehorn}
1107217309Snwhitehorn
1108217309Snwhitehornint
1109217309Snwhitehorndlg_check_scrolled(int key, int last, int page, bool * show, int *offset)
1110217309Snwhitehorn{
1111217309Snwhitehorn    int code = 0;
1112217309Snwhitehorn
1113217309Snwhitehorn    *show = FALSE;
1114217309Snwhitehorn
1115217309Snwhitehorn    switch (key) {
1116217309Snwhitehorn    case DLGK_PAGE_FIRST:
1117217309Snwhitehorn	if (*offset > 0) {
1118217309Snwhitehorn	    *offset = 0;
1119217309Snwhitehorn	    *show = TRUE;
1120217309Snwhitehorn	}
1121217309Snwhitehorn	break;
1122217309Snwhitehorn    case DLGK_PAGE_LAST:
1123217309Snwhitehorn	if (*offset < last) {
1124217309Snwhitehorn	    *offset = last;
1125217309Snwhitehorn	    *show = TRUE;
1126217309Snwhitehorn	}
1127217309Snwhitehorn	break;
1128217309Snwhitehorn    case DLGK_GRID_UP:
1129217309Snwhitehorn	if (*offset > 0) {
1130217309Snwhitehorn	    --(*offset);
1131217309Snwhitehorn	    *show = TRUE;
1132217309Snwhitehorn	}
1133217309Snwhitehorn	break;
1134217309Snwhitehorn    case DLGK_GRID_DOWN:
1135217309Snwhitehorn	if (*offset < last) {
1136217309Snwhitehorn	    ++(*offset);
1137217309Snwhitehorn	    *show = TRUE;
1138217309Snwhitehorn	}
1139217309Snwhitehorn	break;
1140217309Snwhitehorn    case DLGK_PAGE_PREV:
1141217309Snwhitehorn	if (*offset > 0) {
1142217309Snwhitehorn	    *offset -= page;
1143217309Snwhitehorn	    if (*offset < 0)
1144217309Snwhitehorn		*offset = 0;
1145217309Snwhitehorn	    *show = TRUE;
1146217309Snwhitehorn	}
1147217309Snwhitehorn	break;
1148217309Snwhitehorn    case DLGK_PAGE_NEXT:
1149217309Snwhitehorn	if (*offset < last) {
1150217309Snwhitehorn	    *offset += page;
1151217309Snwhitehorn	    if (*offset > last)
1152217309Snwhitehorn		*offset = last;
1153217309Snwhitehorn	    *show = TRUE;
1154217309Snwhitehorn	}
1155217309Snwhitehorn	break;
1156217309Snwhitehorn    default:
1157217309Snwhitehorn	code = -1;
1158217309Snwhitehorn	break;
1159217309Snwhitehorn    }
1160217309Snwhitehorn    return code;
1161217309Snwhitehorn}
1162217309Snwhitehorn
1163217309Snwhitehorn/*
1164217309Snwhitehorn * Calculate the window size for preformatted text.  This will calculate box
1165217309Snwhitehorn * dimensions that are at or close to the specified aspect ratio for the prompt
1166217309Snwhitehorn * string with all spaces and newlines preserved and additional newlines added
1167217309Snwhitehorn * as necessary.
1168217309Snwhitehorn */
1169217309Snwhitehornstatic void
1170217309Snwhitehornauto_size_preformatted(const char *prompt, int *height, int *width)
1171217309Snwhitehorn{
1172217309Snwhitehorn    int high = 0, wide = 0;
1173217309Snwhitehorn    float car;			/* Calculated Aspect Ratio */
1174217309Snwhitehorn    float diff;
1175217309Snwhitehorn    int max_y = SLINES - 1;
1176217309Snwhitehorn    int max_x = SCOLS - 2;
1177217309Snwhitehorn    int max_width = max_x;
1178217309Snwhitehorn    int ar = dialog_state.aspect_ratio;
1179217309Snwhitehorn
1180217309Snwhitehorn    /* Get the initial dimensions */
1181217309Snwhitehorn    justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
1182217309Snwhitehorn    car = (float) (wide / high);
1183217309Snwhitehorn
1184217309Snwhitehorn    /*
1185217309Snwhitehorn     * If the aspect ratio is greater than it should be, then decrease the
1186217309Snwhitehorn     * width proportionately.
1187217309Snwhitehorn     */
1188217309Snwhitehorn    if (car > ar) {
1189217309Snwhitehorn	diff = car / (float) ar;
1190217309Snwhitehorn	max_x = (int) ((float) wide / diff + 4);
1191217309Snwhitehorn	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
1192217309Snwhitehorn	car = (float) wide / (float) high;
1193217309Snwhitehorn    }
1194217309Snwhitehorn
1195217309Snwhitehorn    /*
1196217309Snwhitehorn     * If the aspect ratio is too small after decreasing the width, then
1197217309Snwhitehorn     * incrementally increase the width until the aspect ratio is equal to or
1198217309Snwhitehorn     * greater than the specified aspect ratio.
1199217309Snwhitehorn     */
1200217309Snwhitehorn    while (car < ar && max_x < max_width) {
1201217309Snwhitehorn	max_x += 4;
1202217309Snwhitehorn	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
1203217309Snwhitehorn	car = (float) (wide / high);
1204217309Snwhitehorn    }
1205217309Snwhitehorn
1206217309Snwhitehorn    *height = high;
1207217309Snwhitehorn    *width = wide;
1208217309Snwhitehorn}
1209217309Snwhitehorn
1210217309Snwhitehorn/*
1211217309Snwhitehorn * Find the length of the longest "word" in the given string.  By setting the
1212217309Snwhitehorn * widget width at least this long, we can avoid splitting a word on the
1213217309Snwhitehorn * margin.
1214217309Snwhitehorn */
1215217309Snwhitehornstatic int
1216217309Snwhitehornlongest_word(const char *string)
1217217309Snwhitehorn{
1218217309Snwhitehorn    int length, result = 0;
1219217309Snwhitehorn
1220217309Snwhitehorn    while (*string != '\0') {
1221217309Snwhitehorn	length = 0;
1222217309Snwhitehorn	while (*string != '\0' && !isspace(UCH(*string))) {
1223217309Snwhitehorn	    length++;
1224217309Snwhitehorn	    string++;
1225217309Snwhitehorn	}
1226217309Snwhitehorn	result = MAX(result, length);
1227217309Snwhitehorn	if (*string != '\0')
1228217309Snwhitehorn	    string++;
1229217309Snwhitehorn    }
1230217309Snwhitehorn    return result;
1231217309Snwhitehorn}
1232217309Snwhitehorn
1233217309Snwhitehorn/*
1234217309Snwhitehorn * if (height or width == -1) Maximize()
1235217309Snwhitehorn * if (height or width == 0), justify and return actual limits.
1236217309Snwhitehorn */
1237217309Snwhitehornstatic void
1238217309Snwhitehornreal_auto_size(const char *title,
1239217309Snwhitehorn	       const char *prompt,
1240217309Snwhitehorn	       int *height, int *width,
1241217309Snwhitehorn	       int boxlines, int mincols)
1242217309Snwhitehorn{
1243217309Snwhitehorn    int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2);
1244217309Snwhitehorn    int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1);
1245217309Snwhitehorn    int title_length = title ? dlg_count_columns(title) : 0;
1246217309Snwhitehorn    int nc = 4;
1247217309Snwhitehorn    int high;
1248217309Snwhitehorn    int wide;
1249217309Snwhitehorn    int save_high = *height;
1250217309Snwhitehorn    int save_wide = *width;
1251217309Snwhitehorn
1252217309Snwhitehorn    if (prompt == 0) {
1253217309Snwhitehorn	if (*height == 0)
1254217309Snwhitehorn	    *height = -1;
1255217309Snwhitehorn	if (*width == 0)
1256217309Snwhitehorn	    *width = -1;
1257217309Snwhitehorn    }
1258217309Snwhitehorn
1259217309Snwhitehorn    if (*height > 0) {
1260217309Snwhitehorn	high = *height;
1261217309Snwhitehorn    } else {
1262217309Snwhitehorn	high = SLINES - y;
1263217309Snwhitehorn    }
1264217309Snwhitehorn
1265251843Sbapt    if (*width <= 0) {
1266251843Sbapt	if (prompt != 0) {
1267251843Sbapt	    wide = MAX(title_length, mincols);
1268251843Sbapt	    if (strchr(prompt, '\n') == 0) {
1269251843Sbapt		double val = (dialog_state.aspect_ratio *
1270251843Sbapt			      dlg_count_real_columns(prompt));
1271251843Sbapt		double xxx = sqrt(val);
1272251843Sbapt		int tmp = (int) xxx;
1273251843Sbapt		wide = MAX(wide, tmp);
1274251843Sbapt		wide = MAX(wide, longest_word(prompt));
1275251843Sbapt		justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1276251843Sbapt	    } else {
1277251843Sbapt		auto_size_preformatted(prompt, height, width);
1278251843Sbapt	    }
1279251843Sbapt	} else {
1280251843Sbapt	    wide = SCOLS - x;
1281244850Snwhitehorn	    justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1282217309Snwhitehorn	}
1283217309Snwhitehorn    }
1284217309Snwhitehorn
1285217309Snwhitehorn    if (*width < title_length) {
1286217309Snwhitehorn	justify_text((WINDOW *) 0, prompt, high, title_length, height, width);
1287217309Snwhitehorn	*width = title_length;
1288217309Snwhitehorn    }
1289217309Snwhitehorn
1290217309Snwhitehorn    if (*width < mincols && save_wide == 0)
1291217309Snwhitehorn	*width = mincols;
1292217309Snwhitehorn    if (prompt != 0) {
1293217309Snwhitehorn	*width += nc;
1294217309Snwhitehorn	*height += boxlines + 2;
1295217309Snwhitehorn    }
1296217309Snwhitehorn    if (save_high > 0)
1297217309Snwhitehorn	*height = save_high;
1298217309Snwhitehorn    if (save_wide > 0)
1299217309Snwhitehorn	*width = save_wide;
1300217309Snwhitehorn}
1301217309Snwhitehorn
1302217309Snwhitehorn/* End of real_auto_size() */
1303217309Snwhitehorn
1304217309Snwhitehornvoid
1305217309Snwhitehorndlg_auto_size(const char *title,
1306217309Snwhitehorn	      const char *prompt,
1307217309Snwhitehorn	      int *height,
1308217309Snwhitehorn	      int *width,
1309217309Snwhitehorn	      int boxlines,
1310217309Snwhitehorn	      int mincols)
1311217309Snwhitehorn{
1312217309Snwhitehorn    real_auto_size(title, prompt, height, width, boxlines, mincols);
1313217309Snwhitehorn
1314217309Snwhitehorn    if (*width > SCOLS) {
1315217309Snwhitehorn	(*height)++;
1316217309Snwhitehorn	*width = SCOLS;
1317217309Snwhitehorn    }
1318217309Snwhitehorn
1319217309Snwhitehorn    if (*height > SLINES)
1320217309Snwhitehorn	*height = SLINES;
1321217309Snwhitehorn}
1322217309Snwhitehorn
1323217309Snwhitehorn/*
1324217309Snwhitehorn * if (height or width == -1) Maximize()
1325217309Snwhitehorn * if (height or width == 0)
1326217309Snwhitehorn *    height=MIN(SLINES, num.lines in fd+n);
1327217309Snwhitehorn *    width=MIN(SCOLS, MAX(longer line+n, mincols));
1328217309Snwhitehorn */
1329217309Snwhitehornvoid
1330217309Snwhitehorndlg_auto_sizefile(const char *title,
1331217309Snwhitehorn		  const char *file,
1332217309Snwhitehorn		  int *height,
1333217309Snwhitehorn		  int *width,
1334217309Snwhitehorn		  int boxlines,
1335217309Snwhitehorn		  int mincols)
1336217309Snwhitehorn{
1337217309Snwhitehorn    int count = 0;
1338217309Snwhitehorn    int len = title ? dlg_count_columns(title) : 0;
1339217309Snwhitehorn    int nc = 4;
1340217309Snwhitehorn    int numlines = 2;
1341217309Snwhitehorn    long offset;
1342217309Snwhitehorn    int ch;
1343217309Snwhitehorn    FILE *fd;
1344217309Snwhitehorn
1345217309Snwhitehorn    /* Open input file for reading */
1346217309Snwhitehorn    if ((fd = fopen(file, "rb")) == NULL)
1347217309Snwhitehorn	dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file);
1348217309Snwhitehorn
1349217309Snwhitehorn    if ((*height == -1) || (*width == -1)) {
1350217309Snwhitehorn	*height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1351217309Snwhitehorn	*width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
1352217309Snwhitehorn    }
1353217309Snwhitehorn    if ((*height != 0) && (*width != 0)) {
1354217309Snwhitehorn	(void) fclose(fd);
1355217309Snwhitehorn	if (*width > SCOLS)
1356217309Snwhitehorn	    *width = SCOLS;
1357217309Snwhitehorn	if (*height > SLINES)
1358217309Snwhitehorn	    *height = SLINES;
1359217309Snwhitehorn	return;
1360217309Snwhitehorn    }
1361217309Snwhitehorn
1362217309Snwhitehorn    while (!feof(fd)) {
1363217309Snwhitehorn	offset = 0;
1364217309Snwhitehorn	while (((ch = getc(fd)) != '\n') && !feof(fd))
1365217309Snwhitehorn	    if ((ch == TAB) && (dialog_vars.tab_correct))
1366217309Snwhitehorn		offset += dialog_state.tab_len - (offset % dialog_state.tab_len);
1367217309Snwhitehorn	    else
1368217309Snwhitehorn		offset++;
1369217309Snwhitehorn
1370217309Snwhitehorn	if (offset > len)
1371220749Snwhitehorn	    len = (int) offset;
1372217309Snwhitehorn
1373217309Snwhitehorn	count++;
1374217309Snwhitehorn    }
1375217309Snwhitehorn
1376220749Snwhitehorn    /* now 'count' has the number of lines of fd and 'len' the max length */
1377217309Snwhitehorn
1378217309Snwhitehorn    *height = MIN(SLINES, count + numlines + boxlines);
1379217309Snwhitehorn    *width = MIN(SCOLS, MAX((len + nc), mincols));
1380217309Snwhitehorn    /* here width and height can be maximized if > SCOLS|SLINES because
1381217309Snwhitehorn       textbox-like widgets don't put all <file> on the screen.
1382217309Snwhitehorn       Msgbox-like widget instead have to put all <text> correctly. */
1383217309Snwhitehorn
1384217309Snwhitehorn    (void) fclose(fd);
1385217309Snwhitehorn}
1386217309Snwhitehorn
1387224014Snwhitehornstatic chtype
1388224014Snwhitehorndlg_get_cell_attrs(WINDOW *win)
1389224014Snwhitehorn{
1390224014Snwhitehorn    chtype result;
1391224014Snwhitehorn#ifdef USE_WIDE_CURSES
1392224014Snwhitehorn    cchar_t wch;
1393224014Snwhitehorn    wchar_t cc;
1394224014Snwhitehorn    attr_t attrs;
1395224014Snwhitehorn    short pair;
1396224014Snwhitehorn    if (win_wch(win, &wch) == OK
1397224014Snwhitehorn	&& getcchar(&wch, &cc, &attrs, &pair, NULL) == OK) {
1398224014Snwhitehorn	result = attrs;
1399224014Snwhitehorn    } else {
1400224014Snwhitehorn	result = 0;
1401224014Snwhitehorn    }
1402224014Snwhitehorn#else
1403224014Snwhitehorn    result = winch(win) & (A_ATTRIBUTES & ~A_COLOR);
1404224014Snwhitehorn#endif
1405224014Snwhitehorn    return result;
1406224014Snwhitehorn}
1407224014Snwhitehorn
1408217309Snwhitehorn/*
1409217309Snwhitehorn * Draw a rectangular box with line drawing characters.
1410217309Snwhitehorn *
1411217309Snwhitehorn * borderchar is used to color the upper/left edges.
1412217309Snwhitehorn *
1413217309Snwhitehorn * boxchar is used to color the right/lower edges.  It also is fill-color used
1414217309Snwhitehorn * for the box contents.
1415217309Snwhitehorn *
1416217309Snwhitehorn * Normally, if you are drawing a scrollable box, use menubox_border_attr for
1417217309Snwhitehorn * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn
1418217309Snwhitehorn * with menubox_attr at the top, and menubox_border_attr at the bottom.  That
1419217309Snwhitehorn * also (given the default color choices) produces a recessed effect.
1420217309Snwhitehorn *
1421217309Snwhitehorn * If you want a raised effect (and are not going to use the scroll-arrows),
1422217309Snwhitehorn * reverse this choice.
1423217309Snwhitehorn */
1424217309Snwhitehornvoid
1425251843Sbaptdlg_draw_box2(WINDOW *win, int y, int x, int height, int width,
1426251843Sbapt	      chtype boxchar, chtype borderchar, chtype borderchar2)
1427217309Snwhitehorn{
1428217309Snwhitehorn    int i, j;
1429220749Snwhitehorn    chtype save = dlg_get_attrs(win);
1430217309Snwhitehorn
1431251843Sbapt    (void) wattrset(win, 0);
1432217309Snwhitehorn    for (i = 0; i < height; i++) {
1433217309Snwhitehorn	(void) wmove(win, y + i, x);
1434217309Snwhitehorn	for (j = 0; j < width; j++)
1435217309Snwhitehorn	    if (!i && !j)
1436217309Snwhitehorn		(void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER));
1437217309Snwhitehorn	    else if (i == height - 1 && !j)
1438217309Snwhitehorn		(void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER));
1439217309Snwhitehorn	    else if (!i && j == width - 1)
1440251843Sbapt		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_URCORNER));
1441217309Snwhitehorn	    else if (i == height - 1 && j == width - 1)
1442251843Sbapt		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_LRCORNER));
1443217309Snwhitehorn	    else if (!i)
1444217309Snwhitehorn		(void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE));
1445217309Snwhitehorn	    else if (i == height - 1)
1446251843Sbapt		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_HLINE));
1447217309Snwhitehorn	    else if (!j)
1448217309Snwhitehorn		(void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE));
1449217309Snwhitehorn	    else if (j == width - 1)
1450251843Sbapt		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_VLINE));
1451217309Snwhitehorn	    else
1452217309Snwhitehorn		(void) waddch(win, boxchar | ' ');
1453217309Snwhitehorn    }
1454251843Sbapt    (void) wattrset(win, save);
1455217309Snwhitehorn}
1456217309Snwhitehorn
1457251843Sbaptvoid
1458251843Sbaptdlg_draw_box(WINDOW *win, int y, int x, int height, int width,
1459251843Sbapt	     chtype boxchar, chtype borderchar)
1460251843Sbapt{
1461251843Sbapt    dlg_draw_box2(win, y, x, height, width, boxchar, borderchar, boxchar);
1462251843Sbapt}
1463251843Sbapt
1464224014Snwhitehornstatic DIALOG_WINDOWS *
1465224014Snwhitehornfind_window(WINDOW *win)
1466224014Snwhitehorn{
1467224014Snwhitehorn    DIALOG_WINDOWS *result = 0;
1468224014Snwhitehorn    DIALOG_WINDOWS *p;
1469224014Snwhitehorn
1470224014Snwhitehorn    for (p = dialog_state.all_windows; p != 0; p = p->next) {
1471224014Snwhitehorn	if (p->normal == win) {
1472224014Snwhitehorn	    result = p;
1473224014Snwhitehorn	    break;
1474224014Snwhitehorn	}
1475224014Snwhitehorn    }
1476224014Snwhitehorn    return result;
1477224014Snwhitehorn}
1478224014Snwhitehorn
1479217309Snwhitehorn#ifdef HAVE_COLOR
1480217309Snwhitehorn/*
1481224014Snwhitehorn * If we have wchgat(), use that for updating shadow attributes, to work with
1482224014Snwhitehorn * wide-character data.
1483217309Snwhitehorn */
1484224014Snwhitehorn
1485224014Snwhitehorn/*
1486224014Snwhitehorn * Check if the given point is "in" the given window.  If so, return the window
1487224014Snwhitehorn * pointer, otherwise null.
1488224014Snwhitehorn */
1489224014Snwhitehornstatic WINDOW *
1490224014Snwhitehornin_window(WINDOW *win, int y, int x)
1491217309Snwhitehorn{
1492224014Snwhitehorn    WINDOW *result = 0;
1493224014Snwhitehorn    int y_base = getbegy(win);
1494224014Snwhitehorn    int x_base = getbegx(win);
1495224014Snwhitehorn    int y_last = getmaxy(win) + y_base;
1496224014Snwhitehorn    int x_last = getmaxx(win) + x_base;
1497217309Snwhitehorn
1498224014Snwhitehorn    if (y >= y_base && y <= y_last && x >= x_base && x <= x_last)
1499224014Snwhitehorn	result = win;
1500224014Snwhitehorn    return result;
1501224014Snwhitehorn}
1502224014Snwhitehorn
1503224014Snwhitehornstatic WINDOW *
1504224014Snwhitehornwindow_at_cell(DIALOG_WINDOWS * dw, int y, int x)
1505224014Snwhitehorn{
1506224014Snwhitehorn    WINDOW *result = 0;
1507224014Snwhitehorn    DIALOG_WINDOWS *p;
1508224014Snwhitehorn    int y_want = y + getbegy(dw->shadow);
1509224014Snwhitehorn    int x_want = x + getbegx(dw->shadow);
1510224014Snwhitehorn
1511224014Snwhitehorn    for (p = dialog_state.all_windows; p != 0; p = p->next) {
1512224014Snwhitehorn	if (dw->normal != p->normal
1513224014Snwhitehorn	    && dw->shadow != p->normal
1514224014Snwhitehorn	    && (result = in_window(p->normal, y_want, x_want)) != 0) {
1515224014Snwhitehorn	    break;
1516224014Snwhitehorn	}
1517217309Snwhitehorn    }
1518224014Snwhitehorn    if (result == 0) {
1519224014Snwhitehorn	result = stdscr;
1520224014Snwhitehorn    }
1521224014Snwhitehorn    return result;
1522217309Snwhitehorn}
1523217309Snwhitehorn
1524224014Snwhitehornstatic bool
1525224014Snwhitehornin_shadow(WINDOW *normal, WINDOW *shadow, int y, int x)
1526224014Snwhitehorn{
1527224014Snwhitehorn    bool result = FALSE;
1528224014Snwhitehorn    int ybase = getbegy(normal);
1529224014Snwhitehorn    int ylast = getmaxy(normal) + ybase;
1530224014Snwhitehorn    int xbase = getbegx(normal);
1531224014Snwhitehorn    int xlast = getmaxx(normal) + xbase;
1532224014Snwhitehorn
1533224014Snwhitehorn    y += getbegy(shadow);
1534224014Snwhitehorn    x += getbegx(shadow);
1535224014Snwhitehorn
1536224014Snwhitehorn    if (y >= ybase + SHADOW_ROWS
1537224014Snwhitehorn	&& y < ylast + SHADOW_ROWS
1538224014Snwhitehorn	&& x >= xlast
1539224014Snwhitehorn	&& x < xlast + SHADOW_COLS) {
1540224014Snwhitehorn	/* in the right-side */
1541224014Snwhitehorn	result = TRUE;
1542224014Snwhitehorn    } else if (y >= ylast
1543224014Snwhitehorn	       && y < ylast + SHADOW_ROWS
1544224014Snwhitehorn	       && x >= ybase + SHADOW_COLS
1545224014Snwhitehorn	       && x < ylast + SHADOW_COLS) {
1546224014Snwhitehorn	/* check the bottom */
1547224014Snwhitehorn	result = TRUE;
1548224014Snwhitehorn    }
1549224014Snwhitehorn
1550224014Snwhitehorn    return result;
1551224014Snwhitehorn}
1552224014Snwhitehorn
1553217309Snwhitehorn/*
1554224014Snwhitehorn * When erasing a shadow, check each cell to make sure that it is not part of
1555224014Snwhitehorn * another box's shadow.  This is a little complicated since most shadows are
1556224014Snwhitehorn * merged onto stdscr.
1557217309Snwhitehorn */
1558224014Snwhitehornstatic bool
1559224014Snwhitehornlast_shadow(DIALOG_WINDOWS * dw, int y, int x)
1560217309Snwhitehorn{
1561224014Snwhitehorn    DIALOG_WINDOWS *p;
1562224014Snwhitehorn    bool result = TRUE;
1563224014Snwhitehorn
1564224014Snwhitehorn    for (p = dialog_state.all_windows; p != 0; p = p->next) {
1565224014Snwhitehorn	if (p->normal != dw->normal
1566224014Snwhitehorn	    && in_shadow(p->normal, dw->shadow, y, x)) {
1567224014Snwhitehorn	    result = FALSE;
1568224014Snwhitehorn	    break;
1569224014Snwhitehorn	}
1570224014Snwhitehorn    }
1571224014Snwhitehorn    return result;
1572224014Snwhitehorn}
1573224014Snwhitehorn
1574224014Snwhitehornstatic void
1575224014Snwhitehornrepaint_cell(DIALOG_WINDOWS * dw, bool draw, int y, int x)
1576224014Snwhitehorn{
1577224014Snwhitehorn    WINDOW *win = dw->shadow;
1578224014Snwhitehorn    WINDOW *cellwin;
1579224014Snwhitehorn    int y2, x2;
1580224014Snwhitehorn
1581224014Snwhitehorn    if ((cellwin = window_at_cell(dw, y, x)) != 0
1582224014Snwhitehorn	&& (draw || last_shadow(dw, y, x))
1583224014Snwhitehorn	&& (y2 = (y + getbegy(win) - getbegy(cellwin))) >= 0
1584224014Snwhitehorn	&& (x2 = (x + getbegx(win) - getbegx(cellwin))) >= 0
1585224014Snwhitehorn	&& wmove(cellwin, y2, x2) != ERR) {
1586224014Snwhitehorn	chtype the_cell = dlg_get_attrs(cellwin);
1587224014Snwhitehorn	chtype the_attr = (draw ? shadow_attr : the_cell);
1588224014Snwhitehorn
1589224014Snwhitehorn	if (dlg_get_cell_attrs(cellwin) & A_ALTCHARSET) {
1590224014Snwhitehorn	    the_attr |= A_ALTCHARSET;
1591224014Snwhitehorn	}
1592224014Snwhitehorn#if USE_WCHGAT
1593224014Snwhitehorn	wchgat(cellwin, 1,
1594224014Snwhitehorn	       the_attr & (chtype) (~A_COLOR),
1595251843Sbapt	       (short) PAIR_NUMBER(the_attr),
1596224014Snwhitehorn	       NULL);
1597224014Snwhitehorn#else
1598224014Snwhitehorn	{
1599224014Snwhitehorn	    chtype the_char = ((winch(cellwin) & A_CHARTEXT) | the_attr);
1600224014Snwhitehorn	    (void) waddch(cellwin, the_char);
1601224014Snwhitehorn	}
1602224014Snwhitehorn#endif
1603224014Snwhitehorn	wnoutrefresh(cellwin);
1604224014Snwhitehorn    }
1605224014Snwhitehorn}
1606224014Snwhitehorn
1607224014Snwhitehorn#define RepaintCell(dw, draw, y, x) repaint_cell(dw, draw, y, x)
1608224014Snwhitehorn
1609224014Snwhitehornstatic void
1610224014Snwhitehornrepaint_shadow(DIALOG_WINDOWS * dw, bool draw, int y, int x, int height, int width)
1611224014Snwhitehorn{
1612217309Snwhitehorn    int i, j;
1613217309Snwhitehorn
1614224014Snwhitehorn    if (UseShadow(dw)) {
1615224014Snwhitehorn#if !USE_WCHGAT
1616224014Snwhitehorn	chtype save = dlg_get_attrs(dw->shadow);
1617251843Sbapt	(void) wattrset(dw->shadow, draw ? shadow_attr : screen_attr);
1618224014Snwhitehorn#endif
1619217309Snwhitehorn	for (i = 0; i < SHADOW_ROWS; ++i) {
1620217309Snwhitehorn	    for (j = 0; j < width; ++j) {
1621224014Snwhitehorn		RepaintCell(dw, draw, i + y + height, j + x + SHADOW_COLS);
1622217309Snwhitehorn	    }
1623217309Snwhitehorn	}
1624217309Snwhitehorn	for (i = 0; i < height; i++) {
1625217309Snwhitehorn	    for (j = 0; j < SHADOW_COLS; ++j) {
1626224014Snwhitehorn		RepaintCell(dw, draw, i + y + SHADOW_ROWS, j + x + width);
1627217309Snwhitehorn	    }
1628217309Snwhitehorn	}
1629224014Snwhitehorn	(void) wnoutrefresh(dw->shadow);
1630224014Snwhitehorn#if !USE_WCHGAT
1631251843Sbapt	(void) wattrset(dw->shadow, save);
1632224014Snwhitehorn#endif
1633217309Snwhitehorn    }
1634217309Snwhitehorn}
1635224014Snwhitehorn
1636224014Snwhitehorn/*
1637224014Snwhitehorn * Draw a shadow on the parent window corresponding to the right- and
1638224014Snwhitehorn * bottom-edge of the child window, to give a 3-dimensional look.
1639224014Snwhitehorn */
1640224014Snwhitehornstatic void
1641224014Snwhitehorndraw_childs_shadow(DIALOG_WINDOWS * dw)
1642224014Snwhitehorn{
1643224014Snwhitehorn    if (UseShadow(dw)) {
1644224014Snwhitehorn	repaint_shadow(dw,
1645224014Snwhitehorn		       TRUE,
1646224014Snwhitehorn		       getbegy(dw->normal) - getbegy(dw->shadow),
1647224014Snwhitehorn		       getbegx(dw->normal) - getbegx(dw->shadow),
1648224014Snwhitehorn		       getmaxy(dw->normal),
1649224014Snwhitehorn		       getmaxx(dw->normal));
1650224014Snwhitehorn    }
1651224014Snwhitehorn}
1652224014Snwhitehorn
1653224014Snwhitehorn/*
1654224014Snwhitehorn * Erase a shadow on the parent window corresponding to the right- and
1655224014Snwhitehorn * bottom-edge of the child window.
1656224014Snwhitehorn */
1657224014Snwhitehornstatic void
1658224014Snwhitehornerase_childs_shadow(DIALOG_WINDOWS * dw)
1659224014Snwhitehorn{
1660224014Snwhitehorn    if (UseShadow(dw)) {
1661224014Snwhitehorn	repaint_shadow(dw,
1662224014Snwhitehorn		       FALSE,
1663224014Snwhitehorn		       getbegy(dw->normal) - getbegy(dw->shadow),
1664224014Snwhitehorn		       getbegx(dw->normal) - getbegx(dw->shadow),
1665224014Snwhitehorn		       getmaxy(dw->normal),
1666224014Snwhitehorn		       getmaxx(dw->normal));
1667224014Snwhitehorn    }
1668224014Snwhitehorn}
1669224014Snwhitehorn
1670224014Snwhitehorn/*
1671224014Snwhitehorn * Draw shadows along the right and bottom edge to give a more 3D look
1672224014Snwhitehorn * to the boxes.
1673224014Snwhitehorn */
1674224014Snwhitehornvoid
1675224014Snwhitehorndlg_draw_shadow(WINDOW *win, int y, int x, int height, int width)
1676224014Snwhitehorn{
1677224014Snwhitehorn    repaint_shadow(find_window(win), TRUE, y, x, height, width);
1678224014Snwhitehorn}
1679217309Snwhitehorn#endif /* HAVE_COLOR */
1680217309Snwhitehorn
1681217309Snwhitehorn/*
1682217309Snwhitehorn * Allow shell scripts to remap the exit codes so they can distinguish ESC
1683217309Snwhitehorn * from ERROR.
1684217309Snwhitehorn */
1685217309Snwhitehornvoid
1686217309Snwhitehorndlg_exit(int code)
1687217309Snwhitehorn{
1688217309Snwhitehorn    /* *INDENT-OFF* */
1689217309Snwhitehorn    static const struct {
1690217309Snwhitehorn	int code;
1691217309Snwhitehorn	const char *name;
1692217309Snwhitehorn    } table[] = {
1693217309Snwhitehorn	{ DLG_EXIT_CANCEL, 	"DIALOG_CANCEL" },
1694217309Snwhitehorn	{ DLG_EXIT_ERROR,  	"DIALOG_ERROR" },
1695217309Snwhitehorn	{ DLG_EXIT_ESC,	   	"DIALOG_ESC" },
1696217309Snwhitehorn	{ DLG_EXIT_EXTRA,  	"DIALOG_EXTRA" },
1697217309Snwhitehorn	{ DLG_EXIT_HELP,   	"DIALOG_HELP" },
1698217309Snwhitehorn	{ DLG_EXIT_OK,	   	"DIALOG_OK" },
1699217309Snwhitehorn	{ DLG_EXIT_ITEM_HELP,	"DIALOG_ITEM_HELP" },
1700217309Snwhitehorn    };
1701217309Snwhitehorn    /* *INDENT-ON* */
1702217309Snwhitehorn
1703217309Snwhitehorn    unsigned n;
1704217309Snwhitehorn    char *name;
1705217309Snwhitehorn    char *temp;
1706217309Snwhitehorn    long value;
1707217309Snwhitehorn    bool overridden = FALSE;
1708217309Snwhitehorn
1709217309Snwhitehorn  retry:
1710217309Snwhitehorn    for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) {
1711217309Snwhitehorn	if (table[n].code == code) {
1712217309Snwhitehorn	    if ((name = getenv(table[n].name)) != 0) {
1713217309Snwhitehorn		value = strtol(name, &temp, 0);
1714217309Snwhitehorn		if (temp != 0 && temp != name && *temp == '\0') {
1715220749Snwhitehorn		    code = (int) value;
1716217309Snwhitehorn		    overridden = TRUE;
1717217309Snwhitehorn		}
1718217309Snwhitehorn	    }
1719217309Snwhitehorn	    break;
1720217309Snwhitehorn	}
1721217309Snwhitehorn    }
1722217309Snwhitehorn
1723217309Snwhitehorn    /*
1724217309Snwhitehorn     * Prior to 2004/12/19, a widget using --item-help would exit with "OK"
1725217309Snwhitehorn     * if the help button were selected.  Now we want to exit with "HELP",
1726217309Snwhitehorn     * but allow the environment variable to override.
1727217309Snwhitehorn     */
1728217309Snwhitehorn    if (code == DLG_EXIT_ITEM_HELP && !overridden) {
1729217309Snwhitehorn	code = DLG_EXIT_HELP;
1730217309Snwhitehorn	goto retry;
1731217309Snwhitehorn    }
1732224014Snwhitehorn#ifdef HAVE_DLG_TRACE
1733224014Snwhitehorn    dlg_trace((const char *) 0);	/* close it */
1734224014Snwhitehorn#endif
1735224014Snwhitehorn
1736217309Snwhitehorn#ifdef NO_LEAKS
1737217309Snwhitehorn    _dlg_inputstr_leaks();
1738217309Snwhitehorn#if defined(NCURSES_VERSION) && defined(HAVE__NC_FREE_AND_EXIT)
1739217309Snwhitehorn    _nc_free_and_exit(code);
1740217309Snwhitehorn#endif
1741217309Snwhitehorn#endif
1742217309Snwhitehorn
1743217309Snwhitehorn    if (dialog_state.input == stdin) {
1744217309Snwhitehorn	exit(code);
1745217309Snwhitehorn    } else {
1746217309Snwhitehorn	/*
1747217309Snwhitehorn	 * Just in case of using --input-fd option, do not
1748217309Snwhitehorn	 * call atexit functions of ncurses which may hang.
1749217309Snwhitehorn	 */
1750217309Snwhitehorn	if (dialog_state.input) {
1751217309Snwhitehorn	    fclose(dialog_state.input);
1752217309Snwhitehorn	    dialog_state.input = 0;
1753217309Snwhitehorn	}
1754217309Snwhitehorn	if (dialog_state.pipe_input) {
1755217309Snwhitehorn	    if (dialog_state.pipe_input != stdin) {
1756217309Snwhitehorn		fclose(dialog_state.pipe_input);
1757217309Snwhitehorn		dialog_state.pipe_input = 0;
1758217309Snwhitehorn	    }
1759217309Snwhitehorn	}
1760217309Snwhitehorn	_exit(code);
1761217309Snwhitehorn    }
1762217309Snwhitehorn}
1763217309Snwhitehorn
1764217309Snwhitehorn/* quit program killing all tailbg */
1765217309Snwhitehornvoid
1766217309Snwhitehorndlg_exiterr(const char *fmt,...)
1767217309Snwhitehorn{
1768217309Snwhitehorn    int retval;
1769217309Snwhitehorn    va_list ap;
1770217309Snwhitehorn
1771217309Snwhitehorn    end_dialog();
1772217309Snwhitehorn
1773217309Snwhitehorn    (void) fputc('\n', stderr);
1774217309Snwhitehorn    va_start(ap, fmt);
1775217309Snwhitehorn    (void) vfprintf(stderr, fmt, ap);
1776217309Snwhitehorn    va_end(ap);
1777217309Snwhitehorn    (void) fputc('\n', stderr);
1778217309Snwhitehorn
1779217309Snwhitehorn    dlg_killall_bg(&retval);
1780217309Snwhitehorn
1781217309Snwhitehorn    (void) fflush(stderr);
1782217309Snwhitehorn    (void) fflush(stdout);
1783217309Snwhitehorn    dlg_exit(DLG_EXIT_ERROR);
1784217309Snwhitehorn}
1785217309Snwhitehorn
1786217309Snwhitehornvoid
1787217309Snwhitehorndlg_beeping(void)
1788217309Snwhitehorn{
1789217309Snwhitehorn    if (dialog_vars.beep_signal) {
1790217309Snwhitehorn	(void) beep();
1791217309Snwhitehorn	dialog_vars.beep_signal = 0;
1792217309Snwhitehorn    }
1793217309Snwhitehorn}
1794217309Snwhitehorn
1795217309Snwhitehornvoid
1796217309Snwhitehorndlg_print_size(int height, int width)
1797217309Snwhitehorn{
1798217309Snwhitehorn    if (dialog_vars.print_siz)
1799217309Snwhitehorn	fprintf(dialog_state.output, "Size: %d, %d\n", height, width);
1800217309Snwhitehorn}
1801217309Snwhitehorn
1802217309Snwhitehornvoid
1803217309Snwhitehorndlg_ctl_size(int height, int width)
1804217309Snwhitehorn{
1805217309Snwhitehorn    if (dialog_vars.size_err) {
1806217309Snwhitehorn	if ((width > COLS) || (height > LINES)) {
1807217309Snwhitehorn	    dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1808217309Snwhitehorn			height, width, LINES, COLS);
1809217309Snwhitehorn	}
1810217309Snwhitehorn#ifdef HAVE_COLOR
1811217309Snwhitehorn	else if ((dialog_state.use_shadow)
1812217309Snwhitehorn		 && ((width > SCOLS || height > SLINES))) {
1813217309Snwhitehorn	    if ((width <= COLS) && (height <= LINES)) {
1814217309Snwhitehorn		/* try again, without shadows */
1815217309Snwhitehorn		dialog_state.use_shadow = 0;
1816217309Snwhitehorn	    } else {
1817217309Snwhitehorn		dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1818217309Snwhitehorn			    height, width, SLINES, SCOLS);
1819217309Snwhitehorn	    }
1820217309Snwhitehorn	}
1821217309Snwhitehorn#endif
1822217309Snwhitehorn    }
1823217309Snwhitehorn}
1824217309Snwhitehorn
1825217309Snwhitehorn/*
1826217309Snwhitehorn * If the --tab-correct was not selected, convert tabs to single spaces.
1827217309Snwhitehorn */
1828217309Snwhitehornvoid
1829217309Snwhitehorndlg_tab_correct_str(char *prompt)
1830217309Snwhitehorn{
1831217309Snwhitehorn    char *ptr;
1832217309Snwhitehorn
1833217309Snwhitehorn    if (dialog_vars.tab_correct) {
1834217309Snwhitehorn	while ((ptr = strchr(prompt, TAB)) != NULL) {
1835217309Snwhitehorn	    *ptr = ' ';
1836217309Snwhitehorn	    prompt = ptr;
1837217309Snwhitehorn	}
1838217309Snwhitehorn    }
1839217309Snwhitehorn}
1840217309Snwhitehorn
1841217309Snwhitehornvoid
1842217309Snwhitehorndlg_calc_listh(int *height, int *list_height, int item_no)
1843217309Snwhitehorn{
1844217309Snwhitehorn    /* calculate new height and list_height */
1845217309Snwhitehorn    int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1846217309Snwhitehorn    if (rows - (*height) > 0) {
1847217309Snwhitehorn	if (rows - (*height) > item_no)
1848217309Snwhitehorn	    *list_height = item_no;
1849217309Snwhitehorn	else
1850217309Snwhitehorn	    *list_height = rows - (*height);
1851217309Snwhitehorn    }
1852217309Snwhitehorn    (*height) += (*list_height);
1853217309Snwhitehorn}
1854217309Snwhitehorn
1855217309Snwhitehorn/* obsolete */
1856217309Snwhitehornint
1857217309Snwhitehorndlg_calc_listw(int item_no, char **items, int group)
1858217309Snwhitehorn{
1859217309Snwhitehorn    int n, i, len1 = 0, len2 = 0;
1860217309Snwhitehorn    for (i = 0; i < (item_no * group); i += group) {
1861217309Snwhitehorn	if ((n = dlg_count_columns(items[i])) > len1)
1862217309Snwhitehorn	    len1 = n;
1863217309Snwhitehorn	if ((n = dlg_count_columns(items[i + 1])) > len2)
1864217309Snwhitehorn	    len2 = n;
1865217309Snwhitehorn    }
1866217309Snwhitehorn    return len1 + len2;
1867217309Snwhitehorn}
1868217309Snwhitehorn
1869217309Snwhitehornint
1870217309Snwhitehorndlg_calc_list_width(int item_no, DIALOG_LISTITEM * items)
1871217309Snwhitehorn{
1872217309Snwhitehorn    int n, i, len1 = 0, len2 = 0;
1873251843Sbapt    int bits = ((dialog_vars.no_tags ? 1 : 0)
1874251843Sbapt		+ (dialog_vars.no_items ? 2 : 0));
1875251843Sbapt
1876217309Snwhitehorn    for (i = 0; i < item_no; ++i) {
1877251843Sbapt	switch (bits) {
1878251843Sbapt	case 0:
1879251843Sbapt	    /* FALLTHRU */
1880251843Sbapt	case 1:
1881251843Sbapt	    if ((n = dlg_count_columns(items[i].name)) > len1)
1882251843Sbapt		len1 = n;
1883251843Sbapt	    if ((n = dlg_count_columns(items[i].text)) > len2)
1884251843Sbapt		len2 = n;
1885251843Sbapt	    break;
1886251843Sbapt	case 2:
1887251843Sbapt	    /* FALLTHRU */
1888251843Sbapt	case 3:
1889251843Sbapt	    if ((n = dlg_count_columns(items[i].name)) > len1)
1890251843Sbapt		len1 = n;
1891251843Sbapt	    break;
1892251843Sbapt	}
1893217309Snwhitehorn    }
1894217309Snwhitehorn    return len1 + len2;
1895217309Snwhitehorn}
1896217309Snwhitehorn
1897217309Snwhitehornchar *
1898217309Snwhitehorndlg_strempty(void)
1899217309Snwhitehorn{
1900217309Snwhitehorn    static char empty[] = "";
1901217309Snwhitehorn    return empty;
1902217309Snwhitehorn}
1903217309Snwhitehorn
1904217309Snwhitehornchar *
1905217309Snwhitehorndlg_strclone(const char *cprompt)
1906217309Snwhitehorn{
1907217309Snwhitehorn    char *prompt = dlg_malloc(char, strlen(cprompt) + 1);
1908217309Snwhitehorn    assert_ptr(prompt, "dlg_strclone");
1909217309Snwhitehorn    strcpy(prompt, cprompt);
1910217309Snwhitehorn    return prompt;
1911217309Snwhitehorn}
1912217309Snwhitehorn
1913217309Snwhitehornchtype
1914217309Snwhitehorndlg_asciibox(chtype ch)
1915217309Snwhitehorn{
1916217309Snwhitehorn    chtype result = 0;
1917217309Snwhitehorn
1918217309Snwhitehorn    if (ch == ACS_ULCORNER)
1919217309Snwhitehorn	result = '+';
1920217309Snwhitehorn    else if (ch == ACS_LLCORNER)
1921217309Snwhitehorn	result = '+';
1922217309Snwhitehorn    else if (ch == ACS_URCORNER)
1923217309Snwhitehorn	result = '+';
1924217309Snwhitehorn    else if (ch == ACS_LRCORNER)
1925217309Snwhitehorn	result = '+';
1926217309Snwhitehorn    else if (ch == ACS_HLINE)
1927217309Snwhitehorn	result = '-';
1928217309Snwhitehorn    else if (ch == ACS_VLINE)
1929217309Snwhitehorn	result = '|';
1930217309Snwhitehorn    else if (ch == ACS_LTEE)
1931217309Snwhitehorn	result = '+';
1932217309Snwhitehorn    else if (ch == ACS_RTEE)
1933217309Snwhitehorn	result = '+';
1934217309Snwhitehorn    else if (ch == ACS_UARROW)
1935217309Snwhitehorn	result = '^';
1936217309Snwhitehorn    else if (ch == ACS_DARROW)
1937217309Snwhitehorn	result = 'v';
1938217309Snwhitehorn
1939217309Snwhitehorn    return result;
1940217309Snwhitehorn}
1941217309Snwhitehorn
1942217309Snwhitehornchtype
1943217309Snwhitehorndlg_boxchar(chtype ch)
1944217309Snwhitehorn{
1945217309Snwhitehorn    chtype result = dlg_asciibox(ch);
1946217309Snwhitehorn
1947217309Snwhitehorn    if (result != 0) {
1948217309Snwhitehorn	if (dialog_vars.ascii_lines)
1949217309Snwhitehorn	    ch = result;
1950217309Snwhitehorn	else if (dialog_vars.no_lines)
1951217309Snwhitehorn	    ch = ' ';
1952217309Snwhitehorn    }
1953217309Snwhitehorn    return ch;
1954217309Snwhitehorn}
1955217309Snwhitehorn
1956217309Snwhitehornint
1957217309Snwhitehorndlg_box_x_ordinate(int width)
1958217309Snwhitehorn{
1959217309Snwhitehorn    int x;
1960217309Snwhitehorn
1961217309Snwhitehorn    if (dialog_vars.begin_set == 1) {
1962217309Snwhitehorn	x = dialog_vars.begin_x;
1963217309Snwhitehorn    } else {
1964217309Snwhitehorn	/* center dialog box on screen unless --begin-set */
1965217309Snwhitehorn	x = (SCOLS - width) / 2;
1966217309Snwhitehorn    }
1967217309Snwhitehorn    return x;
1968217309Snwhitehorn}
1969217309Snwhitehorn
1970217309Snwhitehornint
1971217309Snwhitehorndlg_box_y_ordinate(int height)
1972217309Snwhitehorn{
1973217309Snwhitehorn    int y;
1974217309Snwhitehorn
1975217309Snwhitehorn    if (dialog_vars.begin_set == 1) {
1976217309Snwhitehorn	y = dialog_vars.begin_y;
1977217309Snwhitehorn    } else {
1978217309Snwhitehorn	/* center dialog box on screen unless --begin-set */
1979217309Snwhitehorn	y = (SLINES - height) / 2;
1980217309Snwhitehorn    }
1981217309Snwhitehorn    return y;
1982217309Snwhitehorn}
1983217309Snwhitehorn
1984217309Snwhitehornvoid
1985217309Snwhitehorndlg_draw_title(WINDOW *win, const char *title)
1986217309Snwhitehorn{
1987217309Snwhitehorn    if (title != NULL) {
1988217309Snwhitehorn	chtype attr = A_NORMAL;
1989220749Snwhitehorn	chtype save = dlg_get_attrs(win);
1990217309Snwhitehorn	int x = centered(getmaxx(win), title);
1991217309Snwhitehorn
1992251843Sbapt	(void) wattrset(win, title_attr);
1993217309Snwhitehorn	wmove(win, 0, x);
1994217309Snwhitehorn	dlg_print_text(win, title, getmaxx(win) - x, &attr);
1995251843Sbapt	(void) wattrset(win, save);
1996255852Sdteske	dlg_finish_string(title);
1997217309Snwhitehorn    }
1998217309Snwhitehorn}
1999217309Snwhitehorn
2000217309Snwhitehornvoid
2001251843Sbaptdlg_draw_bottom_box2(WINDOW *win, chtype on_left, chtype on_right, chtype on_inside)
2002217309Snwhitehorn{
2003217309Snwhitehorn    int width = getmaxx(win);
2004217309Snwhitehorn    int height = getmaxy(win);
2005217309Snwhitehorn    int i;
2006217309Snwhitehorn
2007251843Sbapt    (void) wattrset(win, on_left);
2008217309Snwhitehorn    (void) wmove(win, height - 3, 0);
2009217309Snwhitehorn    (void) waddch(win, dlg_boxchar(ACS_LTEE));
2010217309Snwhitehorn    for (i = 0; i < width - 2; i++)
2011217309Snwhitehorn	(void) waddch(win, dlg_boxchar(ACS_HLINE));
2012251843Sbapt    (void) wattrset(win, on_right);
2013217309Snwhitehorn    (void) waddch(win, dlg_boxchar(ACS_RTEE));
2014251843Sbapt    (void) wattrset(win, on_inside);
2015217309Snwhitehorn    (void) wmove(win, height - 2, 1);
2016217309Snwhitehorn    for (i = 0; i < width - 2; i++)
2017217309Snwhitehorn	(void) waddch(win, ' ');
2018217309Snwhitehorn}
2019217309Snwhitehorn
2020251843Sbaptvoid
2021251843Sbaptdlg_draw_bottom_box(WINDOW *win)
2022251843Sbapt{
2023251843Sbapt    dlg_draw_bottom_box2(win, border_attr, dialog_attr, dialog_attr);
2024251843Sbapt}
2025251843Sbapt
2026217309Snwhitehorn/*
2027217309Snwhitehorn * Remove a window, repainting everything else.  This would be simpler if we
2028217309Snwhitehorn * used the panel library, but that is not _always_ available.
2029217309Snwhitehorn */
2030217309Snwhitehornvoid
2031217309Snwhitehorndlg_del_window(WINDOW *win)
2032217309Snwhitehorn{
2033217309Snwhitehorn    DIALOG_WINDOWS *p, *q, *r;
2034217309Snwhitehorn
2035217309Snwhitehorn    /*
2036217309Snwhitehorn     * If --keep-window was set, do not delete/repaint the windows.
2037217309Snwhitehorn     */
2038217309Snwhitehorn    if (dialog_vars.keep_window)
2039217309Snwhitehorn	return;
2040217309Snwhitehorn
2041217309Snwhitehorn    /* Leave the main window untouched if there are no background windows.
2042217309Snwhitehorn     * We do this so the current window will not be cleared on exit, allowing
2043217309Snwhitehorn     * things like the infobox demo to run without flicker.
2044217309Snwhitehorn     */
2045217309Snwhitehorn    if (dialog_state.getc_callbacks != 0) {
2046217309Snwhitehorn	touchwin(stdscr);
2047217309Snwhitehorn	wnoutrefresh(stdscr);
2048217309Snwhitehorn    }
2049217309Snwhitehorn
2050217309Snwhitehorn    for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) {
2051217309Snwhitehorn	if (p->normal == win) {
2052217309Snwhitehorn	    q = p;		/* found a match - should be only one */
2053217309Snwhitehorn	    if (r == 0) {
2054217309Snwhitehorn		dialog_state.all_windows = p->next;
2055217309Snwhitehorn	    } else {
2056217309Snwhitehorn		r->next = p->next;
2057217309Snwhitehorn	    }
2058217309Snwhitehorn	} else {
2059217309Snwhitehorn	    if (p->shadow != 0) {
2060217309Snwhitehorn		touchwin(p->shadow);
2061217309Snwhitehorn		wnoutrefresh(p->shadow);
2062217309Snwhitehorn	    }
2063217309Snwhitehorn	    touchwin(p->normal);
2064217309Snwhitehorn	    wnoutrefresh(p->normal);
2065217309Snwhitehorn	}
2066217309Snwhitehorn    }
2067217309Snwhitehorn
2068217309Snwhitehorn    if (q) {
2069224014Snwhitehorn	if (dialog_state.all_windows != 0)
2070224014Snwhitehorn	    erase_childs_shadow(q);
2071251843Sbapt	del_subwindows(q->normal);
2072251843Sbapt	dlg_unregister_window(q->normal);
2073217309Snwhitehorn	delwin(q->normal);
2074217309Snwhitehorn	free(q);
2075217309Snwhitehorn    }
2076217309Snwhitehorn    doupdate();
2077217309Snwhitehorn}
2078217309Snwhitehorn
2079217309Snwhitehorn/*
2080217309Snwhitehorn * Create a window, optionally with a shadow.
2081217309Snwhitehorn */
2082217309SnwhitehornWINDOW *
2083217309Snwhitehorndlg_new_window(int height, int width, int y, int x)
2084217309Snwhitehorn{
2085224014Snwhitehorn    return dlg_new_modal_window(stdscr, height, width, y, x);
2086217309Snwhitehorn}
2087217309Snwhitehorn
2088224014Snwhitehorn/*
2089224014Snwhitehorn * "Modal" windows differ from normal ones by having a shadow in a window
2090224014Snwhitehorn * separate from the standard screen.
2091224014Snwhitehorn */
2092217309SnwhitehornWINDOW *
2093217309Snwhitehorndlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x)
2094217309Snwhitehorn{
2095217309Snwhitehorn    WINDOW *win;
2096217309Snwhitehorn    DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
2097217309Snwhitehorn
2098217309Snwhitehorn    (void) parent;
2099251843Sbapt    if (p == 0
2100251843Sbapt	|| (win = newwin(height, width, y, x)) == 0) {
2101217309Snwhitehorn	dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
2102217309Snwhitehorn		    y, x, height, width);
2103217309Snwhitehorn    }
2104217309Snwhitehorn    p->next = dialog_state.all_windows;
2105217309Snwhitehorn    p->normal = win;
2106217309Snwhitehorn    dialog_state.all_windows = p;
2107217309Snwhitehorn#ifdef HAVE_COLOR
2108217309Snwhitehorn    if (dialog_state.use_shadow) {
2109224014Snwhitehorn	p->shadow = parent;
2110224014Snwhitehorn	draw_childs_shadow(p);
2111217309Snwhitehorn    }
2112217309Snwhitehorn#endif
2113217309Snwhitehorn
2114217309Snwhitehorn    (void) keypad(win, TRUE);
2115217309Snwhitehorn    return win;
2116217309Snwhitehorn}
2117217309Snwhitehorn
2118217309Snwhitehorn/*
2119217309Snwhitehorn * Move/Resize a window, optionally with a shadow.
2120217309Snwhitehorn */
2121217309Snwhitehorn#ifdef KEY_RESIZE
2122217309Snwhitehornvoid
2123217309Snwhitehorndlg_move_window(WINDOW *win, int height, int width, int y, int x)
2124217309Snwhitehorn{
2125224014Snwhitehorn    DIALOG_WINDOWS *p;
2126217309Snwhitehorn
2127217309Snwhitehorn    if (win != 0) {
2128217309Snwhitehorn	dlg_ctl_size(height, width);
2129217309Snwhitehorn
2130224014Snwhitehorn	if ((p = find_window(win)) != 0) {
2131217309Snwhitehorn	    (void) wresize(win, height, width);
2132217309Snwhitehorn	    (void) mvwin(win, y, x);
2133217309Snwhitehorn#ifdef HAVE_COLOR
2134217309Snwhitehorn	    if (p->shadow != 0) {
2135217309Snwhitehorn		if (dialog_state.use_shadow) {
2136217309Snwhitehorn		    (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS);
2137217309Snwhitehorn		} else {
2138217309Snwhitehorn		    p->shadow = 0;
2139217309Snwhitehorn		}
2140217309Snwhitehorn	    }
2141217309Snwhitehorn#endif
2142217309Snwhitehorn	    (void) refresh();
2143217309Snwhitehorn
2144217309Snwhitehorn#ifdef HAVE_COLOR
2145224014Snwhitehorn	    draw_childs_shadow(p);
2146217309Snwhitehorn#endif
2147217309Snwhitehorn	}
2148217309Snwhitehorn    }
2149217309Snwhitehorn}
2150217309Snwhitehorn#endif /* KEY_RESIZE */
2151217309Snwhitehorn
2152217309SnwhitehornWINDOW *
2153217309Snwhitehorndlg_sub_window(WINDOW *parent, int height, int width, int y, int x)
2154217309Snwhitehorn{
2155217309Snwhitehorn    WINDOW *win;
2156217309Snwhitehorn
2157217309Snwhitehorn    if ((win = subwin(parent, height, width, y, x)) == 0) {
2158217309Snwhitehorn	dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n",
2159217309Snwhitehorn		    y, x, height, width);
2160217309Snwhitehorn    }
2161217309Snwhitehorn
2162251843Sbapt    add_subwindow(parent, win);
2163217309Snwhitehorn    (void) keypad(win, TRUE);
2164217309Snwhitehorn    return win;
2165217309Snwhitehorn}
2166217309Snwhitehorn
2167217309Snwhitehorn/* obsolete */
2168217309Snwhitehornint
2169217309Snwhitehorndlg_default_item(char **items, int llen)
2170217309Snwhitehorn{
2171217309Snwhitehorn    int result = 0;
2172217309Snwhitehorn
2173217309Snwhitehorn    if (dialog_vars.default_item != 0) {
2174217309Snwhitehorn	int count = 0;
2175217309Snwhitehorn	while (*items != 0) {
2176217309Snwhitehorn	    if (!strcmp(dialog_vars.default_item, *items)) {
2177217309Snwhitehorn		result = count;
2178217309Snwhitehorn		break;
2179217309Snwhitehorn	    }
2180217309Snwhitehorn	    items += llen;
2181217309Snwhitehorn	    count++;
2182217309Snwhitehorn	}
2183217309Snwhitehorn    }
2184217309Snwhitehorn    return result;
2185217309Snwhitehorn}
2186217309Snwhitehorn
2187217309Snwhitehornint
2188217309Snwhitehorndlg_default_listitem(DIALOG_LISTITEM * items)
2189217309Snwhitehorn{
2190217309Snwhitehorn    int result = 0;
2191217309Snwhitehorn
2192217309Snwhitehorn    if (dialog_vars.default_item != 0) {
2193217309Snwhitehorn	int count = 0;
2194217309Snwhitehorn	while (items->name != 0) {
2195217309Snwhitehorn	    if (!strcmp(dialog_vars.default_item, items->name)) {
2196217309Snwhitehorn		result = count;
2197217309Snwhitehorn		break;
2198217309Snwhitehorn	    }
2199217309Snwhitehorn	    ++items;
2200217309Snwhitehorn	    count++;
2201217309Snwhitehorn	}
2202217309Snwhitehorn    }
2203217309Snwhitehorn    return result;
2204217309Snwhitehorn}
2205217309Snwhitehorn
2206217309Snwhitehorn/*
2207217309Snwhitehorn * Draw the string for item_help
2208217309Snwhitehorn */
2209217309Snwhitehornvoid
2210217309Snwhitehorndlg_item_help(const char *txt)
2211217309Snwhitehorn{
2212217309Snwhitehorn    if (USE_ITEM_HELP(txt)) {
2213217309Snwhitehorn	chtype attr = A_NORMAL;
2214217309Snwhitehorn	int y, x;
2215217309Snwhitehorn
2216251843Sbapt	(void) wattrset(stdscr, itemhelp_attr);
2217217309Snwhitehorn	(void) wmove(stdscr, LINES - 1, 0);
2218217309Snwhitehorn	(void) wclrtoeol(stdscr);
2219217309Snwhitehorn	(void) addch(' ');
2220217309Snwhitehorn	dlg_print_text(stdscr, txt, COLS - 1, &attr);
2221217309Snwhitehorn	if (itemhelp_attr & A_COLOR) {
2222217309Snwhitehorn	    /* fill the remainder of the line with the window's attributes */
2223217309Snwhitehorn	    getyx(stdscr, y, x);
2224251843Sbapt	    (void) y;
2225217309Snwhitehorn	    while (x < COLS) {
2226217309Snwhitehorn		(void) addch(' ');
2227217309Snwhitehorn		++x;
2228217309Snwhitehorn	    }
2229217309Snwhitehorn	}
2230217309Snwhitehorn	(void) wnoutrefresh(stdscr);
2231217309Snwhitehorn    }
2232217309Snwhitehorn}
2233217309Snwhitehorn
2234217309Snwhitehorn#ifndef HAVE_STRCASECMP
2235217309Snwhitehornint
2236217309Snwhitehorndlg_strcmp(const char *a, const char *b)
2237217309Snwhitehorn{
2238217309Snwhitehorn    int ac, bc, cmp;
2239217309Snwhitehorn
2240217309Snwhitehorn    for (;;) {
2241217309Snwhitehorn	ac = UCH(*a++);
2242217309Snwhitehorn	bc = UCH(*b++);
2243217309Snwhitehorn	if (isalpha(ac) && islower(ac))
2244217309Snwhitehorn	    ac = _toupper(ac);
2245217309Snwhitehorn	if (isalpha(bc) && islower(bc))
2246217309Snwhitehorn	    bc = _toupper(bc);
2247217309Snwhitehorn	cmp = ac - bc;
2248217309Snwhitehorn	if (ac == 0 || bc == 0 || cmp != 0)
2249217309Snwhitehorn	    break;
2250217309Snwhitehorn    }
2251217309Snwhitehorn    return cmp;
2252217309Snwhitehorn}
2253217309Snwhitehorn#endif
2254217309Snwhitehorn
2255217309Snwhitehorn/*
2256217309Snwhitehorn * Returns true if 'dst' points to a blank which follows another blank which
2257217309Snwhitehorn * is not a leading blank on a line.
2258217309Snwhitehorn */
2259217309Snwhitehornstatic bool
2260217309Snwhitehorntrim_blank(char *base, char *dst)
2261217309Snwhitehorn{
2262217309Snwhitehorn    int count = 0;
2263217309Snwhitehorn
2264217309Snwhitehorn    while (dst-- != base) {
2265217309Snwhitehorn	if (*dst == '\n') {
2266217309Snwhitehorn	    return FALSE;
2267217309Snwhitehorn	} else if (*dst != ' ') {
2268217309Snwhitehorn	    return (count > 1);
2269217309Snwhitehorn	} else {
2270217309Snwhitehorn	    count++;
2271217309Snwhitehorn	}
2272217309Snwhitehorn    }
2273217309Snwhitehorn    return FALSE;
2274217309Snwhitehorn}
2275217309Snwhitehorn
2276217309Snwhitehorn/*
2277217309Snwhitehorn * Change embedded "\n" substrings to '\n' characters and tabs to single
2278217309Snwhitehorn * spaces.  If there are no "\n"s, it will strip all extra spaces, for
2279217309Snwhitehorn * justification.  If it has "\n"'s, it will preserve extra spaces.  If cr_wrap
2280217309Snwhitehorn * is set, it will preserve '\n's.
2281217309Snwhitehorn */
2282217309Snwhitehornvoid
2283217309Snwhitehorndlg_trim_string(char *s)
2284217309Snwhitehorn{
2285217309Snwhitehorn    char *base = s;
2286217309Snwhitehorn    char *p1;
2287217309Snwhitehorn    char *p = s;
2288224014Snwhitehorn    int has_newlines = !dialog_vars.no_nl_expand && (strstr(s, "\\n") != 0);
2289217309Snwhitehorn
2290217309Snwhitehorn    while (*p != '\0') {
2291217309Snwhitehorn	if (*p == TAB && !dialog_vars.nocollapse)
2292217309Snwhitehorn	    *p = ' ';
2293217309Snwhitehorn
2294217309Snwhitehorn	if (has_newlines) {	/* If prompt contains "\n" strings */
2295217309Snwhitehorn	    if (*p == '\\' && *(p + 1) == 'n') {
2296217309Snwhitehorn		*s++ = '\n';
2297217309Snwhitehorn		p += 2;
2298217309Snwhitehorn		p1 = p;
2299217309Snwhitehorn		/*
2300217309Snwhitehorn		 * Handle end of lines intelligently.  If '\n' follows "\n"
2301217309Snwhitehorn		 * then ignore the '\n'.  This eliminates the need to escape
2302217309Snwhitehorn		 * the '\n' character (no need to use "\n\").
2303217309Snwhitehorn		 */
2304217309Snwhitehorn		while (*p1 == ' ')
2305217309Snwhitehorn		    p1++;
2306217309Snwhitehorn		if (*p1 == '\n')
2307217309Snwhitehorn		    p = p1 + 1;
2308217309Snwhitehorn	    } else if (*p == '\n') {
2309217309Snwhitehorn		if (dialog_vars.cr_wrap)
2310217309Snwhitehorn		    *s++ = *p++;
2311217309Snwhitehorn		else {
2312217309Snwhitehorn		    /* Replace the '\n' with a space if cr_wrap is not set */
2313217309Snwhitehorn		    if (!trim_blank(base, s))
2314217309Snwhitehorn			*s++ = ' ';
2315217309Snwhitehorn		    p++;
2316217309Snwhitehorn		}
2317217309Snwhitehorn	    } else		/* If *p != '\n' */
2318217309Snwhitehorn		*s++ = *p++;
2319217309Snwhitehorn	} else if (dialog_vars.trim_whitespace) {
2320217309Snwhitehorn	    if (*p == ' ') {
2321217309Snwhitehorn		if (*(s - 1) != ' ') {
2322217309Snwhitehorn		    *s++ = ' ';
2323217309Snwhitehorn		    p++;
2324217309Snwhitehorn		} else
2325217309Snwhitehorn		    p++;
2326217309Snwhitehorn	    } else if (*p == '\n') {
2327217309Snwhitehorn		if (dialog_vars.cr_wrap)
2328217309Snwhitehorn		    *s++ = *p++;
2329217309Snwhitehorn		else if (*(s - 1) != ' ') {
2330217309Snwhitehorn		    /* Strip '\n's if cr_wrap is not set. */
2331217309Snwhitehorn		    *s++ = ' ';
2332217309Snwhitehorn		    p++;
2333217309Snwhitehorn		} else
2334217309Snwhitehorn		    p++;
2335217309Snwhitehorn	    } else
2336217309Snwhitehorn		*s++ = *p++;
2337217309Snwhitehorn	} else {		/* If there are no "\n" strings */
2338217309Snwhitehorn	    if (*p == ' ' && !dialog_vars.nocollapse) {
2339217309Snwhitehorn		if (!trim_blank(base, s))
2340217309Snwhitehorn		    *s++ = *p;
2341217309Snwhitehorn		p++;
2342217309Snwhitehorn	    } else
2343217309Snwhitehorn		*s++ = *p++;
2344217309Snwhitehorn	}
2345217309Snwhitehorn    }
2346217309Snwhitehorn
2347217309Snwhitehorn    *s = '\0';
2348217309Snwhitehorn}
2349217309Snwhitehorn
2350217309Snwhitehornvoid
2351217309Snwhitehorndlg_set_focus(WINDOW *parent, WINDOW *win)
2352217309Snwhitehorn{
2353217309Snwhitehorn    if (win != 0) {
2354217309Snwhitehorn	(void) wmove(parent,
2355217309Snwhitehorn		     getpary(win) + getcury(win),
2356217309Snwhitehorn		     getparx(win) + getcurx(win));
2357217309Snwhitehorn	(void) wnoutrefresh(win);
2358217309Snwhitehorn	(void) doupdate();
2359217309Snwhitehorn    }
2360217309Snwhitehorn}
2361217309Snwhitehorn
2362217309Snwhitehorn/*
2363217309Snwhitehorn * Returns the nominal maximum buffer size.
2364217309Snwhitehorn */
2365217309Snwhitehornint
2366217309Snwhitehorndlg_max_input(int max_len)
2367217309Snwhitehorn{
2368217309Snwhitehorn    if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN)
2369217309Snwhitehorn	max_len = dialog_vars.max_input;
2370217309Snwhitehorn
2371217309Snwhitehorn    return max_len;
2372217309Snwhitehorn}
2373217309Snwhitehorn
2374217309Snwhitehorn/*
2375217309Snwhitehorn * Free storage used for the result buffer.
2376217309Snwhitehorn */
2377217309Snwhitehornvoid
2378217309Snwhitehorndlg_clr_result(void)
2379217309Snwhitehorn{
2380217309Snwhitehorn    if (dialog_vars.input_length) {
2381217309Snwhitehorn	dialog_vars.input_length = 0;
2382217309Snwhitehorn	if (dialog_vars.input_result)
2383217309Snwhitehorn	    free(dialog_vars.input_result);
2384217309Snwhitehorn    }
2385217309Snwhitehorn    dialog_vars.input_result = 0;
2386217309Snwhitehorn}
2387217309Snwhitehorn
2388217309Snwhitehorn/*
2389217309Snwhitehorn * Setup a fixed-buffer for the result.
2390217309Snwhitehorn */
2391217309Snwhitehornchar *
2392217309Snwhitehorndlg_set_result(const char *string)
2393217309Snwhitehorn{
2394220749Snwhitehorn    unsigned need = string ? (unsigned) strlen(string) + 1 : 0;
2395217309Snwhitehorn
2396217309Snwhitehorn    /* inputstr.c needs a fixed buffer */
2397217309Snwhitehorn    if (need < MAX_LEN)
2398217309Snwhitehorn	need = MAX_LEN;
2399217309Snwhitehorn
2400217309Snwhitehorn    /*
2401217309Snwhitehorn     * If the buffer is not big enough, allocate a new one.
2402217309Snwhitehorn     */
2403217309Snwhitehorn    if (dialog_vars.input_length != 0
2404217309Snwhitehorn	|| dialog_vars.input_result == 0
2405217309Snwhitehorn	|| need > MAX_LEN) {
2406217309Snwhitehorn
2407217309Snwhitehorn	dlg_clr_result();
2408217309Snwhitehorn
2409217309Snwhitehorn	dialog_vars.input_length = need;
2410217309Snwhitehorn	dialog_vars.input_result = dlg_malloc(char, need);
2411217309Snwhitehorn	assert_ptr(dialog_vars.input_result, "dlg_set_result");
2412217309Snwhitehorn    }
2413217309Snwhitehorn
2414217309Snwhitehorn    strcpy(dialog_vars.input_result, string ? string : "");
2415217309Snwhitehorn
2416217309Snwhitehorn    return dialog_vars.input_result;
2417217309Snwhitehorn}
2418217309Snwhitehorn
2419217309Snwhitehorn/*
2420217309Snwhitehorn * Accumulate results in dynamically allocated buffer.
2421217309Snwhitehorn * If input_length is zero, it is a MAX_LEN buffer belonging to the caller.
2422217309Snwhitehorn */
2423217309Snwhitehornvoid
2424217309Snwhitehorndlg_add_result(const char *string)
2425217309Snwhitehorn{
2426217309Snwhitehorn    unsigned have = (dialog_vars.input_result
2427220749Snwhitehorn		     ? (unsigned) strlen(dialog_vars.input_result)
2428217309Snwhitehorn		     : 0);
2429220749Snwhitehorn    unsigned want = (unsigned) strlen(string) + 1 + have;
2430217309Snwhitehorn
2431217309Snwhitehorn    if ((want >= MAX_LEN)
2432217309Snwhitehorn	|| (dialog_vars.input_length != 0)
2433217309Snwhitehorn	|| (dialog_vars.input_result == 0)) {
2434217309Snwhitehorn
2435217309Snwhitehorn	if (dialog_vars.input_length == 0
2436217309Snwhitehorn	    || dialog_vars.input_result == 0) {
2437217309Snwhitehorn
2438220749Snwhitehorn	    char *save_result = dialog_vars.input_result;
2439217309Snwhitehorn
2440217309Snwhitehorn	    dialog_vars.input_length = want * 2;
2441217309Snwhitehorn	    dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length);
2442217309Snwhitehorn	    assert_ptr(dialog_vars.input_result, "dlg_add_result malloc");
2443220749Snwhitehorn	    dialog_vars.input_result[0] = '\0';
2444220749Snwhitehorn	    if (save_result != 0)
2445220749Snwhitehorn		strcpy(dialog_vars.input_result, save_result);
2446217309Snwhitehorn	} else if (want >= dialog_vars.input_length) {
2447217309Snwhitehorn	    dialog_vars.input_length = want * 2;
2448217309Snwhitehorn	    dialog_vars.input_result = dlg_realloc(char,
2449217309Snwhitehorn						   dialog_vars.input_length,
2450217309Snwhitehorn						   dialog_vars.input_result);
2451217309Snwhitehorn	    assert_ptr(dialog_vars.input_result, "dlg_add_result realloc");
2452217309Snwhitehorn	}
2453217309Snwhitehorn    }
2454217309Snwhitehorn    strcat(dialog_vars.input_result, string);
2455217309Snwhitehorn}
2456217309Snwhitehorn
2457217309Snwhitehorn/*
2458217309Snwhitehorn * These are characters that (aside from the quote-delimiter) will have to
2459217309Snwhitehorn * be escaped in a single- or double-quoted string.
2460217309Snwhitehorn */
2461217309Snwhitehorn#define FIX_SINGLE "\n\\"
2462217309Snwhitehorn#define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>"
2463217309Snwhitehorn
2464217309Snwhitehorn/*
2465217309Snwhitehorn * Returns the quote-delimiter.
2466217309Snwhitehorn */
2467217309Snwhitehornstatic const char *
2468217309Snwhitehornquote_delimiter(void)
2469217309Snwhitehorn{
2470217309Snwhitehorn    return dialog_vars.single_quoted ? "'" : "\"";
2471217309Snwhitehorn}
2472217309Snwhitehorn
2473217309Snwhitehorn/*
2474217309Snwhitehorn * Returns true if we should quote the given string.
2475217309Snwhitehorn */
2476217309Snwhitehornstatic bool
2477217309Snwhitehornmust_quote(char *string)
2478217309Snwhitehorn{
2479217309Snwhitehorn    bool code = FALSE;
2480217309Snwhitehorn
2481217309Snwhitehorn    if (*string != '\0') {
2482220749Snwhitehorn	size_t len = strlen(string);
2483217309Snwhitehorn	if (strcspn(string, quote_delimiter()) != len)
2484217309Snwhitehorn	    code = TRUE;
2485217309Snwhitehorn	else if (strcspn(string, "\n\t ") != len)
2486217309Snwhitehorn	    code = TRUE;
2487217309Snwhitehorn	else
2488217309Snwhitehorn	    code = (strcspn(string, FIX_DOUBLE) != len);
2489217309Snwhitehorn    } else {
2490217309Snwhitehorn	code = TRUE;
2491217309Snwhitehorn    }
2492217309Snwhitehorn
2493217309Snwhitehorn    return code;
2494217309Snwhitehorn}
2495217309Snwhitehorn
2496217309Snwhitehorn/*
2497217309Snwhitehorn * Add a quoted string to the result buffer.
2498217309Snwhitehorn */
2499217309Snwhitehornvoid
2500217309Snwhitehorndlg_add_quoted(char *string)
2501217309Snwhitehorn{
2502217309Snwhitehorn    char temp[2];
2503217309Snwhitehorn    const char *my_quote = quote_delimiter();
2504217309Snwhitehorn    const char *must_fix = (dialog_vars.single_quoted
2505217309Snwhitehorn			    ? FIX_SINGLE
2506217309Snwhitehorn			    : FIX_DOUBLE);
2507217309Snwhitehorn
2508251843Sbapt    if (must_quote(string)) {
2509217309Snwhitehorn	temp[1] = '\0';
2510217309Snwhitehorn	dlg_add_result(my_quote);
2511217309Snwhitehorn	while (*string != '\0') {
2512217309Snwhitehorn	    temp[0] = *string++;
2513217309Snwhitehorn	    if (strchr(my_quote, *temp) || strchr(must_fix, *temp))
2514217309Snwhitehorn		dlg_add_result("\\");
2515217309Snwhitehorn	    dlg_add_result(temp);
2516217309Snwhitehorn	}
2517217309Snwhitehorn	dlg_add_result(my_quote);
2518217309Snwhitehorn    } else {
2519217309Snwhitehorn	dlg_add_result(string);
2520217309Snwhitehorn    }
2521217309Snwhitehorn}
2522217309Snwhitehorn
2523217309Snwhitehorn/*
2524217309Snwhitehorn * When adding a result, make that depend on whether "--quoted" is used.
2525217309Snwhitehorn */
2526217309Snwhitehornvoid
2527217309Snwhitehorndlg_add_string(char *string)
2528217309Snwhitehorn{
2529217309Snwhitehorn    if (dialog_vars.quoted) {
2530217309Snwhitehorn	dlg_add_quoted(string);
2531217309Snwhitehorn    } else {
2532217309Snwhitehorn	dlg_add_result(string);
2533217309Snwhitehorn    }
2534217309Snwhitehorn}
2535217309Snwhitehorn
2536217309Snwhitehornbool
2537217309Snwhitehorndlg_need_separator(void)
2538217309Snwhitehorn{
2539217309Snwhitehorn    bool result = FALSE;
2540217309Snwhitehorn
2541217309Snwhitehorn    if (dialog_vars.output_separator) {
2542217309Snwhitehorn	result = TRUE;
2543217309Snwhitehorn    } else if (dialog_vars.input_result && *(dialog_vars.input_result)) {
2544217309Snwhitehorn	result = TRUE;
2545217309Snwhitehorn    }
2546217309Snwhitehorn    return result;
2547217309Snwhitehorn}
2548217309Snwhitehorn
2549217309Snwhitehornvoid
2550217309Snwhitehorndlg_add_separator(void)
2551217309Snwhitehorn{
2552217309Snwhitehorn    const char *separator = (dialog_vars.separate_output) ? "\n" : " ";
2553217309Snwhitehorn
2554217309Snwhitehorn    if (dialog_vars.output_separator)
2555217309Snwhitehorn	separator = dialog_vars.output_separator;
2556217309Snwhitehorn
2557217309Snwhitehorn    dlg_add_result(separator);
2558217309Snwhitehorn}
2559217309Snwhitehorn
2560255852Sdteske#define HELP_PREFIX		"HELP "
2561255852Sdteske
2562255852Sdteskevoid
2563255852Sdteskedlg_add_help_listitem(int *result, char **tag, DIALOG_LISTITEM * item)
2564255852Sdteske{
2565255852Sdteske    dlg_add_result(HELP_PREFIX);
2566255852Sdteske    if (USE_ITEM_HELP(item->help)) {
2567255852Sdteske	*tag = dialog_vars.help_tags ? item->name : item->help;
2568255852Sdteske	*result = DLG_EXIT_ITEM_HELP;
2569255852Sdteske    } else {
2570255852Sdteske	*tag = item->name;
2571255852Sdteske    }
2572255852Sdteske}
2573255852Sdteske
2574255852Sdteskevoid
2575255852Sdteskedlg_add_help_formitem(int *result, char **tag, DIALOG_FORMITEM * item)
2576255852Sdteske{
2577255852Sdteske    dlg_add_result(HELP_PREFIX);
2578255852Sdteske    if (USE_ITEM_HELP(item->help)) {
2579255852Sdteske	*tag = dialog_vars.help_tags ? item->name : item->help;
2580255852Sdteske	*result = DLG_EXIT_ITEM_HELP;
2581255852Sdteske    } else {
2582255852Sdteske	*tag = item->name;
2583255852Sdteske    }
2584255852Sdteske}
2585255852Sdteske
2586217309Snwhitehorn/*
2587217309Snwhitehorn * Some widgets support only one value of a given variable - save/restore the
2588217309Snwhitehorn * global dialog_vars so we can override it consistently.
2589217309Snwhitehorn */
2590217309Snwhitehornvoid
2591217309Snwhitehorndlg_save_vars(DIALOG_VARS * vars)
2592217309Snwhitehorn{
2593217309Snwhitehorn    *vars = dialog_vars;
2594217309Snwhitehorn}
2595217309Snwhitehorn
2596220749Snwhitehorn/*
2597220749Snwhitehorn * Most of the data in DIALOG_VARS is normally set by command-line options.
2598220749Snwhitehorn * The input_result member is an exception; it is normally set by the dialog
2599220749Snwhitehorn * library to return result values.
2600220749Snwhitehorn */
2601217309Snwhitehornvoid
2602217309Snwhitehorndlg_restore_vars(DIALOG_VARS * vars)
2603217309Snwhitehorn{
2604220749Snwhitehorn    char *save_result = dialog_vars.input_result;
2605220749Snwhitehorn    unsigned save_length = dialog_vars.input_length;
2606220749Snwhitehorn
2607217309Snwhitehorn    dialog_vars = *vars;
2608220749Snwhitehorn    dialog_vars.input_result = save_result;
2609220749Snwhitehorn    dialog_vars.input_length = save_length;
2610217309Snwhitehorn}
2611217309Snwhitehorn
2612217309Snwhitehorn/*
2613217309Snwhitehorn * Called each time a widget is invoked which may do output, increment a count.
2614217309Snwhitehorn */
2615217309Snwhitehornvoid
2616217309Snwhitehorndlg_does_output(void)
2617217309Snwhitehorn{
2618217309Snwhitehorn    dialog_state.output_count += 1;
2619217309Snwhitehorn}
2620217309Snwhitehorn
2621217309Snwhitehorn/*
2622217309Snwhitehorn * Compatibility for different versions of curses.
2623217309Snwhitehorn */
2624217309Snwhitehorn#if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY))
2625217309Snwhitehornint
2626251843Sbaptdlg_getbegx(WINDOW *win)
2627217309Snwhitehorn{
2628217309Snwhitehorn    int y, x;
2629217309Snwhitehorn    getbegyx(win, y, x);
2630217309Snwhitehorn    return x;
2631217309Snwhitehorn}
2632217309Snwhitehornint
2633251843Sbaptdlg_getbegy(WINDOW *win)
2634217309Snwhitehorn{
2635217309Snwhitehorn    int y, x;
2636217309Snwhitehorn    getbegyx(win, y, x);
2637217309Snwhitehorn    return y;
2638217309Snwhitehorn}
2639217309Snwhitehorn#endif
2640217309Snwhitehorn
2641217309Snwhitehorn#if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY))
2642217309Snwhitehornint
2643251843Sbaptdlg_getcurx(WINDOW *win)
2644217309Snwhitehorn{
2645217309Snwhitehorn    int y, x;
2646217309Snwhitehorn    getyx(win, y, x);
2647217309Snwhitehorn    return x;
2648217309Snwhitehorn}
2649217309Snwhitehornint
2650251843Sbaptdlg_getcury(WINDOW *win)
2651217309Snwhitehorn{
2652217309Snwhitehorn    int y, x;
2653217309Snwhitehorn    getyx(win, y, x);
2654217309Snwhitehorn    return y;
2655217309Snwhitehorn}
2656217309Snwhitehorn#endif
2657217309Snwhitehorn
2658217309Snwhitehorn#if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY))
2659217309Snwhitehornint
2660251843Sbaptdlg_getmaxx(WINDOW *win)
2661217309Snwhitehorn{
2662217309Snwhitehorn    int y, x;
2663217309Snwhitehorn    getmaxyx(win, y, x);
2664217309Snwhitehorn    return x;
2665217309Snwhitehorn}
2666217309Snwhitehornint
2667251843Sbaptdlg_getmaxy(WINDOW *win)
2668217309Snwhitehorn{
2669217309Snwhitehorn    int y, x;
2670217309Snwhitehorn    getmaxyx(win, y, x);
2671217309Snwhitehorn    return y;
2672217309Snwhitehorn}
2673217309Snwhitehorn#endif
2674217309Snwhitehorn
2675217309Snwhitehorn#if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY))
2676217309Snwhitehornint
2677251843Sbaptdlg_getparx(WINDOW *win)
2678217309Snwhitehorn{
2679217309Snwhitehorn    int y, x;
2680217309Snwhitehorn    getparyx(win, y, x);
2681217309Snwhitehorn    return x;
2682217309Snwhitehorn}
2683217309Snwhitehornint
2684251843Sbaptdlg_getpary(WINDOW *win)
2685217309Snwhitehorn{
2686217309Snwhitehorn    int y, x;
2687217309Snwhitehorn    getparyx(win, y, x);
2688217309Snwhitehorn    return y;
2689217309Snwhitehorn}
2690217309Snwhitehorn#endif
2691251843Sbapt
2692251843Sbapt#ifdef NEED_WGETPARENT
2693251843SbaptWINDOW *
2694251843Sbaptdlg_wgetparent(WINDOW *win)
2695251843Sbapt{
2696251843Sbapt#undef wgetparent
2697251843Sbapt    WINDOW *result = 0;
2698251843Sbapt    DIALOG_WINDOWS *p;
2699251843Sbapt
2700251843Sbapt    for (p = dialog_state.all_subwindows; p != 0; p = p->next) {
2701251843Sbapt	if (p->shadow == win) {
2702251843Sbapt	    result = p->normal;
2703251843Sbapt	    break;
2704251843Sbapt	}
2705251843Sbapt    }
2706251843Sbapt    return result;
2707251843Sbapt}
2708251843Sbapt#endif
2709