xref: /freebsd/contrib/dialog/util.c (revision 2a3e3873a1e4cd958f2b0f85d3b10cfa40575d30)
14c8945a0SNathan Whitehorn /*
2*2a3e3873SBaptiste Daroussin  *  $Id: util.c,v 1.255 2013/05/23 22:58:28 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  util.c -- miscellaneous utilities for dialog
54c8945a0SNathan Whitehorn  *
6*2a3e3873SBaptiste Daroussin  *  Copyright 2000-2012,2013	Thomas E. Dickey
74c8945a0SNathan Whitehorn  *
84c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
94c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
104c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
114c8945a0SNathan Whitehorn  *
124c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
134c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
144c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
164c8945a0SNathan Whitehorn  *
174c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
184c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
194c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
204c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
214c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
224c8945a0SNathan Whitehorn  *
234c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors
244c8945a0SNathan Whitehorn  *	Savio Lam (lam836@cs.cuhk.hk)
254c8945a0SNathan Whitehorn  */
264c8945a0SNathan Whitehorn 
274c8945a0SNathan Whitehorn #include <dialog.h>
284c8945a0SNathan Whitehorn #include <dlg_keys.h>
294c8945a0SNathan Whitehorn 
30*2a3e3873SBaptiste Daroussin #ifdef HAVE_SETLOCALE
31*2a3e3873SBaptiste Daroussin #include <locale.h>
32*2a3e3873SBaptiste Daroussin #endif
33*2a3e3873SBaptiste Daroussin 
34*2a3e3873SBaptiste Daroussin #ifdef NEED_WCHAR_H
35*2a3e3873SBaptiste Daroussin #include <wchar.h>
36*2a3e3873SBaptiste Daroussin #endif
37*2a3e3873SBaptiste Daroussin 
384c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
394c8945a0SNathan Whitehorn #if defined(HAVE_NCURSESW_TERM_H)
404c8945a0SNathan Whitehorn #include <ncursesw/term.h>
414c8945a0SNathan Whitehorn #elif defined(HAVE_NCURSES_TERM_H)
424c8945a0SNathan Whitehorn #include <ncurses/term.h>
434c8945a0SNathan Whitehorn #else
444c8945a0SNathan Whitehorn #include <term.h>
454c8945a0SNathan Whitehorn #endif
464c8945a0SNathan Whitehorn #endif
474c8945a0SNathan Whitehorn 
48682c9e0fSNathan Whitehorn #if defined(HAVE_WCHGAT)
49682c9e0fSNathan Whitehorn #  if defined(NCURSES_VERSION_PATCH)
50682c9e0fSNathan Whitehorn #    if NCURSES_VERSION_PATCH >= 20060715
51682c9e0fSNathan Whitehorn #      define USE_WCHGAT 1
52682c9e0fSNathan Whitehorn #    else
53682c9e0fSNathan Whitehorn #      define USE_WCHGAT 0
54682c9e0fSNathan Whitehorn #    endif
55682c9e0fSNathan Whitehorn #  else
56682c9e0fSNathan Whitehorn #    define USE_WCHGAT 1
57682c9e0fSNathan Whitehorn #  endif
58682c9e0fSNathan Whitehorn #else
59682c9e0fSNathan Whitehorn #  define USE_WCHGAT 0
60682c9e0fSNathan Whitehorn #endif
61682c9e0fSNathan Whitehorn 
624c8945a0SNathan Whitehorn /* globals */
634c8945a0SNathan Whitehorn DIALOG_STATE dialog_state;
644c8945a0SNathan Whitehorn DIALOG_VARS dialog_vars;
654c8945a0SNathan Whitehorn 
66*2a3e3873SBaptiste Daroussin #if !(defined(HAVE_WGETPARENT) && defined(HAVE_WINDOW__PARENT))
67*2a3e3873SBaptiste Daroussin #define NEED_WGETPARENT 1
68*2a3e3873SBaptiste Daroussin #else
69*2a3e3873SBaptiste Daroussin #undef NEED_WGETPARENT
70*2a3e3873SBaptiste Daroussin #endif
71*2a3e3873SBaptiste Daroussin 
724c8945a0SNathan Whitehorn #define concat(a,b) a##b
734c8945a0SNathan Whitehorn 
744c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
754c8945a0SNathan Whitehorn #define RC_DATA(name,comment) , #name "_color", comment " color"
764c8945a0SNathan Whitehorn #else
774c8945a0SNathan Whitehorn #define RC_DATA(name,comment)	/*nothing */
784c8945a0SNathan Whitehorn #endif
794c8945a0SNathan Whitehorn 
804c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
814c8945a0SNathan Whitehorn #include <dlg_colors.h>
824c8945a0SNathan Whitehorn #define COLOR_DATA(upr) , \
834c8945a0SNathan Whitehorn 	concat(DLGC_FG_,upr), \
844c8945a0SNathan Whitehorn 	concat(DLGC_BG_,upr), \
854c8945a0SNathan Whitehorn 	concat(DLGC_HL_,upr)
864c8945a0SNathan Whitehorn #else
874c8945a0SNathan Whitehorn #define COLOR_DATA(upr)		/*nothing */
884c8945a0SNathan Whitehorn #endif
894c8945a0SNathan Whitehorn 
904c8945a0SNathan Whitehorn #define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }
914c8945a0SNathan Whitehorn 
92682c9e0fSNathan Whitehorn #define UseShadow(dw) ((dw) != 0 && (dw)->normal != 0 && (dw)->shadow != 0)
93682c9e0fSNathan Whitehorn 
944c8945a0SNathan Whitehorn /*
954c8945a0SNathan Whitehorn  * Table of color and attribute values, default is for mono display.
96*2a3e3873SBaptiste Daroussin  * The order matches the DIALOG_ATR() values.
974c8945a0SNathan Whitehorn  */
984c8945a0SNathan Whitehorn /* *INDENT-OFF* */
994c8945a0SNathan Whitehorn DIALOG_COLORS dlg_color_table[] =
1004c8945a0SNathan Whitehorn {
1014c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SCREEN,			screen, "Screen"),
1024c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SHADOW,			shadow, "Shadow"),
1034c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DIALOG,			dialog, "Dialog box"),
1044c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TITLE,			title, "Dialog box title"),
1054c8945a0SNathan Whitehorn     DATA(A_REVERSE,	BORDER,			border, "Dialog box border"),
1064c8945a0SNathan Whitehorn     DATA(A_BOLD,	BUTTON_ACTIVE,		button_active, "Active button"),
1074c8945a0SNathan Whitehorn     DATA(A_DIM,		BUTTON_INACTIVE,	button_inactive, "Inactive button"),
1084c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_ACTIVE,	button_key_active, "Active button key"),
1094c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_INACTIVE,	button_key_inactive, "Inactive button key"),
1104c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_ACTIVE,	button_label_active, "Active button label"),
1114c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_INACTIVE,	button_label_inactive, "Inactive button label"),
1124c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX,		inputbox, "Input box"),
1134c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX_BORDER,	inputbox_border, "Input box border"),
1144c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX,		searchbox, "Search box"),
1154c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_TITLE,	searchbox_title, "Search box title"),
1164c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_BORDER,	searchbox_border, "Search box border"),
1174c8945a0SNathan Whitehorn     DATA(A_REVERSE,	POSITION_INDICATOR,	position_indicator, "File position indicator"),
1184c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX,		menubox, "Menu box"),
1194c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX_BORDER,		menubox_border, "Menu box border"),
1204c8945a0SNathan Whitehorn     DATA(A_REVERSE,	ITEM,			item, "Item"),
1214c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEM_SELECTED,		item_selected, "Selected item"),
1224c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG,			tag, "Tag"),
1234c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG_SELECTED,		tag_selected, "Selected tag"),
1244c8945a0SNathan Whitehorn     DATA(A_NORMAL,	TAG_KEY,		tag_key, "Tag key"),
1254c8945a0SNathan Whitehorn     DATA(A_BOLD,	TAG_KEY_SELECTED,	tag_key_selected, "Selected tag key"),
1264c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK,			check, "Check box"),
1274c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK_SELECTED,		check_selected, "Selected check box"),
1284c8945a0SNathan Whitehorn     DATA(A_REVERSE,	UARROW,			uarrow, "Up arrow"),
1294c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DARROW,			darrow, "Down arrow"),
1304c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEMHELP,		itemhelp, "Item help-text"),
1314c8945a0SNathan Whitehorn     DATA(A_BOLD,	FORM_ACTIVE_TEXT,	form_active_text, "Active form text"),
1324c8945a0SNathan Whitehorn     DATA(A_REVERSE,	FORM_TEXT,		form_text, "Form text"),
1337a1c0d96SNathan Whitehorn     DATA(A_NORMAL,	FORM_ITEM_READONLY,	form_item_readonly, "Readonly form item"),
134*2a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	GAUGE,			gauge, "Dialog box gauge"),
135*2a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	BORDER2,		border2, "Dialog box border2"),
136*2a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	INPUTBOX_BORDER2,	inputbox_border2, "Input box border2"),
137*2a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	SEARCHBOX_BORDER2,	searchbox_border2, "Search box border2"),
138*2a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	MENUBOX_BORDER2,	menubox_border2, "Menu box border2")
1394c8945a0SNathan Whitehorn };
1404c8945a0SNathan Whitehorn /* *INDENT-ON* */
1414c8945a0SNathan Whitehorn 
1424c8945a0SNathan Whitehorn /*
143*2a3e3873SBaptiste Daroussin  * Maintain a list of subwindows so that we can delete them to cleanup.
144*2a3e3873SBaptiste Daroussin  * More important, this provides a fallback when wgetparent() is not available.
145*2a3e3873SBaptiste Daroussin  */
146*2a3e3873SBaptiste Daroussin static void
147*2a3e3873SBaptiste Daroussin add_subwindow(WINDOW *parent, WINDOW *child)
148*2a3e3873SBaptiste Daroussin {
149*2a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
150*2a3e3873SBaptiste Daroussin 
151*2a3e3873SBaptiste Daroussin     if (p != 0) {
152*2a3e3873SBaptiste Daroussin 	p->normal = parent;
153*2a3e3873SBaptiste Daroussin 	p->shadow = child;
154*2a3e3873SBaptiste Daroussin 	p->next = dialog_state.all_subwindows;
155*2a3e3873SBaptiste Daroussin 	dialog_state.all_subwindows = p;
156*2a3e3873SBaptiste Daroussin     }
157*2a3e3873SBaptiste Daroussin }
158*2a3e3873SBaptiste Daroussin 
159*2a3e3873SBaptiste Daroussin static void
160*2a3e3873SBaptiste Daroussin del_subwindows(WINDOW *parent)
161*2a3e3873SBaptiste Daroussin {
162*2a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p = dialog_state.all_subwindows;
163*2a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *q = 0;
164*2a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *r;
165*2a3e3873SBaptiste Daroussin 
166*2a3e3873SBaptiste Daroussin     while (p != 0) {
167*2a3e3873SBaptiste Daroussin 	if (p->normal == parent) {
168*2a3e3873SBaptiste Daroussin 	    delwin(p->shadow);
169*2a3e3873SBaptiste Daroussin 	    r = p->next;
170*2a3e3873SBaptiste Daroussin 	    if (q == 0) {
171*2a3e3873SBaptiste Daroussin 		dialog_state.all_subwindows = r;
172*2a3e3873SBaptiste Daroussin 	    } else {
173*2a3e3873SBaptiste Daroussin 		q->next = r;
174*2a3e3873SBaptiste Daroussin 	    }
175*2a3e3873SBaptiste Daroussin 	    free(p);
176*2a3e3873SBaptiste Daroussin 	    p = r;
177*2a3e3873SBaptiste Daroussin 	} else {
178*2a3e3873SBaptiste Daroussin 	    q = p;
179*2a3e3873SBaptiste Daroussin 	    p = p->next;
180*2a3e3873SBaptiste Daroussin 	}
181*2a3e3873SBaptiste Daroussin     }
182*2a3e3873SBaptiste Daroussin }
183*2a3e3873SBaptiste Daroussin 
184*2a3e3873SBaptiste Daroussin /*
1854c8945a0SNathan Whitehorn  * Display background title if it exists ...
1864c8945a0SNathan Whitehorn  */
1874c8945a0SNathan Whitehorn void
1884c8945a0SNathan Whitehorn dlg_put_backtitle(void)
1894c8945a0SNathan Whitehorn {
1904c8945a0SNathan Whitehorn     int i;
1914c8945a0SNathan Whitehorn 
1924c8945a0SNathan Whitehorn     if (dialog_vars.backtitle != NULL) {
1934c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
1944c8945a0SNathan Whitehorn 	int backwidth = dlg_count_columns(dialog_vars.backtitle);
1954c8945a0SNathan Whitehorn 
196*2a3e3873SBaptiste Daroussin 	(void) wattrset(stdscr, screen_attr);
1974c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 0, 1);
1984c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);
1994c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - backwidth; i++)
2004c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, ' ');
2014c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 1, 1);
2024c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - 2; i++)
2034c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, dlg_boxchar(ACS_HLINE));
2044c8945a0SNathan Whitehorn     }
2054c8945a0SNathan Whitehorn 
2064c8945a0SNathan Whitehorn     (void) wnoutrefresh(stdscr);
2074c8945a0SNathan Whitehorn }
2084c8945a0SNathan Whitehorn 
2094c8945a0SNathan Whitehorn /*
2104c8945a0SNathan Whitehorn  * Set window to attribute 'attr'.  There are more efficient ways to do this,
2114c8945a0SNathan Whitehorn  * but will not work on older/buggy ncurses versions.
2124c8945a0SNathan Whitehorn  */
2134c8945a0SNathan Whitehorn void
2144c8945a0SNathan Whitehorn dlg_attr_clear(WINDOW *win, int height, int width, chtype attr)
2154c8945a0SNathan Whitehorn {
2164c8945a0SNathan Whitehorn     int i, j;
2174c8945a0SNathan Whitehorn 
218*2a3e3873SBaptiste Daroussin     (void) wattrset(win, attr);
2194c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
2204c8945a0SNathan Whitehorn 	(void) wmove(win, i, 0);
2214c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
2224c8945a0SNathan Whitehorn 	    (void) waddch(win, ' ');
2234c8945a0SNathan Whitehorn     }
2244c8945a0SNathan Whitehorn     (void) touchwin(win);
2254c8945a0SNathan Whitehorn }
2264c8945a0SNathan Whitehorn 
2274c8945a0SNathan Whitehorn void
2284c8945a0SNathan Whitehorn dlg_clear(void)
2294c8945a0SNathan Whitehorn {
2304c8945a0SNathan Whitehorn     dlg_attr_clear(stdscr, LINES, COLS, screen_attr);
2314c8945a0SNathan Whitehorn }
2324c8945a0SNathan Whitehorn 
2334c8945a0SNathan Whitehorn #define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)
2344c8945a0SNathan Whitehorn 
2354c8945a0SNathan Whitehorn #define TTY_DEVICE "/dev/tty"
2364c8945a0SNathan Whitehorn 
2374c8945a0SNathan Whitehorn /*
2384c8945a0SNathan Whitehorn  * If $DIALOG_TTY exists, allow the program to try to open the terminal
2394c8945a0SNathan Whitehorn  * directly when stdout is redirected.  By default we require the "--stdout"
2404c8945a0SNathan Whitehorn  * option to be given, but some scripts were written making use of the
2414c8945a0SNathan Whitehorn  * behavior of dialog which tried opening the terminal anyway.
2424c8945a0SNathan Whitehorn  */
2434c8945a0SNathan Whitehorn static char *
2444c8945a0SNathan Whitehorn dialog_tty(void)
2454c8945a0SNathan Whitehorn {
2464c8945a0SNathan Whitehorn     char *result = getenv("DIALOG_TTY");
2474c8945a0SNathan Whitehorn     if (result != 0 && atoi(result) == 0)
2484c8945a0SNathan Whitehorn 	result = 0;
2494c8945a0SNathan Whitehorn     return result;
2504c8945a0SNathan Whitehorn }
2514c8945a0SNathan Whitehorn 
2524c8945a0SNathan Whitehorn /*
2534c8945a0SNathan Whitehorn  * Open the terminal directly.  If one of stdin, stdout or stderr really points
2544c8945a0SNathan Whitehorn  * to a tty, use it.  Otherwise give up and open /dev/tty.
2554c8945a0SNathan Whitehorn  */
2564c8945a0SNathan Whitehorn static int
2574c8945a0SNathan Whitehorn open_terminal(char **result, int mode)
2584c8945a0SNathan Whitehorn {
2594c8945a0SNathan Whitehorn     const char *device = TTY_DEVICE;
2604c8945a0SNathan Whitehorn     if (!isatty(fileno(stderr))
2614c8945a0SNathan Whitehorn 	|| (device = ttyname(fileno(stderr))) == 0) {
2624c8945a0SNathan Whitehorn 	if (!isatty(fileno(stdout))
2634c8945a0SNathan Whitehorn 	    || (device = ttyname(fileno(stdout))) == 0) {
2644c8945a0SNathan Whitehorn 	    if (!isatty(fileno(stdin))
2654c8945a0SNathan Whitehorn 		|| (device = ttyname(fileno(stdin))) == 0) {
2664c8945a0SNathan Whitehorn 		device = TTY_DEVICE;
2674c8945a0SNathan Whitehorn 	    }
2684c8945a0SNathan Whitehorn 	}
2694c8945a0SNathan Whitehorn     }
2704c8945a0SNathan Whitehorn     *result = dlg_strclone(device);
2714c8945a0SNathan Whitehorn     return open(device, mode);
2724c8945a0SNathan Whitehorn }
2734c8945a0SNathan Whitehorn 
274*2a3e3873SBaptiste Daroussin #ifdef NCURSES_VERSION
275*2a3e3873SBaptiste Daroussin static int
276*2a3e3873SBaptiste Daroussin my_putc(int ch)
277*2a3e3873SBaptiste Daroussin {
278*2a3e3873SBaptiste Daroussin     char buffer[2];
279*2a3e3873SBaptiste Daroussin     int fd = fileno(dialog_state.screen_output);
280*2a3e3873SBaptiste Daroussin 
281*2a3e3873SBaptiste Daroussin     buffer[0] = (char) ch;
282*2a3e3873SBaptiste Daroussin     return (int) write(fd, buffer, (size_t) 1);
283*2a3e3873SBaptiste Daroussin }
284*2a3e3873SBaptiste Daroussin #endif
285*2a3e3873SBaptiste Daroussin 
2864c8945a0SNathan Whitehorn /*
2874c8945a0SNathan Whitehorn  * Do some initialization for dialog.
2884c8945a0SNathan Whitehorn  *
2894c8945a0SNathan Whitehorn  * 'input' is the real tty input of dialog.  Usually it is stdin, but if
2904c8945a0SNathan Whitehorn  * --input-fd option is used, it may be anything.
2914c8945a0SNathan Whitehorn  *
2924c8945a0SNathan Whitehorn  * 'output' is where dialog will send its result.  Usually it is stderr, but
2934c8945a0SNathan Whitehorn  * if --stdout or --output-fd is used, it may be anything.  We are concerned
2944c8945a0SNathan Whitehorn  * mainly with the case where it happens to be the same as stdout.
2954c8945a0SNathan Whitehorn  */
2964c8945a0SNathan Whitehorn void
2974c8945a0SNathan Whitehorn init_dialog(FILE *input, FILE *output)
2984c8945a0SNathan Whitehorn {
2994c8945a0SNathan Whitehorn     int fd1, fd2;
3004c8945a0SNathan Whitehorn     char *device = 0;
3014c8945a0SNathan Whitehorn 
302*2a3e3873SBaptiste Daroussin     setlocale(LC_ALL, "");
303*2a3e3873SBaptiste Daroussin 
3044c8945a0SNathan Whitehorn     dialog_state.output = output;
3054c8945a0SNathan Whitehorn     dialog_state.tab_len = TAB_LEN;
3064c8945a0SNathan Whitehorn     dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;
3074c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
3084c8945a0SNathan Whitehorn     dialog_state.use_colors = USE_COLORS;	/* use colors by default? */
3094c8945a0SNathan Whitehorn     dialog_state.use_shadow = USE_SHADOW;	/* shadow dialog boxes by default? */
3104c8945a0SNathan Whitehorn #endif
3114c8945a0SNathan Whitehorn 
3124c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
3134c8945a0SNathan Whitehorn     if (dlg_parse_rc() == -1)	/* Read the configuration file */
3144c8945a0SNathan Whitehorn 	dlg_exiterr("init_dialog: dlg_parse_rc");
3154c8945a0SNathan Whitehorn #endif
3164c8945a0SNathan Whitehorn 
3174c8945a0SNathan Whitehorn     /*
3184c8945a0SNathan Whitehorn      * Some widgets (such as gauge) may read from the standard input.  Pipes
3194c8945a0SNathan Whitehorn      * only connect stdout/stdin, so there is not much choice.  But reading a
3204c8945a0SNathan Whitehorn      * pipe would get in the way of curses' normal reading stdin for getch.
3214c8945a0SNathan Whitehorn      *
3224c8945a0SNathan Whitehorn      * As in the --stdout (see below), reopening the terminal does not always
3234c8945a0SNathan Whitehorn      * work properly.  dialog provides a --pipe-fd option for this purpose.  We
3244c8945a0SNathan Whitehorn      * test that case first (differing fileno's for input/stdin).  If the
3254c8945a0SNathan Whitehorn      * fileno's are equal, but we're not reading from a tty, see if we can open
3264c8945a0SNathan Whitehorn      * /dev/tty.
3274c8945a0SNathan Whitehorn      */
3284c8945a0SNathan Whitehorn     dialog_state.pipe_input = stdin;
3294c8945a0SNathan Whitehorn     if (fileno(input) != fileno(stdin)) {
33019718649SNathan Whitehorn 	if ((fd1 = dup(fileno(input))) >= 0
3314c8945a0SNathan Whitehorn 	    && (fd2 = dup(fileno(stdin))) >= 0) {
3324c8945a0SNathan Whitehorn 	    (void) dup2(fileno(input), fileno(stdin));
3334c8945a0SNathan Whitehorn 	    dialog_state.pipe_input = fdopen(fd2, "r");
3344c8945a0SNathan Whitehorn 	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */
3354c8945a0SNathan Whitehorn 		(void) dup2(fileno(stdin), 0);
336*2a3e3873SBaptiste Daroussin 	} else {
3374c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-input");
338*2a3e3873SBaptiste Daroussin 	}
339*2a3e3873SBaptiste Daroussin 	close(fd1);
3404c8945a0SNathan Whitehorn     } else if (!isatty(fileno(stdin))) {
341*2a3e3873SBaptiste Daroussin 	if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0) {
342*2a3e3873SBaptiste Daroussin 	    if ((fd2 = dup(fileno(stdin))) >= 0) {
3434c8945a0SNathan Whitehorn 		dialog_state.pipe_input = fdopen(fd2, "r");
3444c8945a0SNathan Whitehorn 		if (freopen(device, "r", stdin) == 0)
3454c8945a0SNathan Whitehorn 		    dlg_exiterr("cannot open tty-input");
3464c8945a0SNathan Whitehorn 		if (fileno(stdin) != 0)		/* some functions may read fd #0 */
3474c8945a0SNathan Whitehorn 		    (void) dup2(fileno(stdin), 0);
3484c8945a0SNathan Whitehorn 	    }
349*2a3e3873SBaptiste Daroussin 	    close(fd1);
350*2a3e3873SBaptiste Daroussin 	}
3514c8945a0SNathan Whitehorn 	free(device);
3524c8945a0SNathan Whitehorn     }
3534c8945a0SNathan Whitehorn 
3544c8945a0SNathan Whitehorn     /*
3554c8945a0SNathan Whitehorn      * If stdout is not a tty and dialog is called with the --stdout option, we
3564c8945a0SNathan Whitehorn      * have to provide for a way to write to the screen.
3574c8945a0SNathan Whitehorn      *
3584c8945a0SNathan Whitehorn      * The curses library normally writes its output to stdout, leaving stderr
3594c8945a0SNathan Whitehorn      * free for scripting.  Scripts are simpler when stdout is redirected.  The
3604c8945a0SNathan Whitehorn      * newterm function is useful; it allows us to specify where the output
3614c8945a0SNathan Whitehorn      * goes.  Reopening the terminal is not portable since several
3624c8945a0SNathan Whitehorn      * configurations do not allow this to work properly:
3634c8945a0SNathan Whitehorn      *
3644c8945a0SNathan Whitehorn      * a) some getty implementations (and possibly broken tty drivers, e.g., on
3654c8945a0SNathan Whitehorn      *    HPUX 10 and 11) cause stdin to act as if it is still in cooked mode
3664c8945a0SNathan Whitehorn      *    even though results from ioctl's state that it is successfully
3674c8945a0SNathan Whitehorn      *    altered to raw mode.  Broken is the proper term.
3684c8945a0SNathan Whitehorn      *
3694c8945a0SNathan Whitehorn      * b) the user may not have permissions on the device, e.g., if one su's
3704c8945a0SNathan Whitehorn      *    from the login user to another non-privileged user.
3714c8945a0SNathan Whitehorn      */
3724c8945a0SNathan Whitehorn     if (!isatty(fileno(stdout))
3734c8945a0SNathan Whitehorn 	&& (fileno(stdout) == fileno(output) || dialog_tty())) {
3744c8945a0SNathan Whitehorn 	if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0
3754c8945a0SNathan Whitehorn 	    && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {
3764c8945a0SNathan Whitehorn 	    if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {
3774c8945a0SNathan Whitehorn 		dlg_exiterr("cannot initialize curses");
3784c8945a0SNathan Whitehorn 	    }
3794c8945a0SNathan Whitehorn 	    free(device);
3804c8945a0SNathan Whitehorn 	} else {
3814c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-output");
3824c8945a0SNathan Whitehorn 	}
3834c8945a0SNathan Whitehorn     } else {
3844c8945a0SNathan Whitehorn 	dialog_state.screen_output = stdout;
3854c8945a0SNathan Whitehorn 	(void) initscr();
3864c8945a0SNathan Whitehorn     }
3874c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
3884c8945a0SNathan Whitehorn     /*
3894c8945a0SNathan Whitehorn      * Cancel xterm's alternate-screen mode.
3904c8945a0SNathan Whitehorn      */
3914c8945a0SNathan Whitehorn     if (!dialog_vars.keep_tite
392*2a3e3873SBaptiste Daroussin 	&& (fileno(dialog_state.screen_output) != fileno(stdout)
3934c8945a0SNathan Whitehorn 	    || isatty(fileno(dialog_state.screen_output)))
3944c8945a0SNathan Whitehorn 	&& key_mouse != 0	/* xterm and kindred */
3954c8945a0SNathan Whitehorn 	&& isprivate(enter_ca_mode)
3964c8945a0SNathan Whitehorn 	&& isprivate(exit_ca_mode)) {
3974c8945a0SNathan Whitehorn 	/*
398*2a3e3873SBaptiste Daroussin 	 * initscr() or newterm() already wrote enter_ca_mode as a side
3994c8945a0SNathan Whitehorn 	 * effect of initializing the screen.  It would be nice to not even
4004c8945a0SNathan Whitehorn 	 * do that, but we do not really have access to the correct copy of
4014c8945a0SNathan Whitehorn 	 * the terminfo description until those functions have been invoked.
4024c8945a0SNathan Whitehorn 	 */
403*2a3e3873SBaptiste Daroussin 	(void) refresh();
404*2a3e3873SBaptiste Daroussin 	(void) tputs(exit_ca_mode, 0, my_putc);
405*2a3e3873SBaptiste Daroussin 	(void) tputs(clear_screen, 0, my_putc);
4064c8945a0SNathan Whitehorn 	/*
4074c8945a0SNathan Whitehorn 	 * Prevent ncurses from switching "back" to the normal screen when
4084c8945a0SNathan Whitehorn 	 * exiting from dialog.  That would move the cursor to the original
4094c8945a0SNathan Whitehorn 	 * location saved in xterm.  Normally curses sets the cursor position
4104c8945a0SNathan Whitehorn 	 * to the first line after the display, but the alternate screen
4114c8945a0SNathan Whitehorn 	 * switching is done after that point.
4124c8945a0SNathan Whitehorn 	 *
4134c8945a0SNathan Whitehorn 	 * Cancelling the strings altogether also works around the buggy
4144c8945a0SNathan Whitehorn 	 * implementation of alternate-screen in rxvt, etc., which clear
4154c8945a0SNathan Whitehorn 	 * more of the display than they should.
4164c8945a0SNathan Whitehorn 	 */
4174c8945a0SNathan Whitehorn 	enter_ca_mode = 0;
4184c8945a0SNathan Whitehorn 	exit_ca_mode = 0;
4194c8945a0SNathan Whitehorn     }
4204c8945a0SNathan Whitehorn #endif
4214c8945a0SNathan Whitehorn #ifdef HAVE_FLUSHINP
4224c8945a0SNathan Whitehorn     (void) flushinp();
4234c8945a0SNathan Whitehorn #endif
4244c8945a0SNathan Whitehorn     (void) keypad(stdscr, TRUE);
4254c8945a0SNathan Whitehorn     (void) cbreak();
4264c8945a0SNathan Whitehorn     (void) noecho();
4277a1c0d96SNathan Whitehorn 
4287a1c0d96SNathan Whitehorn     if (!dialog_state.no_mouse) {
4294c8945a0SNathan Whitehorn 	mouse_open();
4307a1c0d96SNathan Whitehorn     }
4317a1c0d96SNathan Whitehorn 
4324c8945a0SNathan Whitehorn     dialog_state.screen_initialized = TRUE;
4334c8945a0SNathan Whitehorn 
4344c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4354c8945a0SNathan Whitehorn     if (dialog_state.use_colors || dialog_state.use_shadow)
4364c8945a0SNathan Whitehorn 	dlg_color_setup();	/* Set up colors */
4374c8945a0SNathan Whitehorn #endif
4384c8945a0SNathan Whitehorn 
4394c8945a0SNathan Whitehorn     /* Set screen to screen attribute */
4404c8945a0SNathan Whitehorn     dlg_clear();
4414c8945a0SNathan Whitehorn }
4424c8945a0SNathan Whitehorn 
4434c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4444c8945a0SNathan Whitehorn static int defined_colors = 1;	/* pair-0 is reserved */
4454c8945a0SNathan Whitehorn /*
4464c8945a0SNathan Whitehorn  * Setup for color display
4474c8945a0SNathan Whitehorn  */
4484c8945a0SNathan Whitehorn void
4494c8945a0SNathan Whitehorn dlg_color_setup(void)
4504c8945a0SNathan Whitehorn {
4514c8945a0SNathan Whitehorn     unsigned i;
4524c8945a0SNathan Whitehorn 
4534c8945a0SNathan Whitehorn     if (has_colors()) {		/* Terminal supports color? */
4544c8945a0SNathan Whitehorn 	(void) start_color();
4554c8945a0SNathan Whitehorn 
4564c8945a0SNathan Whitehorn #if defined(HAVE_USE_DEFAULT_COLORS)
4574c8945a0SNathan Whitehorn 	use_default_colors();
4584c8945a0SNathan Whitehorn #endif
4594c8945a0SNathan Whitehorn 
4604c8945a0SNathan Whitehorn #if defined(__NetBSD__) && defined(_CURSES_)
4614c8945a0SNathan Whitehorn #define C_ATTR(x,y) (((x) != 0 ? A_BOLD :  0) | COLOR_PAIR((y)))
4624c8945a0SNathan Whitehorn 	/* work around bug in NetBSD curses */
4634c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
4644c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
4654c8945a0SNathan Whitehorn 
4664c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
4674c8945a0SNathan Whitehorn 	    (void) init_pair(i + 1,
4684c8945a0SNathan Whitehorn 			     dlg_color_table[i].fg,
4694c8945a0SNathan Whitehorn 			     dlg_color_table[i].bg);
4704c8945a0SNathan Whitehorn 
4714c8945a0SNathan Whitehorn 	    /* Setup color attributes */
4724c8945a0SNathan Whitehorn 	    dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);
4734c8945a0SNathan Whitehorn 	}
4744c8945a0SNathan Whitehorn 	defined_colors = i + 1;
4754c8945a0SNathan Whitehorn #else
4764c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
4774c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
4784c8945a0SNathan Whitehorn 
4794c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
4804c8945a0SNathan Whitehorn 	    chtype color = dlg_color_pair(dlg_color_table[i].fg,
4814c8945a0SNathan Whitehorn 					  dlg_color_table[i].bg);
4824c8945a0SNathan Whitehorn 
4834c8945a0SNathan Whitehorn 	    /* Setup color attributes */
4844c8945a0SNathan Whitehorn 	    dlg_color_table[i].atr = ((dlg_color_table[i].hilite
4854c8945a0SNathan Whitehorn 				       ? A_BOLD
4864c8945a0SNathan Whitehorn 				       : 0)
4874c8945a0SNathan Whitehorn 				      | color);
4884c8945a0SNathan Whitehorn 	}
4894c8945a0SNathan Whitehorn #endif
4904c8945a0SNathan Whitehorn     } else {
4914c8945a0SNathan Whitehorn 	dialog_state.use_colors = FALSE;
4924c8945a0SNathan Whitehorn 	dialog_state.use_shadow = FALSE;
4934c8945a0SNathan Whitehorn     }
4944c8945a0SNathan Whitehorn }
4954c8945a0SNathan Whitehorn 
4964c8945a0SNathan Whitehorn int
4974c8945a0SNathan Whitehorn dlg_color_count(void)
4984c8945a0SNathan Whitehorn {
4994c8945a0SNathan Whitehorn     return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]);
5004c8945a0SNathan Whitehorn }
5014c8945a0SNathan Whitehorn 
5024c8945a0SNathan Whitehorn /*
5037a1c0d96SNathan Whitehorn  * Wrapper for getattrs(), or the more cumbersome X/Open wattr_get().
5047a1c0d96SNathan Whitehorn  */
5057a1c0d96SNathan Whitehorn chtype
5067a1c0d96SNathan Whitehorn dlg_get_attrs(WINDOW *win)
5077a1c0d96SNathan Whitehorn {
5087a1c0d96SNathan Whitehorn     chtype result;
5097a1c0d96SNathan Whitehorn #ifdef HAVE_GETATTRS
510682c9e0fSNathan Whitehorn     result = (chtype) getattrs(win);
5117a1c0d96SNathan Whitehorn #else
5127a1c0d96SNathan Whitehorn     attr_t my_result;
5137a1c0d96SNathan Whitehorn     short my_pair;
5147a1c0d96SNathan Whitehorn     wattr_get(win, &my_result, &my_pair, NULL);
5157a1c0d96SNathan Whitehorn     result = my_result;
5167a1c0d96SNathan Whitehorn #endif
5177a1c0d96SNathan Whitehorn     return result;
5187a1c0d96SNathan Whitehorn }
5197a1c0d96SNathan Whitehorn 
5207a1c0d96SNathan Whitehorn /*
5214c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
5224c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
5234c8945a0SNathan Whitehorn  * window's defined background.
5244c8945a0SNathan Whitehorn  */
5254c8945a0SNathan Whitehorn chtype
5264c8945a0SNathan Whitehorn dlg_color_pair(int foreground, int background)
5274c8945a0SNathan Whitehorn {
5284c8945a0SNathan Whitehorn     chtype result = 0;
5294c8945a0SNathan Whitehorn     int pair;
5304c8945a0SNathan Whitehorn     short fg, bg;
5314c8945a0SNathan Whitehorn     bool found = FALSE;
5324c8945a0SNathan Whitehorn 
5334c8945a0SNathan Whitehorn     for (pair = 1; pair < defined_colors; ++pair) {
5344c8945a0SNathan Whitehorn 	if (pair_content((short) pair, &fg, &bg) != ERR
5354c8945a0SNathan Whitehorn 	    && fg == foreground
5364c8945a0SNathan Whitehorn 	    && bg == background) {
5374c8945a0SNathan Whitehorn 	    result = (chtype) COLOR_PAIR(pair);
5384c8945a0SNathan Whitehorn 	    found = TRUE;
5394c8945a0SNathan Whitehorn 	    break;
5404c8945a0SNathan Whitehorn 	}
5414c8945a0SNathan Whitehorn     }
5424c8945a0SNathan Whitehorn     if (!found && (defined_colors + 1) < COLOR_PAIRS) {
5434c8945a0SNathan Whitehorn 	pair = defined_colors++;
5444c8945a0SNathan Whitehorn 	(void) init_pair((short) pair, (short) foreground, (short) background);
5454c8945a0SNathan Whitehorn 	result = (chtype) COLOR_PAIR(pair);
5464c8945a0SNathan Whitehorn     }
5474c8945a0SNathan Whitehorn     return result;
5484c8945a0SNathan Whitehorn }
5494c8945a0SNathan Whitehorn 
5504c8945a0SNathan Whitehorn /*
5514c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
5524c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
5534c8945a0SNathan Whitehorn  * window's defined background.
5544c8945a0SNathan Whitehorn  */
5554c8945a0SNathan Whitehorn static chtype
5564c8945a0SNathan Whitehorn define_color(WINDOW *win, int foreground)
5574c8945a0SNathan Whitehorn {
5587a1c0d96SNathan Whitehorn     chtype attrs = dlg_get_attrs(win);
5594c8945a0SNathan Whitehorn     int pair;
5604c8945a0SNathan Whitehorn     short fg, bg, background;
5614c8945a0SNathan Whitehorn 
5624c8945a0SNathan Whitehorn     if ((pair = PAIR_NUMBER(attrs)) != 0
5634c8945a0SNathan Whitehorn 	&& pair_content((short) pair, &fg, &bg) != ERR) {
5644c8945a0SNathan Whitehorn 	background = bg;
5654c8945a0SNathan Whitehorn     } else {
5664c8945a0SNathan Whitehorn 	background = COLOR_BLACK;
5674c8945a0SNathan Whitehorn     }
5684c8945a0SNathan Whitehorn     return dlg_color_pair(foreground, background);
5694c8945a0SNathan Whitehorn }
5704c8945a0SNathan Whitehorn #endif
5714c8945a0SNathan Whitehorn 
5724c8945a0SNathan Whitehorn /*
5734c8945a0SNathan Whitehorn  * End using dialog functions.
5744c8945a0SNathan Whitehorn  */
5754c8945a0SNathan Whitehorn void
5764c8945a0SNathan Whitehorn end_dialog(void)
5774c8945a0SNathan Whitehorn {
5784c8945a0SNathan Whitehorn     if (dialog_state.screen_initialized) {
5794c8945a0SNathan Whitehorn 	dialog_state.screen_initialized = FALSE;
5804c8945a0SNathan Whitehorn 	mouse_close();
5814c8945a0SNathan Whitehorn 	(void) endwin();
5824c8945a0SNathan Whitehorn 	(void) fflush(stdout);
5834c8945a0SNathan Whitehorn     }
5844c8945a0SNathan Whitehorn }
5854c8945a0SNathan Whitehorn 
586682c9e0fSNathan Whitehorn #define ESCAPE_LEN 3
5874c8945a0SNathan Whitehorn #define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))
5884c8945a0SNathan Whitehorn 
589*2a3e3873SBaptiste Daroussin int
590*2a3e3873SBaptiste Daroussin dlg_count_real_columns(const char *text)
591*2a3e3873SBaptiste Daroussin {
592*2a3e3873SBaptiste Daroussin     int result = dlg_count_columns(text);
593*2a3e3873SBaptiste Daroussin     if (result && dialog_vars.colors) {
594*2a3e3873SBaptiste Daroussin 	int hidden = 0;
595*2a3e3873SBaptiste Daroussin 	while (*text) {
596*2a3e3873SBaptiste Daroussin 	    if (dialog_vars.colors && isOurEscape(text)) {
597*2a3e3873SBaptiste Daroussin 		hidden += ESCAPE_LEN;
598*2a3e3873SBaptiste Daroussin 		text += ESCAPE_LEN;
599*2a3e3873SBaptiste Daroussin 	    } else {
600*2a3e3873SBaptiste Daroussin 		++text;
601*2a3e3873SBaptiste Daroussin 	    }
602*2a3e3873SBaptiste Daroussin 	}
603*2a3e3873SBaptiste Daroussin 	result -= hidden;
604*2a3e3873SBaptiste Daroussin     }
605*2a3e3873SBaptiste Daroussin     return result;
606*2a3e3873SBaptiste Daroussin }
607*2a3e3873SBaptiste Daroussin 
6084c8945a0SNathan Whitehorn static int
6094c8945a0SNathan Whitehorn centered(int width, const char *string)
6104c8945a0SNathan Whitehorn {
611*2a3e3873SBaptiste Daroussin     int need = dlg_count_real_columns(string);
6124c8945a0SNathan Whitehorn     int left;
6134c8945a0SNathan Whitehorn 
614*2a3e3873SBaptiste Daroussin     left = (width - need) / 2 - 1;
6154c8945a0SNathan Whitehorn     if (left < 0)
6164c8945a0SNathan Whitehorn 	left = 0;
6174c8945a0SNathan Whitehorn     return left;
6184c8945a0SNathan Whitehorn }
6194c8945a0SNathan Whitehorn 
6207a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
6217a1c0d96SNathan Whitehorn static bool
6227a1c0d96SNathan Whitehorn is_combining(const char *txt, int *combined)
6237a1c0d96SNathan Whitehorn {
6247a1c0d96SNathan Whitehorn     bool result = FALSE;
6257a1c0d96SNathan Whitehorn 
6267a1c0d96SNathan Whitehorn     if (*combined == 0) {
6277a1c0d96SNathan Whitehorn 	if (UCH(*txt) >= 128) {
6287a1c0d96SNathan Whitehorn 	    wchar_t wch;
6297a1c0d96SNathan Whitehorn 	    mbstate_t state;
6307a1c0d96SNathan Whitehorn 	    size_t given = strlen(txt);
6317a1c0d96SNathan Whitehorn 	    size_t len;
6327a1c0d96SNathan Whitehorn 
6337a1c0d96SNathan Whitehorn 	    memset(&state, 0, sizeof(state));
6347a1c0d96SNathan Whitehorn 	    len = mbrtowc(&wch, txt, given, &state);
6357a1c0d96SNathan Whitehorn 	    if ((int) len > 0 && wcwidth(wch) == 0) {
6367a1c0d96SNathan Whitehorn 		*combined = (int) len - 1;
6377a1c0d96SNathan Whitehorn 		result = TRUE;
6387a1c0d96SNathan Whitehorn 	    }
6397a1c0d96SNathan Whitehorn 	}
6407a1c0d96SNathan Whitehorn     } else {
6417a1c0d96SNathan Whitehorn 	result = TRUE;
6427a1c0d96SNathan Whitehorn 	*combined -= 1;
6437a1c0d96SNathan Whitehorn     }
6447a1c0d96SNathan Whitehorn     return result;
6457a1c0d96SNathan Whitehorn }
6467a1c0d96SNathan Whitehorn #endif
6477a1c0d96SNathan Whitehorn 
6484c8945a0SNathan Whitehorn /*
649*2a3e3873SBaptiste Daroussin  * Print the name (tag) or text from a DIALOG_LISTITEM, highlighting the
650*2a3e3873SBaptiste Daroussin  * first character if selected.
651*2a3e3873SBaptiste Daroussin  */
652*2a3e3873SBaptiste Daroussin void
653*2a3e3873SBaptiste Daroussin dlg_print_listitem(WINDOW *win,
654*2a3e3873SBaptiste Daroussin 		   const char *text,
655*2a3e3873SBaptiste Daroussin 		   int climit,
656*2a3e3873SBaptiste Daroussin 		   bool first,
657*2a3e3873SBaptiste Daroussin 		   int selected)
658*2a3e3873SBaptiste Daroussin {
659*2a3e3873SBaptiste Daroussin     chtype attr = A_NORMAL;
660*2a3e3873SBaptiste Daroussin     int limit;
661*2a3e3873SBaptiste Daroussin     const int *cols;
662*2a3e3873SBaptiste Daroussin     chtype attrs[4];
663*2a3e3873SBaptiste Daroussin 
664*2a3e3873SBaptiste Daroussin     if (text == 0)
665*2a3e3873SBaptiste Daroussin 	text = "";
666*2a3e3873SBaptiste Daroussin 
667*2a3e3873SBaptiste Daroussin     if (first) {
668*2a3e3873SBaptiste Daroussin 	const int *indx = dlg_index_wchars(text);
669*2a3e3873SBaptiste Daroussin 	attrs[3] = tag_key_selected_attr;
670*2a3e3873SBaptiste Daroussin 	attrs[2] = tag_key_attr;
671*2a3e3873SBaptiste Daroussin 	attrs[1] = tag_selected_attr;
672*2a3e3873SBaptiste Daroussin 	attrs[0] = tag_attr;
673*2a3e3873SBaptiste Daroussin 
674*2a3e3873SBaptiste Daroussin 	(void) wattrset(win, selected ? attrs[3] : attrs[2]);
675*2a3e3873SBaptiste Daroussin 	(void) waddnstr(win, text, indx[1]);
676*2a3e3873SBaptiste Daroussin 
677*2a3e3873SBaptiste Daroussin 	if ((int) strlen(text) > indx[1]) {
678*2a3e3873SBaptiste Daroussin 	    limit = dlg_limit_columns(text, climit, 1);
679*2a3e3873SBaptiste Daroussin 	    if (limit > 1) {
680*2a3e3873SBaptiste Daroussin 		(void) wattrset(win, selected ? attrs[1] : attrs[0]);
681*2a3e3873SBaptiste Daroussin 		(void) waddnstr(win,
682*2a3e3873SBaptiste Daroussin 				text + indx[1],
683*2a3e3873SBaptiste Daroussin 				indx[limit] - indx[1]);
684*2a3e3873SBaptiste Daroussin 	    }
685*2a3e3873SBaptiste Daroussin 	}
686*2a3e3873SBaptiste Daroussin     } else {
687*2a3e3873SBaptiste Daroussin 	attrs[1] = item_selected_attr;
688*2a3e3873SBaptiste Daroussin 	attrs[0] = item_attr;
689*2a3e3873SBaptiste Daroussin 
690*2a3e3873SBaptiste Daroussin 	cols = dlg_index_columns(text);
691*2a3e3873SBaptiste Daroussin 	limit = dlg_limit_columns(text, climit, 0);
692*2a3e3873SBaptiste Daroussin 
693*2a3e3873SBaptiste Daroussin 	if (limit > 0) {
694*2a3e3873SBaptiste Daroussin 	    (void) wattrset(win, selected ? attrs[1] : attrs[0]);
695*2a3e3873SBaptiste Daroussin 	    dlg_print_text(win, text, cols[limit], &attr);
696*2a3e3873SBaptiste Daroussin 	}
697*2a3e3873SBaptiste Daroussin     }
698*2a3e3873SBaptiste Daroussin }
699*2a3e3873SBaptiste Daroussin 
700*2a3e3873SBaptiste Daroussin /*
7014c8945a0SNathan Whitehorn  * Print up to 'cols' columns from 'text', optionally rendering our escape
7024c8945a0SNathan Whitehorn  * sequence for attributes and color.
7034c8945a0SNathan Whitehorn  */
7044c8945a0SNathan Whitehorn void
7054c8945a0SNathan Whitehorn dlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr)
7064c8945a0SNathan Whitehorn {
7074c8945a0SNathan Whitehorn     int y_origin, x_origin;
7084c8945a0SNathan Whitehorn     int y_before, x_before = 0;
7094c8945a0SNathan Whitehorn     int y_after, x_after;
7104c8945a0SNathan Whitehorn     int tabbed = 0;
7114c8945a0SNathan Whitehorn     bool thisTab;
7124c8945a0SNathan Whitehorn     bool ended = FALSE;
7134c8945a0SNathan Whitehorn     chtype useattr;
7147a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
7157a1c0d96SNathan Whitehorn     int combined = 0;
7167a1c0d96SNathan Whitehorn #endif
7174c8945a0SNathan Whitehorn 
7184c8945a0SNathan Whitehorn     getyx(win, y_origin, x_origin);
7194c8945a0SNathan Whitehorn     while (cols > 0 && (*txt != '\0')) {
7204c8945a0SNathan Whitehorn 	if (dialog_vars.colors) {
7214c8945a0SNathan Whitehorn 	    while (isOurEscape(txt)) {
7224c8945a0SNathan Whitehorn 		int code;
7234c8945a0SNathan Whitehorn 
7244c8945a0SNathan Whitehorn 		txt += 2;
7254c8945a0SNathan Whitehorn 		switch (code = CharOf(*txt)) {
7264c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
7274c8945a0SNathan Whitehorn 		case '0':
7284c8945a0SNathan Whitehorn 		case '1':
7294c8945a0SNathan Whitehorn 		case '2':
7304c8945a0SNathan Whitehorn 		case '3':
7314c8945a0SNathan Whitehorn 		case '4':
7324c8945a0SNathan Whitehorn 		case '5':
7334c8945a0SNathan Whitehorn 		case '6':
7344c8945a0SNathan Whitehorn 		case '7':
7354c8945a0SNathan Whitehorn 		    *attr &= ~A_COLOR;
7364c8945a0SNathan Whitehorn 		    *attr |= define_color(win, code - '0');
7374c8945a0SNathan Whitehorn 		    break;
7384c8945a0SNathan Whitehorn #endif
7394c8945a0SNathan Whitehorn 		case 'B':
7404c8945a0SNathan Whitehorn 		    *attr &= ~A_BOLD;
7414c8945a0SNathan Whitehorn 		    break;
7424c8945a0SNathan Whitehorn 		case 'b':
7434c8945a0SNathan Whitehorn 		    *attr |= A_BOLD;
7444c8945a0SNathan Whitehorn 		    break;
7454c8945a0SNathan Whitehorn 		case 'R':
7464c8945a0SNathan Whitehorn 		    *attr &= ~A_REVERSE;
7474c8945a0SNathan Whitehorn 		    break;
7484c8945a0SNathan Whitehorn 		case 'r':
7494c8945a0SNathan Whitehorn 		    *attr |= A_REVERSE;
7504c8945a0SNathan Whitehorn 		    break;
7514c8945a0SNathan Whitehorn 		case 'U':
7524c8945a0SNathan Whitehorn 		    *attr &= ~A_UNDERLINE;
7534c8945a0SNathan Whitehorn 		    break;
7544c8945a0SNathan Whitehorn 		case 'u':
7554c8945a0SNathan Whitehorn 		    *attr |= A_UNDERLINE;
7564c8945a0SNathan Whitehorn 		    break;
7574c8945a0SNathan Whitehorn 		case 'n':
7584c8945a0SNathan Whitehorn 		    *attr = A_NORMAL;
7594c8945a0SNathan Whitehorn 		    break;
7604c8945a0SNathan Whitehorn 		}
7614c8945a0SNathan Whitehorn 		++txt;
7624c8945a0SNathan Whitehorn 	    }
7634c8945a0SNathan Whitehorn 	}
7644c8945a0SNathan Whitehorn 	if (ended || *txt == '\n' || *txt == '\0')
7654c8945a0SNathan Whitehorn 	    break;
7664c8945a0SNathan Whitehorn 	useattr = (*attr) & A_ATTRIBUTES;
7674c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
7684c8945a0SNathan Whitehorn 	/*
7694c8945a0SNathan Whitehorn 	 * Prevent this from making text invisible when the foreground and
7704c8945a0SNathan Whitehorn 	 * background colors happen to be the same, and there's no bold
7714c8945a0SNathan Whitehorn 	 * attribute.
7724c8945a0SNathan Whitehorn 	 */
7734c8945a0SNathan Whitehorn 	if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) {
7744c8945a0SNathan Whitehorn 	    short pair = (short) PAIR_NUMBER(useattr);
7754c8945a0SNathan Whitehorn 	    short fg, bg;
7764c8945a0SNathan Whitehorn 	    if (pair_content(pair, &fg, &bg) != ERR
7774c8945a0SNathan Whitehorn 		&& fg == bg) {
7784c8945a0SNathan Whitehorn 		useattr &= ~A_COLOR;
7794c8945a0SNathan Whitehorn 		useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK)
7804c8945a0SNathan Whitehorn 					       ? COLOR_WHITE
7814c8945a0SNathan Whitehorn 					       : COLOR_BLACK));
7824c8945a0SNathan Whitehorn 	    }
7834c8945a0SNathan Whitehorn 	}
7844c8945a0SNathan Whitehorn #endif
7854c8945a0SNathan Whitehorn 	/*
7864c8945a0SNathan Whitehorn 	 * Write the character, using curses to tell exactly how wide it
7874c8945a0SNathan Whitehorn 	 * is.  If it is a tab, discount that, since the caller thinks
7884c8945a0SNathan Whitehorn 	 * tabs are nonprinting, and curses will expand tabs to one or
7894c8945a0SNathan Whitehorn 	 * more blanks.
7904c8945a0SNathan Whitehorn 	 */
7914c8945a0SNathan Whitehorn 	thisTab = (CharOf(*txt) == TAB);
792*2a3e3873SBaptiste Daroussin 	if (thisTab) {
7934c8945a0SNathan Whitehorn 	    getyx(win, y_before, x_before);
794*2a3e3873SBaptiste Daroussin 	    (void) y_before;
795*2a3e3873SBaptiste Daroussin 	}
7964c8945a0SNathan Whitehorn 	(void) waddch(win, CharOf(*txt++) | useattr);
7974c8945a0SNathan Whitehorn 	getyx(win, y_after, x_after);
7984c8945a0SNathan Whitehorn 	if (thisTab && (y_after == y_origin))
7994c8945a0SNathan Whitehorn 	    tabbed += (x_after - x_before);
8007a1c0d96SNathan Whitehorn 	if ((y_after != y_origin) ||
8017a1c0d96SNathan Whitehorn 	    (x_after >= (cols + tabbed + x_origin)
8027a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
8037a1c0d96SNathan Whitehorn 	     && !is_combining(txt, &combined)
8047a1c0d96SNathan Whitehorn #endif
8057a1c0d96SNathan Whitehorn 	    )) {
8064c8945a0SNathan Whitehorn 	    ended = TRUE;
8074c8945a0SNathan Whitehorn 	}
8084c8945a0SNathan Whitehorn     }
8094c8945a0SNathan Whitehorn }
8104c8945a0SNathan Whitehorn 
8114c8945a0SNathan Whitehorn /*
8124c8945a0SNathan Whitehorn  * Print one line of the prompt in the window within the limits of the
8134c8945a0SNathan Whitehorn  * specified right margin.  The line will end on a word boundary and a pointer
8144c8945a0SNathan Whitehorn  * to the start of the next line is returned, or a NULL pointer if the end of
8154c8945a0SNathan Whitehorn  * *prompt is reached.
8164c8945a0SNathan Whitehorn  */
8174c8945a0SNathan Whitehorn const char *
8184c8945a0SNathan Whitehorn dlg_print_line(WINDOW *win,
8194c8945a0SNathan Whitehorn 	       chtype *attr,
8204c8945a0SNathan Whitehorn 	       const char *prompt,
8214c8945a0SNathan Whitehorn 	       int lm, int rm, int *x)
8224c8945a0SNathan Whitehorn {
823*2a3e3873SBaptiste Daroussin     const char *wrap_ptr;
824*2a3e3873SBaptiste Daroussin     const char *test_ptr;
825682c9e0fSNathan Whitehorn     const char *hide_ptr = 0;
8264c8945a0SNathan Whitehorn     const int *cols = dlg_index_columns(prompt);
8274c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(prompt);
8284c8945a0SNathan Whitehorn     int wrap_inx = 0;
8294c8945a0SNathan Whitehorn     int test_inx = 0;
8304c8945a0SNathan Whitehorn     int cur_x = lm;
8314c8945a0SNathan Whitehorn     int hidden = 0;
8324c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(prompt);
8334c8945a0SNathan Whitehorn     int n;
8344c8945a0SNathan Whitehorn     int tabbed = 0;
8354c8945a0SNathan Whitehorn 
8364c8945a0SNathan Whitehorn     *x = 1;
8374c8945a0SNathan Whitehorn 
8384c8945a0SNathan Whitehorn     /*
8394c8945a0SNathan Whitehorn      * Set *test_ptr to the end of the line or the right margin (rm), whichever
8404c8945a0SNathan Whitehorn      * is less, and set wrap_ptr to the end of the last word in the line.
8414c8945a0SNathan Whitehorn      */
8424c8945a0SNathan Whitehorn     for (n = 0; n < limit; ++n) {
8434c8945a0SNathan Whitehorn 	test_ptr = prompt + indx[test_inx];
8444c8945a0SNathan Whitehorn 	if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden))
8454c8945a0SNathan Whitehorn 	    break;
8464c8945a0SNathan Whitehorn 	if (*test_ptr == TAB && n == 0) {
8474c8945a0SNathan Whitehorn 	    tabbed = 8;		/* workaround for leading tabs */
8484c8945a0SNathan Whitehorn 	} else if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') {
8494c8945a0SNathan Whitehorn 	    wrap_inx = n;
8504c8945a0SNathan Whitehorn 	    *x = cur_x;
851*2a3e3873SBaptiste Daroussin 	} else if (dialog_vars.colors && isOurEscape(test_ptr)) {
852682c9e0fSNathan Whitehorn 	    hide_ptr = test_ptr;
853682c9e0fSNathan Whitehorn 	    hidden += ESCAPE_LEN;
854682c9e0fSNathan Whitehorn 	    n += (ESCAPE_LEN - 1);
8554c8945a0SNathan Whitehorn 	}
8564c8945a0SNathan Whitehorn 	cur_x = lm + tabbed + cols[n + 1];
8574c8945a0SNathan Whitehorn 	if (cur_x > (rm + hidden))
8584c8945a0SNathan Whitehorn 	    break;
8594c8945a0SNathan Whitehorn 	test_inx = n + 1;
8604c8945a0SNathan Whitehorn     }
8614c8945a0SNathan Whitehorn 
8624c8945a0SNathan Whitehorn     /*
8634c8945a0SNathan Whitehorn      * If the line doesn't reach the right margin in the middle of a word, then
8644c8945a0SNathan Whitehorn      * we don't have to wrap it at the end of the previous word.
8654c8945a0SNathan Whitehorn      */
8664c8945a0SNathan Whitehorn     test_ptr = prompt + indx[test_inx];
8674c8945a0SNathan Whitehorn     if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') {
8684c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
8694c8945a0SNathan Whitehorn 	while (wrap_inx > 0 && prompt[indx[wrap_inx - 1]] == ' ') {
8704c8945a0SNathan Whitehorn 	    wrap_inx--;
8714c8945a0SNathan Whitehorn 	}
8724c8945a0SNathan Whitehorn 	*x = lm + indx[wrap_inx];
8734c8945a0SNathan Whitehorn     } else if (*x == 1 && cur_x >= rm) {
8744c8945a0SNathan Whitehorn 	/*
8754c8945a0SNathan Whitehorn 	 * If the line has no spaces, then wrap it anyway at the right margin
8764c8945a0SNathan Whitehorn 	 */
8774c8945a0SNathan Whitehorn 	*x = rm;
8784c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
8794c8945a0SNathan Whitehorn     }
8804c8945a0SNathan Whitehorn     wrap_ptr = prompt + indx[wrap_inx];
8817a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
8827a1c0d96SNathan Whitehorn     if (UCH(*wrap_ptr) >= 128) {
8837a1c0d96SNathan Whitehorn 	int combined = 0;
8847a1c0d96SNathan Whitehorn 	while (is_combining(wrap_ptr, &combined)) {
8857a1c0d96SNathan Whitehorn 	    ++wrap_ptr;
8867a1c0d96SNathan Whitehorn 	}
8877a1c0d96SNathan Whitehorn     }
8887a1c0d96SNathan Whitehorn #endif
8894c8945a0SNathan Whitehorn 
8904c8945a0SNathan Whitehorn     /*
891682c9e0fSNathan Whitehorn      * If we found hidden text past the last point that we will display,
892682c9e0fSNathan Whitehorn      * discount that from the displayed length.
893682c9e0fSNathan Whitehorn      */
894682c9e0fSNathan Whitehorn     if ((hide_ptr != 0) && (hide_ptr >= wrap_ptr)) {
895682c9e0fSNathan Whitehorn 	hidden -= ESCAPE_LEN;
896682c9e0fSNathan Whitehorn 	test_ptr = wrap_ptr;
897682c9e0fSNathan Whitehorn 	while (test_ptr < wrap_ptr) {
898*2a3e3873SBaptiste Daroussin 	    if (dialog_vars.colors && isOurEscape(test_ptr)) {
899682c9e0fSNathan Whitehorn 		hidden -= ESCAPE_LEN;
900682c9e0fSNathan Whitehorn 		test_ptr += ESCAPE_LEN;
901682c9e0fSNathan Whitehorn 	    } else {
902682c9e0fSNathan Whitehorn 		++test_ptr;
903682c9e0fSNathan Whitehorn 	    }
904682c9e0fSNathan Whitehorn 	}
905682c9e0fSNathan Whitehorn     }
906682c9e0fSNathan Whitehorn 
907682c9e0fSNathan Whitehorn     /*
9084c8945a0SNathan Whitehorn      * Print the line if we have a window pointer.  Otherwise this routine
9094c8945a0SNathan Whitehorn      * is just being called for sizing the window.
9104c8945a0SNathan Whitehorn      */
9114c8945a0SNathan Whitehorn     if (win) {
9124c8945a0SNathan Whitehorn 	dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr);
9134c8945a0SNathan Whitehorn     }
9144c8945a0SNathan Whitehorn 
9154c8945a0SNathan Whitehorn     /* *x tells the calling function how long the line was */
9164c8945a0SNathan Whitehorn     if (*x == 1)
9174c8945a0SNathan Whitehorn 	*x = rm;
9184c8945a0SNathan Whitehorn 
919682c9e0fSNathan Whitehorn     *x -= hidden;
920682c9e0fSNathan Whitehorn 
9214c8945a0SNathan Whitehorn     /* Find the start of the next line and return a pointer to it */
9224c8945a0SNathan Whitehorn     test_ptr = wrap_ptr;
9234c8945a0SNathan Whitehorn     while (*test_ptr == ' ')
9244c8945a0SNathan Whitehorn 	test_ptr++;
9254c8945a0SNathan Whitehorn     if (*test_ptr == '\n')
9264c8945a0SNathan Whitehorn 	test_ptr++;
9274c8945a0SNathan Whitehorn     return (test_ptr);
9284c8945a0SNathan Whitehorn }
9294c8945a0SNathan Whitehorn 
9304c8945a0SNathan Whitehorn static void
9314c8945a0SNathan Whitehorn justify_text(WINDOW *win,
9324c8945a0SNathan Whitehorn 	     const char *prompt,
9334c8945a0SNathan Whitehorn 	     int limit_y,
9344c8945a0SNathan Whitehorn 	     int limit_x,
9354c8945a0SNathan Whitehorn 	     int *high, int *wide)
9364c8945a0SNathan Whitehorn {
9374c8945a0SNathan Whitehorn     chtype attr = A_NORMAL;
9384c8945a0SNathan Whitehorn     int x = (2 * MARGIN);
9394c8945a0SNathan Whitehorn     int y = MARGIN;
9404c8945a0SNathan Whitehorn     int max_x = 2;
9414c8945a0SNathan Whitehorn     int lm = (2 * MARGIN);	/* left margin (box-border plus a space) */
9424c8945a0SNathan Whitehorn     int rm = limit_x;		/* right margin */
9434c8945a0SNathan Whitehorn     int bm = limit_y;		/* bottom margin */
9444c8945a0SNathan Whitehorn     int last_y = 0, last_x = 0;
9454c8945a0SNathan Whitehorn 
9464c8945a0SNathan Whitehorn     if (win) {
9474c8945a0SNathan Whitehorn 	rm -= (2 * MARGIN);
9484c8945a0SNathan Whitehorn 	bm -= (2 * MARGIN);
9494c8945a0SNathan Whitehorn     }
9504c8945a0SNathan Whitehorn     if (prompt == 0)
9514c8945a0SNathan Whitehorn 	prompt = "";
9524c8945a0SNathan Whitehorn 
9534c8945a0SNathan Whitehorn     if (win != 0)
9544c8945a0SNathan Whitehorn 	getyx(win, last_y, last_x);
9554c8945a0SNathan Whitehorn     while (y <= bm && *prompt) {
9564c8945a0SNathan Whitehorn 	x = lm;
9574c8945a0SNathan Whitehorn 
9584c8945a0SNathan Whitehorn 	if (*prompt == '\n') {
9594c8945a0SNathan Whitehorn 	    while (*prompt == '\n' && y < bm) {
9604c8945a0SNathan Whitehorn 		if (*(prompt + 1) != '\0') {
9614c8945a0SNathan Whitehorn 		    ++y;
9624c8945a0SNathan Whitehorn 		    if (win != 0)
9634c8945a0SNathan Whitehorn 			(void) wmove(win, y, lm);
9644c8945a0SNathan Whitehorn 		}
9654c8945a0SNathan Whitehorn 		prompt++;
9664c8945a0SNathan Whitehorn 	    }
9674c8945a0SNathan Whitehorn 	} else if (win != 0)
9684c8945a0SNathan Whitehorn 	    (void) wmove(win, y, lm);
9694c8945a0SNathan Whitehorn 
9704c8945a0SNathan Whitehorn 	if (*prompt) {
9714c8945a0SNathan Whitehorn 	    prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x);
9724c8945a0SNathan Whitehorn 	    if (win != 0)
9734c8945a0SNathan Whitehorn 		getyx(win, last_y, last_x);
9744c8945a0SNathan Whitehorn 	}
9754c8945a0SNathan Whitehorn 	if (*prompt) {
9764c8945a0SNathan Whitehorn 	    ++y;
9774c8945a0SNathan Whitehorn 	    if (win != 0)
9784c8945a0SNathan Whitehorn 		(void) wmove(win, y, lm);
9794c8945a0SNathan Whitehorn 	}
9804c8945a0SNathan Whitehorn 	max_x = MAX(max_x, x);
9814c8945a0SNathan Whitehorn     }
9824c8945a0SNathan Whitehorn     /* Move back to the last position after drawing prompt, for msgbox. */
9834c8945a0SNathan Whitehorn     if (win != 0)
9844c8945a0SNathan Whitehorn 	(void) wmove(win, last_y, last_x);
9854c8945a0SNathan Whitehorn 
9864c8945a0SNathan Whitehorn     /* Set the final height and width for the calling function */
9874c8945a0SNathan Whitehorn     if (high != 0)
9884c8945a0SNathan Whitehorn 	*high = y;
9894c8945a0SNathan Whitehorn     if (wide != 0)
9904c8945a0SNathan Whitehorn 	*wide = max_x;
9914c8945a0SNathan Whitehorn }
9924c8945a0SNathan Whitehorn 
9934c8945a0SNathan Whitehorn /*
9944c8945a0SNathan Whitehorn  * Print a string of text in a window, automatically wrap around to the next
9954c8945a0SNathan Whitehorn  * line if the string is too long to fit on one line.  Note that the string may
9964c8945a0SNathan Whitehorn  * contain embedded newlines.
9974c8945a0SNathan Whitehorn  */
9984c8945a0SNathan Whitehorn void
9994c8945a0SNathan Whitehorn dlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width)
10004c8945a0SNathan Whitehorn {
10014c8945a0SNathan Whitehorn     justify_text(win, prompt,
10024c8945a0SNathan Whitehorn 		 height,
10034c8945a0SNathan Whitehorn 		 width,
10044c8945a0SNathan Whitehorn 		 (int *) 0, (int *) 0);
10054c8945a0SNathan Whitehorn }
10064c8945a0SNathan Whitehorn 
10074c8945a0SNathan Whitehorn /*
10084c8945a0SNathan Whitehorn  * Display the message in a scrollable window.  Actually the way it works is
10094c8945a0SNathan Whitehorn  * that we create a "tall" window of the proper width, let the text wrap within
10104c8945a0SNathan Whitehorn  * that, and copy a slice of the result to the dialog.
10114c8945a0SNathan Whitehorn  *
10124c8945a0SNathan Whitehorn  * It works for ncurses.  Other curses implementations show only blanks (Tru64)
10134c8945a0SNathan Whitehorn  * or garbage (NetBSD).
10144c8945a0SNathan Whitehorn  */
10154c8945a0SNathan Whitehorn int
10164c8945a0SNathan Whitehorn dlg_print_scrolled(WINDOW *win,
10174c8945a0SNathan Whitehorn 		   const char *prompt,
10184c8945a0SNathan Whitehorn 		   int offset,
10194c8945a0SNathan Whitehorn 		   int height,
10204c8945a0SNathan Whitehorn 		   int width,
10214c8945a0SNathan Whitehorn 		   int pauseopt)
10224c8945a0SNathan Whitehorn {
10234c8945a0SNathan Whitehorn     int oldy, oldx;
10244c8945a0SNathan Whitehorn     int last = 0;
10254c8945a0SNathan Whitehorn 
10267a1c0d96SNathan Whitehorn     (void) pauseopt;		/* used only for ncurses */
10277a1c0d96SNathan Whitehorn 
10284c8945a0SNathan Whitehorn     getyx(win, oldy, oldx);
10294c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
10304c8945a0SNathan Whitehorn     if (pauseopt) {
10314c8945a0SNathan Whitehorn 	int wide = width - (2 * MARGIN);
10324c8945a0SNathan Whitehorn 	int high = LINES;
10334c8945a0SNathan Whitehorn 	int y, x;
10344c8945a0SNathan Whitehorn 	int len;
10354c8945a0SNathan Whitehorn 	int percent;
10364c8945a0SNathan Whitehorn 	WINDOW *dummy;
10374c8945a0SNathan Whitehorn 	char buffer[5];
10384c8945a0SNathan Whitehorn 
10394c8945a0SNathan Whitehorn #if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417
10404c8945a0SNathan Whitehorn 	/*
10414c8945a0SNathan Whitehorn 	 * If we're not limited by the screensize, allow text to possibly be
10424c8945a0SNathan Whitehorn 	 * one character per line.
10434c8945a0SNathan Whitehorn 	 */
10444c8945a0SNathan Whitehorn 	if ((len = dlg_count_columns(prompt)) > high)
10454c8945a0SNathan Whitehorn 	    high = len;
10464c8945a0SNathan Whitehorn #endif
10474c8945a0SNathan Whitehorn 	dummy = newwin(high, width, 0, 0);
1048682c9e0fSNathan Whitehorn 	if (dummy == 0) {
1049*2a3e3873SBaptiste Daroussin 	    (void) wattrset(win, dialog_attr);
1050682c9e0fSNathan Whitehorn 	    dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
1051682c9e0fSNathan Whitehorn 	    last = 0;
1052682c9e0fSNathan Whitehorn 	} else {
10534c8945a0SNathan Whitehorn 	    wbkgdset(dummy, dialog_attr | ' ');
1054*2a3e3873SBaptiste Daroussin 	    (void) wattrset(dummy, dialog_attr);
10554c8945a0SNathan Whitehorn 	    werase(dummy);
10564c8945a0SNathan Whitehorn 	    dlg_print_autowrap(dummy, prompt, high, width);
10574c8945a0SNathan Whitehorn 	    getyx(dummy, y, x);
1058*2a3e3873SBaptiste Daroussin 	    (void) x;
10594c8945a0SNathan Whitehorn 
10604c8945a0SNathan Whitehorn 	    copywin(dummy,	/* srcwin */
10614c8945a0SNathan Whitehorn 		    win,	/* dstwin */
10624c8945a0SNathan Whitehorn 		    offset + MARGIN,	/* sminrow */
10634c8945a0SNathan Whitehorn 		    MARGIN,	/* smincol */
10644c8945a0SNathan Whitehorn 		    MARGIN,	/* dminrow */
10654c8945a0SNathan Whitehorn 		    MARGIN,	/* dmincol */
10664c8945a0SNathan Whitehorn 		    height,	/* dmaxrow */
10674c8945a0SNathan Whitehorn 		    wide,	/* dmaxcol */
10684c8945a0SNathan Whitehorn 		    FALSE);
10694c8945a0SNathan Whitehorn 
10704c8945a0SNathan Whitehorn 	    delwin(dummy);
10714c8945a0SNathan Whitehorn 
10724c8945a0SNathan Whitehorn 	    /* if the text is incomplete, or we have scrolled, show the percentage */
10734c8945a0SNathan Whitehorn 	    if (y > 0 && wide > 4) {
10744c8945a0SNathan Whitehorn 		percent = (int) ((height + offset) * 100.0 / y);
10754c8945a0SNathan Whitehorn 		if (percent < 0)
10764c8945a0SNathan Whitehorn 		    percent = 0;
10774c8945a0SNathan Whitehorn 		if (percent > 100)
10784c8945a0SNathan Whitehorn 		    percent = 100;
10794c8945a0SNathan Whitehorn 		if (offset != 0 || percent != 100) {
10804c8945a0SNathan Whitehorn 		    (void) wattrset(win, position_indicator_attr);
10814c8945a0SNathan Whitehorn 		    (void) wmove(win, MARGIN + height, wide - 4);
10824c8945a0SNathan Whitehorn 		    (void) sprintf(buffer, "%d%%", percent);
10834c8945a0SNathan Whitehorn 		    (void) waddstr(win, buffer);
10844c8945a0SNathan Whitehorn 		    if ((len = (int) strlen(buffer)) < 4) {
1085*2a3e3873SBaptiste Daroussin 			(void) wattrset(win, border_attr);
10864c8945a0SNathan Whitehorn 			whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
10874c8945a0SNathan Whitehorn 		    }
10884c8945a0SNathan Whitehorn 		}
10894c8945a0SNathan Whitehorn 	    }
10904c8945a0SNathan Whitehorn 	    last = (y - height);
1091682c9e0fSNathan Whitehorn 	}
10924c8945a0SNathan Whitehorn     } else
10934c8945a0SNathan Whitehorn #endif
10944c8945a0SNathan Whitehorn     {
10954c8945a0SNathan Whitehorn 	(void) offset;
1096*2a3e3873SBaptiste Daroussin 	(void) wattrset(win, dialog_attr);
10974c8945a0SNathan Whitehorn 	dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
10984c8945a0SNathan Whitehorn 	last = 0;
10994c8945a0SNathan Whitehorn     }
11004c8945a0SNathan Whitehorn     wmove(win, oldy, oldx);
11014c8945a0SNathan Whitehorn     return last;
11024c8945a0SNathan Whitehorn }
11034c8945a0SNathan Whitehorn 
11044c8945a0SNathan Whitehorn int
11054c8945a0SNathan Whitehorn dlg_check_scrolled(int key, int last, int page, bool * show, int *offset)
11064c8945a0SNathan Whitehorn {
11074c8945a0SNathan Whitehorn     int code = 0;
11084c8945a0SNathan Whitehorn 
11094c8945a0SNathan Whitehorn     *show = FALSE;
11104c8945a0SNathan Whitehorn 
11114c8945a0SNathan Whitehorn     switch (key) {
11124c8945a0SNathan Whitehorn     case DLGK_PAGE_FIRST:
11134c8945a0SNathan Whitehorn 	if (*offset > 0) {
11144c8945a0SNathan Whitehorn 	    *offset = 0;
11154c8945a0SNathan Whitehorn 	    *show = TRUE;
11164c8945a0SNathan Whitehorn 	}
11174c8945a0SNathan Whitehorn 	break;
11184c8945a0SNathan Whitehorn     case DLGK_PAGE_LAST:
11194c8945a0SNathan Whitehorn 	if (*offset < last) {
11204c8945a0SNathan Whitehorn 	    *offset = last;
11214c8945a0SNathan Whitehorn 	    *show = TRUE;
11224c8945a0SNathan Whitehorn 	}
11234c8945a0SNathan Whitehorn 	break;
11244c8945a0SNathan Whitehorn     case DLGK_GRID_UP:
11254c8945a0SNathan Whitehorn 	if (*offset > 0) {
11264c8945a0SNathan Whitehorn 	    --(*offset);
11274c8945a0SNathan Whitehorn 	    *show = TRUE;
11284c8945a0SNathan Whitehorn 	}
11294c8945a0SNathan Whitehorn 	break;
11304c8945a0SNathan Whitehorn     case DLGK_GRID_DOWN:
11314c8945a0SNathan Whitehorn 	if (*offset < last) {
11324c8945a0SNathan Whitehorn 	    ++(*offset);
11334c8945a0SNathan Whitehorn 	    *show = TRUE;
11344c8945a0SNathan Whitehorn 	}
11354c8945a0SNathan Whitehorn 	break;
11364c8945a0SNathan Whitehorn     case DLGK_PAGE_PREV:
11374c8945a0SNathan Whitehorn 	if (*offset > 0) {
11384c8945a0SNathan Whitehorn 	    *offset -= page;
11394c8945a0SNathan Whitehorn 	    if (*offset < 0)
11404c8945a0SNathan Whitehorn 		*offset = 0;
11414c8945a0SNathan Whitehorn 	    *show = TRUE;
11424c8945a0SNathan Whitehorn 	}
11434c8945a0SNathan Whitehorn 	break;
11444c8945a0SNathan Whitehorn     case DLGK_PAGE_NEXT:
11454c8945a0SNathan Whitehorn 	if (*offset < last) {
11464c8945a0SNathan Whitehorn 	    *offset += page;
11474c8945a0SNathan Whitehorn 	    if (*offset > last)
11484c8945a0SNathan Whitehorn 		*offset = last;
11494c8945a0SNathan Whitehorn 	    *show = TRUE;
11504c8945a0SNathan Whitehorn 	}
11514c8945a0SNathan Whitehorn 	break;
11524c8945a0SNathan Whitehorn     default:
11534c8945a0SNathan Whitehorn 	code = -1;
11544c8945a0SNathan Whitehorn 	break;
11554c8945a0SNathan Whitehorn     }
11564c8945a0SNathan Whitehorn     return code;
11574c8945a0SNathan Whitehorn }
11584c8945a0SNathan Whitehorn 
11594c8945a0SNathan Whitehorn /*
11604c8945a0SNathan Whitehorn  * Calculate the window size for preformatted text.  This will calculate box
11614c8945a0SNathan Whitehorn  * dimensions that are at or close to the specified aspect ratio for the prompt
11624c8945a0SNathan Whitehorn  * string with all spaces and newlines preserved and additional newlines added
11634c8945a0SNathan Whitehorn  * as necessary.
11644c8945a0SNathan Whitehorn  */
11654c8945a0SNathan Whitehorn static void
11664c8945a0SNathan Whitehorn auto_size_preformatted(const char *prompt, int *height, int *width)
11674c8945a0SNathan Whitehorn {
11684c8945a0SNathan Whitehorn     int high = 0, wide = 0;
11694c8945a0SNathan Whitehorn     float car;			/* Calculated Aspect Ratio */
11704c8945a0SNathan Whitehorn     float diff;
11714c8945a0SNathan Whitehorn     int max_y = SLINES - 1;
11724c8945a0SNathan Whitehorn     int max_x = SCOLS - 2;
11734c8945a0SNathan Whitehorn     int max_width = max_x;
11744c8945a0SNathan Whitehorn     int ar = dialog_state.aspect_ratio;
11754c8945a0SNathan Whitehorn 
11764c8945a0SNathan Whitehorn     /* Get the initial dimensions */
11774c8945a0SNathan Whitehorn     justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
11784c8945a0SNathan Whitehorn     car = (float) (wide / high);
11794c8945a0SNathan Whitehorn 
11804c8945a0SNathan Whitehorn     /*
11814c8945a0SNathan Whitehorn      * If the aspect ratio is greater than it should be, then decrease the
11824c8945a0SNathan Whitehorn      * width proportionately.
11834c8945a0SNathan Whitehorn      */
11844c8945a0SNathan Whitehorn     if (car > ar) {
11854c8945a0SNathan Whitehorn 	diff = car / (float) ar;
11864c8945a0SNathan Whitehorn 	max_x = (int) ((float) wide / diff + 4);
11874c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
11884c8945a0SNathan Whitehorn 	car = (float) wide / (float) high;
11894c8945a0SNathan Whitehorn     }
11904c8945a0SNathan Whitehorn 
11914c8945a0SNathan Whitehorn     /*
11924c8945a0SNathan Whitehorn      * If the aspect ratio is too small after decreasing the width, then
11934c8945a0SNathan Whitehorn      * incrementally increase the width until the aspect ratio is equal to or
11944c8945a0SNathan Whitehorn      * greater than the specified aspect ratio.
11954c8945a0SNathan Whitehorn      */
11964c8945a0SNathan Whitehorn     while (car < ar && max_x < max_width) {
11974c8945a0SNathan Whitehorn 	max_x += 4;
11984c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
11994c8945a0SNathan Whitehorn 	car = (float) (wide / high);
12004c8945a0SNathan Whitehorn     }
12014c8945a0SNathan Whitehorn 
12024c8945a0SNathan Whitehorn     *height = high;
12034c8945a0SNathan Whitehorn     *width = wide;
12044c8945a0SNathan Whitehorn }
12054c8945a0SNathan Whitehorn 
12064c8945a0SNathan Whitehorn /*
12074c8945a0SNathan Whitehorn  * Find the length of the longest "word" in the given string.  By setting the
12084c8945a0SNathan Whitehorn  * widget width at least this long, we can avoid splitting a word on the
12094c8945a0SNathan Whitehorn  * margin.
12104c8945a0SNathan Whitehorn  */
12114c8945a0SNathan Whitehorn static int
12124c8945a0SNathan Whitehorn longest_word(const char *string)
12134c8945a0SNathan Whitehorn {
12144c8945a0SNathan Whitehorn     int length, result = 0;
12154c8945a0SNathan Whitehorn 
12164c8945a0SNathan Whitehorn     while (*string != '\0') {
12174c8945a0SNathan Whitehorn 	length = 0;
12184c8945a0SNathan Whitehorn 	while (*string != '\0' && !isspace(UCH(*string))) {
12194c8945a0SNathan Whitehorn 	    length++;
12204c8945a0SNathan Whitehorn 	    string++;
12214c8945a0SNathan Whitehorn 	}
12224c8945a0SNathan Whitehorn 	result = MAX(result, length);
12234c8945a0SNathan Whitehorn 	if (*string != '\0')
12244c8945a0SNathan Whitehorn 	    string++;
12254c8945a0SNathan Whitehorn     }
12264c8945a0SNathan Whitehorn     return result;
12274c8945a0SNathan Whitehorn }
12284c8945a0SNathan Whitehorn 
12294c8945a0SNathan Whitehorn /*
12304c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
12314c8945a0SNathan Whitehorn  * if (height or width == 0), justify and return actual limits.
12324c8945a0SNathan Whitehorn  */
12334c8945a0SNathan Whitehorn static void
12344c8945a0SNathan Whitehorn real_auto_size(const char *title,
12354c8945a0SNathan Whitehorn 	       const char *prompt,
12364c8945a0SNathan Whitehorn 	       int *height, int *width,
12374c8945a0SNathan Whitehorn 	       int boxlines, int mincols)
12384c8945a0SNathan Whitehorn {
12394c8945a0SNathan Whitehorn     int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2);
12404c8945a0SNathan Whitehorn     int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1);
12414c8945a0SNathan Whitehorn     int title_length = title ? dlg_count_columns(title) : 0;
12424c8945a0SNathan Whitehorn     int nc = 4;
12434c8945a0SNathan Whitehorn     int high;
12444c8945a0SNathan Whitehorn     int wide;
12454c8945a0SNathan Whitehorn     int save_high = *height;
12464c8945a0SNathan Whitehorn     int save_wide = *width;
12474c8945a0SNathan Whitehorn 
12484c8945a0SNathan Whitehorn     if (prompt == 0) {
12494c8945a0SNathan Whitehorn 	if (*height == 0)
12504c8945a0SNathan Whitehorn 	    *height = -1;
12514c8945a0SNathan Whitehorn 	if (*width == 0)
12524c8945a0SNathan Whitehorn 	    *width = -1;
12534c8945a0SNathan Whitehorn     }
12544c8945a0SNathan Whitehorn 
12554c8945a0SNathan Whitehorn     if (*height > 0) {
12564c8945a0SNathan Whitehorn 	high = *height;
12574c8945a0SNathan Whitehorn     } else {
12584c8945a0SNathan Whitehorn 	high = SLINES - y;
12594c8945a0SNathan Whitehorn     }
12604c8945a0SNathan Whitehorn 
1261*2a3e3873SBaptiste Daroussin     if (*width <= 0) {
1262*2a3e3873SBaptiste Daroussin 	if (prompt != 0) {
12634c8945a0SNathan Whitehorn 	    wide = MAX(title_length, mincols);
12644c8945a0SNathan Whitehorn 	    if (strchr(prompt, '\n') == 0) {
1265*2a3e3873SBaptiste Daroussin 		double val = (dialog_state.aspect_ratio *
1266*2a3e3873SBaptiste Daroussin 			      dlg_count_real_columns(prompt));
12674c8945a0SNathan Whitehorn 		double xxx = sqrt(val);
12684c8945a0SNathan Whitehorn 		int tmp = (int) xxx;
12694c8945a0SNathan Whitehorn 		wide = MAX(wide, tmp);
12704c8945a0SNathan Whitehorn 		wide = MAX(wide, longest_word(prompt));
12714c8945a0SNathan Whitehorn 		justify_text((WINDOW *) 0, prompt, high, wide, height, width);
12724c8945a0SNathan Whitehorn 	    } else {
12734c8945a0SNathan Whitehorn 		auto_size_preformatted(prompt, height, width);
12744c8945a0SNathan Whitehorn 	    }
12754c8945a0SNathan Whitehorn 	} else {
12764c8945a0SNathan Whitehorn 	    wide = SCOLS - x;
12774c8945a0SNathan Whitehorn 	    justify_text((WINDOW *) 0, prompt, high, wide, height, width);
12784c8945a0SNathan Whitehorn 	}
1279*2a3e3873SBaptiste Daroussin     }
12804c8945a0SNathan Whitehorn 
12814c8945a0SNathan Whitehorn     if (*width < title_length) {
12824c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, high, title_length, height, width);
12834c8945a0SNathan Whitehorn 	*width = title_length;
12844c8945a0SNathan Whitehorn     }
12854c8945a0SNathan Whitehorn 
12864c8945a0SNathan Whitehorn     if (*width < mincols && save_wide == 0)
12874c8945a0SNathan Whitehorn 	*width = mincols;
12884c8945a0SNathan Whitehorn     if (prompt != 0) {
12894c8945a0SNathan Whitehorn 	*width += nc;
12904c8945a0SNathan Whitehorn 	*height += boxlines + 2;
12914c8945a0SNathan Whitehorn     }
12924c8945a0SNathan Whitehorn     if (save_high > 0)
12934c8945a0SNathan Whitehorn 	*height = save_high;
12944c8945a0SNathan Whitehorn     if (save_wide > 0)
12954c8945a0SNathan Whitehorn 	*width = save_wide;
12964c8945a0SNathan Whitehorn }
12974c8945a0SNathan Whitehorn 
12984c8945a0SNathan Whitehorn /* End of real_auto_size() */
12994c8945a0SNathan Whitehorn 
13004c8945a0SNathan Whitehorn void
13014c8945a0SNathan Whitehorn dlg_auto_size(const char *title,
13024c8945a0SNathan Whitehorn 	      const char *prompt,
13034c8945a0SNathan Whitehorn 	      int *height,
13044c8945a0SNathan Whitehorn 	      int *width,
13054c8945a0SNathan Whitehorn 	      int boxlines,
13064c8945a0SNathan Whitehorn 	      int mincols)
13074c8945a0SNathan Whitehorn {
13084c8945a0SNathan Whitehorn     real_auto_size(title, prompt, height, width, boxlines, mincols);
13094c8945a0SNathan Whitehorn 
13104c8945a0SNathan Whitehorn     if (*width > SCOLS) {
13114c8945a0SNathan Whitehorn 	(*height)++;
13124c8945a0SNathan Whitehorn 	*width = SCOLS;
13134c8945a0SNathan Whitehorn     }
13144c8945a0SNathan Whitehorn 
13154c8945a0SNathan Whitehorn     if (*height > SLINES)
13164c8945a0SNathan Whitehorn 	*height = SLINES;
13174c8945a0SNathan Whitehorn }
13184c8945a0SNathan Whitehorn 
13194c8945a0SNathan Whitehorn /*
13204c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
13214c8945a0SNathan Whitehorn  * if (height or width == 0)
13224c8945a0SNathan Whitehorn  *    height=MIN(SLINES, num.lines in fd+n);
13234c8945a0SNathan Whitehorn  *    width=MIN(SCOLS, MAX(longer line+n, mincols));
13244c8945a0SNathan Whitehorn  */
13254c8945a0SNathan Whitehorn void
13264c8945a0SNathan Whitehorn dlg_auto_sizefile(const char *title,
13274c8945a0SNathan Whitehorn 		  const char *file,
13284c8945a0SNathan Whitehorn 		  int *height,
13294c8945a0SNathan Whitehorn 		  int *width,
13304c8945a0SNathan Whitehorn 		  int boxlines,
13314c8945a0SNathan Whitehorn 		  int mincols)
13324c8945a0SNathan Whitehorn {
13334c8945a0SNathan Whitehorn     int count = 0;
13344c8945a0SNathan Whitehorn     int len = title ? dlg_count_columns(title) : 0;
13354c8945a0SNathan Whitehorn     int nc = 4;
13364c8945a0SNathan Whitehorn     int numlines = 2;
13374c8945a0SNathan Whitehorn     long offset;
13384c8945a0SNathan Whitehorn     int ch;
13394c8945a0SNathan Whitehorn     FILE *fd;
13404c8945a0SNathan Whitehorn 
13414c8945a0SNathan Whitehorn     /* Open input file for reading */
13424c8945a0SNathan Whitehorn     if ((fd = fopen(file, "rb")) == NULL)
13434c8945a0SNathan Whitehorn 	dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file);
13444c8945a0SNathan Whitehorn 
13454c8945a0SNathan Whitehorn     if ((*height == -1) || (*width == -1)) {
13464c8945a0SNathan Whitehorn 	*height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
13474c8945a0SNathan Whitehorn 	*width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
13484c8945a0SNathan Whitehorn     }
13494c8945a0SNathan Whitehorn     if ((*height != 0) && (*width != 0)) {
13504c8945a0SNathan Whitehorn 	(void) fclose(fd);
13514c8945a0SNathan Whitehorn 	if (*width > SCOLS)
13524c8945a0SNathan Whitehorn 	    *width = SCOLS;
13534c8945a0SNathan Whitehorn 	if (*height > SLINES)
13544c8945a0SNathan Whitehorn 	    *height = SLINES;
13554c8945a0SNathan Whitehorn 	return;
13564c8945a0SNathan Whitehorn     }
13574c8945a0SNathan Whitehorn 
13584c8945a0SNathan Whitehorn     while (!feof(fd)) {
13594c8945a0SNathan Whitehorn 	offset = 0;
13604c8945a0SNathan Whitehorn 	while (((ch = getc(fd)) != '\n') && !feof(fd))
13614c8945a0SNathan Whitehorn 	    if ((ch == TAB) && (dialog_vars.tab_correct))
13624c8945a0SNathan Whitehorn 		offset += dialog_state.tab_len - (offset % dialog_state.tab_len);
13634c8945a0SNathan Whitehorn 	    else
13644c8945a0SNathan Whitehorn 		offset++;
13654c8945a0SNathan Whitehorn 
13664c8945a0SNathan Whitehorn 	if (offset > len)
13677a1c0d96SNathan Whitehorn 	    len = (int) offset;
13684c8945a0SNathan Whitehorn 
13694c8945a0SNathan Whitehorn 	count++;
13704c8945a0SNathan Whitehorn     }
13714c8945a0SNathan Whitehorn 
13727a1c0d96SNathan Whitehorn     /* now 'count' has the number of lines of fd and 'len' the max length */
13734c8945a0SNathan Whitehorn 
13744c8945a0SNathan Whitehorn     *height = MIN(SLINES, count + numlines + boxlines);
13754c8945a0SNathan Whitehorn     *width = MIN(SCOLS, MAX((len + nc), mincols));
13764c8945a0SNathan Whitehorn     /* here width and height can be maximized if > SCOLS|SLINES because
13774c8945a0SNathan Whitehorn        textbox-like widgets don't put all <file> on the screen.
13784c8945a0SNathan Whitehorn        Msgbox-like widget instead have to put all <text> correctly. */
13794c8945a0SNathan Whitehorn 
13804c8945a0SNathan Whitehorn     (void) fclose(fd);
13814c8945a0SNathan Whitehorn }
13824c8945a0SNathan Whitehorn 
1383682c9e0fSNathan Whitehorn static chtype
1384682c9e0fSNathan Whitehorn dlg_get_cell_attrs(WINDOW *win)
1385682c9e0fSNathan Whitehorn {
1386682c9e0fSNathan Whitehorn     chtype result;
1387682c9e0fSNathan Whitehorn #ifdef USE_WIDE_CURSES
1388682c9e0fSNathan Whitehorn     cchar_t wch;
1389682c9e0fSNathan Whitehorn     wchar_t cc;
1390682c9e0fSNathan Whitehorn     attr_t attrs;
1391682c9e0fSNathan Whitehorn     short pair;
1392682c9e0fSNathan Whitehorn     if (win_wch(win, &wch) == OK
1393682c9e0fSNathan Whitehorn 	&& getcchar(&wch, &cc, &attrs, &pair, NULL) == OK) {
1394682c9e0fSNathan Whitehorn 	result = attrs;
1395682c9e0fSNathan Whitehorn     } else {
1396682c9e0fSNathan Whitehorn 	result = 0;
1397682c9e0fSNathan Whitehorn     }
1398682c9e0fSNathan Whitehorn #else
1399682c9e0fSNathan Whitehorn     result = winch(win) & (A_ATTRIBUTES & ~A_COLOR);
1400682c9e0fSNathan Whitehorn #endif
1401682c9e0fSNathan Whitehorn     return result;
1402682c9e0fSNathan Whitehorn }
1403682c9e0fSNathan Whitehorn 
14044c8945a0SNathan Whitehorn /*
14054c8945a0SNathan Whitehorn  * Draw a rectangular box with line drawing characters.
14064c8945a0SNathan Whitehorn  *
14074c8945a0SNathan Whitehorn  * borderchar is used to color the upper/left edges.
14084c8945a0SNathan Whitehorn  *
14094c8945a0SNathan Whitehorn  * boxchar is used to color the right/lower edges.  It also is fill-color used
14104c8945a0SNathan Whitehorn  * for the box contents.
14114c8945a0SNathan Whitehorn  *
14124c8945a0SNathan Whitehorn  * Normally, if you are drawing a scrollable box, use menubox_border_attr for
14134c8945a0SNathan Whitehorn  * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn
14144c8945a0SNathan Whitehorn  * with menubox_attr at the top, and menubox_border_attr at the bottom.  That
14154c8945a0SNathan Whitehorn  * also (given the default color choices) produces a recessed effect.
14164c8945a0SNathan Whitehorn  *
14174c8945a0SNathan Whitehorn  * If you want a raised effect (and are not going to use the scroll-arrows),
14184c8945a0SNathan Whitehorn  * reverse this choice.
14194c8945a0SNathan Whitehorn  */
14204c8945a0SNathan Whitehorn void
1421*2a3e3873SBaptiste Daroussin dlg_draw_box2(WINDOW *win, int y, int x, int height, int width,
1422*2a3e3873SBaptiste Daroussin 	      chtype boxchar, chtype borderchar, chtype borderchar2)
14234c8945a0SNathan Whitehorn {
14244c8945a0SNathan Whitehorn     int i, j;
14257a1c0d96SNathan Whitehorn     chtype save = dlg_get_attrs(win);
14264c8945a0SNathan Whitehorn 
1427*2a3e3873SBaptiste Daroussin     (void) wattrset(win, 0);
14284c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
14294c8945a0SNathan Whitehorn 	(void) wmove(win, y + i, x);
14304c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
14314c8945a0SNathan Whitehorn 	    if (!i && !j)
14324c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER));
14334c8945a0SNathan Whitehorn 	    else if (i == height - 1 && !j)
14344c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER));
14354c8945a0SNathan Whitehorn 	    else if (!i && j == width - 1)
1436*2a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_URCORNER));
14374c8945a0SNathan Whitehorn 	    else if (i == height - 1 && j == width - 1)
1438*2a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_LRCORNER));
14394c8945a0SNathan Whitehorn 	    else if (!i)
14404c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE));
14414c8945a0SNathan Whitehorn 	    else if (i == height - 1)
1442*2a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_HLINE));
14434c8945a0SNathan Whitehorn 	    else if (!j)
14444c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE));
14454c8945a0SNathan Whitehorn 	    else if (j == width - 1)
1446*2a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_VLINE));
14474c8945a0SNathan Whitehorn 	    else
14484c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | ' ');
14494c8945a0SNathan Whitehorn     }
1450*2a3e3873SBaptiste Daroussin     (void) wattrset(win, save);
1451*2a3e3873SBaptiste Daroussin }
1452*2a3e3873SBaptiste Daroussin 
1453*2a3e3873SBaptiste Daroussin void
1454*2a3e3873SBaptiste Daroussin dlg_draw_box(WINDOW *win, int y, int x, int height, int width,
1455*2a3e3873SBaptiste Daroussin 	     chtype boxchar, chtype borderchar)
1456*2a3e3873SBaptiste Daroussin {
1457*2a3e3873SBaptiste Daroussin     dlg_draw_box2(win, y, x, height, width, boxchar, borderchar, boxchar);
14584c8945a0SNathan Whitehorn }
14594c8945a0SNathan Whitehorn 
1460682c9e0fSNathan Whitehorn static DIALOG_WINDOWS *
1461682c9e0fSNathan Whitehorn find_window(WINDOW *win)
1462682c9e0fSNathan Whitehorn {
1463682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *result = 0;
1464682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1465682c9e0fSNathan Whitehorn 
1466682c9e0fSNathan Whitehorn     for (p = dialog_state.all_windows; p != 0; p = p->next) {
1467682c9e0fSNathan Whitehorn 	if (p->normal == win) {
1468682c9e0fSNathan Whitehorn 	    result = p;
1469682c9e0fSNathan Whitehorn 	    break;
1470682c9e0fSNathan Whitehorn 	}
1471682c9e0fSNathan Whitehorn     }
1472682c9e0fSNathan Whitehorn     return result;
1473682c9e0fSNathan Whitehorn }
1474682c9e0fSNathan Whitehorn 
14754c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
14764c8945a0SNathan Whitehorn /*
1477682c9e0fSNathan Whitehorn  * If we have wchgat(), use that for updating shadow attributes, to work with
1478682c9e0fSNathan Whitehorn  * wide-character data.
1479682c9e0fSNathan Whitehorn  */
1480682c9e0fSNathan Whitehorn 
1481682c9e0fSNathan Whitehorn /*
1482682c9e0fSNathan Whitehorn  * Check if the given point is "in" the given window.  If so, return the window
1483682c9e0fSNathan Whitehorn  * pointer, otherwise null.
1484682c9e0fSNathan Whitehorn  */
1485682c9e0fSNathan Whitehorn static WINDOW *
1486682c9e0fSNathan Whitehorn in_window(WINDOW *win, int y, int x)
1487682c9e0fSNathan Whitehorn {
1488682c9e0fSNathan Whitehorn     WINDOW *result = 0;
1489682c9e0fSNathan Whitehorn     int y_base = getbegy(win);
1490682c9e0fSNathan Whitehorn     int x_base = getbegx(win);
1491682c9e0fSNathan Whitehorn     int y_last = getmaxy(win) + y_base;
1492682c9e0fSNathan Whitehorn     int x_last = getmaxx(win) + x_base;
1493682c9e0fSNathan Whitehorn 
1494682c9e0fSNathan Whitehorn     if (y >= y_base && y <= y_last && x >= x_base && x <= x_last)
1495682c9e0fSNathan Whitehorn 	result = win;
1496682c9e0fSNathan Whitehorn     return result;
1497682c9e0fSNathan Whitehorn }
1498682c9e0fSNathan Whitehorn 
1499682c9e0fSNathan Whitehorn static WINDOW *
1500682c9e0fSNathan Whitehorn window_at_cell(DIALOG_WINDOWS * dw, int y, int x)
1501682c9e0fSNathan Whitehorn {
1502682c9e0fSNathan Whitehorn     WINDOW *result = 0;
1503682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1504682c9e0fSNathan Whitehorn     int y_want = y + getbegy(dw->shadow);
1505682c9e0fSNathan Whitehorn     int x_want = x + getbegx(dw->shadow);
1506682c9e0fSNathan Whitehorn 
1507682c9e0fSNathan Whitehorn     for (p = dialog_state.all_windows; p != 0; p = p->next) {
1508682c9e0fSNathan Whitehorn 	if (dw->normal != p->normal
1509682c9e0fSNathan Whitehorn 	    && dw->shadow != p->normal
1510682c9e0fSNathan Whitehorn 	    && (result = in_window(p->normal, y_want, x_want)) != 0) {
1511682c9e0fSNathan Whitehorn 	    break;
1512682c9e0fSNathan Whitehorn 	}
1513682c9e0fSNathan Whitehorn     }
1514682c9e0fSNathan Whitehorn     if (result == 0) {
1515682c9e0fSNathan Whitehorn 	result = stdscr;
1516682c9e0fSNathan Whitehorn     }
1517682c9e0fSNathan Whitehorn     return result;
1518682c9e0fSNathan Whitehorn }
1519682c9e0fSNathan Whitehorn 
1520682c9e0fSNathan Whitehorn static bool
1521682c9e0fSNathan Whitehorn in_shadow(WINDOW *normal, WINDOW *shadow, int y, int x)
1522682c9e0fSNathan Whitehorn {
1523682c9e0fSNathan Whitehorn     bool result = FALSE;
1524682c9e0fSNathan Whitehorn     int ybase = getbegy(normal);
1525682c9e0fSNathan Whitehorn     int ylast = getmaxy(normal) + ybase;
1526682c9e0fSNathan Whitehorn     int xbase = getbegx(normal);
1527682c9e0fSNathan Whitehorn     int xlast = getmaxx(normal) + xbase;
1528682c9e0fSNathan Whitehorn 
1529682c9e0fSNathan Whitehorn     y += getbegy(shadow);
1530682c9e0fSNathan Whitehorn     x += getbegx(shadow);
1531682c9e0fSNathan Whitehorn 
1532682c9e0fSNathan Whitehorn     if (y >= ybase + SHADOW_ROWS
1533682c9e0fSNathan Whitehorn 	&& y < ylast + SHADOW_ROWS
1534682c9e0fSNathan Whitehorn 	&& x >= xlast
1535682c9e0fSNathan Whitehorn 	&& x < xlast + SHADOW_COLS) {
1536682c9e0fSNathan Whitehorn 	/* in the right-side */
1537682c9e0fSNathan Whitehorn 	result = TRUE;
1538682c9e0fSNathan Whitehorn     } else if (y >= ylast
1539682c9e0fSNathan Whitehorn 	       && y < ylast + SHADOW_ROWS
1540682c9e0fSNathan Whitehorn 	       && x >= ybase + SHADOW_COLS
1541682c9e0fSNathan Whitehorn 	       && x < ylast + SHADOW_COLS) {
1542682c9e0fSNathan Whitehorn 	/* check the bottom */
1543682c9e0fSNathan Whitehorn 	result = TRUE;
1544682c9e0fSNathan Whitehorn     }
1545682c9e0fSNathan Whitehorn 
1546682c9e0fSNathan Whitehorn     return result;
1547682c9e0fSNathan Whitehorn }
1548682c9e0fSNathan Whitehorn 
1549682c9e0fSNathan Whitehorn /*
1550682c9e0fSNathan Whitehorn  * When erasing a shadow, check each cell to make sure that it is not part of
1551682c9e0fSNathan Whitehorn  * another box's shadow.  This is a little complicated since most shadows are
1552682c9e0fSNathan Whitehorn  * merged onto stdscr.
1553682c9e0fSNathan Whitehorn  */
1554682c9e0fSNathan Whitehorn static bool
1555682c9e0fSNathan Whitehorn last_shadow(DIALOG_WINDOWS * dw, int y, int x)
1556682c9e0fSNathan Whitehorn {
1557682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1558682c9e0fSNathan Whitehorn     bool result = TRUE;
1559682c9e0fSNathan Whitehorn 
1560682c9e0fSNathan Whitehorn     for (p = dialog_state.all_windows; p != 0; p = p->next) {
1561682c9e0fSNathan Whitehorn 	if (p->normal != dw->normal
1562682c9e0fSNathan Whitehorn 	    && in_shadow(p->normal, dw->shadow, y, x)) {
1563682c9e0fSNathan Whitehorn 	    result = FALSE;
1564682c9e0fSNathan Whitehorn 	    break;
1565682c9e0fSNathan Whitehorn 	}
1566682c9e0fSNathan Whitehorn     }
1567682c9e0fSNathan Whitehorn     return result;
1568682c9e0fSNathan Whitehorn }
1569682c9e0fSNathan Whitehorn 
1570682c9e0fSNathan Whitehorn static void
1571682c9e0fSNathan Whitehorn repaint_cell(DIALOG_WINDOWS * dw, bool draw, int y, int x)
1572682c9e0fSNathan Whitehorn {
1573682c9e0fSNathan Whitehorn     WINDOW *win = dw->shadow;
1574682c9e0fSNathan Whitehorn     WINDOW *cellwin;
1575682c9e0fSNathan Whitehorn     int y2, x2;
1576682c9e0fSNathan Whitehorn 
1577682c9e0fSNathan Whitehorn     if ((cellwin = window_at_cell(dw, y, x)) != 0
1578682c9e0fSNathan Whitehorn 	&& (draw || last_shadow(dw, y, x))
1579682c9e0fSNathan Whitehorn 	&& (y2 = (y + getbegy(win) - getbegy(cellwin))) >= 0
1580682c9e0fSNathan Whitehorn 	&& (x2 = (x + getbegx(win) - getbegx(cellwin))) >= 0
1581682c9e0fSNathan Whitehorn 	&& wmove(cellwin, y2, x2) != ERR) {
1582682c9e0fSNathan Whitehorn 	chtype the_cell = dlg_get_attrs(cellwin);
1583682c9e0fSNathan Whitehorn 	chtype the_attr = (draw ? shadow_attr : the_cell);
1584682c9e0fSNathan Whitehorn 
1585682c9e0fSNathan Whitehorn 	if (dlg_get_cell_attrs(cellwin) & A_ALTCHARSET) {
1586682c9e0fSNathan Whitehorn 	    the_attr |= A_ALTCHARSET;
1587682c9e0fSNathan Whitehorn 	}
1588682c9e0fSNathan Whitehorn #if USE_WCHGAT
1589682c9e0fSNathan Whitehorn 	wchgat(cellwin, 1,
1590682c9e0fSNathan Whitehorn 	       the_attr & (chtype) (~A_COLOR),
1591*2a3e3873SBaptiste Daroussin 	       (short) PAIR_NUMBER(the_attr),
1592682c9e0fSNathan Whitehorn 	       NULL);
1593682c9e0fSNathan Whitehorn #else
1594682c9e0fSNathan Whitehorn 	{
1595682c9e0fSNathan Whitehorn 	    chtype the_char = ((winch(cellwin) & A_CHARTEXT) | the_attr);
1596682c9e0fSNathan Whitehorn 	    (void) waddch(cellwin, the_char);
1597682c9e0fSNathan Whitehorn 	}
1598682c9e0fSNathan Whitehorn #endif
1599682c9e0fSNathan Whitehorn 	wnoutrefresh(cellwin);
1600682c9e0fSNathan Whitehorn     }
1601682c9e0fSNathan Whitehorn }
1602682c9e0fSNathan Whitehorn 
1603682c9e0fSNathan Whitehorn #define RepaintCell(dw, draw, y, x) repaint_cell(dw, draw, y, x)
1604682c9e0fSNathan Whitehorn 
1605682c9e0fSNathan Whitehorn static void
1606682c9e0fSNathan Whitehorn repaint_shadow(DIALOG_WINDOWS * dw, bool draw, int y, int x, int height, int width)
1607682c9e0fSNathan Whitehorn {
1608682c9e0fSNathan Whitehorn     int i, j;
1609682c9e0fSNathan Whitehorn 
1610682c9e0fSNathan Whitehorn     if (UseShadow(dw)) {
1611682c9e0fSNathan Whitehorn #if !USE_WCHGAT
1612682c9e0fSNathan Whitehorn 	chtype save = dlg_get_attrs(dw->shadow);
1613*2a3e3873SBaptiste Daroussin 	(void) wattrset(dw->shadow, draw ? shadow_attr : screen_attr);
1614682c9e0fSNathan Whitehorn #endif
1615682c9e0fSNathan Whitehorn 	for (i = 0; i < SHADOW_ROWS; ++i) {
1616682c9e0fSNathan Whitehorn 	    for (j = 0; j < width; ++j) {
1617682c9e0fSNathan Whitehorn 		RepaintCell(dw, draw, i + y + height, j + x + SHADOW_COLS);
1618682c9e0fSNathan Whitehorn 	    }
1619682c9e0fSNathan Whitehorn 	}
1620682c9e0fSNathan Whitehorn 	for (i = 0; i < height; i++) {
1621682c9e0fSNathan Whitehorn 	    for (j = 0; j < SHADOW_COLS; ++j) {
1622682c9e0fSNathan Whitehorn 		RepaintCell(dw, draw, i + y + SHADOW_ROWS, j + x + width);
1623682c9e0fSNathan Whitehorn 	    }
1624682c9e0fSNathan Whitehorn 	}
1625682c9e0fSNathan Whitehorn 	(void) wnoutrefresh(dw->shadow);
1626682c9e0fSNathan Whitehorn #if !USE_WCHGAT
1627*2a3e3873SBaptiste Daroussin 	(void) wattrset(dw->shadow, save);
1628682c9e0fSNathan Whitehorn #endif
1629682c9e0fSNathan Whitehorn     }
1630682c9e0fSNathan Whitehorn }
1631682c9e0fSNathan Whitehorn 
1632682c9e0fSNathan Whitehorn /*
16334c8945a0SNathan Whitehorn  * Draw a shadow on the parent window corresponding to the right- and
16344c8945a0SNathan Whitehorn  * bottom-edge of the child window, to give a 3-dimensional look.
16354c8945a0SNathan Whitehorn  */
16364c8945a0SNathan Whitehorn static void
1637682c9e0fSNathan Whitehorn draw_childs_shadow(DIALOG_WINDOWS * dw)
16384c8945a0SNathan Whitehorn {
1639682c9e0fSNathan Whitehorn     if (UseShadow(dw)) {
1640682c9e0fSNathan Whitehorn 	repaint_shadow(dw,
1641682c9e0fSNathan Whitehorn 		       TRUE,
1642682c9e0fSNathan Whitehorn 		       getbegy(dw->normal) - getbegy(dw->shadow),
1643682c9e0fSNathan Whitehorn 		       getbegx(dw->normal) - getbegx(dw->shadow),
1644682c9e0fSNathan Whitehorn 		       getmaxy(dw->normal),
1645682c9e0fSNathan Whitehorn 		       getmaxx(dw->normal));
1646682c9e0fSNathan Whitehorn     }
1647682c9e0fSNathan Whitehorn }
16484c8945a0SNathan Whitehorn 
1649682c9e0fSNathan Whitehorn /*
1650682c9e0fSNathan Whitehorn  * Erase a shadow on the parent window corresponding to the right- and
1651682c9e0fSNathan Whitehorn  * bottom-edge of the child window.
1652682c9e0fSNathan Whitehorn  */
1653682c9e0fSNathan Whitehorn static void
1654682c9e0fSNathan Whitehorn erase_childs_shadow(DIALOG_WINDOWS * dw)
1655682c9e0fSNathan Whitehorn {
1656682c9e0fSNathan Whitehorn     if (UseShadow(dw)) {
1657682c9e0fSNathan Whitehorn 	repaint_shadow(dw,
1658682c9e0fSNathan Whitehorn 		       FALSE,
1659682c9e0fSNathan Whitehorn 		       getbegy(dw->normal) - getbegy(dw->shadow),
1660682c9e0fSNathan Whitehorn 		       getbegx(dw->normal) - getbegx(dw->shadow),
1661682c9e0fSNathan Whitehorn 		       getmaxy(dw->normal),
1662682c9e0fSNathan Whitehorn 		       getmaxx(dw->normal));
16634c8945a0SNathan Whitehorn     }
16644c8945a0SNathan Whitehorn }
16654c8945a0SNathan Whitehorn 
16664c8945a0SNathan Whitehorn /*
16674c8945a0SNathan Whitehorn  * Draw shadows along the right and bottom edge to give a more 3D look
1668682c9e0fSNathan Whitehorn  * to the boxes.
16694c8945a0SNathan Whitehorn  */
16704c8945a0SNathan Whitehorn void
16714c8945a0SNathan Whitehorn dlg_draw_shadow(WINDOW *win, int y, int x, int height, int width)
16724c8945a0SNathan Whitehorn {
1673682c9e0fSNathan Whitehorn     repaint_shadow(find_window(win), TRUE, y, x, height, width);
16744c8945a0SNathan Whitehorn }
16754c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
16764c8945a0SNathan Whitehorn 
16774c8945a0SNathan Whitehorn /*
16784c8945a0SNathan Whitehorn  * Allow shell scripts to remap the exit codes so they can distinguish ESC
16794c8945a0SNathan Whitehorn  * from ERROR.
16804c8945a0SNathan Whitehorn  */
16814c8945a0SNathan Whitehorn void
16824c8945a0SNathan Whitehorn dlg_exit(int code)
16834c8945a0SNathan Whitehorn {
16844c8945a0SNathan Whitehorn     /* *INDENT-OFF* */
16854c8945a0SNathan Whitehorn     static const struct {
16864c8945a0SNathan Whitehorn 	int code;
16874c8945a0SNathan Whitehorn 	const char *name;
16884c8945a0SNathan Whitehorn     } table[] = {
16894c8945a0SNathan Whitehorn 	{ DLG_EXIT_CANCEL, 	"DIALOG_CANCEL" },
16904c8945a0SNathan Whitehorn 	{ DLG_EXIT_ERROR,  	"DIALOG_ERROR" },
16914c8945a0SNathan Whitehorn 	{ DLG_EXIT_ESC,	   	"DIALOG_ESC" },
16924c8945a0SNathan Whitehorn 	{ DLG_EXIT_EXTRA,  	"DIALOG_EXTRA" },
16934c8945a0SNathan Whitehorn 	{ DLG_EXIT_HELP,   	"DIALOG_HELP" },
16944c8945a0SNathan Whitehorn 	{ DLG_EXIT_OK,	   	"DIALOG_OK" },
16954c8945a0SNathan Whitehorn 	{ DLG_EXIT_ITEM_HELP,	"DIALOG_ITEM_HELP" },
16964c8945a0SNathan Whitehorn     };
16974c8945a0SNathan Whitehorn     /* *INDENT-ON* */
16984c8945a0SNathan Whitehorn 
16994c8945a0SNathan Whitehorn     unsigned n;
17004c8945a0SNathan Whitehorn     char *name;
17014c8945a0SNathan Whitehorn     char *temp;
17024c8945a0SNathan Whitehorn     long value;
17034c8945a0SNathan Whitehorn     bool overridden = FALSE;
17044c8945a0SNathan Whitehorn 
17054c8945a0SNathan Whitehorn   retry:
17064c8945a0SNathan Whitehorn     for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) {
17074c8945a0SNathan Whitehorn 	if (table[n].code == code) {
17084c8945a0SNathan Whitehorn 	    if ((name = getenv(table[n].name)) != 0) {
17094c8945a0SNathan Whitehorn 		value = strtol(name, &temp, 0);
17104c8945a0SNathan Whitehorn 		if (temp != 0 && temp != name && *temp == '\0') {
17117a1c0d96SNathan Whitehorn 		    code = (int) value;
17124c8945a0SNathan Whitehorn 		    overridden = TRUE;
17134c8945a0SNathan Whitehorn 		}
17144c8945a0SNathan Whitehorn 	    }
17154c8945a0SNathan Whitehorn 	    break;
17164c8945a0SNathan Whitehorn 	}
17174c8945a0SNathan Whitehorn     }
17184c8945a0SNathan Whitehorn 
17194c8945a0SNathan Whitehorn     /*
17204c8945a0SNathan Whitehorn      * Prior to 2004/12/19, a widget using --item-help would exit with "OK"
17214c8945a0SNathan Whitehorn      * if the help button were selected.  Now we want to exit with "HELP",
17224c8945a0SNathan Whitehorn      * but allow the environment variable to override.
17234c8945a0SNathan Whitehorn      */
17244c8945a0SNathan Whitehorn     if (code == DLG_EXIT_ITEM_HELP && !overridden) {
17254c8945a0SNathan Whitehorn 	code = DLG_EXIT_HELP;
17264c8945a0SNathan Whitehorn 	goto retry;
17274c8945a0SNathan Whitehorn     }
1728682c9e0fSNathan Whitehorn #ifdef HAVE_DLG_TRACE
1729682c9e0fSNathan Whitehorn     dlg_trace((const char *) 0);	/* close it */
1730682c9e0fSNathan Whitehorn #endif
1731682c9e0fSNathan Whitehorn 
17324c8945a0SNathan Whitehorn #ifdef NO_LEAKS
17334c8945a0SNathan Whitehorn     _dlg_inputstr_leaks();
17344c8945a0SNathan Whitehorn #if defined(NCURSES_VERSION) && defined(HAVE__NC_FREE_AND_EXIT)
17354c8945a0SNathan Whitehorn     _nc_free_and_exit(code);
17364c8945a0SNathan Whitehorn #endif
17374c8945a0SNathan Whitehorn #endif
17384c8945a0SNathan Whitehorn 
17394c8945a0SNathan Whitehorn     if (dialog_state.input == stdin) {
17404c8945a0SNathan Whitehorn 	exit(code);
17414c8945a0SNathan Whitehorn     } else {
17424c8945a0SNathan Whitehorn 	/*
17434c8945a0SNathan Whitehorn 	 * Just in case of using --input-fd option, do not
17444c8945a0SNathan Whitehorn 	 * call atexit functions of ncurses which may hang.
17454c8945a0SNathan Whitehorn 	 */
17464c8945a0SNathan Whitehorn 	if (dialog_state.input) {
17474c8945a0SNathan Whitehorn 	    fclose(dialog_state.input);
17484c8945a0SNathan Whitehorn 	    dialog_state.input = 0;
17494c8945a0SNathan Whitehorn 	}
17504c8945a0SNathan Whitehorn 	if (dialog_state.pipe_input) {
17514c8945a0SNathan Whitehorn 	    if (dialog_state.pipe_input != stdin) {
17524c8945a0SNathan Whitehorn 		fclose(dialog_state.pipe_input);
17534c8945a0SNathan Whitehorn 		dialog_state.pipe_input = 0;
17544c8945a0SNathan Whitehorn 	    }
17554c8945a0SNathan Whitehorn 	}
17564c8945a0SNathan Whitehorn 	_exit(code);
17574c8945a0SNathan Whitehorn     }
17584c8945a0SNathan Whitehorn }
17594c8945a0SNathan Whitehorn 
17604c8945a0SNathan Whitehorn /* quit program killing all tailbg */
17614c8945a0SNathan Whitehorn void
17624c8945a0SNathan Whitehorn dlg_exiterr(const char *fmt,...)
17634c8945a0SNathan Whitehorn {
17644c8945a0SNathan Whitehorn     int retval;
17654c8945a0SNathan Whitehorn     va_list ap;
17664c8945a0SNathan Whitehorn 
17674c8945a0SNathan Whitehorn     end_dialog();
17684c8945a0SNathan Whitehorn 
17694c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
17704c8945a0SNathan Whitehorn     va_start(ap, fmt);
17714c8945a0SNathan Whitehorn     (void) vfprintf(stderr, fmt, ap);
17724c8945a0SNathan Whitehorn     va_end(ap);
17734c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
17744c8945a0SNathan Whitehorn 
17754c8945a0SNathan Whitehorn     dlg_killall_bg(&retval);
17764c8945a0SNathan Whitehorn 
17774c8945a0SNathan Whitehorn     (void) fflush(stderr);
17784c8945a0SNathan Whitehorn     (void) fflush(stdout);
17794c8945a0SNathan Whitehorn     dlg_exit(DLG_EXIT_ERROR);
17804c8945a0SNathan Whitehorn }
17814c8945a0SNathan Whitehorn 
17824c8945a0SNathan Whitehorn void
17834c8945a0SNathan Whitehorn dlg_beeping(void)
17844c8945a0SNathan Whitehorn {
17854c8945a0SNathan Whitehorn     if (dialog_vars.beep_signal) {
17864c8945a0SNathan Whitehorn 	(void) beep();
17874c8945a0SNathan Whitehorn 	dialog_vars.beep_signal = 0;
17884c8945a0SNathan Whitehorn     }
17894c8945a0SNathan Whitehorn }
17904c8945a0SNathan Whitehorn 
17914c8945a0SNathan Whitehorn void
17924c8945a0SNathan Whitehorn dlg_print_size(int height, int width)
17934c8945a0SNathan Whitehorn {
17944c8945a0SNathan Whitehorn     if (dialog_vars.print_siz)
17954c8945a0SNathan Whitehorn 	fprintf(dialog_state.output, "Size: %d, %d\n", height, width);
17964c8945a0SNathan Whitehorn }
17974c8945a0SNathan Whitehorn 
17984c8945a0SNathan Whitehorn void
17994c8945a0SNathan Whitehorn dlg_ctl_size(int height, int width)
18004c8945a0SNathan Whitehorn {
18014c8945a0SNathan Whitehorn     if (dialog_vars.size_err) {
18024c8945a0SNathan Whitehorn 	if ((width > COLS) || (height > LINES)) {
18034c8945a0SNathan Whitehorn 	    dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
18044c8945a0SNathan Whitehorn 			height, width, LINES, COLS);
18054c8945a0SNathan Whitehorn 	}
18064c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
18074c8945a0SNathan Whitehorn 	else if ((dialog_state.use_shadow)
18084c8945a0SNathan Whitehorn 		 && ((width > SCOLS || height > SLINES))) {
18094c8945a0SNathan Whitehorn 	    if ((width <= COLS) && (height <= LINES)) {
18104c8945a0SNathan Whitehorn 		/* try again, without shadows */
18114c8945a0SNathan Whitehorn 		dialog_state.use_shadow = 0;
18124c8945a0SNathan Whitehorn 	    } else {
18134c8945a0SNathan Whitehorn 		dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
18144c8945a0SNathan Whitehorn 			    height, width, SLINES, SCOLS);
18154c8945a0SNathan Whitehorn 	    }
18164c8945a0SNathan Whitehorn 	}
18174c8945a0SNathan Whitehorn #endif
18184c8945a0SNathan Whitehorn     }
18194c8945a0SNathan Whitehorn }
18204c8945a0SNathan Whitehorn 
18214c8945a0SNathan Whitehorn /*
18224c8945a0SNathan Whitehorn  * If the --tab-correct was not selected, convert tabs to single spaces.
18234c8945a0SNathan Whitehorn  */
18244c8945a0SNathan Whitehorn void
18254c8945a0SNathan Whitehorn dlg_tab_correct_str(char *prompt)
18264c8945a0SNathan Whitehorn {
18274c8945a0SNathan Whitehorn     char *ptr;
18284c8945a0SNathan Whitehorn 
18294c8945a0SNathan Whitehorn     if (dialog_vars.tab_correct) {
18304c8945a0SNathan Whitehorn 	while ((ptr = strchr(prompt, TAB)) != NULL) {
18314c8945a0SNathan Whitehorn 	    *ptr = ' ';
18324c8945a0SNathan Whitehorn 	    prompt = ptr;
18334c8945a0SNathan Whitehorn 	}
18344c8945a0SNathan Whitehorn     }
18354c8945a0SNathan Whitehorn }
18364c8945a0SNathan Whitehorn 
18374c8945a0SNathan Whitehorn void
18384c8945a0SNathan Whitehorn dlg_calc_listh(int *height, int *list_height, int item_no)
18394c8945a0SNathan Whitehorn {
18404c8945a0SNathan Whitehorn     /* calculate new height and list_height */
18414c8945a0SNathan Whitehorn     int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
18424c8945a0SNathan Whitehorn     if (rows - (*height) > 0) {
18434c8945a0SNathan Whitehorn 	if (rows - (*height) > item_no)
18444c8945a0SNathan Whitehorn 	    *list_height = item_no;
18454c8945a0SNathan Whitehorn 	else
18464c8945a0SNathan Whitehorn 	    *list_height = rows - (*height);
18474c8945a0SNathan Whitehorn     }
18484c8945a0SNathan Whitehorn     (*height) += (*list_height);
18494c8945a0SNathan Whitehorn }
18504c8945a0SNathan Whitehorn 
18514c8945a0SNathan Whitehorn /* obsolete */
18524c8945a0SNathan Whitehorn int
18534c8945a0SNathan Whitehorn dlg_calc_listw(int item_no, char **items, int group)
18544c8945a0SNathan Whitehorn {
18554c8945a0SNathan Whitehorn     int n, i, len1 = 0, len2 = 0;
18564c8945a0SNathan Whitehorn     for (i = 0; i < (item_no * group); i += group) {
18574c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i])) > len1)
18584c8945a0SNathan Whitehorn 	    len1 = n;
18594c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i + 1])) > len2)
18604c8945a0SNathan Whitehorn 	    len2 = n;
18614c8945a0SNathan Whitehorn     }
18624c8945a0SNathan Whitehorn     return len1 + len2;
18634c8945a0SNathan Whitehorn }
18644c8945a0SNathan Whitehorn 
18654c8945a0SNathan Whitehorn int
18664c8945a0SNathan Whitehorn dlg_calc_list_width(int item_no, DIALOG_LISTITEM * items)
18674c8945a0SNathan Whitehorn {
18684c8945a0SNathan Whitehorn     int n, i, len1 = 0, len2 = 0;
1869*2a3e3873SBaptiste Daroussin     int bits = ((dialog_vars.no_tags ? 1 : 0)
1870*2a3e3873SBaptiste Daroussin 		+ (dialog_vars.no_items ? 2 : 0));
1871*2a3e3873SBaptiste Daroussin 
18724c8945a0SNathan Whitehorn     for (i = 0; i < item_no; ++i) {
1873*2a3e3873SBaptiste Daroussin 	switch (bits) {
1874*2a3e3873SBaptiste Daroussin 	case 0:
1875*2a3e3873SBaptiste Daroussin 	    /* FALLTHRU */
1876*2a3e3873SBaptiste Daroussin 	case 1:
18774c8945a0SNathan Whitehorn 	    if ((n = dlg_count_columns(items[i].name)) > len1)
18784c8945a0SNathan Whitehorn 		len1 = n;
18794c8945a0SNathan Whitehorn 	    if ((n = dlg_count_columns(items[i].text)) > len2)
18804c8945a0SNathan Whitehorn 		len2 = n;
1881*2a3e3873SBaptiste Daroussin 	    break;
1882*2a3e3873SBaptiste Daroussin 	case 2:
1883*2a3e3873SBaptiste Daroussin 	    /* FALLTHRU */
1884*2a3e3873SBaptiste Daroussin 	case 3:
1885*2a3e3873SBaptiste Daroussin 	    if ((n = dlg_count_columns(items[i].name)) > len1)
1886*2a3e3873SBaptiste Daroussin 		len1 = n;
1887*2a3e3873SBaptiste Daroussin 	    break;
1888*2a3e3873SBaptiste Daroussin 	}
18894c8945a0SNathan Whitehorn     }
18904c8945a0SNathan Whitehorn     return len1 + len2;
18914c8945a0SNathan Whitehorn }
18924c8945a0SNathan Whitehorn 
18934c8945a0SNathan Whitehorn char *
18944c8945a0SNathan Whitehorn dlg_strempty(void)
18954c8945a0SNathan Whitehorn {
18964c8945a0SNathan Whitehorn     static char empty[] = "";
18974c8945a0SNathan Whitehorn     return empty;
18984c8945a0SNathan Whitehorn }
18994c8945a0SNathan Whitehorn 
19004c8945a0SNathan Whitehorn char *
19014c8945a0SNathan Whitehorn dlg_strclone(const char *cprompt)
19024c8945a0SNathan Whitehorn {
19034c8945a0SNathan Whitehorn     char *prompt = dlg_malloc(char, strlen(cprompt) + 1);
19044c8945a0SNathan Whitehorn     assert_ptr(prompt, "dlg_strclone");
19054c8945a0SNathan Whitehorn     strcpy(prompt, cprompt);
19064c8945a0SNathan Whitehorn     return prompt;
19074c8945a0SNathan Whitehorn }
19084c8945a0SNathan Whitehorn 
19094c8945a0SNathan Whitehorn chtype
19104c8945a0SNathan Whitehorn dlg_asciibox(chtype ch)
19114c8945a0SNathan Whitehorn {
19124c8945a0SNathan Whitehorn     chtype result = 0;
19134c8945a0SNathan Whitehorn 
19144c8945a0SNathan Whitehorn     if (ch == ACS_ULCORNER)
19154c8945a0SNathan Whitehorn 	result = '+';
19164c8945a0SNathan Whitehorn     else if (ch == ACS_LLCORNER)
19174c8945a0SNathan Whitehorn 	result = '+';
19184c8945a0SNathan Whitehorn     else if (ch == ACS_URCORNER)
19194c8945a0SNathan Whitehorn 	result = '+';
19204c8945a0SNathan Whitehorn     else if (ch == ACS_LRCORNER)
19214c8945a0SNathan Whitehorn 	result = '+';
19224c8945a0SNathan Whitehorn     else if (ch == ACS_HLINE)
19234c8945a0SNathan Whitehorn 	result = '-';
19244c8945a0SNathan Whitehorn     else if (ch == ACS_VLINE)
19254c8945a0SNathan Whitehorn 	result = '|';
19264c8945a0SNathan Whitehorn     else if (ch == ACS_LTEE)
19274c8945a0SNathan Whitehorn 	result = '+';
19284c8945a0SNathan Whitehorn     else if (ch == ACS_RTEE)
19294c8945a0SNathan Whitehorn 	result = '+';
19304c8945a0SNathan Whitehorn     else if (ch == ACS_UARROW)
19314c8945a0SNathan Whitehorn 	result = '^';
19324c8945a0SNathan Whitehorn     else if (ch == ACS_DARROW)
19334c8945a0SNathan Whitehorn 	result = 'v';
19344c8945a0SNathan Whitehorn 
19354c8945a0SNathan Whitehorn     return result;
19364c8945a0SNathan Whitehorn }
19374c8945a0SNathan Whitehorn 
19384c8945a0SNathan Whitehorn chtype
19394c8945a0SNathan Whitehorn dlg_boxchar(chtype ch)
19404c8945a0SNathan Whitehorn {
19414c8945a0SNathan Whitehorn     chtype result = dlg_asciibox(ch);
19424c8945a0SNathan Whitehorn 
19434c8945a0SNathan Whitehorn     if (result != 0) {
19444c8945a0SNathan Whitehorn 	if (dialog_vars.ascii_lines)
19454c8945a0SNathan Whitehorn 	    ch = result;
19464c8945a0SNathan Whitehorn 	else if (dialog_vars.no_lines)
19474c8945a0SNathan Whitehorn 	    ch = ' ';
19484c8945a0SNathan Whitehorn     }
19494c8945a0SNathan Whitehorn     return ch;
19504c8945a0SNathan Whitehorn }
19514c8945a0SNathan Whitehorn 
19524c8945a0SNathan Whitehorn int
19534c8945a0SNathan Whitehorn dlg_box_x_ordinate(int width)
19544c8945a0SNathan Whitehorn {
19554c8945a0SNathan Whitehorn     int x;
19564c8945a0SNathan Whitehorn 
19574c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
19584c8945a0SNathan Whitehorn 	x = dialog_vars.begin_x;
19594c8945a0SNathan Whitehorn     } else {
19604c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
19614c8945a0SNathan Whitehorn 	x = (SCOLS - width) / 2;
19624c8945a0SNathan Whitehorn     }
19634c8945a0SNathan Whitehorn     return x;
19644c8945a0SNathan Whitehorn }
19654c8945a0SNathan Whitehorn 
19664c8945a0SNathan Whitehorn int
19674c8945a0SNathan Whitehorn dlg_box_y_ordinate(int height)
19684c8945a0SNathan Whitehorn {
19694c8945a0SNathan Whitehorn     int y;
19704c8945a0SNathan Whitehorn 
19714c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
19724c8945a0SNathan Whitehorn 	y = dialog_vars.begin_y;
19734c8945a0SNathan Whitehorn     } else {
19744c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
19754c8945a0SNathan Whitehorn 	y = (SLINES - height) / 2;
19764c8945a0SNathan Whitehorn     }
19774c8945a0SNathan Whitehorn     return y;
19784c8945a0SNathan Whitehorn }
19794c8945a0SNathan Whitehorn 
19804c8945a0SNathan Whitehorn void
19814c8945a0SNathan Whitehorn dlg_draw_title(WINDOW *win, const char *title)
19824c8945a0SNathan Whitehorn {
19834c8945a0SNathan Whitehorn     if (title != NULL) {
19844c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
19857a1c0d96SNathan Whitehorn 	chtype save = dlg_get_attrs(win);
19864c8945a0SNathan Whitehorn 	int x = centered(getmaxx(win), title);
19874c8945a0SNathan Whitehorn 
1988*2a3e3873SBaptiste Daroussin 	(void) wattrset(win, title_attr);
19894c8945a0SNathan Whitehorn 	wmove(win, 0, x);
19904c8945a0SNathan Whitehorn 	dlg_print_text(win, title, getmaxx(win) - x, &attr);
1991*2a3e3873SBaptiste Daroussin 	(void) wattrset(win, save);
19924c8945a0SNathan Whitehorn     }
19934c8945a0SNathan Whitehorn }
19944c8945a0SNathan Whitehorn 
19954c8945a0SNathan Whitehorn void
1996*2a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(WINDOW *win, chtype on_left, chtype on_right, chtype on_inside)
19974c8945a0SNathan Whitehorn {
19984c8945a0SNathan Whitehorn     int width = getmaxx(win);
19994c8945a0SNathan Whitehorn     int height = getmaxy(win);
20004c8945a0SNathan Whitehorn     int i;
20014c8945a0SNathan Whitehorn 
2002*2a3e3873SBaptiste Daroussin     (void) wattrset(win, on_left);
20034c8945a0SNathan Whitehorn     (void) wmove(win, height - 3, 0);
20044c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_LTEE));
20054c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
20064c8945a0SNathan Whitehorn 	(void) waddch(win, dlg_boxchar(ACS_HLINE));
2007*2a3e3873SBaptiste Daroussin     (void) wattrset(win, on_right);
20084c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_RTEE));
2009*2a3e3873SBaptiste Daroussin     (void) wattrset(win, on_inside);
20104c8945a0SNathan Whitehorn     (void) wmove(win, height - 2, 1);
20114c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
20124c8945a0SNathan Whitehorn 	(void) waddch(win, ' ');
20134c8945a0SNathan Whitehorn }
20144c8945a0SNathan Whitehorn 
2015*2a3e3873SBaptiste Daroussin void
2016*2a3e3873SBaptiste Daroussin dlg_draw_bottom_box(WINDOW *win)
2017*2a3e3873SBaptiste Daroussin {
2018*2a3e3873SBaptiste Daroussin     dlg_draw_bottom_box2(win, border_attr, dialog_attr, dialog_attr);
2019*2a3e3873SBaptiste Daroussin }
2020*2a3e3873SBaptiste Daroussin 
20214c8945a0SNathan Whitehorn /*
20224c8945a0SNathan Whitehorn  * Remove a window, repainting everything else.  This would be simpler if we
20234c8945a0SNathan Whitehorn  * used the panel library, but that is not _always_ available.
20244c8945a0SNathan Whitehorn  */
20254c8945a0SNathan Whitehorn void
20264c8945a0SNathan Whitehorn dlg_del_window(WINDOW *win)
20274c8945a0SNathan Whitehorn {
20284c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p, *q, *r;
20294c8945a0SNathan Whitehorn 
20304c8945a0SNathan Whitehorn     /*
20314c8945a0SNathan Whitehorn      * If --keep-window was set, do not delete/repaint the windows.
20324c8945a0SNathan Whitehorn      */
20334c8945a0SNathan Whitehorn     if (dialog_vars.keep_window)
20344c8945a0SNathan Whitehorn 	return;
20354c8945a0SNathan Whitehorn 
20364c8945a0SNathan Whitehorn     /* Leave the main window untouched if there are no background windows.
20374c8945a0SNathan Whitehorn      * We do this so the current window will not be cleared on exit, allowing
20384c8945a0SNathan Whitehorn      * things like the infobox demo to run without flicker.
20394c8945a0SNathan Whitehorn      */
20404c8945a0SNathan Whitehorn     if (dialog_state.getc_callbacks != 0) {
20414c8945a0SNathan Whitehorn 	touchwin(stdscr);
20424c8945a0SNathan Whitehorn 	wnoutrefresh(stdscr);
20434c8945a0SNathan Whitehorn     }
20444c8945a0SNathan Whitehorn 
20454c8945a0SNathan Whitehorn     for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) {
20464c8945a0SNathan Whitehorn 	if (p->normal == win) {
20474c8945a0SNathan Whitehorn 	    q = p;		/* found a match - should be only one */
20484c8945a0SNathan Whitehorn 	    if (r == 0) {
20494c8945a0SNathan Whitehorn 		dialog_state.all_windows = p->next;
20504c8945a0SNathan Whitehorn 	    } else {
20514c8945a0SNathan Whitehorn 		r->next = p->next;
20524c8945a0SNathan Whitehorn 	    }
20534c8945a0SNathan Whitehorn 	} else {
20544c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
20554c8945a0SNathan Whitehorn 		touchwin(p->shadow);
20564c8945a0SNathan Whitehorn 		wnoutrefresh(p->shadow);
20574c8945a0SNathan Whitehorn 	    }
20584c8945a0SNathan Whitehorn 	    touchwin(p->normal);
20594c8945a0SNathan Whitehorn 	    wnoutrefresh(p->normal);
20604c8945a0SNathan Whitehorn 	}
20614c8945a0SNathan Whitehorn     }
20624c8945a0SNathan Whitehorn 
20634c8945a0SNathan Whitehorn     if (q) {
2064682c9e0fSNathan Whitehorn 	if (dialog_state.all_windows != 0)
2065682c9e0fSNathan Whitehorn 	    erase_childs_shadow(q);
2066*2a3e3873SBaptiste Daroussin 	del_subwindows(q->normal);
20674c8945a0SNathan Whitehorn 	dlg_unregister_window(q->normal);
2068*2a3e3873SBaptiste Daroussin 	delwin(q->normal);
20694c8945a0SNathan Whitehorn 	free(q);
20704c8945a0SNathan Whitehorn     }
20714c8945a0SNathan Whitehorn     doupdate();
20724c8945a0SNathan Whitehorn }
20734c8945a0SNathan Whitehorn 
20744c8945a0SNathan Whitehorn /*
20754c8945a0SNathan Whitehorn  * Create a window, optionally with a shadow.
20764c8945a0SNathan Whitehorn  */
20774c8945a0SNathan Whitehorn WINDOW *
20784c8945a0SNathan Whitehorn dlg_new_window(int height, int width, int y, int x)
20794c8945a0SNathan Whitehorn {
2080682c9e0fSNathan Whitehorn     return dlg_new_modal_window(stdscr, height, width, y, x);
20814c8945a0SNathan Whitehorn }
20824c8945a0SNathan Whitehorn 
2083682c9e0fSNathan Whitehorn /*
2084682c9e0fSNathan Whitehorn  * "Modal" windows differ from normal ones by having a shadow in a window
2085682c9e0fSNathan Whitehorn  * separate from the standard screen.
2086682c9e0fSNathan Whitehorn  */
20874c8945a0SNathan Whitehorn WINDOW *
20884c8945a0SNathan Whitehorn dlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x)
20894c8945a0SNathan Whitehorn {
20904c8945a0SNathan Whitehorn     WINDOW *win;
20914c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
20924c8945a0SNathan Whitehorn 
20934c8945a0SNathan Whitehorn     (void) parent;
2094*2a3e3873SBaptiste Daroussin     if (p == 0
2095*2a3e3873SBaptiste Daroussin 	|| (win = newwin(height, width, y, x)) == 0) {
20964c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
20974c8945a0SNathan Whitehorn 		    y, x, height, width);
20984c8945a0SNathan Whitehorn     }
20994c8945a0SNathan Whitehorn     p->next = dialog_state.all_windows;
21004c8945a0SNathan Whitehorn     p->normal = win;
21014c8945a0SNathan Whitehorn     dialog_state.all_windows = p;
21024c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
21034c8945a0SNathan Whitehorn     if (dialog_state.use_shadow) {
2104682c9e0fSNathan Whitehorn 	p->shadow = parent;
2105682c9e0fSNathan Whitehorn 	draw_childs_shadow(p);
21064c8945a0SNathan Whitehorn     }
21074c8945a0SNathan Whitehorn #endif
21084c8945a0SNathan Whitehorn 
21094c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
21104c8945a0SNathan Whitehorn     return win;
21114c8945a0SNathan Whitehorn }
21124c8945a0SNathan Whitehorn 
21134c8945a0SNathan Whitehorn /*
21144c8945a0SNathan Whitehorn  * Move/Resize a window, optionally with a shadow.
21154c8945a0SNathan Whitehorn  */
21164c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
21174c8945a0SNathan Whitehorn void
21184c8945a0SNathan Whitehorn dlg_move_window(WINDOW *win, int height, int width, int y, int x)
21194c8945a0SNathan Whitehorn {
2120682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
21214c8945a0SNathan Whitehorn 
21224c8945a0SNathan Whitehorn     if (win != 0) {
21234c8945a0SNathan Whitehorn 	dlg_ctl_size(height, width);
21244c8945a0SNathan Whitehorn 
2125682c9e0fSNathan Whitehorn 	if ((p = find_window(win)) != 0) {
21264c8945a0SNathan Whitehorn 	    (void) wresize(win, height, width);
21274c8945a0SNathan Whitehorn 	    (void) mvwin(win, y, x);
21284c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
21294c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
21304c8945a0SNathan Whitehorn 		if (dialog_state.use_shadow) {
21314c8945a0SNathan Whitehorn 		    (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS);
21324c8945a0SNathan Whitehorn 		} else {
21334c8945a0SNathan Whitehorn 		    p->shadow = 0;
21344c8945a0SNathan Whitehorn 		}
21354c8945a0SNathan Whitehorn 	    }
21364c8945a0SNathan Whitehorn #endif
21374c8945a0SNathan Whitehorn 	    (void) refresh();
21384c8945a0SNathan Whitehorn 
21394c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
2140682c9e0fSNathan Whitehorn 	    draw_childs_shadow(p);
21414c8945a0SNathan Whitehorn #endif
21424c8945a0SNathan Whitehorn 	}
21434c8945a0SNathan Whitehorn     }
21444c8945a0SNathan Whitehorn }
21454c8945a0SNathan Whitehorn #endif /* KEY_RESIZE */
21464c8945a0SNathan Whitehorn 
21474c8945a0SNathan Whitehorn WINDOW *
21484c8945a0SNathan Whitehorn dlg_sub_window(WINDOW *parent, int height, int width, int y, int x)
21494c8945a0SNathan Whitehorn {
21504c8945a0SNathan Whitehorn     WINDOW *win;
21514c8945a0SNathan Whitehorn 
21524c8945a0SNathan Whitehorn     if ((win = subwin(parent, height, width, y, x)) == 0) {
21534c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n",
21544c8945a0SNathan Whitehorn 		    y, x, height, width);
21554c8945a0SNathan Whitehorn     }
21564c8945a0SNathan Whitehorn 
2157*2a3e3873SBaptiste Daroussin     add_subwindow(parent, win);
21584c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
21594c8945a0SNathan Whitehorn     return win;
21604c8945a0SNathan Whitehorn }
21614c8945a0SNathan Whitehorn 
21624c8945a0SNathan Whitehorn /* obsolete */
21634c8945a0SNathan Whitehorn int
21644c8945a0SNathan Whitehorn dlg_default_item(char **items, int llen)
21654c8945a0SNathan Whitehorn {
21664c8945a0SNathan Whitehorn     int result = 0;
21674c8945a0SNathan Whitehorn 
21684c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
21694c8945a0SNathan Whitehorn 	int count = 0;
21704c8945a0SNathan Whitehorn 	while (*items != 0) {
21714c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, *items)) {
21724c8945a0SNathan Whitehorn 		result = count;
21734c8945a0SNathan Whitehorn 		break;
21744c8945a0SNathan Whitehorn 	    }
21754c8945a0SNathan Whitehorn 	    items += llen;
21764c8945a0SNathan Whitehorn 	    count++;
21774c8945a0SNathan Whitehorn 	}
21784c8945a0SNathan Whitehorn     }
21794c8945a0SNathan Whitehorn     return result;
21804c8945a0SNathan Whitehorn }
21814c8945a0SNathan Whitehorn 
21824c8945a0SNathan Whitehorn int
21834c8945a0SNathan Whitehorn dlg_default_listitem(DIALOG_LISTITEM * items)
21844c8945a0SNathan Whitehorn {
21854c8945a0SNathan Whitehorn     int result = 0;
21864c8945a0SNathan Whitehorn 
21874c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
21884c8945a0SNathan Whitehorn 	int count = 0;
21894c8945a0SNathan Whitehorn 	while (items->name != 0) {
21904c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, items->name)) {
21914c8945a0SNathan Whitehorn 		result = count;
21924c8945a0SNathan Whitehorn 		break;
21934c8945a0SNathan Whitehorn 	    }
21944c8945a0SNathan Whitehorn 	    ++items;
21954c8945a0SNathan Whitehorn 	    count++;
21964c8945a0SNathan Whitehorn 	}
21974c8945a0SNathan Whitehorn     }
21984c8945a0SNathan Whitehorn     return result;
21994c8945a0SNathan Whitehorn }
22004c8945a0SNathan Whitehorn 
22014c8945a0SNathan Whitehorn /*
22024c8945a0SNathan Whitehorn  * Draw the string for item_help
22034c8945a0SNathan Whitehorn  */
22044c8945a0SNathan Whitehorn void
22054c8945a0SNathan Whitehorn dlg_item_help(const char *txt)
22064c8945a0SNathan Whitehorn {
22074c8945a0SNathan Whitehorn     if (USE_ITEM_HELP(txt)) {
22084c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
22094c8945a0SNathan Whitehorn 	int y, x;
22104c8945a0SNathan Whitehorn 
2211*2a3e3873SBaptiste Daroussin 	(void) wattrset(stdscr, itemhelp_attr);
22124c8945a0SNathan Whitehorn 	(void) wmove(stdscr, LINES - 1, 0);
22134c8945a0SNathan Whitehorn 	(void) wclrtoeol(stdscr);
22144c8945a0SNathan Whitehorn 	(void) addch(' ');
22154c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, txt, COLS - 1, &attr);
22164c8945a0SNathan Whitehorn 	if (itemhelp_attr & A_COLOR) {
22174c8945a0SNathan Whitehorn 	    /* fill the remainder of the line with the window's attributes */
22184c8945a0SNathan Whitehorn 	    getyx(stdscr, y, x);
2219*2a3e3873SBaptiste Daroussin 	    (void) y;
22204c8945a0SNathan Whitehorn 	    while (x < COLS) {
22214c8945a0SNathan Whitehorn 		(void) addch(' ');
22224c8945a0SNathan Whitehorn 		++x;
22234c8945a0SNathan Whitehorn 	    }
22244c8945a0SNathan Whitehorn 	}
22254c8945a0SNathan Whitehorn 	(void) wnoutrefresh(stdscr);
22264c8945a0SNathan Whitehorn     }
22274c8945a0SNathan Whitehorn }
22284c8945a0SNathan Whitehorn 
22294c8945a0SNathan Whitehorn #ifndef HAVE_STRCASECMP
22304c8945a0SNathan Whitehorn int
22314c8945a0SNathan Whitehorn dlg_strcmp(const char *a, const char *b)
22324c8945a0SNathan Whitehorn {
22334c8945a0SNathan Whitehorn     int ac, bc, cmp;
22344c8945a0SNathan Whitehorn 
22354c8945a0SNathan Whitehorn     for (;;) {
22364c8945a0SNathan Whitehorn 	ac = UCH(*a++);
22374c8945a0SNathan Whitehorn 	bc = UCH(*b++);
22384c8945a0SNathan Whitehorn 	if (isalpha(ac) && islower(ac))
22394c8945a0SNathan Whitehorn 	    ac = _toupper(ac);
22404c8945a0SNathan Whitehorn 	if (isalpha(bc) && islower(bc))
22414c8945a0SNathan Whitehorn 	    bc = _toupper(bc);
22424c8945a0SNathan Whitehorn 	cmp = ac - bc;
22434c8945a0SNathan Whitehorn 	if (ac == 0 || bc == 0 || cmp != 0)
22444c8945a0SNathan Whitehorn 	    break;
22454c8945a0SNathan Whitehorn     }
22464c8945a0SNathan Whitehorn     return cmp;
22474c8945a0SNathan Whitehorn }
22484c8945a0SNathan Whitehorn #endif
22494c8945a0SNathan Whitehorn 
22504c8945a0SNathan Whitehorn /*
22514c8945a0SNathan Whitehorn  * Returns true if 'dst' points to a blank which follows another blank which
22524c8945a0SNathan Whitehorn  * is not a leading blank on a line.
22534c8945a0SNathan Whitehorn  */
22544c8945a0SNathan Whitehorn static bool
22554c8945a0SNathan Whitehorn trim_blank(char *base, char *dst)
22564c8945a0SNathan Whitehorn {
22574c8945a0SNathan Whitehorn     int count = 0;
22584c8945a0SNathan Whitehorn 
22594c8945a0SNathan Whitehorn     while (dst-- != base) {
22604c8945a0SNathan Whitehorn 	if (*dst == '\n') {
22614c8945a0SNathan Whitehorn 	    return FALSE;
22624c8945a0SNathan Whitehorn 	} else if (*dst != ' ') {
22634c8945a0SNathan Whitehorn 	    return (count > 1);
22644c8945a0SNathan Whitehorn 	} else {
22654c8945a0SNathan Whitehorn 	    count++;
22664c8945a0SNathan Whitehorn 	}
22674c8945a0SNathan Whitehorn     }
22684c8945a0SNathan Whitehorn     return FALSE;
22694c8945a0SNathan Whitehorn }
22704c8945a0SNathan Whitehorn 
22714c8945a0SNathan Whitehorn /*
22724c8945a0SNathan Whitehorn  * Change embedded "\n" substrings to '\n' characters and tabs to single
22734c8945a0SNathan Whitehorn  * spaces.  If there are no "\n"s, it will strip all extra spaces, for
22744c8945a0SNathan Whitehorn  * justification.  If it has "\n"'s, it will preserve extra spaces.  If cr_wrap
22754c8945a0SNathan Whitehorn  * is set, it will preserve '\n's.
22764c8945a0SNathan Whitehorn  */
22774c8945a0SNathan Whitehorn void
22784c8945a0SNathan Whitehorn dlg_trim_string(char *s)
22794c8945a0SNathan Whitehorn {
22804c8945a0SNathan Whitehorn     char *base = s;
22814c8945a0SNathan Whitehorn     char *p1;
22824c8945a0SNathan Whitehorn     char *p = s;
2283682c9e0fSNathan Whitehorn     int has_newlines = !dialog_vars.no_nl_expand && (strstr(s, "\\n") != 0);
22844c8945a0SNathan Whitehorn 
22854c8945a0SNathan Whitehorn     while (*p != '\0') {
22864c8945a0SNathan Whitehorn 	if (*p == TAB && !dialog_vars.nocollapse)
22874c8945a0SNathan Whitehorn 	    *p = ' ';
22884c8945a0SNathan Whitehorn 
22894c8945a0SNathan Whitehorn 	if (has_newlines) {	/* If prompt contains "\n" strings */
22904c8945a0SNathan Whitehorn 	    if (*p == '\\' && *(p + 1) == 'n') {
22914c8945a0SNathan Whitehorn 		*s++ = '\n';
22924c8945a0SNathan Whitehorn 		p += 2;
22934c8945a0SNathan Whitehorn 		p1 = p;
22944c8945a0SNathan Whitehorn 		/*
22954c8945a0SNathan Whitehorn 		 * Handle end of lines intelligently.  If '\n' follows "\n"
22964c8945a0SNathan Whitehorn 		 * then ignore the '\n'.  This eliminates the need to escape
22974c8945a0SNathan Whitehorn 		 * the '\n' character (no need to use "\n\").
22984c8945a0SNathan Whitehorn 		 */
22994c8945a0SNathan Whitehorn 		while (*p1 == ' ')
23004c8945a0SNathan Whitehorn 		    p1++;
23014c8945a0SNathan Whitehorn 		if (*p1 == '\n')
23024c8945a0SNathan Whitehorn 		    p = p1 + 1;
23034c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
23044c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
23054c8945a0SNathan Whitehorn 		    *s++ = *p++;
23064c8945a0SNathan Whitehorn 		else {
23074c8945a0SNathan Whitehorn 		    /* Replace the '\n' with a space if cr_wrap is not set */
23084c8945a0SNathan Whitehorn 		    if (!trim_blank(base, s))
23094c8945a0SNathan Whitehorn 			*s++ = ' ';
23104c8945a0SNathan Whitehorn 		    p++;
23114c8945a0SNathan Whitehorn 		}
23124c8945a0SNathan Whitehorn 	    } else		/* If *p != '\n' */
23134c8945a0SNathan Whitehorn 		*s++ = *p++;
23144c8945a0SNathan Whitehorn 	} else if (dialog_vars.trim_whitespace) {
23154c8945a0SNathan Whitehorn 	    if (*p == ' ') {
23164c8945a0SNathan Whitehorn 		if (*(s - 1) != ' ') {
23174c8945a0SNathan Whitehorn 		    *s++ = ' ';
23184c8945a0SNathan Whitehorn 		    p++;
23194c8945a0SNathan Whitehorn 		} else
23204c8945a0SNathan Whitehorn 		    p++;
23214c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
23224c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
23234c8945a0SNathan Whitehorn 		    *s++ = *p++;
23244c8945a0SNathan Whitehorn 		else if (*(s - 1) != ' ') {
23254c8945a0SNathan Whitehorn 		    /* Strip '\n's if cr_wrap is not set. */
23264c8945a0SNathan Whitehorn 		    *s++ = ' ';
23274c8945a0SNathan Whitehorn 		    p++;
23284c8945a0SNathan Whitehorn 		} else
23294c8945a0SNathan Whitehorn 		    p++;
23304c8945a0SNathan Whitehorn 	    } else
23314c8945a0SNathan Whitehorn 		*s++ = *p++;
23324c8945a0SNathan Whitehorn 	} else {		/* If there are no "\n" strings */
23334c8945a0SNathan Whitehorn 	    if (*p == ' ' && !dialog_vars.nocollapse) {
23344c8945a0SNathan Whitehorn 		if (!trim_blank(base, s))
23354c8945a0SNathan Whitehorn 		    *s++ = *p;
23364c8945a0SNathan Whitehorn 		p++;
23374c8945a0SNathan Whitehorn 	    } else
23384c8945a0SNathan Whitehorn 		*s++ = *p++;
23394c8945a0SNathan Whitehorn 	}
23404c8945a0SNathan Whitehorn     }
23414c8945a0SNathan Whitehorn 
23424c8945a0SNathan Whitehorn     *s = '\0';
23434c8945a0SNathan Whitehorn }
23444c8945a0SNathan Whitehorn 
23454c8945a0SNathan Whitehorn void
23464c8945a0SNathan Whitehorn dlg_set_focus(WINDOW *parent, WINDOW *win)
23474c8945a0SNathan Whitehorn {
23484c8945a0SNathan Whitehorn     if (win != 0) {
23494c8945a0SNathan Whitehorn 	(void) wmove(parent,
23504c8945a0SNathan Whitehorn 		     getpary(win) + getcury(win),
23514c8945a0SNathan Whitehorn 		     getparx(win) + getcurx(win));
23524c8945a0SNathan Whitehorn 	(void) wnoutrefresh(win);
23534c8945a0SNathan Whitehorn 	(void) doupdate();
23544c8945a0SNathan Whitehorn     }
23554c8945a0SNathan Whitehorn }
23564c8945a0SNathan Whitehorn 
23574c8945a0SNathan Whitehorn /*
23584c8945a0SNathan Whitehorn  * Returns the nominal maximum buffer size.
23594c8945a0SNathan Whitehorn  */
23604c8945a0SNathan Whitehorn int
23614c8945a0SNathan Whitehorn dlg_max_input(int max_len)
23624c8945a0SNathan Whitehorn {
23634c8945a0SNathan Whitehorn     if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN)
23644c8945a0SNathan Whitehorn 	max_len = dialog_vars.max_input;
23654c8945a0SNathan Whitehorn 
23664c8945a0SNathan Whitehorn     return max_len;
23674c8945a0SNathan Whitehorn }
23684c8945a0SNathan Whitehorn 
23694c8945a0SNathan Whitehorn /*
23704c8945a0SNathan Whitehorn  * Free storage used for the result buffer.
23714c8945a0SNathan Whitehorn  */
23724c8945a0SNathan Whitehorn void
23734c8945a0SNathan Whitehorn dlg_clr_result(void)
23744c8945a0SNathan Whitehorn {
23754c8945a0SNathan Whitehorn     if (dialog_vars.input_length) {
23764c8945a0SNathan Whitehorn 	dialog_vars.input_length = 0;
23774c8945a0SNathan Whitehorn 	if (dialog_vars.input_result)
23784c8945a0SNathan Whitehorn 	    free(dialog_vars.input_result);
23794c8945a0SNathan Whitehorn     }
23804c8945a0SNathan Whitehorn     dialog_vars.input_result = 0;
23814c8945a0SNathan Whitehorn }
23824c8945a0SNathan Whitehorn 
23834c8945a0SNathan Whitehorn /*
23844c8945a0SNathan Whitehorn  * Setup a fixed-buffer for the result.
23854c8945a0SNathan Whitehorn  */
23864c8945a0SNathan Whitehorn char *
23874c8945a0SNathan Whitehorn dlg_set_result(const char *string)
23884c8945a0SNathan Whitehorn {
23897a1c0d96SNathan Whitehorn     unsigned need = string ? (unsigned) strlen(string) + 1 : 0;
23904c8945a0SNathan Whitehorn 
23914c8945a0SNathan Whitehorn     /* inputstr.c needs a fixed buffer */
23924c8945a0SNathan Whitehorn     if (need < MAX_LEN)
23934c8945a0SNathan Whitehorn 	need = MAX_LEN;
23944c8945a0SNathan Whitehorn 
23954c8945a0SNathan Whitehorn     /*
23964c8945a0SNathan Whitehorn      * If the buffer is not big enough, allocate a new one.
23974c8945a0SNathan Whitehorn      */
23984c8945a0SNathan Whitehorn     if (dialog_vars.input_length != 0
23994c8945a0SNathan Whitehorn 	|| dialog_vars.input_result == 0
24004c8945a0SNathan Whitehorn 	|| need > MAX_LEN) {
24014c8945a0SNathan Whitehorn 
24024c8945a0SNathan Whitehorn 	dlg_clr_result();
24034c8945a0SNathan Whitehorn 
24044c8945a0SNathan Whitehorn 	dialog_vars.input_length = need;
24054c8945a0SNathan Whitehorn 	dialog_vars.input_result = dlg_malloc(char, need);
24064c8945a0SNathan Whitehorn 	assert_ptr(dialog_vars.input_result, "dlg_set_result");
24074c8945a0SNathan Whitehorn     }
24084c8945a0SNathan Whitehorn 
24094c8945a0SNathan Whitehorn     strcpy(dialog_vars.input_result, string ? string : "");
24104c8945a0SNathan Whitehorn 
24114c8945a0SNathan Whitehorn     return dialog_vars.input_result;
24124c8945a0SNathan Whitehorn }
24134c8945a0SNathan Whitehorn 
24144c8945a0SNathan Whitehorn /*
24154c8945a0SNathan Whitehorn  * Accumulate results in dynamically allocated buffer.
24164c8945a0SNathan Whitehorn  * If input_length is zero, it is a MAX_LEN buffer belonging to the caller.
24174c8945a0SNathan Whitehorn  */
24184c8945a0SNathan Whitehorn void
24194c8945a0SNathan Whitehorn dlg_add_result(const char *string)
24204c8945a0SNathan Whitehorn {
24214c8945a0SNathan Whitehorn     unsigned have = (dialog_vars.input_result
24227a1c0d96SNathan Whitehorn 		     ? (unsigned) strlen(dialog_vars.input_result)
24234c8945a0SNathan Whitehorn 		     : 0);
24247a1c0d96SNathan Whitehorn     unsigned want = (unsigned) strlen(string) + 1 + have;
24254c8945a0SNathan Whitehorn 
24264c8945a0SNathan Whitehorn     if ((want >= MAX_LEN)
24274c8945a0SNathan Whitehorn 	|| (dialog_vars.input_length != 0)
24284c8945a0SNathan Whitehorn 	|| (dialog_vars.input_result == 0)) {
24294c8945a0SNathan Whitehorn 
24304c8945a0SNathan Whitehorn 	if (dialog_vars.input_length == 0
24314c8945a0SNathan Whitehorn 	    || dialog_vars.input_result == 0) {
24324c8945a0SNathan Whitehorn 
24337a1c0d96SNathan Whitehorn 	    char *save_result = dialog_vars.input_result;
24344c8945a0SNathan Whitehorn 
24354c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
24364c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length);
24374c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result malloc");
24387a1c0d96SNathan Whitehorn 	    dialog_vars.input_result[0] = '\0';
24397a1c0d96SNathan Whitehorn 	    if (save_result != 0)
24407a1c0d96SNathan Whitehorn 		strcpy(dialog_vars.input_result, save_result);
24414c8945a0SNathan Whitehorn 	} else if (want >= dialog_vars.input_length) {
24424c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
24434c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_realloc(char,
24444c8945a0SNathan Whitehorn 						   dialog_vars.input_length,
24454c8945a0SNathan Whitehorn 						   dialog_vars.input_result);
24464c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result realloc");
24474c8945a0SNathan Whitehorn 	}
24484c8945a0SNathan Whitehorn     }
24494c8945a0SNathan Whitehorn     strcat(dialog_vars.input_result, string);
24504c8945a0SNathan Whitehorn }
24514c8945a0SNathan Whitehorn 
24524c8945a0SNathan Whitehorn /*
24534c8945a0SNathan Whitehorn  * These are characters that (aside from the quote-delimiter) will have to
24544c8945a0SNathan Whitehorn  * be escaped in a single- or double-quoted string.
24554c8945a0SNathan Whitehorn  */
24564c8945a0SNathan Whitehorn #define FIX_SINGLE "\n\\"
24574c8945a0SNathan Whitehorn #define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>"
24584c8945a0SNathan Whitehorn 
24594c8945a0SNathan Whitehorn /*
24604c8945a0SNathan Whitehorn  * Returns the quote-delimiter.
24614c8945a0SNathan Whitehorn  */
24624c8945a0SNathan Whitehorn static const char *
24634c8945a0SNathan Whitehorn quote_delimiter(void)
24644c8945a0SNathan Whitehorn {
24654c8945a0SNathan Whitehorn     return dialog_vars.single_quoted ? "'" : "\"";
24664c8945a0SNathan Whitehorn }
24674c8945a0SNathan Whitehorn 
24684c8945a0SNathan Whitehorn /*
24694c8945a0SNathan Whitehorn  * Returns true if we should quote the given string.
24704c8945a0SNathan Whitehorn  */
24714c8945a0SNathan Whitehorn static bool
24724c8945a0SNathan Whitehorn must_quote(char *string)
24734c8945a0SNathan Whitehorn {
24744c8945a0SNathan Whitehorn     bool code = FALSE;
24754c8945a0SNathan Whitehorn 
24764c8945a0SNathan Whitehorn     if (*string != '\0') {
24777a1c0d96SNathan Whitehorn 	size_t len = strlen(string);
24784c8945a0SNathan Whitehorn 	if (strcspn(string, quote_delimiter()) != len)
24794c8945a0SNathan Whitehorn 	    code = TRUE;
24804c8945a0SNathan Whitehorn 	else if (strcspn(string, "\n\t ") != len)
24814c8945a0SNathan Whitehorn 	    code = TRUE;
24824c8945a0SNathan Whitehorn 	else
24834c8945a0SNathan Whitehorn 	    code = (strcspn(string, FIX_DOUBLE) != len);
24844c8945a0SNathan Whitehorn     } else {
24854c8945a0SNathan Whitehorn 	code = TRUE;
24864c8945a0SNathan Whitehorn     }
24874c8945a0SNathan Whitehorn 
24884c8945a0SNathan Whitehorn     return code;
24894c8945a0SNathan Whitehorn }
24904c8945a0SNathan Whitehorn 
24914c8945a0SNathan Whitehorn /*
24924c8945a0SNathan Whitehorn  * Add a quoted string to the result buffer.
24934c8945a0SNathan Whitehorn  */
24944c8945a0SNathan Whitehorn void
24954c8945a0SNathan Whitehorn dlg_add_quoted(char *string)
24964c8945a0SNathan Whitehorn {
24974c8945a0SNathan Whitehorn     char temp[2];
24984c8945a0SNathan Whitehorn     const char *my_quote = quote_delimiter();
24994c8945a0SNathan Whitehorn     const char *must_fix = (dialog_vars.single_quoted
25004c8945a0SNathan Whitehorn 			    ? FIX_SINGLE
25014c8945a0SNathan Whitehorn 			    : FIX_DOUBLE);
25024c8945a0SNathan Whitehorn 
2503*2a3e3873SBaptiste Daroussin     if (must_quote(string)) {
25044c8945a0SNathan Whitehorn 	temp[1] = '\0';
25054c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
25064c8945a0SNathan Whitehorn 	while (*string != '\0') {
25074c8945a0SNathan Whitehorn 	    temp[0] = *string++;
25084c8945a0SNathan Whitehorn 	    if (strchr(my_quote, *temp) || strchr(must_fix, *temp))
25094c8945a0SNathan Whitehorn 		dlg_add_result("\\");
25104c8945a0SNathan Whitehorn 	    dlg_add_result(temp);
25114c8945a0SNathan Whitehorn 	}
25124c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
25134c8945a0SNathan Whitehorn     } else {
25144c8945a0SNathan Whitehorn 	dlg_add_result(string);
25154c8945a0SNathan Whitehorn     }
25164c8945a0SNathan Whitehorn }
25174c8945a0SNathan Whitehorn 
25184c8945a0SNathan Whitehorn /*
25194c8945a0SNathan Whitehorn  * When adding a result, make that depend on whether "--quoted" is used.
25204c8945a0SNathan Whitehorn  */
25214c8945a0SNathan Whitehorn void
25224c8945a0SNathan Whitehorn dlg_add_string(char *string)
25234c8945a0SNathan Whitehorn {
25244c8945a0SNathan Whitehorn     if (dialog_vars.quoted) {
25254c8945a0SNathan Whitehorn 	dlg_add_quoted(string);
25264c8945a0SNathan Whitehorn     } else {
25274c8945a0SNathan Whitehorn 	dlg_add_result(string);
25284c8945a0SNathan Whitehorn     }
25294c8945a0SNathan Whitehorn }
25304c8945a0SNathan Whitehorn 
25314c8945a0SNathan Whitehorn bool
25324c8945a0SNathan Whitehorn dlg_need_separator(void)
25334c8945a0SNathan Whitehorn {
25344c8945a0SNathan Whitehorn     bool result = FALSE;
25354c8945a0SNathan Whitehorn 
25364c8945a0SNathan Whitehorn     if (dialog_vars.output_separator) {
25374c8945a0SNathan Whitehorn 	result = TRUE;
25384c8945a0SNathan Whitehorn     } else if (dialog_vars.input_result && *(dialog_vars.input_result)) {
25394c8945a0SNathan Whitehorn 	result = TRUE;
25404c8945a0SNathan Whitehorn     }
25414c8945a0SNathan Whitehorn     return result;
25424c8945a0SNathan Whitehorn }
25434c8945a0SNathan Whitehorn 
25444c8945a0SNathan Whitehorn void
25454c8945a0SNathan Whitehorn dlg_add_separator(void)
25464c8945a0SNathan Whitehorn {
25474c8945a0SNathan Whitehorn     const char *separator = (dialog_vars.separate_output) ? "\n" : " ";
25484c8945a0SNathan Whitehorn 
25494c8945a0SNathan Whitehorn     if (dialog_vars.output_separator)
25504c8945a0SNathan Whitehorn 	separator = dialog_vars.output_separator;
25514c8945a0SNathan Whitehorn 
25524c8945a0SNathan Whitehorn     dlg_add_result(separator);
25534c8945a0SNathan Whitehorn }
25544c8945a0SNathan Whitehorn 
25554c8945a0SNathan Whitehorn /*
25564c8945a0SNathan Whitehorn  * Some widgets support only one value of a given variable - save/restore the
25574c8945a0SNathan Whitehorn  * global dialog_vars so we can override it consistently.
25584c8945a0SNathan Whitehorn  */
25594c8945a0SNathan Whitehorn void
25604c8945a0SNathan Whitehorn dlg_save_vars(DIALOG_VARS * vars)
25614c8945a0SNathan Whitehorn {
25624c8945a0SNathan Whitehorn     *vars = dialog_vars;
25634c8945a0SNathan Whitehorn }
25644c8945a0SNathan Whitehorn 
25657a1c0d96SNathan Whitehorn /*
25667a1c0d96SNathan Whitehorn  * Most of the data in DIALOG_VARS is normally set by command-line options.
25677a1c0d96SNathan Whitehorn  * The input_result member is an exception; it is normally set by the dialog
25687a1c0d96SNathan Whitehorn  * library to return result values.
25697a1c0d96SNathan Whitehorn  */
25704c8945a0SNathan Whitehorn void
25714c8945a0SNathan Whitehorn dlg_restore_vars(DIALOG_VARS * vars)
25724c8945a0SNathan Whitehorn {
25737a1c0d96SNathan Whitehorn     char *save_result = dialog_vars.input_result;
25747a1c0d96SNathan Whitehorn     unsigned save_length = dialog_vars.input_length;
25757a1c0d96SNathan Whitehorn 
25764c8945a0SNathan Whitehorn     dialog_vars = *vars;
25777a1c0d96SNathan Whitehorn     dialog_vars.input_result = save_result;
25787a1c0d96SNathan Whitehorn     dialog_vars.input_length = save_length;
25794c8945a0SNathan Whitehorn }
25804c8945a0SNathan Whitehorn 
25814c8945a0SNathan Whitehorn /*
25824c8945a0SNathan Whitehorn  * Called each time a widget is invoked which may do output, increment a count.
25834c8945a0SNathan Whitehorn  */
25844c8945a0SNathan Whitehorn void
25854c8945a0SNathan Whitehorn dlg_does_output(void)
25864c8945a0SNathan Whitehorn {
25874c8945a0SNathan Whitehorn     dialog_state.output_count += 1;
25884c8945a0SNathan Whitehorn }
25894c8945a0SNathan Whitehorn 
25904c8945a0SNathan Whitehorn /*
25914c8945a0SNathan Whitehorn  * Compatibility for different versions of curses.
25924c8945a0SNathan Whitehorn  */
25934c8945a0SNathan Whitehorn #if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY))
25944c8945a0SNathan Whitehorn int
2595*2a3e3873SBaptiste Daroussin dlg_getbegx(WINDOW *win)
25964c8945a0SNathan Whitehorn {
25974c8945a0SNathan Whitehorn     int y, x;
25984c8945a0SNathan Whitehorn     getbegyx(win, y, x);
25994c8945a0SNathan Whitehorn     return x;
26004c8945a0SNathan Whitehorn }
26014c8945a0SNathan Whitehorn int
2602*2a3e3873SBaptiste Daroussin dlg_getbegy(WINDOW *win)
26034c8945a0SNathan Whitehorn {
26044c8945a0SNathan Whitehorn     int y, x;
26054c8945a0SNathan Whitehorn     getbegyx(win, y, x);
26064c8945a0SNathan Whitehorn     return y;
26074c8945a0SNathan Whitehorn }
26084c8945a0SNathan Whitehorn #endif
26094c8945a0SNathan Whitehorn 
26104c8945a0SNathan Whitehorn #if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY))
26114c8945a0SNathan Whitehorn int
2612*2a3e3873SBaptiste Daroussin dlg_getcurx(WINDOW *win)
26134c8945a0SNathan Whitehorn {
26144c8945a0SNathan Whitehorn     int y, x;
26154c8945a0SNathan Whitehorn     getyx(win, y, x);
26164c8945a0SNathan Whitehorn     return x;
26174c8945a0SNathan Whitehorn }
26184c8945a0SNathan Whitehorn int
2619*2a3e3873SBaptiste Daroussin dlg_getcury(WINDOW *win)
26204c8945a0SNathan Whitehorn {
26214c8945a0SNathan Whitehorn     int y, x;
26224c8945a0SNathan Whitehorn     getyx(win, y, x);
26234c8945a0SNathan Whitehorn     return y;
26244c8945a0SNathan Whitehorn }
26254c8945a0SNathan Whitehorn #endif
26264c8945a0SNathan Whitehorn 
26274c8945a0SNathan Whitehorn #if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY))
26284c8945a0SNathan Whitehorn int
2629*2a3e3873SBaptiste Daroussin dlg_getmaxx(WINDOW *win)
26304c8945a0SNathan Whitehorn {
26314c8945a0SNathan Whitehorn     int y, x;
26324c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
26334c8945a0SNathan Whitehorn     return x;
26344c8945a0SNathan Whitehorn }
26354c8945a0SNathan Whitehorn int
2636*2a3e3873SBaptiste Daroussin dlg_getmaxy(WINDOW *win)
26374c8945a0SNathan Whitehorn {
26384c8945a0SNathan Whitehorn     int y, x;
26394c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
26404c8945a0SNathan Whitehorn     return y;
26414c8945a0SNathan Whitehorn }
26424c8945a0SNathan Whitehorn #endif
26434c8945a0SNathan Whitehorn 
26444c8945a0SNathan Whitehorn #if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY))
26454c8945a0SNathan Whitehorn int
2646*2a3e3873SBaptiste Daroussin dlg_getparx(WINDOW *win)
26474c8945a0SNathan Whitehorn {
26484c8945a0SNathan Whitehorn     int y, x;
26494c8945a0SNathan Whitehorn     getparyx(win, y, x);
26504c8945a0SNathan Whitehorn     return x;
26514c8945a0SNathan Whitehorn }
26524c8945a0SNathan Whitehorn int
2653*2a3e3873SBaptiste Daroussin dlg_getpary(WINDOW *win)
26544c8945a0SNathan Whitehorn {
26554c8945a0SNathan Whitehorn     int y, x;
26564c8945a0SNathan Whitehorn     getparyx(win, y, x);
26574c8945a0SNathan Whitehorn     return y;
26584c8945a0SNathan Whitehorn }
26594c8945a0SNathan Whitehorn #endif
2660*2a3e3873SBaptiste Daroussin 
2661*2a3e3873SBaptiste Daroussin #ifdef NEED_WGETPARENT
2662*2a3e3873SBaptiste Daroussin WINDOW *
2663*2a3e3873SBaptiste Daroussin dlg_wgetparent(WINDOW *win)
2664*2a3e3873SBaptiste Daroussin {
2665*2a3e3873SBaptiste Daroussin #undef wgetparent
2666*2a3e3873SBaptiste Daroussin     WINDOW *result = 0;
2667*2a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p;
2668*2a3e3873SBaptiste Daroussin 
2669*2a3e3873SBaptiste Daroussin     for (p = dialog_state.all_subwindows; p != 0; p = p->next) {
2670*2a3e3873SBaptiste Daroussin 	if (p->shadow == win) {
2671*2a3e3873SBaptiste Daroussin 	    result = p->normal;
2672*2a3e3873SBaptiste Daroussin 	    break;
2673*2a3e3873SBaptiste Daroussin 	}
2674*2a3e3873SBaptiste Daroussin     }
2675*2a3e3873SBaptiste Daroussin     return result;
2676*2a3e3873SBaptiste Daroussin }
2677*2a3e3873SBaptiste Daroussin #endif
2678