xref: /freebsd/contrib/dialog/util.c (revision a96ef4501919d7ac08e94e98dc34b0bdd744802b)
14c8945a0SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin  *  $Id: util.c,v 1.300 2021/01/17 22:10:56 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  util.c -- miscellaneous utilities for dialog
54c8945a0SNathan Whitehorn  *
6*a96ef450SBaptiste Daroussin  *  Copyright 2000-2020,2021	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>
29*a96ef450SBaptiste Daroussin #include <dlg_internals.h>
30*a96ef450SBaptiste Daroussin 
31*a96ef450SBaptiste Daroussin #include <sys/time.h>
324c8945a0SNathan Whitehorn 
332a3e3873SBaptiste Daroussin #ifdef HAVE_SETLOCALE
342a3e3873SBaptiste Daroussin #include <locale.h>
352a3e3873SBaptiste Daroussin #endif
362a3e3873SBaptiste Daroussin 
372a3e3873SBaptiste Daroussin #ifdef NEED_WCHAR_H
382a3e3873SBaptiste Daroussin #include <wchar.h>
392a3e3873SBaptiste Daroussin #endif
402a3e3873SBaptiste Daroussin 
41*a96ef450SBaptiste Daroussin #ifdef HAVE_SYS_PARAM_H
42*a96ef450SBaptiste Daroussin #include <sys/param.h>
43*a96ef450SBaptiste Daroussin #endif
44*a96ef450SBaptiste Daroussin 
45*a96ef450SBaptiste Daroussin #if defined(NCURSES_VERSION)
46*a96ef450SBaptiste Daroussin #define CAN_KEEP_TITE 1
47*a96ef450SBaptiste Daroussin #elif defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 800000000)
48*a96ef450SBaptiste Daroussin #define CAN_KEEP_TITE 1
49*a96ef450SBaptiste Daroussin #else
50*a96ef450SBaptiste Daroussin #define CAN_KEEP_TITE 0
51*a96ef450SBaptiste Daroussin #endif
52*a96ef450SBaptiste Daroussin 
53*a96ef450SBaptiste Daroussin #if CAN_KEEP_TITE
54*a96ef450SBaptiste Daroussin #if defined(NCURSES_VERSION) && defined(HAVE_NCURSESW_TERM_H)
554c8945a0SNathan Whitehorn #include <ncursesw/term.h>
56*a96ef450SBaptiste Daroussin #elif defined(NCURSES_VERSION) && defined(HAVE_NCURSES_TERM_H)
574c8945a0SNathan Whitehorn #include <ncurses/term.h>
584c8945a0SNathan Whitehorn #else
594c8945a0SNathan Whitehorn #include <term.h>
604c8945a0SNathan Whitehorn #endif
614c8945a0SNathan Whitehorn #endif
624c8945a0SNathan Whitehorn 
63682c9e0fSNathan Whitehorn #if defined(HAVE_WCHGAT)
64682c9e0fSNathan Whitehorn #  if defined(NCURSES_VERSION_PATCH)
65682c9e0fSNathan Whitehorn #    if NCURSES_VERSION_PATCH >= 20060715
66682c9e0fSNathan Whitehorn #      define USE_WCHGAT 1
67682c9e0fSNathan Whitehorn #    else
68682c9e0fSNathan Whitehorn #      define USE_WCHGAT 0
69682c9e0fSNathan Whitehorn #    endif
70682c9e0fSNathan Whitehorn #  else
71682c9e0fSNathan Whitehorn #    define USE_WCHGAT 1
72682c9e0fSNathan Whitehorn #  endif
73682c9e0fSNathan Whitehorn #else
74682c9e0fSNathan Whitehorn #  define USE_WCHGAT 0
75682c9e0fSNathan Whitehorn #endif
76682c9e0fSNathan Whitehorn 
774c8945a0SNathan Whitehorn /* globals */
784c8945a0SNathan Whitehorn DIALOG_STATE dialog_state;
794c8945a0SNathan Whitehorn DIALOG_VARS dialog_vars;
804c8945a0SNathan Whitehorn 
812a3e3873SBaptiste Daroussin #if !(defined(HAVE_WGETPARENT) && defined(HAVE_WINDOW__PARENT))
822a3e3873SBaptiste Daroussin #define NEED_WGETPARENT 1
832a3e3873SBaptiste Daroussin #else
842a3e3873SBaptiste Daroussin #undef NEED_WGETPARENT
852a3e3873SBaptiste Daroussin #endif
862a3e3873SBaptiste Daroussin 
874c8945a0SNathan Whitehorn #define concat(a,b) a##b
884c8945a0SNathan Whitehorn 
894c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
904c8945a0SNathan Whitehorn #define RC_DATA(name,comment) , #name "_color", comment " color"
914c8945a0SNathan Whitehorn #else
924c8945a0SNathan Whitehorn #define RC_DATA(name,comment)	/*nothing */
934c8945a0SNathan Whitehorn #endif
944c8945a0SNathan Whitehorn 
954c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
964c8945a0SNathan Whitehorn #include <dlg_colors.h>
97*a96ef450SBaptiste Daroussin #ifdef HAVE_RC_FILE2
98*a96ef450SBaptiste Daroussin #define COLOR_DATA(upr) , \
99*a96ef450SBaptiste Daroussin 	concat(DLGC_FG_,upr), \
100*a96ef450SBaptiste Daroussin 	concat(DLGC_BG_,upr), \
101*a96ef450SBaptiste Daroussin 	concat(DLGC_HL_,upr), \
102*a96ef450SBaptiste Daroussin 	concat(DLGC_UL_,upr), \
103*a96ef450SBaptiste Daroussin 	concat(DLGC_RV_,upr)
104*a96ef450SBaptiste Daroussin #else /* HAVE_RC_FILE2 */
1054c8945a0SNathan Whitehorn #define COLOR_DATA(upr) , \
1064c8945a0SNathan Whitehorn 	concat(DLGC_FG_,upr), \
1074c8945a0SNathan Whitehorn 	concat(DLGC_BG_,upr), \
1084c8945a0SNathan Whitehorn 	concat(DLGC_HL_,upr)
109*a96ef450SBaptiste Daroussin #endif /* HAVE_RC_FILE2 */
110*a96ef450SBaptiste Daroussin #else /* HAVE_COLOR */
1114c8945a0SNathan Whitehorn #define COLOR_DATA(upr)		/*nothing */
112*a96ef450SBaptiste Daroussin #endif /* HAVE_COLOR */
1134c8945a0SNathan Whitehorn 
114682c9e0fSNathan Whitehorn #define UseShadow(dw) ((dw) != 0 && (dw)->normal != 0 && (dw)->shadow != 0)
115682c9e0fSNathan Whitehorn 
1164c8945a0SNathan Whitehorn /*
1174c8945a0SNathan Whitehorn  * Table of color and attribute values, default is for mono display.
1182a3e3873SBaptiste Daroussin  * The order matches the DIALOG_ATR() values.
1194c8945a0SNathan Whitehorn  */
120*a96ef450SBaptiste Daroussin #define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }
1214c8945a0SNathan Whitehorn /* *INDENT-OFF* */
1224c8945a0SNathan Whitehorn DIALOG_COLORS dlg_color_table[] =
1234c8945a0SNathan Whitehorn {
1244c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SCREEN,			screen, "Screen"),
1254c8945a0SNathan Whitehorn     DATA(A_NORMAL,	SHADOW,			shadow, "Shadow"),
1264c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DIALOG,			dialog, "Dialog box"),
1274c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TITLE,			title, "Dialog box title"),
1284c8945a0SNathan Whitehorn     DATA(A_REVERSE,	BORDER,			border, "Dialog box border"),
1294c8945a0SNathan Whitehorn     DATA(A_BOLD,	BUTTON_ACTIVE,		button_active, "Active button"),
1304c8945a0SNathan Whitehorn     DATA(A_DIM,		BUTTON_INACTIVE,	button_inactive, "Inactive button"),
1314c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_ACTIVE,	button_key_active, "Active button key"),
1324c8945a0SNathan Whitehorn     DATA(A_UNDERLINE,	BUTTON_KEY_INACTIVE,	button_key_inactive, "Inactive button key"),
1334c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_ACTIVE,	button_label_active, "Active button label"),
1344c8945a0SNathan Whitehorn     DATA(A_NORMAL,	BUTTON_LABEL_INACTIVE,	button_label_inactive, "Inactive button label"),
1354c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX,		inputbox, "Input box"),
1364c8945a0SNathan Whitehorn     DATA(A_REVERSE,	INPUTBOX_BORDER,	inputbox_border, "Input box border"),
1374c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX,		searchbox, "Search box"),
1384c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_TITLE,	searchbox_title, "Search box title"),
1394c8945a0SNathan Whitehorn     DATA(A_REVERSE,	SEARCHBOX_BORDER,	searchbox_border, "Search box border"),
1404c8945a0SNathan Whitehorn     DATA(A_REVERSE,	POSITION_INDICATOR,	position_indicator, "File position indicator"),
1414c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX,		menubox, "Menu box"),
1424c8945a0SNathan Whitehorn     DATA(A_REVERSE,	MENUBOX_BORDER,		menubox_border, "Menu box border"),
1434c8945a0SNathan Whitehorn     DATA(A_REVERSE,	ITEM,			item, "Item"),
1444c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEM_SELECTED,		item_selected, "Selected item"),
1454c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG,			tag, "Tag"),
1464c8945a0SNathan Whitehorn     DATA(A_REVERSE,	TAG_SELECTED,		tag_selected, "Selected tag"),
1474c8945a0SNathan Whitehorn     DATA(A_NORMAL,	TAG_KEY,		tag_key, "Tag key"),
1484c8945a0SNathan Whitehorn     DATA(A_BOLD,	TAG_KEY_SELECTED,	tag_key_selected, "Selected tag key"),
1494c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK,			check, "Check box"),
1504c8945a0SNathan Whitehorn     DATA(A_REVERSE,	CHECK_SELECTED,		check_selected, "Selected check box"),
1514c8945a0SNathan Whitehorn     DATA(A_REVERSE,	UARROW,			uarrow, "Up arrow"),
1524c8945a0SNathan Whitehorn     DATA(A_REVERSE,	DARROW,			darrow, "Down arrow"),
1534c8945a0SNathan Whitehorn     DATA(A_NORMAL,	ITEMHELP,		itemhelp, "Item help-text"),
1544c8945a0SNathan Whitehorn     DATA(A_BOLD,	FORM_ACTIVE_TEXT,	form_active_text, "Active form text"),
1554c8945a0SNathan Whitehorn     DATA(A_REVERSE,	FORM_TEXT,		form_text, "Form text"),
1567a1c0d96SNathan Whitehorn     DATA(A_NORMAL,	FORM_ITEM_READONLY,	form_item_readonly, "Readonly form item"),
1572a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	GAUGE,			gauge, "Dialog box gauge"),
1582a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	BORDER2,		border2, "Dialog box border2"),
1592a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	INPUTBOX_BORDER2,	inputbox_border2, "Input box border2"),
1602a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	SEARCHBOX_BORDER2,	searchbox_border2, "Search box border2"),
1612a3e3873SBaptiste Daroussin     DATA(A_REVERSE,	MENUBOX_BORDER2,	menubox_border2, "Menu box border2")
1624c8945a0SNathan Whitehorn };
163*a96ef450SBaptiste Daroussin #undef DATA
1644c8945a0SNathan Whitehorn /* *INDENT-ON* */
1654c8945a0SNathan Whitehorn 
1664c8945a0SNathan Whitehorn /*
1672a3e3873SBaptiste Daroussin  * Maintain a list of subwindows so that we can delete them to cleanup.
1682a3e3873SBaptiste Daroussin  * More important, this provides a fallback when wgetparent() is not available.
1692a3e3873SBaptiste Daroussin  */
1702a3e3873SBaptiste Daroussin static void
1712a3e3873SBaptiste Daroussin add_subwindow(WINDOW *parent, WINDOW *child)
1722a3e3873SBaptiste Daroussin {
1732a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
1742a3e3873SBaptiste Daroussin 
1752a3e3873SBaptiste Daroussin     if (p != 0) {
1762a3e3873SBaptiste Daroussin 	p->normal = parent;
1772a3e3873SBaptiste Daroussin 	p->shadow = child;
178*a96ef450SBaptiste Daroussin 	p->getc_timeout = WTIMEOUT_OFF;
1792a3e3873SBaptiste Daroussin 	p->next = dialog_state.all_subwindows;
1802a3e3873SBaptiste Daroussin 	dialog_state.all_subwindows = p;
1812a3e3873SBaptiste Daroussin     }
1822a3e3873SBaptiste Daroussin }
1832a3e3873SBaptiste Daroussin 
1842a3e3873SBaptiste Daroussin static void
1852a3e3873SBaptiste Daroussin del_subwindows(WINDOW *parent)
1862a3e3873SBaptiste Daroussin {
1872a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p = dialog_state.all_subwindows;
1882a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *q = 0;
1892a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *r;
1902a3e3873SBaptiste Daroussin 
1912a3e3873SBaptiste Daroussin     while (p != 0) {
1922a3e3873SBaptiste Daroussin 	if (p->normal == parent) {
1932a3e3873SBaptiste Daroussin 	    delwin(p->shadow);
1942a3e3873SBaptiste Daroussin 	    r = p->next;
1952a3e3873SBaptiste Daroussin 	    if (q == 0) {
1962a3e3873SBaptiste Daroussin 		dialog_state.all_subwindows = r;
1972a3e3873SBaptiste Daroussin 	    } else {
1982a3e3873SBaptiste Daroussin 		q->next = r;
1992a3e3873SBaptiste Daroussin 	    }
2002a3e3873SBaptiste Daroussin 	    free(p);
2012a3e3873SBaptiste Daroussin 	    p = r;
2022a3e3873SBaptiste Daroussin 	} else {
2032a3e3873SBaptiste Daroussin 	    q = p;
2042a3e3873SBaptiste Daroussin 	    p = p->next;
2052a3e3873SBaptiste Daroussin 	}
2062a3e3873SBaptiste Daroussin     }
2072a3e3873SBaptiste Daroussin }
2082a3e3873SBaptiste Daroussin 
2092a3e3873SBaptiste Daroussin /*
2104c8945a0SNathan Whitehorn  * Display background title if it exists ...
2114c8945a0SNathan Whitehorn  */
2124c8945a0SNathan Whitehorn void
2134c8945a0SNathan Whitehorn dlg_put_backtitle(void)
2144c8945a0SNathan Whitehorn {
2154c8945a0SNathan Whitehorn 
2164c8945a0SNathan Whitehorn     if (dialog_vars.backtitle != NULL) {
2174c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
2184c8945a0SNathan Whitehorn 	int backwidth = dlg_count_columns(dialog_vars.backtitle);
219*a96ef450SBaptiste Daroussin 	int i;
2204c8945a0SNathan Whitehorn 
221f4f33ea0SBaptiste Daroussin 	dlg_attrset(stdscr, screen_attr);
2224c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 0, 1);
2234c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);
2244c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - backwidth; i++)
2254c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, ' ');
2264c8945a0SNathan Whitehorn 	(void) wmove(stdscr, 1, 1);
2274c8945a0SNathan Whitehorn 	for (i = 0; i < COLS - 2; i++)
2284c8945a0SNathan Whitehorn 	    (void) waddch(stdscr, dlg_boxchar(ACS_HLINE));
2294c8945a0SNathan Whitehorn     }
2304c8945a0SNathan Whitehorn 
2314c8945a0SNathan Whitehorn     (void) wnoutrefresh(stdscr);
2324c8945a0SNathan Whitehorn }
2334c8945a0SNathan Whitehorn 
2344c8945a0SNathan Whitehorn /*
2354c8945a0SNathan Whitehorn  * Set window to attribute 'attr'.  There are more efficient ways to do this,
2364c8945a0SNathan Whitehorn  * but will not work on older/buggy ncurses versions.
2374c8945a0SNathan Whitehorn  */
2384c8945a0SNathan Whitehorn void
2394c8945a0SNathan Whitehorn dlg_attr_clear(WINDOW *win, int height, int width, chtype attr)
2404c8945a0SNathan Whitehorn {
2414c8945a0SNathan Whitehorn     int i, j;
2424c8945a0SNathan Whitehorn 
243f4f33ea0SBaptiste Daroussin     dlg_attrset(win, attr);
2444c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
2454c8945a0SNathan Whitehorn 	(void) wmove(win, i, 0);
2464c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
2474c8945a0SNathan Whitehorn 	    (void) waddch(win, ' ');
2484c8945a0SNathan Whitehorn     }
2494c8945a0SNathan Whitehorn     (void) touchwin(win);
2504c8945a0SNathan Whitehorn }
2514c8945a0SNathan Whitehorn 
2524c8945a0SNathan Whitehorn void
2534c8945a0SNathan Whitehorn dlg_clear(void)
2544c8945a0SNathan Whitehorn {
2554c8945a0SNathan Whitehorn     dlg_attr_clear(stdscr, LINES, COLS, screen_attr);
2564c8945a0SNathan Whitehorn }
2574c8945a0SNathan Whitehorn 
258*a96ef450SBaptiste Daroussin #ifdef KEY_RESIZE
259*a96ef450SBaptiste Daroussin void
260*a96ef450SBaptiste Daroussin _dlg_resize_cleanup(WINDOW *w)
261*a96ef450SBaptiste Daroussin {
262*a96ef450SBaptiste Daroussin     dlg_clear();
263*a96ef450SBaptiste Daroussin     dlg_put_backtitle();
264*a96ef450SBaptiste Daroussin     dlg_del_window(w);
265*a96ef450SBaptiste Daroussin     dlg_mouse_free_regions();
266*a96ef450SBaptiste Daroussin }
267*a96ef450SBaptiste Daroussin #endif /* KEY_RESIZE */
268*a96ef450SBaptiste Daroussin 
2694c8945a0SNathan Whitehorn #define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)
2704c8945a0SNathan Whitehorn 
2714c8945a0SNathan Whitehorn #define TTY_DEVICE "/dev/tty"
2724c8945a0SNathan Whitehorn 
2734c8945a0SNathan Whitehorn /*
2744c8945a0SNathan Whitehorn  * If $DIALOG_TTY exists, allow the program to try to open the terminal
2754c8945a0SNathan Whitehorn  * directly when stdout is redirected.  By default we require the "--stdout"
2764c8945a0SNathan Whitehorn  * option to be given, but some scripts were written making use of the
2774c8945a0SNathan Whitehorn  * behavior of dialog which tried opening the terminal anyway.
2784c8945a0SNathan Whitehorn  */
279*a96ef450SBaptiste Daroussin #define dialog_tty() (dlg_getenv_num("DIALOG_TTY", (int *)0) > 0)
2804c8945a0SNathan Whitehorn 
2814c8945a0SNathan Whitehorn /*
2824c8945a0SNathan Whitehorn  * Open the terminal directly.  If one of stdin, stdout or stderr really points
2834c8945a0SNathan Whitehorn  * to a tty, use it.  Otherwise give up and open /dev/tty.
2844c8945a0SNathan Whitehorn  */
2854c8945a0SNathan Whitehorn static int
2864c8945a0SNathan Whitehorn open_terminal(char **result, int mode)
2874c8945a0SNathan Whitehorn {
2884c8945a0SNathan Whitehorn     const char *device = TTY_DEVICE;
2894c8945a0SNathan Whitehorn     if (!isatty(fileno(stderr))
2904c8945a0SNathan Whitehorn 	|| (device = ttyname(fileno(stderr))) == 0) {
2914c8945a0SNathan Whitehorn 	if (!isatty(fileno(stdout))
2924c8945a0SNathan Whitehorn 	    || (device = ttyname(fileno(stdout))) == 0) {
2934c8945a0SNathan Whitehorn 	    if (!isatty(fileno(stdin))
2944c8945a0SNathan Whitehorn 		|| (device = ttyname(fileno(stdin))) == 0) {
2954c8945a0SNathan Whitehorn 		device = TTY_DEVICE;
2964c8945a0SNathan Whitehorn 	    }
2974c8945a0SNathan Whitehorn 	}
2984c8945a0SNathan Whitehorn     }
2994c8945a0SNathan Whitehorn     *result = dlg_strclone(device);
3004c8945a0SNathan Whitehorn     return open(device, mode);
3014c8945a0SNathan Whitehorn }
3024c8945a0SNathan Whitehorn 
303*a96ef450SBaptiste Daroussin #if CAN_KEEP_TITE
3042a3e3873SBaptiste Daroussin static int
3052a3e3873SBaptiste Daroussin my_putc(int ch)
3062a3e3873SBaptiste Daroussin {
3072a3e3873SBaptiste Daroussin     char buffer[2];
3082a3e3873SBaptiste Daroussin     int fd = fileno(dialog_state.screen_output);
3092a3e3873SBaptiste Daroussin 
3102a3e3873SBaptiste Daroussin     buffer[0] = (char) ch;
3112a3e3873SBaptiste Daroussin     return (int) write(fd, buffer, (size_t) 1);
3122a3e3873SBaptiste Daroussin }
3132a3e3873SBaptiste Daroussin #endif
3142a3e3873SBaptiste Daroussin 
3154c8945a0SNathan Whitehorn /*
3164c8945a0SNathan Whitehorn  * Do some initialization for dialog.
3174c8945a0SNathan Whitehorn  *
3184c8945a0SNathan Whitehorn  * 'input' is the real tty input of dialog.  Usually it is stdin, but if
3194c8945a0SNathan Whitehorn  * --input-fd option is used, it may be anything.
3204c8945a0SNathan Whitehorn  *
3214c8945a0SNathan Whitehorn  * 'output' is where dialog will send its result.  Usually it is stderr, but
3224c8945a0SNathan Whitehorn  * if --stdout or --output-fd is used, it may be anything.  We are concerned
3234c8945a0SNathan Whitehorn  * mainly with the case where it happens to be the same as stdout.
3244c8945a0SNathan Whitehorn  */
3254c8945a0SNathan Whitehorn void
3264c8945a0SNathan Whitehorn init_dialog(FILE *input, FILE *output)
3274c8945a0SNathan Whitehorn {
3284c8945a0SNathan Whitehorn     int fd1, fd2;
3294c8945a0SNathan Whitehorn     char *device = 0;
3304c8945a0SNathan Whitehorn 
3312a3e3873SBaptiste Daroussin     setlocale(LC_ALL, "");
3322a3e3873SBaptiste Daroussin 
3334c8945a0SNathan Whitehorn     dialog_state.output = output;
334*a96ef450SBaptiste Daroussin     if (dialog_state.tab_len == 0)
3354c8945a0SNathan Whitehorn 	dialog_state.tab_len = TAB_LEN;
336*a96ef450SBaptiste Daroussin     if (dialog_state.aspect_ratio == 0)
3374c8945a0SNathan Whitehorn 	dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;
3384c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
3394c8945a0SNathan Whitehorn     dialog_state.use_colors = USE_COLORS;	/* use colors by default? */
3404c8945a0SNathan Whitehorn     dialog_state.use_shadow = USE_SHADOW;	/* shadow dialog boxes by default? */
3414c8945a0SNathan Whitehorn #endif
3424c8945a0SNathan Whitehorn 
3434c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
3444c8945a0SNathan Whitehorn     if (dlg_parse_rc() == -1)	/* Read the configuration file */
3454c8945a0SNathan Whitehorn 	dlg_exiterr("init_dialog: dlg_parse_rc");
3464c8945a0SNathan Whitehorn #endif
3474c8945a0SNathan Whitehorn 
3484c8945a0SNathan Whitehorn     /*
3494c8945a0SNathan Whitehorn      * Some widgets (such as gauge) may read from the standard input.  Pipes
3504c8945a0SNathan Whitehorn      * only connect stdout/stdin, so there is not much choice.  But reading a
3514c8945a0SNathan Whitehorn      * pipe would get in the way of curses' normal reading stdin for getch.
3524c8945a0SNathan Whitehorn      *
3534c8945a0SNathan Whitehorn      * As in the --stdout (see below), reopening the terminal does not always
3544c8945a0SNathan Whitehorn      * work properly.  dialog provides a --pipe-fd option for this purpose.  We
3554c8945a0SNathan Whitehorn      * test that case first (differing fileno's for input/stdin).  If the
3564c8945a0SNathan Whitehorn      * fileno's are equal, but we're not reading from a tty, see if we can open
3574c8945a0SNathan Whitehorn      * /dev/tty.
3584c8945a0SNathan Whitehorn      */
3594c8945a0SNathan Whitehorn     dialog_state.pipe_input = stdin;
3604c8945a0SNathan Whitehorn     if (fileno(input) != fileno(stdin)) {
36119718649SNathan Whitehorn 	if ((fd1 = dup(fileno(input))) >= 0
3624c8945a0SNathan Whitehorn 	    && (fd2 = dup(fileno(stdin))) >= 0) {
3634c8945a0SNathan Whitehorn 	    (void) dup2(fileno(input), fileno(stdin));
3644c8945a0SNathan Whitehorn 	    dialog_state.pipe_input = fdopen(fd2, "r");
3654c8945a0SNathan Whitehorn 	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */
3664c8945a0SNathan Whitehorn 		(void) dup2(fileno(stdin), 0);
3672a3e3873SBaptiste Daroussin 	} else {
3684c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-input");
3692a3e3873SBaptiste Daroussin 	}
3702a3e3873SBaptiste Daroussin 	close(fd1);
3714c8945a0SNathan Whitehorn     } else if (!isatty(fileno(stdin))) {
3722a3e3873SBaptiste Daroussin 	if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0) {
3732a3e3873SBaptiste Daroussin 	    if ((fd2 = dup(fileno(stdin))) >= 0) {
3744c8945a0SNathan Whitehorn 		dialog_state.pipe_input = fdopen(fd2, "r");
3754c8945a0SNathan Whitehorn 		if (freopen(device, "r", stdin) == 0)
3764c8945a0SNathan Whitehorn 		    dlg_exiterr("cannot open tty-input");
3774c8945a0SNathan Whitehorn 		if (fileno(stdin) != 0)		/* some functions may read fd #0 */
3784c8945a0SNathan Whitehorn 		    (void) dup2(fileno(stdin), 0);
3794c8945a0SNathan Whitehorn 	    }
3802a3e3873SBaptiste Daroussin 	    close(fd1);
3812a3e3873SBaptiste Daroussin 	}
3824c8945a0SNathan Whitehorn 	free(device);
3834c8945a0SNathan Whitehorn     }
3844c8945a0SNathan Whitehorn 
3854c8945a0SNathan Whitehorn     /*
3864c8945a0SNathan Whitehorn      * If stdout is not a tty and dialog is called with the --stdout option, we
3874c8945a0SNathan Whitehorn      * have to provide for a way to write to the screen.
3884c8945a0SNathan Whitehorn      *
3894c8945a0SNathan Whitehorn      * The curses library normally writes its output to stdout, leaving stderr
3904c8945a0SNathan Whitehorn      * free for scripting.  Scripts are simpler when stdout is redirected.  The
3914c8945a0SNathan Whitehorn      * newterm function is useful; it allows us to specify where the output
3924c8945a0SNathan Whitehorn      * goes.  Reopening the terminal is not portable since several
3934c8945a0SNathan Whitehorn      * configurations do not allow this to work properly:
3944c8945a0SNathan Whitehorn      *
3954c8945a0SNathan Whitehorn      * a) some getty implementations (and possibly broken tty drivers, e.g., on
3964c8945a0SNathan Whitehorn      *    HPUX 10 and 11) cause stdin to act as if it is still in cooked mode
3974c8945a0SNathan Whitehorn      *    even though results from ioctl's state that it is successfully
3984c8945a0SNathan Whitehorn      *    altered to raw mode.  Broken is the proper term.
3994c8945a0SNathan Whitehorn      *
4004c8945a0SNathan Whitehorn      * b) the user may not have permissions on the device, e.g., if one su's
4014c8945a0SNathan Whitehorn      *    from the login user to another non-privileged user.
4024c8945a0SNathan Whitehorn      */
4034c8945a0SNathan Whitehorn     if (!isatty(fileno(stdout))
4044c8945a0SNathan Whitehorn 	&& (fileno(stdout) == fileno(output) || dialog_tty())) {
4054c8945a0SNathan Whitehorn 	if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0
4064c8945a0SNathan Whitehorn 	    && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {
4074c8945a0SNathan Whitehorn 	    if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {
4084c8945a0SNathan Whitehorn 		dlg_exiterr("cannot initialize curses");
4094c8945a0SNathan Whitehorn 	    }
4104c8945a0SNathan Whitehorn 	    free(device);
4114c8945a0SNathan Whitehorn 	} else {
4124c8945a0SNathan Whitehorn 	    dlg_exiterr("cannot open tty-output");
4134c8945a0SNathan Whitehorn 	}
4144c8945a0SNathan Whitehorn     } else {
4154c8945a0SNathan Whitehorn 	dialog_state.screen_output = stdout;
4164c8945a0SNathan Whitehorn 	(void) initscr();
4174c8945a0SNathan Whitehorn     }
418*a96ef450SBaptiste Daroussin     dlg_keep_tite(dialog_state.screen_output);
4194c8945a0SNathan Whitehorn #ifdef HAVE_FLUSHINP
4204c8945a0SNathan Whitehorn     (void) flushinp();
4214c8945a0SNathan Whitehorn #endif
4224c8945a0SNathan Whitehorn     (void) keypad(stdscr, TRUE);
4234c8945a0SNathan Whitehorn     (void) cbreak();
4244c8945a0SNathan Whitehorn     (void) noecho();
4257a1c0d96SNathan Whitehorn 
4267a1c0d96SNathan Whitehorn     if (!dialog_state.no_mouse) {
4274c8945a0SNathan Whitehorn 	mouse_open();
4287a1c0d96SNathan Whitehorn     }
4297a1c0d96SNathan Whitehorn 
4304c8945a0SNathan Whitehorn     dialog_state.screen_initialized = TRUE;
4314c8945a0SNathan Whitehorn 
4324c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4334c8945a0SNathan Whitehorn     if (dialog_state.use_colors || dialog_state.use_shadow)
4344c8945a0SNathan Whitehorn 	dlg_color_setup();	/* Set up colors */
4354c8945a0SNathan Whitehorn #endif
4364c8945a0SNathan Whitehorn 
4374c8945a0SNathan Whitehorn     /* Set screen to screen attribute */
4384c8945a0SNathan Whitehorn     dlg_clear();
4394c8945a0SNathan Whitehorn }
4404c8945a0SNathan Whitehorn 
441*a96ef450SBaptiste Daroussin void
442*a96ef450SBaptiste Daroussin dlg_keep_tite(FILE *output)
443*a96ef450SBaptiste Daroussin {
444*a96ef450SBaptiste Daroussin     if (!dialog_vars.keep_tite) {
445*a96ef450SBaptiste Daroussin #if CAN_KEEP_TITE
446*a96ef450SBaptiste Daroussin 	/*
447*a96ef450SBaptiste Daroussin 	 * Cancel xterm's alternate-screen mode.
448*a96ef450SBaptiste Daroussin 	 */
449*a96ef450SBaptiste Daroussin 	if ((fileno(output) != fileno(stdout)
450*a96ef450SBaptiste Daroussin 	     || isatty(fileno(output)))
451*a96ef450SBaptiste Daroussin 	    && key_mouse != 0	/* xterm and kindred */
452*a96ef450SBaptiste Daroussin 	    && isprivate(enter_ca_mode)
453*a96ef450SBaptiste Daroussin 	    && isprivate(exit_ca_mode)) {
454*a96ef450SBaptiste Daroussin 	    FILE *save = dialog_state.screen_output;
455*a96ef450SBaptiste Daroussin 
456*a96ef450SBaptiste Daroussin 	    /*
457*a96ef450SBaptiste Daroussin 	     * initscr() or newterm() already wrote enter_ca_mode as a side
458*a96ef450SBaptiste Daroussin 	     * effect of initializing the screen.  It would be nice to not even
459*a96ef450SBaptiste Daroussin 	     * do that, but we do not really have access to the correct copy of
460*a96ef450SBaptiste Daroussin 	     * the terminfo description until those functions have been
461*a96ef450SBaptiste Daroussin 	     * invoked.
462*a96ef450SBaptiste Daroussin 	     */
463*a96ef450SBaptiste Daroussin 	    (void) refresh();
464*a96ef450SBaptiste Daroussin 	    dialog_state.screen_output = output;
465*a96ef450SBaptiste Daroussin 	    (void) tputs(exit_ca_mode, 0, my_putc);
466*a96ef450SBaptiste Daroussin 	    (void) tputs(clear_screen, 0, my_putc);
467*a96ef450SBaptiste Daroussin 	    dialog_state.screen_output = save;
468*a96ef450SBaptiste Daroussin 
469*a96ef450SBaptiste Daroussin 	    /*
470*a96ef450SBaptiste Daroussin 	     * Prevent ncurses from switching "back" to the normal screen when
471*a96ef450SBaptiste Daroussin 	     * exiting from dialog.  That would move the cursor to the original
472*a96ef450SBaptiste Daroussin 	     * location saved in xterm.  Normally curses sets the cursor
473*a96ef450SBaptiste Daroussin 	     * position to the first line after the display, but the alternate
474*a96ef450SBaptiste Daroussin 	     * screen switching is done after that point.
475*a96ef450SBaptiste Daroussin 	     *
476*a96ef450SBaptiste Daroussin 	     * Cancelling the strings altogether also works around the buggy
477*a96ef450SBaptiste Daroussin 	     * implementation of alternate-screen in rxvt, etc., which clear
478*a96ef450SBaptiste Daroussin 	     * more of the display than they should.
479*a96ef450SBaptiste Daroussin 	     */
480*a96ef450SBaptiste Daroussin 	    enter_ca_mode = 0;
481*a96ef450SBaptiste Daroussin 	    exit_ca_mode = 0;
482*a96ef450SBaptiste Daroussin 	}
483*a96ef450SBaptiste Daroussin #else
484*a96ef450SBaptiste Daroussin 	/*
485*a96ef450SBaptiste Daroussin 	 * For other implementations, there are no useful answers:
486*a96ef450SBaptiste Daroussin 	 * + SVr4 curses "could" support a similar approach, but the clue about
487*a96ef450SBaptiste Daroussin 	 *   xterm is absent from its terminal database.
488*a96ef450SBaptiste Daroussin 	 * + PDCurses does not provide terminfo.
489*a96ef450SBaptiste Daroussin 	 */
490*a96ef450SBaptiste Daroussin 	(void) output;
491*a96ef450SBaptiste Daroussin #endif
492*a96ef450SBaptiste Daroussin     }
493*a96ef450SBaptiste Daroussin }
494*a96ef450SBaptiste Daroussin 
4954c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4964c8945a0SNathan Whitehorn static int defined_colors = 1;	/* pair-0 is reserved */
4974c8945a0SNathan Whitehorn /*
4984c8945a0SNathan Whitehorn  * Setup for color display
4994c8945a0SNathan Whitehorn  */
5004c8945a0SNathan Whitehorn void
5014c8945a0SNathan Whitehorn dlg_color_setup(void)
5024c8945a0SNathan Whitehorn {
503*a96ef450SBaptiste Daroussin     if (has_colors()) {		/* Terminal supports color? */
5044c8945a0SNathan Whitehorn 	unsigned i;
5054c8945a0SNathan Whitehorn 
5064c8945a0SNathan Whitehorn 	(void) start_color();
5074c8945a0SNathan Whitehorn 
5084c8945a0SNathan Whitehorn #if defined(HAVE_USE_DEFAULT_COLORS)
5094c8945a0SNathan Whitehorn 	use_default_colors();
5104c8945a0SNathan Whitehorn #endif
5114c8945a0SNathan Whitehorn 
5124c8945a0SNathan Whitehorn #if defined(__NetBSD__) && defined(_CURSES_)
5134c8945a0SNathan Whitehorn #define C_ATTR(x,y) (((x) != 0 ? A_BOLD :  0) | COLOR_PAIR((y)))
5144c8945a0SNathan Whitehorn 	/* work around bug in NetBSD curses */
5154c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
5164c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
5174c8945a0SNathan Whitehorn 
5184c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
5194c8945a0SNathan Whitehorn 	    (void) init_pair(i + 1,
5204c8945a0SNathan Whitehorn 			     dlg_color_table[i].fg,
5214c8945a0SNathan Whitehorn 			     dlg_color_table[i].bg);
5224c8945a0SNathan Whitehorn 
5234c8945a0SNathan Whitehorn 	    /* Setup color attributes */
5244c8945a0SNathan Whitehorn 	    dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);
5254c8945a0SNathan Whitehorn 	}
5264c8945a0SNathan Whitehorn 	defined_colors = i + 1;
5274c8945a0SNathan Whitehorn #else
5284c8945a0SNathan Whitehorn 	for (i = 0; i < sizeof(dlg_color_table) /
5294c8945a0SNathan Whitehorn 	     sizeof(dlg_color_table[0]); i++) {
5304c8945a0SNathan Whitehorn 
5314c8945a0SNathan Whitehorn 	    /* Initialize color pairs */
532*a96ef450SBaptiste Daroussin 	    chtype atr = dlg_color_pair(dlg_color_table[i].fg,
5334c8945a0SNathan Whitehorn 					dlg_color_table[i].bg);
5344c8945a0SNathan Whitehorn 
535*a96ef450SBaptiste Daroussin 	    atr |= (dlg_color_table[i].hilite ? A_BOLD : 0);
536*a96ef450SBaptiste Daroussin #ifdef HAVE_RC_FILE2
537*a96ef450SBaptiste Daroussin 	    atr |= (dlg_color_table[i].ul ? A_UNDERLINE : 0);
538*a96ef450SBaptiste Daroussin 	    atr |= (dlg_color_table[i].rv ? A_REVERSE : 0);
539*a96ef450SBaptiste Daroussin #endif /* HAVE_RC_FILE2 */
540*a96ef450SBaptiste Daroussin 
541*a96ef450SBaptiste Daroussin 	    dlg_color_table[i].atr = atr;
5424c8945a0SNathan Whitehorn 	}
5434c8945a0SNathan Whitehorn #endif
5444c8945a0SNathan Whitehorn     } else {
5454c8945a0SNathan Whitehorn 	dialog_state.use_colors = FALSE;
5464c8945a0SNathan Whitehorn 	dialog_state.use_shadow = FALSE;
5474c8945a0SNathan Whitehorn     }
5484c8945a0SNathan Whitehorn }
5494c8945a0SNathan Whitehorn 
5504c8945a0SNathan Whitehorn int
5514c8945a0SNathan Whitehorn dlg_color_count(void)
5524c8945a0SNathan Whitehorn {
553*a96ef450SBaptiste Daroussin     return TableSize(dlg_color_table);
5544c8945a0SNathan Whitehorn }
5554c8945a0SNathan Whitehorn 
5564c8945a0SNathan Whitehorn /*
5577a1c0d96SNathan Whitehorn  * Wrapper for getattrs(), or the more cumbersome X/Open wattr_get().
5587a1c0d96SNathan Whitehorn  */
5597a1c0d96SNathan Whitehorn chtype
5607a1c0d96SNathan Whitehorn dlg_get_attrs(WINDOW *win)
5617a1c0d96SNathan Whitehorn {
5627a1c0d96SNathan Whitehorn     chtype result;
5637a1c0d96SNathan Whitehorn #ifdef HAVE_GETATTRS
564682c9e0fSNathan Whitehorn     result = (chtype) getattrs(win);
5657a1c0d96SNathan Whitehorn #else
5667a1c0d96SNathan Whitehorn     attr_t my_result;
5677a1c0d96SNathan Whitehorn     short my_pair;
5687a1c0d96SNathan Whitehorn     wattr_get(win, &my_result, &my_pair, NULL);
5697a1c0d96SNathan Whitehorn     result = my_result;
5707a1c0d96SNathan Whitehorn #endif
5717a1c0d96SNathan Whitehorn     return result;
5727a1c0d96SNathan Whitehorn }
5737a1c0d96SNathan Whitehorn 
5747a1c0d96SNathan Whitehorn /*
5754c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
5764c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
5774c8945a0SNathan Whitehorn  * window's defined background.
5784c8945a0SNathan Whitehorn  */
5794c8945a0SNathan Whitehorn chtype
5804c8945a0SNathan Whitehorn dlg_color_pair(int foreground, int background)
5814c8945a0SNathan Whitehorn {
5824c8945a0SNathan Whitehorn     chtype result = 0;
5834c8945a0SNathan Whitehorn     int pair;
5844c8945a0SNathan Whitehorn     short fg, bg;
5854c8945a0SNathan Whitehorn     bool found = FALSE;
5864c8945a0SNathan Whitehorn 
5874c8945a0SNathan Whitehorn     for (pair = 1; pair < defined_colors; ++pair) {
5884c8945a0SNathan Whitehorn 	if (pair_content((short) pair, &fg, &bg) != ERR
5894c8945a0SNathan Whitehorn 	    && fg == foreground
5904c8945a0SNathan Whitehorn 	    && bg == background) {
5914c8945a0SNathan Whitehorn 	    result = (chtype) COLOR_PAIR(pair);
5924c8945a0SNathan Whitehorn 	    found = TRUE;
5934c8945a0SNathan Whitehorn 	    break;
5944c8945a0SNathan Whitehorn 	}
5954c8945a0SNathan Whitehorn     }
5964c8945a0SNathan Whitehorn     if (!found && (defined_colors + 1) < COLOR_PAIRS) {
5974c8945a0SNathan Whitehorn 	pair = defined_colors++;
5984c8945a0SNathan Whitehorn 	(void) init_pair((short) pair, (short) foreground, (short) background);
5994c8945a0SNathan Whitehorn 	result = (chtype) COLOR_PAIR(pair);
6004c8945a0SNathan Whitehorn     }
6014c8945a0SNathan Whitehorn     return result;
6024c8945a0SNathan Whitehorn }
6034c8945a0SNathan Whitehorn 
6044c8945a0SNathan Whitehorn /*
6054c8945a0SNathan Whitehorn  * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
6064c8945a0SNathan Whitehorn  * have (or can) define a pair with the given color as foreground on the
6074c8945a0SNathan Whitehorn  * window's defined background.
6084c8945a0SNathan Whitehorn  */
6094c8945a0SNathan Whitehorn static chtype
6104c8945a0SNathan Whitehorn define_color(WINDOW *win, int foreground)
6114c8945a0SNathan Whitehorn {
6124c8945a0SNathan Whitehorn     short fg, bg, background;
613f4f33ea0SBaptiste Daroussin     if (dialog_state.text_only) {
614f4f33ea0SBaptiste Daroussin 	background = COLOR_BLACK;
615f4f33ea0SBaptiste Daroussin     } else {
616f4f33ea0SBaptiste Daroussin 	chtype attrs = dlg_get_attrs(win);
617*a96ef450SBaptiste Daroussin 	int pair;
6184c8945a0SNathan Whitehorn 
6194c8945a0SNathan Whitehorn 	if ((pair = PAIR_NUMBER(attrs)) != 0
6204c8945a0SNathan Whitehorn 	    && pair_content((short) pair, &fg, &bg) != ERR) {
6214c8945a0SNathan Whitehorn 	    background = bg;
6224c8945a0SNathan Whitehorn 	} else {
6234c8945a0SNathan Whitehorn 	    background = COLOR_BLACK;
6244c8945a0SNathan Whitehorn 	}
625f4f33ea0SBaptiste Daroussin     }
6264c8945a0SNathan Whitehorn     return dlg_color_pair(foreground, background);
6274c8945a0SNathan Whitehorn }
6284c8945a0SNathan Whitehorn #endif
6294c8945a0SNathan Whitehorn 
6304c8945a0SNathan Whitehorn /*
6314c8945a0SNathan Whitehorn  * End using dialog functions.
6324c8945a0SNathan Whitehorn  */
6334c8945a0SNathan Whitehorn void
6344c8945a0SNathan Whitehorn end_dialog(void)
6354c8945a0SNathan Whitehorn {
6364c8945a0SNathan Whitehorn     if (dialog_state.screen_initialized) {
6374c8945a0SNathan Whitehorn 	dialog_state.screen_initialized = FALSE;
638*a96ef450SBaptiste Daroussin 	if (dialog_vars.erase_on_exit) {
639*a96ef450SBaptiste Daroussin 	    /*
640*a96ef450SBaptiste Daroussin 	     * Clear the screen to the native background color, and leave the
641*a96ef450SBaptiste Daroussin 	     * terminal cursor at the lower-left corner of the screen.
642*a96ef450SBaptiste Daroussin 	     */
643*a96ef450SBaptiste Daroussin 	    werase(stdscr);
644*a96ef450SBaptiste Daroussin 	    wrefresh(stdscr);
645*a96ef450SBaptiste Daroussin 	}
6464c8945a0SNathan Whitehorn 	mouse_close();
6474c8945a0SNathan Whitehorn 	(void) endwin();
6484c8945a0SNathan Whitehorn 	(void) fflush(stdout);
6494c8945a0SNathan Whitehorn     }
6504c8945a0SNathan Whitehorn }
6514c8945a0SNathan Whitehorn 
652682c9e0fSNathan Whitehorn #define ESCAPE_LEN 3
6534c8945a0SNathan Whitehorn #define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))
6544c8945a0SNathan Whitehorn 
6552a3e3873SBaptiste Daroussin int
6562a3e3873SBaptiste Daroussin dlg_count_real_columns(const char *text)
6572a3e3873SBaptiste Daroussin {
658febdb468SDevin Teske     int result = 0;
659febdb468SDevin Teske     if (*text) {
660febdb468SDevin Teske 	result = dlg_count_columns(text);
6612a3e3873SBaptiste Daroussin 	if (result && dialog_vars.colors) {
6622a3e3873SBaptiste Daroussin 	    int hidden = 0;
6632a3e3873SBaptiste Daroussin 	    while (*text) {
6642a3e3873SBaptiste Daroussin 		if (dialog_vars.colors && isOurEscape(text)) {
6652a3e3873SBaptiste Daroussin 		    hidden += ESCAPE_LEN;
6662a3e3873SBaptiste Daroussin 		    text += ESCAPE_LEN;
6672a3e3873SBaptiste Daroussin 		} else {
6682a3e3873SBaptiste Daroussin 		    ++text;
6692a3e3873SBaptiste Daroussin 		}
6702a3e3873SBaptiste Daroussin 	    }
6712a3e3873SBaptiste Daroussin 	    result -= hidden;
6722a3e3873SBaptiste Daroussin 	}
673febdb468SDevin Teske     }
6742a3e3873SBaptiste Daroussin     return result;
6752a3e3873SBaptiste Daroussin }
6762a3e3873SBaptiste Daroussin 
6774c8945a0SNathan Whitehorn static int
6784c8945a0SNathan Whitehorn centered(int width, const char *string)
6794c8945a0SNathan Whitehorn {
6802a3e3873SBaptiste Daroussin     int need = dlg_count_real_columns(string);
6814c8945a0SNathan Whitehorn     int left;
6824c8945a0SNathan Whitehorn 
6832a3e3873SBaptiste Daroussin     left = (width - need) / 2 - 1;
6844c8945a0SNathan Whitehorn     if (left < 0)
6854c8945a0SNathan Whitehorn 	left = 0;
6864c8945a0SNathan Whitehorn     return left;
6874c8945a0SNathan Whitehorn }
6884c8945a0SNathan Whitehorn 
6897a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
6907a1c0d96SNathan Whitehorn static bool
6917a1c0d96SNathan Whitehorn is_combining(const char *txt, int *combined)
6927a1c0d96SNathan Whitehorn {
6937a1c0d96SNathan Whitehorn     bool result = FALSE;
6947a1c0d96SNathan Whitehorn 
6957a1c0d96SNathan Whitehorn     if (*combined == 0) {
6967a1c0d96SNathan Whitehorn 	if (UCH(*txt) >= 128) {
6977a1c0d96SNathan Whitehorn 	    wchar_t wch;
6987a1c0d96SNathan Whitehorn 	    mbstate_t state;
6997a1c0d96SNathan Whitehorn 	    size_t given = strlen(txt);
7007a1c0d96SNathan Whitehorn 	    size_t len;
7017a1c0d96SNathan Whitehorn 
7027a1c0d96SNathan Whitehorn 	    memset(&state, 0, sizeof(state));
7037a1c0d96SNathan Whitehorn 	    len = mbrtowc(&wch, txt, given, &state);
7047a1c0d96SNathan Whitehorn 	    if ((int) len > 0 && wcwidth(wch) == 0) {
7057a1c0d96SNathan Whitehorn 		*combined = (int) len - 1;
7067a1c0d96SNathan Whitehorn 		result = TRUE;
7077a1c0d96SNathan Whitehorn 	    }
7087a1c0d96SNathan Whitehorn 	}
7097a1c0d96SNathan Whitehorn     } else {
7107a1c0d96SNathan Whitehorn 	result = TRUE;
7117a1c0d96SNathan Whitehorn 	*combined -= 1;
7127a1c0d96SNathan Whitehorn     }
7137a1c0d96SNathan Whitehorn     return result;
7147a1c0d96SNathan Whitehorn }
7157a1c0d96SNathan Whitehorn #endif
7167a1c0d96SNathan Whitehorn 
7174c8945a0SNathan Whitehorn /*
7182a3e3873SBaptiste Daroussin  * Print the name (tag) or text from a DIALOG_LISTITEM, highlighting the
7192a3e3873SBaptiste Daroussin  * first character if selected.
7202a3e3873SBaptiste Daroussin  */
7212a3e3873SBaptiste Daroussin void
7222a3e3873SBaptiste Daroussin dlg_print_listitem(WINDOW *win,
7232a3e3873SBaptiste Daroussin 		   const char *text,
7242a3e3873SBaptiste Daroussin 		   int climit,
7252a3e3873SBaptiste Daroussin 		   bool first,
7262a3e3873SBaptiste Daroussin 		   int selected)
7272a3e3873SBaptiste Daroussin {
7282a3e3873SBaptiste Daroussin     chtype attr = A_NORMAL;
7292a3e3873SBaptiste Daroussin     int limit;
7302a3e3873SBaptiste Daroussin     chtype attrs[4];
7312a3e3873SBaptiste Daroussin 
7322a3e3873SBaptiste Daroussin     if (text == 0)
7332a3e3873SBaptiste Daroussin 	text = "";
7342a3e3873SBaptiste Daroussin 
735*a96ef450SBaptiste Daroussin     if (first && !dialog_vars.no_hot_list) {
7362a3e3873SBaptiste Daroussin 	const int *indx = dlg_index_wchars(text);
7372a3e3873SBaptiste Daroussin 	attrs[3] = tag_key_selected_attr;
7382a3e3873SBaptiste Daroussin 	attrs[2] = tag_key_attr;
7392a3e3873SBaptiste Daroussin 	attrs[1] = tag_selected_attr;
7402a3e3873SBaptiste Daroussin 	attrs[0] = tag_attr;
7412a3e3873SBaptiste Daroussin 
742f4f33ea0SBaptiste Daroussin 	dlg_attrset(win, selected ? attrs[3] : attrs[2]);
743*a96ef450SBaptiste Daroussin 	if (*text != '\0') {
7442a3e3873SBaptiste Daroussin 	    (void) waddnstr(win, text, indx[1]);
7452a3e3873SBaptiste Daroussin 
7462a3e3873SBaptiste Daroussin 	    if ((int) strlen(text) > indx[1]) {
7472a3e3873SBaptiste Daroussin 		limit = dlg_limit_columns(text, climit, 1);
7482a3e3873SBaptiste Daroussin 		if (limit > 1) {
749f4f33ea0SBaptiste Daroussin 		    dlg_attrset(win, selected ? attrs[1] : attrs[0]);
7502a3e3873SBaptiste Daroussin 		    (void) waddnstr(win,
7512a3e3873SBaptiste Daroussin 				    text + indx[1],
7522a3e3873SBaptiste Daroussin 				    indx[limit] - indx[1]);
7532a3e3873SBaptiste Daroussin 		}
7542a3e3873SBaptiste Daroussin 	    }
755*a96ef450SBaptiste Daroussin 	}
7562a3e3873SBaptiste Daroussin     } else {
757*a96ef450SBaptiste Daroussin 	const int *cols;
758*a96ef450SBaptiste Daroussin 
7592a3e3873SBaptiste Daroussin 	attrs[1] = item_selected_attr;
7602a3e3873SBaptiste Daroussin 	attrs[0] = item_attr;
7612a3e3873SBaptiste Daroussin 
7622a3e3873SBaptiste Daroussin 	cols = dlg_index_columns(text);
7632a3e3873SBaptiste Daroussin 	limit = dlg_limit_columns(text, climit, 0);
7642a3e3873SBaptiste Daroussin 
7652a3e3873SBaptiste Daroussin 	if (limit > 0) {
766f4f33ea0SBaptiste Daroussin 	    dlg_attrset(win, selected ? attrs[1] : attrs[0]);
7672a3e3873SBaptiste Daroussin 	    dlg_print_text(win, text, cols[limit], &attr);
7682a3e3873SBaptiste Daroussin 	}
7692a3e3873SBaptiste Daroussin     }
7702a3e3873SBaptiste Daroussin }
7712a3e3873SBaptiste Daroussin 
7722a3e3873SBaptiste Daroussin /*
7734c8945a0SNathan Whitehorn  * Print up to 'cols' columns from 'text', optionally rendering our escape
7744c8945a0SNathan Whitehorn  * sequence for attributes and color.
7754c8945a0SNathan Whitehorn  */
7764c8945a0SNathan Whitehorn void
7774c8945a0SNathan Whitehorn dlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr)
7784c8945a0SNathan Whitehorn {
7794c8945a0SNathan Whitehorn     int y_origin, x_origin;
7804c8945a0SNathan Whitehorn     int y_before, x_before = 0;
7814c8945a0SNathan Whitehorn     int y_after, x_after;
7824c8945a0SNathan Whitehorn     int tabbed = 0;
7834c8945a0SNathan Whitehorn     bool ended = FALSE;
7847a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
7857a1c0d96SNathan Whitehorn     int combined = 0;
7867a1c0d96SNathan Whitehorn #endif
7874c8945a0SNathan Whitehorn 
788f4f33ea0SBaptiste Daroussin     if (dialog_state.text_only) {
789f4f33ea0SBaptiste Daroussin 	y_origin = y_after = 0;
790f4f33ea0SBaptiste Daroussin 	x_origin = x_after = 0;
791f4f33ea0SBaptiste Daroussin     } else {
792*a96ef450SBaptiste Daroussin 	y_after = 0;
793*a96ef450SBaptiste Daroussin 	x_after = 0;
7944c8945a0SNathan Whitehorn 	getyx(win, y_origin, x_origin);
795f4f33ea0SBaptiste Daroussin     }
7964c8945a0SNathan Whitehorn     while (cols > 0 && (*txt != '\0')) {
797*a96ef450SBaptiste Daroussin 	bool thisTab;
798*a96ef450SBaptiste Daroussin 	chtype useattr;
799*a96ef450SBaptiste Daroussin 
8004c8945a0SNathan Whitehorn 	if (dialog_vars.colors) {
8014c8945a0SNathan Whitehorn 	    while (isOurEscape(txt)) {
8024c8945a0SNathan Whitehorn 		int code;
8034c8945a0SNathan Whitehorn 
8044c8945a0SNathan Whitehorn 		txt += 2;
8054c8945a0SNathan Whitehorn 		switch (code = CharOf(*txt)) {
8064c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
8074c8945a0SNathan Whitehorn 		case '0':
8084c8945a0SNathan Whitehorn 		case '1':
8094c8945a0SNathan Whitehorn 		case '2':
8104c8945a0SNathan Whitehorn 		case '3':
8114c8945a0SNathan Whitehorn 		case '4':
8124c8945a0SNathan Whitehorn 		case '5':
8134c8945a0SNathan Whitehorn 		case '6':
8144c8945a0SNathan Whitehorn 		case '7':
8154c8945a0SNathan Whitehorn 		    *attr &= ~A_COLOR;
8164c8945a0SNathan Whitehorn 		    *attr |= define_color(win, code - '0');
8174c8945a0SNathan Whitehorn 		    break;
8184c8945a0SNathan Whitehorn #endif
8194c8945a0SNathan Whitehorn 		case 'B':
8204c8945a0SNathan Whitehorn 		    *attr &= ~A_BOLD;
8214c8945a0SNathan Whitehorn 		    break;
8224c8945a0SNathan Whitehorn 		case 'b':
8234c8945a0SNathan Whitehorn 		    *attr |= A_BOLD;
8244c8945a0SNathan Whitehorn 		    break;
8254c8945a0SNathan Whitehorn 		case 'R':
8264c8945a0SNathan Whitehorn 		    *attr &= ~A_REVERSE;
8274c8945a0SNathan Whitehorn 		    break;
8284c8945a0SNathan Whitehorn 		case 'r':
8294c8945a0SNathan Whitehorn 		    *attr |= A_REVERSE;
8304c8945a0SNathan Whitehorn 		    break;
8314c8945a0SNathan Whitehorn 		case 'U':
8324c8945a0SNathan Whitehorn 		    *attr &= ~A_UNDERLINE;
8334c8945a0SNathan Whitehorn 		    break;
8344c8945a0SNathan Whitehorn 		case 'u':
8354c8945a0SNathan Whitehorn 		    *attr |= A_UNDERLINE;
8364c8945a0SNathan Whitehorn 		    break;
8374c8945a0SNathan Whitehorn 		case 'n':
8384c8945a0SNathan Whitehorn 		    *attr = A_NORMAL;
8394c8945a0SNathan Whitehorn 		    break;
840*a96ef450SBaptiste Daroussin 		default:
841*a96ef450SBaptiste Daroussin 		    break;
8424c8945a0SNathan Whitehorn 		}
8434c8945a0SNathan Whitehorn 		++txt;
8444c8945a0SNathan Whitehorn 	    }
8454c8945a0SNathan Whitehorn 	}
8464c8945a0SNathan Whitehorn 	if (ended || *txt == '\n' || *txt == '\0')
8474c8945a0SNathan Whitehorn 	    break;
8484c8945a0SNathan Whitehorn 	useattr = (*attr) & A_ATTRIBUTES;
8494c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
8504c8945a0SNathan Whitehorn 	/*
8514c8945a0SNathan Whitehorn 	 * Prevent this from making text invisible when the foreground and
8524c8945a0SNathan Whitehorn 	 * background colors happen to be the same, and there's no bold
8534c8945a0SNathan Whitehorn 	 * attribute.
8544c8945a0SNathan Whitehorn 	 */
8554c8945a0SNathan Whitehorn 	if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) {
8564c8945a0SNathan Whitehorn 	    short pair = (short) PAIR_NUMBER(useattr);
8574c8945a0SNathan Whitehorn 	    short fg, bg;
8584c8945a0SNathan Whitehorn 	    if (pair_content(pair, &fg, &bg) != ERR
8594c8945a0SNathan Whitehorn 		&& fg == bg) {
8604c8945a0SNathan Whitehorn 		useattr &= ~A_COLOR;
8614c8945a0SNathan Whitehorn 		useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK)
8624c8945a0SNathan Whitehorn 					       ? COLOR_WHITE
8634c8945a0SNathan Whitehorn 					       : COLOR_BLACK));
8644c8945a0SNathan Whitehorn 	    }
8654c8945a0SNathan Whitehorn 	}
8664c8945a0SNathan Whitehorn #endif
8674c8945a0SNathan Whitehorn 	/*
8684c8945a0SNathan Whitehorn 	 * Write the character, using curses to tell exactly how wide it
8694c8945a0SNathan Whitehorn 	 * is.  If it is a tab, discount that, since the caller thinks
8704c8945a0SNathan Whitehorn 	 * tabs are nonprinting, and curses will expand tabs to one or
8714c8945a0SNathan Whitehorn 	 * more blanks.
8724c8945a0SNathan Whitehorn 	 */
8734c8945a0SNathan Whitehorn 	thisTab = (CharOf(*txt) == TAB);
874f4f33ea0SBaptiste Daroussin 	if (dialog_state.text_only) {
875f4f33ea0SBaptiste Daroussin 	    x_before = x_after;
876f4f33ea0SBaptiste Daroussin 	} else {
8772a3e3873SBaptiste Daroussin 	    if (thisTab) {
8784c8945a0SNathan Whitehorn 		getyx(win, y_before, x_before);
8792a3e3873SBaptiste Daroussin 		(void) y_before;
8802a3e3873SBaptiste Daroussin 	    }
881f4f33ea0SBaptiste Daroussin 	}
882f4f33ea0SBaptiste Daroussin 	if (dialog_state.text_only) {
883f4f33ea0SBaptiste Daroussin 	    int ch = CharOf(*txt++);
884f4f33ea0SBaptiste Daroussin 	    if (thisTab) {
885f4f33ea0SBaptiste Daroussin 		while ((x_after++) % 8) {
886f4f33ea0SBaptiste Daroussin 		    fputc(' ', dialog_state.output);
887f4f33ea0SBaptiste Daroussin 		}
888f4f33ea0SBaptiste Daroussin 	    } else {
889f4f33ea0SBaptiste Daroussin 		fputc(ch, dialog_state.output);
890f4f33ea0SBaptiste Daroussin 		x_after++;	/* FIXME: handle meta per locale */
891f4f33ea0SBaptiste Daroussin 	    }
892f4f33ea0SBaptiste Daroussin 	} else {
8934c8945a0SNathan Whitehorn 	    (void) waddch(win, CharOf(*txt++) | useattr);
8944c8945a0SNathan Whitehorn 	    getyx(win, y_after, x_after);
895f4f33ea0SBaptiste Daroussin 	}
8964c8945a0SNathan Whitehorn 	if (thisTab && (y_after == y_origin))
8974c8945a0SNathan Whitehorn 	    tabbed += (x_after - x_before);
8987a1c0d96SNathan Whitehorn 	if ((y_after != y_origin) ||
8997a1c0d96SNathan Whitehorn 	    (x_after >= (cols + tabbed + x_origin)
9007a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
9017a1c0d96SNathan Whitehorn 	     && !is_combining(txt, &combined)
9027a1c0d96SNathan Whitehorn #endif
9037a1c0d96SNathan Whitehorn 	    )) {
9044c8945a0SNathan Whitehorn 	    ended = TRUE;
9054c8945a0SNathan Whitehorn 	}
9064c8945a0SNathan Whitehorn     }
907f4f33ea0SBaptiste Daroussin     if (dialog_state.text_only) {
908f4f33ea0SBaptiste Daroussin 	fputc('\n', dialog_state.output);
909f4f33ea0SBaptiste Daroussin     }
9104c8945a0SNathan Whitehorn }
9114c8945a0SNathan Whitehorn 
9124c8945a0SNathan Whitehorn /*
9134c8945a0SNathan Whitehorn  * Print one line of the prompt in the window within the limits of the
9144c8945a0SNathan Whitehorn  * specified right margin.  The line will end on a word boundary and a pointer
9154c8945a0SNathan Whitehorn  * to the start of the next line is returned, or a NULL pointer if the end of
9164c8945a0SNathan Whitehorn  * *prompt is reached.
9174c8945a0SNathan Whitehorn  */
9184c8945a0SNathan Whitehorn const char *
9194c8945a0SNathan Whitehorn dlg_print_line(WINDOW *win,
9204c8945a0SNathan Whitehorn 	       chtype *attr,
9214c8945a0SNathan Whitehorn 	       const char *prompt,
9224c8945a0SNathan Whitehorn 	       int lm, int rm, int *x)
9234c8945a0SNathan Whitehorn {
9242a3e3873SBaptiste Daroussin     const char *wrap_ptr;
9252a3e3873SBaptiste Daroussin     const char *test_ptr;
926682c9e0fSNathan Whitehorn     const char *hide_ptr = 0;
9274c8945a0SNathan Whitehorn     const int *cols = dlg_index_columns(prompt);
9284c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(prompt);
9294c8945a0SNathan Whitehorn     int wrap_inx = 0;
9304c8945a0SNathan Whitehorn     int test_inx = 0;
9314c8945a0SNathan Whitehorn     int cur_x = lm;
9324c8945a0SNathan Whitehorn     int hidden = 0;
9334c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(prompt);
9344c8945a0SNathan Whitehorn     int n;
9354c8945a0SNathan Whitehorn     int tabbed = 0;
9364c8945a0SNathan Whitehorn 
9374c8945a0SNathan Whitehorn     *x = 1;
9384c8945a0SNathan Whitehorn 
9394c8945a0SNathan Whitehorn     /*
9404c8945a0SNathan Whitehorn      * Set *test_ptr to the end of the line or the right margin (rm), whichever
9414c8945a0SNathan Whitehorn      * is less, and set wrap_ptr to the end of the last word in the line.
9424c8945a0SNathan Whitehorn      */
9434c8945a0SNathan Whitehorn     for (n = 0; n < limit; ++n) {
944f4f33ea0SBaptiste Daroussin 	int ch = *(test_ptr = prompt + indx[test_inx]);
945f4f33ea0SBaptiste Daroussin 	if (ch == '\n' || ch == '\0' || cur_x >= (rm + hidden))
9464c8945a0SNathan Whitehorn 	    break;
947f4f33ea0SBaptiste Daroussin 	if (ch == TAB && n == 0) {
9484c8945a0SNathan Whitehorn 	    tabbed = 8;		/* workaround for leading tabs */
949f4f33ea0SBaptiste Daroussin 	} else if (isblank(UCH(ch))
950f4f33ea0SBaptiste Daroussin 		   && n != 0
951f4f33ea0SBaptiste Daroussin 		   && !isblank(UCH(prompt[indx[n - 1]]))) {
9524c8945a0SNathan Whitehorn 	    wrap_inx = n;
9534c8945a0SNathan Whitehorn 	    *x = cur_x;
9542a3e3873SBaptiste Daroussin 	} else if (dialog_vars.colors && isOurEscape(test_ptr)) {
955682c9e0fSNathan Whitehorn 	    hide_ptr = test_ptr;
956682c9e0fSNathan Whitehorn 	    hidden += ESCAPE_LEN;
957682c9e0fSNathan Whitehorn 	    n += (ESCAPE_LEN - 1);
9584c8945a0SNathan Whitehorn 	}
9594c8945a0SNathan Whitehorn 	cur_x = lm + tabbed + cols[n + 1];
9604c8945a0SNathan Whitehorn 	if (cur_x > (rm + hidden))
9614c8945a0SNathan Whitehorn 	    break;
9624c8945a0SNathan Whitehorn 	test_inx = n + 1;
9634c8945a0SNathan Whitehorn     }
9644c8945a0SNathan Whitehorn 
9654c8945a0SNathan Whitehorn     /*
9664c8945a0SNathan Whitehorn      * If the line doesn't reach the right margin in the middle of a word, then
9674c8945a0SNathan Whitehorn      * we don't have to wrap it at the end of the previous word.
9684c8945a0SNathan Whitehorn      */
9694c8945a0SNathan Whitehorn     test_ptr = prompt + indx[test_inx];
970f4f33ea0SBaptiste Daroussin     if (*test_ptr == '\n' || isblank(UCH(*test_ptr)) || *test_ptr == '\0') {
9714c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
972f4f33ea0SBaptiste Daroussin 	while (wrap_inx > 0 && isblank(UCH(prompt[indx[wrap_inx - 1]]))) {
9734c8945a0SNathan Whitehorn 	    wrap_inx--;
9744c8945a0SNathan Whitehorn 	}
9754c8945a0SNathan Whitehorn 	*x = lm + indx[wrap_inx];
9764c8945a0SNathan Whitehorn     } else if (*x == 1 && cur_x >= rm) {
9774c8945a0SNathan Whitehorn 	/*
9784c8945a0SNathan Whitehorn 	 * If the line has no spaces, then wrap it anyway at the right margin
9794c8945a0SNathan Whitehorn 	 */
9804c8945a0SNathan Whitehorn 	*x = rm;
9814c8945a0SNathan Whitehorn 	wrap_inx = test_inx;
9824c8945a0SNathan Whitehorn     }
9834c8945a0SNathan Whitehorn     wrap_ptr = prompt + indx[wrap_inx];
9847a1c0d96SNathan Whitehorn #ifdef USE_WIDE_CURSES
9857a1c0d96SNathan Whitehorn     if (UCH(*wrap_ptr) >= 128) {
9867a1c0d96SNathan Whitehorn 	int combined = 0;
9877a1c0d96SNathan Whitehorn 	while (is_combining(wrap_ptr, &combined)) {
9887a1c0d96SNathan Whitehorn 	    ++wrap_ptr;
9897a1c0d96SNathan Whitehorn 	}
9907a1c0d96SNathan Whitehorn     }
9917a1c0d96SNathan Whitehorn #endif
9924c8945a0SNathan Whitehorn 
9934c8945a0SNathan Whitehorn     /*
994682c9e0fSNathan Whitehorn      * If we found hidden text past the last point that we will display,
995682c9e0fSNathan Whitehorn      * discount that from the displayed length.
996682c9e0fSNathan Whitehorn      */
997682c9e0fSNathan Whitehorn     if ((hide_ptr != 0) && (hide_ptr >= wrap_ptr)) {
998682c9e0fSNathan Whitehorn 	hidden -= ESCAPE_LEN;
999682c9e0fSNathan Whitehorn 	test_ptr = wrap_ptr;
1000682c9e0fSNathan Whitehorn 	while (test_ptr < wrap_ptr) {
10012a3e3873SBaptiste Daroussin 	    if (dialog_vars.colors && isOurEscape(test_ptr)) {
1002682c9e0fSNathan Whitehorn 		hidden -= ESCAPE_LEN;
1003682c9e0fSNathan Whitehorn 		test_ptr += ESCAPE_LEN;
1004682c9e0fSNathan Whitehorn 	    } else {
1005682c9e0fSNathan Whitehorn 		++test_ptr;
1006682c9e0fSNathan Whitehorn 	    }
1007682c9e0fSNathan Whitehorn 	}
1008682c9e0fSNathan Whitehorn     }
1009682c9e0fSNathan Whitehorn 
1010682c9e0fSNathan Whitehorn     /*
10114c8945a0SNathan Whitehorn      * Print the line if we have a window pointer.  Otherwise this routine
10124c8945a0SNathan Whitehorn      * is just being called for sizing the window.
10134c8945a0SNathan Whitehorn      */
1014f4f33ea0SBaptiste Daroussin     if (dialog_state.text_only || win) {
10154c8945a0SNathan Whitehorn 	dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr);
10164c8945a0SNathan Whitehorn     }
10174c8945a0SNathan Whitehorn 
10184c8945a0SNathan Whitehorn     /* *x tells the calling function how long the line was */
1019f4f33ea0SBaptiste Daroussin     if (*x == 1) {
10204c8945a0SNathan Whitehorn 	*x = rm;
1021f4f33ea0SBaptiste Daroussin     }
10224c8945a0SNathan Whitehorn 
1023682c9e0fSNathan Whitehorn     *x -= hidden;
1024682c9e0fSNathan Whitehorn 
10254c8945a0SNathan Whitehorn     /* Find the start of the next line and return a pointer to it */
10264c8945a0SNathan Whitehorn     test_ptr = wrap_ptr;
1027f4f33ea0SBaptiste Daroussin     while (isblank(UCH(*test_ptr)))
10284c8945a0SNathan Whitehorn 	test_ptr++;
10294c8945a0SNathan Whitehorn     if (*test_ptr == '\n')
10304c8945a0SNathan Whitehorn 	test_ptr++;
1031febdb468SDevin Teske     dlg_finish_string(prompt);
10324c8945a0SNathan Whitehorn     return (test_ptr);
10334c8945a0SNathan Whitehorn }
10344c8945a0SNathan Whitehorn 
10354c8945a0SNathan Whitehorn static void
10364c8945a0SNathan Whitehorn justify_text(WINDOW *win,
10374c8945a0SNathan Whitehorn 	     const char *prompt,
10384c8945a0SNathan Whitehorn 	     int limit_y,
10394c8945a0SNathan Whitehorn 	     int limit_x,
10404c8945a0SNathan Whitehorn 	     int *high, int *wide)
10414c8945a0SNathan Whitehorn {
10424c8945a0SNathan Whitehorn     chtype attr = A_NORMAL;
1043*a96ef450SBaptiste Daroussin     int x;
10444c8945a0SNathan Whitehorn     int y = MARGIN;
10454c8945a0SNathan Whitehorn     int max_x = 2;
10464c8945a0SNathan Whitehorn     int lm = (2 * MARGIN);	/* left margin (box-border plus a space) */
10474c8945a0SNathan Whitehorn     int rm = limit_x;		/* right margin */
10484c8945a0SNathan Whitehorn     int bm = limit_y;		/* bottom margin */
10494c8945a0SNathan Whitehorn     int last_y = 0, last_x = 0;
10504c8945a0SNathan Whitehorn 
1051f4f33ea0SBaptiste Daroussin     dialog_state.text_height = 0;
1052f4f33ea0SBaptiste Daroussin     dialog_state.text_width = 0;
1053f4f33ea0SBaptiste Daroussin     if (dialog_state.text_only || win) {
10544c8945a0SNathan Whitehorn 	rm -= (2 * MARGIN);
10554c8945a0SNathan Whitehorn 	bm -= (2 * MARGIN);
10564c8945a0SNathan Whitehorn     }
10574c8945a0SNathan Whitehorn     if (prompt == 0)
10584c8945a0SNathan Whitehorn 	prompt = "";
10594c8945a0SNathan Whitehorn 
10604c8945a0SNathan Whitehorn     if (win != 0)
10614c8945a0SNathan Whitehorn 	getyx(win, last_y, last_x);
10624c8945a0SNathan Whitehorn     while (y <= bm && *prompt) {
10634c8945a0SNathan Whitehorn 	x = lm;
10644c8945a0SNathan Whitehorn 
10654c8945a0SNathan Whitehorn 	if (*prompt == '\n') {
10664c8945a0SNathan Whitehorn 	    while (*prompt == '\n' && y < bm) {
10674c8945a0SNathan Whitehorn 		if (*(prompt + 1) != '\0') {
10684c8945a0SNathan Whitehorn 		    ++y;
10694c8945a0SNathan Whitehorn 		    if (win != 0)
10704c8945a0SNathan Whitehorn 			(void) wmove(win, y, lm);
10714c8945a0SNathan Whitehorn 		}
10724c8945a0SNathan Whitehorn 		prompt++;
10734c8945a0SNathan Whitehorn 	    }
10744c8945a0SNathan Whitehorn 	} else if (win != 0)
10754c8945a0SNathan Whitehorn 	    (void) wmove(win, y, lm);
10764c8945a0SNathan Whitehorn 
10774c8945a0SNathan Whitehorn 	if (*prompt) {
10784c8945a0SNathan Whitehorn 	    prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x);
10794c8945a0SNathan Whitehorn 	    if (win != 0)
10804c8945a0SNathan Whitehorn 		getyx(win, last_y, last_x);
10814c8945a0SNathan Whitehorn 	}
10824c8945a0SNathan Whitehorn 	if (*prompt) {
10834c8945a0SNathan Whitehorn 	    ++y;
10844c8945a0SNathan Whitehorn 	    if (win != 0)
10854c8945a0SNathan Whitehorn 		(void) wmove(win, y, lm);
10864c8945a0SNathan Whitehorn 	}
10874c8945a0SNathan Whitehorn 	max_x = MAX(max_x, x);
10884c8945a0SNathan Whitehorn     }
10894c8945a0SNathan Whitehorn     /* Move back to the last position after drawing prompt, for msgbox. */
10904c8945a0SNathan Whitehorn     if (win != 0)
10914c8945a0SNathan Whitehorn 	(void) wmove(win, last_y, last_x);
10924c8945a0SNathan Whitehorn 
10934c8945a0SNathan Whitehorn     /* Set the final height and width for the calling function */
10944c8945a0SNathan Whitehorn     if (high != 0)
10954c8945a0SNathan Whitehorn 	*high = y;
10964c8945a0SNathan Whitehorn     if (wide != 0)
10974c8945a0SNathan Whitehorn 	*wide = max_x;
10984c8945a0SNathan Whitehorn }
10994c8945a0SNathan Whitehorn 
11004c8945a0SNathan Whitehorn /*
11014c8945a0SNathan Whitehorn  * Print a string of text in a window, automatically wrap around to the next
11024c8945a0SNathan Whitehorn  * line if the string is too long to fit on one line.  Note that the string may
11034c8945a0SNathan Whitehorn  * contain embedded newlines.
11044c8945a0SNathan Whitehorn  */
11054c8945a0SNathan Whitehorn void
11064c8945a0SNathan Whitehorn dlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width)
11074c8945a0SNathan Whitehorn {
11084c8945a0SNathan Whitehorn     justify_text(win, prompt,
11094c8945a0SNathan Whitehorn 		 height,
11104c8945a0SNathan Whitehorn 		 width,
11114c8945a0SNathan Whitehorn 		 (int *) 0, (int *) 0);
11124c8945a0SNathan Whitehorn }
11134c8945a0SNathan Whitehorn 
11144c8945a0SNathan Whitehorn /*
11154c8945a0SNathan Whitehorn  * Display the message in a scrollable window.  Actually the way it works is
11164c8945a0SNathan Whitehorn  * that we create a "tall" window of the proper width, let the text wrap within
11174c8945a0SNathan Whitehorn  * that, and copy a slice of the result to the dialog.
11184c8945a0SNathan Whitehorn  *
11194c8945a0SNathan Whitehorn  * It works for ncurses.  Other curses implementations show only blanks (Tru64)
11204c8945a0SNathan Whitehorn  * or garbage (NetBSD).
11214c8945a0SNathan Whitehorn  */
11224c8945a0SNathan Whitehorn int
11234c8945a0SNathan Whitehorn dlg_print_scrolled(WINDOW *win,
11244c8945a0SNathan Whitehorn 		   const char *prompt,
11254c8945a0SNathan Whitehorn 		   int offset,
11264c8945a0SNathan Whitehorn 		   int height,
11274c8945a0SNathan Whitehorn 		   int width,
11284c8945a0SNathan Whitehorn 		   int pauseopt)
11294c8945a0SNathan Whitehorn {
11304c8945a0SNathan Whitehorn     int oldy, oldx;
11314c8945a0SNathan Whitehorn     int last = 0;
11324c8945a0SNathan Whitehorn 
11337a1c0d96SNathan Whitehorn     (void) pauseopt;		/* used only for ncurses */
11347a1c0d96SNathan Whitehorn 
11354c8945a0SNathan Whitehorn     getyx(win, oldy, oldx);
11364c8945a0SNathan Whitehorn #ifdef NCURSES_VERSION
11374c8945a0SNathan Whitehorn     if (pauseopt) {
11384c8945a0SNathan Whitehorn 	int wide = width - (2 * MARGIN);
11394c8945a0SNathan Whitehorn 	int high = LINES;
11404c8945a0SNathan Whitehorn 	int len;
11414c8945a0SNathan Whitehorn 	WINDOW *dummy;
11424c8945a0SNathan Whitehorn 
11434c8945a0SNathan Whitehorn #if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417
11444c8945a0SNathan Whitehorn 	/*
11454c8945a0SNathan Whitehorn 	 * If we're not limited by the screensize, allow text to possibly be
11464c8945a0SNathan Whitehorn 	 * one character per line.
11474c8945a0SNathan Whitehorn 	 */
11484c8945a0SNathan Whitehorn 	if ((len = dlg_count_columns(prompt)) > high)
11494c8945a0SNathan Whitehorn 	    high = len;
11504c8945a0SNathan Whitehorn #endif
11514c8945a0SNathan Whitehorn 	dummy = newwin(high, width, 0, 0);
1152682c9e0fSNathan Whitehorn 	if (dummy == 0) {
1153f4f33ea0SBaptiste Daroussin 	    dlg_attrset(win, dialog_attr);
1154682c9e0fSNathan Whitehorn 	    dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
1155682c9e0fSNathan Whitehorn 	    last = 0;
1156682c9e0fSNathan Whitehorn 	} else {
1157*a96ef450SBaptiste Daroussin 	    int y, x;
1158*a96ef450SBaptiste Daroussin 
11594c8945a0SNathan Whitehorn 	    wbkgdset(dummy, dialog_attr | ' ');
1160f4f33ea0SBaptiste Daroussin 	    dlg_attrset(dummy, dialog_attr);
11614c8945a0SNathan Whitehorn 	    werase(dummy);
11624c8945a0SNathan Whitehorn 	    dlg_print_autowrap(dummy, prompt, high, width);
11634c8945a0SNathan Whitehorn 	    getyx(dummy, y, x);
11642a3e3873SBaptiste Daroussin 	    (void) x;
11654c8945a0SNathan Whitehorn 
11664c8945a0SNathan Whitehorn 	    copywin(dummy,	/* srcwin */
11674c8945a0SNathan Whitehorn 		    win,	/* dstwin */
11684c8945a0SNathan Whitehorn 		    offset + MARGIN,	/* sminrow */
11694c8945a0SNathan Whitehorn 		    MARGIN,	/* smincol */
11704c8945a0SNathan Whitehorn 		    MARGIN,	/* dminrow */
11714c8945a0SNathan Whitehorn 		    MARGIN,	/* dmincol */
11724c8945a0SNathan Whitehorn 		    height,	/* dmaxrow */
11734c8945a0SNathan Whitehorn 		    wide,	/* dmaxcol */
11744c8945a0SNathan Whitehorn 		    FALSE);
11754c8945a0SNathan Whitehorn 
11764c8945a0SNathan Whitehorn 	    delwin(dummy);
11774c8945a0SNathan Whitehorn 
11784c8945a0SNathan Whitehorn 	    /* if the text is incomplete, or we have scrolled, show the percentage */
11794c8945a0SNathan Whitehorn 	    if (y > 0 && wide > 4) {
1180*a96ef450SBaptiste Daroussin 		int percent = (int) ((height + offset) * 100.0 / y);
1181*a96ef450SBaptiste Daroussin 
11824c8945a0SNathan Whitehorn 		if (percent < 0)
11834c8945a0SNathan Whitehorn 		    percent = 0;
11844c8945a0SNathan Whitehorn 		if (percent > 100)
11854c8945a0SNathan Whitehorn 		    percent = 100;
1186*a96ef450SBaptiste Daroussin 
11874c8945a0SNathan Whitehorn 		if (offset != 0 || percent != 100) {
1188*a96ef450SBaptiste Daroussin 		    char buffer[5];
1189*a96ef450SBaptiste Daroussin 
1190f4f33ea0SBaptiste Daroussin 		    dlg_attrset(win, position_indicator_attr);
11914c8945a0SNathan Whitehorn 		    (void) wmove(win, MARGIN + height, wide - 4);
11924c8945a0SNathan Whitehorn 		    (void) sprintf(buffer, "%d%%", percent);
11934c8945a0SNathan Whitehorn 		    (void) waddstr(win, buffer);
11944c8945a0SNathan Whitehorn 		    if ((len = (int) strlen(buffer)) < 4) {
1195f4f33ea0SBaptiste Daroussin 			dlg_attrset(win, border_attr);
11964c8945a0SNathan Whitehorn 			whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
11974c8945a0SNathan Whitehorn 		    }
11984c8945a0SNathan Whitehorn 		}
11994c8945a0SNathan Whitehorn 	    }
12004c8945a0SNathan Whitehorn 	    last = (y - height);
1201682c9e0fSNathan Whitehorn 	}
12024c8945a0SNathan Whitehorn     } else
12034c8945a0SNathan Whitehorn #endif
12044c8945a0SNathan Whitehorn     {
12054c8945a0SNathan Whitehorn 	(void) offset;
1206f4f33ea0SBaptiste Daroussin 	dlg_attrset(win, dialog_attr);
12074c8945a0SNathan Whitehorn 	dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
12084c8945a0SNathan Whitehorn 	last = 0;
12094c8945a0SNathan Whitehorn     }
12104c8945a0SNathan Whitehorn     wmove(win, oldy, oldx);
12114c8945a0SNathan Whitehorn     return last;
12124c8945a0SNathan Whitehorn }
12134c8945a0SNathan Whitehorn 
12144c8945a0SNathan Whitehorn int
12154c8945a0SNathan Whitehorn dlg_check_scrolled(int key, int last, int page, bool * show, int *offset)
12164c8945a0SNathan Whitehorn {
12174c8945a0SNathan Whitehorn     int code = 0;
12184c8945a0SNathan Whitehorn 
12194c8945a0SNathan Whitehorn     *show = FALSE;
12204c8945a0SNathan Whitehorn 
12214c8945a0SNathan Whitehorn     switch (key) {
12224c8945a0SNathan Whitehorn     case DLGK_PAGE_FIRST:
12234c8945a0SNathan Whitehorn 	if (*offset > 0) {
12244c8945a0SNathan Whitehorn 	    *offset = 0;
12254c8945a0SNathan Whitehorn 	    *show = TRUE;
12264c8945a0SNathan Whitehorn 	}
12274c8945a0SNathan Whitehorn 	break;
12284c8945a0SNathan Whitehorn     case DLGK_PAGE_LAST:
12294c8945a0SNathan Whitehorn 	if (*offset < last) {
12304c8945a0SNathan Whitehorn 	    *offset = last;
12314c8945a0SNathan Whitehorn 	    *show = TRUE;
12324c8945a0SNathan Whitehorn 	}
12334c8945a0SNathan Whitehorn 	break;
12344c8945a0SNathan Whitehorn     case DLGK_GRID_UP:
12354c8945a0SNathan Whitehorn 	if (*offset > 0) {
12364c8945a0SNathan Whitehorn 	    --(*offset);
12374c8945a0SNathan Whitehorn 	    *show = TRUE;
12384c8945a0SNathan Whitehorn 	}
12394c8945a0SNathan Whitehorn 	break;
12404c8945a0SNathan Whitehorn     case DLGK_GRID_DOWN:
12414c8945a0SNathan Whitehorn 	if (*offset < last) {
12424c8945a0SNathan Whitehorn 	    ++(*offset);
12434c8945a0SNathan Whitehorn 	    *show = TRUE;
12444c8945a0SNathan Whitehorn 	}
12454c8945a0SNathan Whitehorn 	break;
12464c8945a0SNathan Whitehorn     case DLGK_PAGE_PREV:
12474c8945a0SNathan Whitehorn 	if (*offset > 0) {
12484c8945a0SNathan Whitehorn 	    *offset -= page;
12494c8945a0SNathan Whitehorn 	    if (*offset < 0)
12504c8945a0SNathan Whitehorn 		*offset = 0;
12514c8945a0SNathan Whitehorn 	    *show = TRUE;
12524c8945a0SNathan Whitehorn 	}
12534c8945a0SNathan Whitehorn 	break;
12544c8945a0SNathan Whitehorn     case DLGK_PAGE_NEXT:
12554c8945a0SNathan Whitehorn 	if (*offset < last) {
12564c8945a0SNathan Whitehorn 	    *offset += page;
12574c8945a0SNathan Whitehorn 	    if (*offset > last)
12584c8945a0SNathan Whitehorn 		*offset = last;
12594c8945a0SNathan Whitehorn 	    *show = TRUE;
12604c8945a0SNathan Whitehorn 	}
12614c8945a0SNathan Whitehorn 	break;
12624c8945a0SNathan Whitehorn     default:
12634c8945a0SNathan Whitehorn 	code = -1;
12644c8945a0SNathan Whitehorn 	break;
12654c8945a0SNathan Whitehorn     }
12664c8945a0SNathan Whitehorn     return code;
12674c8945a0SNathan Whitehorn }
12684c8945a0SNathan Whitehorn 
12694c8945a0SNathan Whitehorn /*
12704c8945a0SNathan Whitehorn  * Calculate the window size for preformatted text.  This will calculate box
12714c8945a0SNathan Whitehorn  * dimensions that are at or close to the specified aspect ratio for the prompt
12724c8945a0SNathan Whitehorn  * string with all spaces and newlines preserved and additional newlines added
12734c8945a0SNathan Whitehorn  * as necessary.
12744c8945a0SNathan Whitehorn  */
12754c8945a0SNathan Whitehorn static void
12764c8945a0SNathan Whitehorn auto_size_preformatted(const char *prompt, int *height, int *width)
12774c8945a0SNathan Whitehorn {
12784c8945a0SNathan Whitehorn     int high = 0, wide = 0;
12794c8945a0SNathan Whitehorn     float car;			/* Calculated Aspect Ratio */
12804c8945a0SNathan Whitehorn     int max_y = SLINES - 1;
12814c8945a0SNathan Whitehorn     int max_x = SCOLS - 2;
12824c8945a0SNathan Whitehorn     int max_width = max_x;
12834c8945a0SNathan Whitehorn     int ar = dialog_state.aspect_ratio;
12844c8945a0SNathan Whitehorn 
12854c8945a0SNathan Whitehorn     /* Get the initial dimensions */
12864c8945a0SNathan Whitehorn     justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
12874c8945a0SNathan Whitehorn     car = (float) (wide / high);
12884c8945a0SNathan Whitehorn 
12894c8945a0SNathan Whitehorn     /*
12904c8945a0SNathan Whitehorn      * If the aspect ratio is greater than it should be, then decrease the
12914c8945a0SNathan Whitehorn      * width proportionately.
12924c8945a0SNathan Whitehorn      */
12934c8945a0SNathan Whitehorn     if (car > ar) {
1294*a96ef450SBaptiste Daroussin 	float diff = car / (float) ar;
12954c8945a0SNathan Whitehorn 	max_x = (int) ((float) wide / diff + 4);
12964c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
12974c8945a0SNathan Whitehorn 	car = (float) wide / (float) high;
12984c8945a0SNathan Whitehorn     }
12994c8945a0SNathan Whitehorn 
13004c8945a0SNathan Whitehorn     /*
13014c8945a0SNathan Whitehorn      * If the aspect ratio is too small after decreasing the width, then
13024c8945a0SNathan Whitehorn      * incrementally increase the width until the aspect ratio is equal to or
13034c8945a0SNathan Whitehorn      * greater than the specified aspect ratio.
13044c8945a0SNathan Whitehorn      */
13054c8945a0SNathan Whitehorn     while (car < ar && max_x < max_width) {
13064c8945a0SNathan Whitehorn 	max_x += 4;
13074c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
13084c8945a0SNathan Whitehorn 	car = (float) (wide / high);
13094c8945a0SNathan Whitehorn     }
13104c8945a0SNathan Whitehorn 
13114c8945a0SNathan Whitehorn     *height = high;
13124c8945a0SNathan Whitehorn     *width = wide;
13134c8945a0SNathan Whitehorn }
13144c8945a0SNathan Whitehorn 
13154c8945a0SNathan Whitehorn /*
13164c8945a0SNathan Whitehorn  * Find the length of the longest "word" in the given string.  By setting the
13174c8945a0SNathan Whitehorn  * widget width at least this long, we can avoid splitting a word on the
13184c8945a0SNathan Whitehorn  * margin.
13194c8945a0SNathan Whitehorn  */
13204c8945a0SNathan Whitehorn static int
13214c8945a0SNathan Whitehorn longest_word(const char *string)
13224c8945a0SNathan Whitehorn {
1323*a96ef450SBaptiste Daroussin     int result = 0;
13244c8945a0SNathan Whitehorn 
13254c8945a0SNathan Whitehorn     while (*string != '\0') {
1326*a96ef450SBaptiste Daroussin 	int length = 0;
13274c8945a0SNathan Whitehorn 	while (*string != '\0' && !isspace(UCH(*string))) {
13284c8945a0SNathan Whitehorn 	    length++;
13294c8945a0SNathan Whitehorn 	    string++;
13304c8945a0SNathan Whitehorn 	}
13314c8945a0SNathan Whitehorn 	result = MAX(result, length);
13324c8945a0SNathan Whitehorn 	if (*string != '\0')
13334c8945a0SNathan Whitehorn 	    string++;
13344c8945a0SNathan Whitehorn     }
13354c8945a0SNathan Whitehorn     return result;
13364c8945a0SNathan Whitehorn }
13374c8945a0SNathan Whitehorn 
13384c8945a0SNathan Whitehorn /*
13394c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
13404c8945a0SNathan Whitehorn  * if (height or width == 0), justify and return actual limits.
13414c8945a0SNathan Whitehorn  */
13424c8945a0SNathan Whitehorn static void
13434c8945a0SNathan Whitehorn real_auto_size(const char *title,
13444c8945a0SNathan Whitehorn 	       const char *prompt,
13454c8945a0SNathan Whitehorn 	       int *height, int *width,
13464c8945a0SNathan Whitehorn 	       int boxlines, int mincols)
13474c8945a0SNathan Whitehorn {
13484c8945a0SNathan Whitehorn     int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2);
13494c8945a0SNathan Whitehorn     int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1);
13504c8945a0SNathan Whitehorn     int title_length = title ? dlg_count_columns(title) : 0;
13514c8945a0SNathan Whitehorn     int high;
13524c8945a0SNathan Whitehorn     int save_high = *height;
13534c8945a0SNathan Whitehorn     int save_wide = *width;
1354f4f33ea0SBaptiste Daroussin     int max_high;
1355f4f33ea0SBaptiste Daroussin     int max_wide;
13564c8945a0SNathan Whitehorn 
13574c8945a0SNathan Whitehorn     if (prompt == 0) {
13584c8945a0SNathan Whitehorn 	if (*height == 0)
13594c8945a0SNathan Whitehorn 	    *height = -1;
13604c8945a0SNathan Whitehorn 	if (*width == 0)
13614c8945a0SNathan Whitehorn 	    *width = -1;
13624c8945a0SNathan Whitehorn     }
13634c8945a0SNathan Whitehorn 
1364f4f33ea0SBaptiste Daroussin     max_high = (*height < 0);
1365f4f33ea0SBaptiste Daroussin     max_wide = (*width < 0);
1366f4f33ea0SBaptiste Daroussin 
13674c8945a0SNathan Whitehorn     if (*height > 0) {
13684c8945a0SNathan Whitehorn 	high = *height;
13694c8945a0SNathan Whitehorn     } else {
13704c8945a0SNathan Whitehorn 	high = SLINES - y;
13714c8945a0SNathan Whitehorn     }
13724c8945a0SNathan Whitehorn 
13732a3e3873SBaptiste Daroussin     if (*width <= 0) {
1374*a96ef450SBaptiste Daroussin 	int wide;
1375*a96ef450SBaptiste Daroussin 
13762a3e3873SBaptiste Daroussin 	if (prompt != 0) {
13774c8945a0SNathan Whitehorn 	    wide = MAX(title_length, mincols);
13784c8945a0SNathan Whitehorn 	    if (strchr(prompt, '\n') == 0) {
13792a3e3873SBaptiste Daroussin 		double val = (dialog_state.aspect_ratio *
13802a3e3873SBaptiste Daroussin 			      dlg_count_real_columns(prompt));
13814c8945a0SNathan Whitehorn 		double xxx = sqrt(val);
13824c8945a0SNathan Whitehorn 		int tmp = (int) xxx;
13834c8945a0SNathan Whitehorn 		wide = MAX(wide, tmp);
13844c8945a0SNathan Whitehorn 		wide = MAX(wide, longest_word(prompt));
13854c8945a0SNathan Whitehorn 		justify_text((WINDOW *) 0, prompt, high, wide, height, width);
13864c8945a0SNathan Whitehorn 	    } else {
13874c8945a0SNathan Whitehorn 		auto_size_preformatted(prompt, height, width);
13884c8945a0SNathan Whitehorn 	    }
13894c8945a0SNathan Whitehorn 	} else {
13904c8945a0SNathan Whitehorn 	    wide = SCOLS - x;
13914c8945a0SNathan Whitehorn 	    justify_text((WINDOW *) 0, prompt, high, wide, height, width);
13924c8945a0SNathan Whitehorn 	}
13932a3e3873SBaptiste Daroussin     }
13944c8945a0SNathan Whitehorn 
13954c8945a0SNathan Whitehorn     if (*width < title_length) {
13964c8945a0SNathan Whitehorn 	justify_text((WINDOW *) 0, prompt, high, title_length, height, width);
13974c8945a0SNathan Whitehorn 	*width = title_length;
13984c8945a0SNathan Whitehorn     }
13994c8945a0SNathan Whitehorn 
1400f4f33ea0SBaptiste Daroussin     dialog_state.text_height = *height;
1401f4f33ea0SBaptiste Daroussin     dialog_state.text_width = *width;
1402f4f33ea0SBaptiste Daroussin 
14034c8945a0SNathan Whitehorn     if (*width < mincols && save_wide == 0)
14044c8945a0SNathan Whitehorn 	*width = mincols;
14054c8945a0SNathan Whitehorn     if (prompt != 0) {
1406f4f33ea0SBaptiste Daroussin 	*width += ((2 * MARGIN) + SHADOW_COLS);
1407f4f33ea0SBaptiste Daroussin 	*height += boxlines + (2 * MARGIN);
14084c8945a0SNathan Whitehorn     }
1409f4f33ea0SBaptiste Daroussin 
14104c8945a0SNathan Whitehorn     if (save_high > 0)
14114c8945a0SNathan Whitehorn 	*height = save_high;
14124c8945a0SNathan Whitehorn     if (save_wide > 0)
14134c8945a0SNathan Whitehorn 	*width = save_wide;
1414f4f33ea0SBaptiste Daroussin 
1415f4f33ea0SBaptiste Daroussin     if (max_high)
1416f4f33ea0SBaptiste Daroussin 	*height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1417f4f33ea0SBaptiste Daroussin     if (max_wide)
1418f4f33ea0SBaptiste Daroussin 	*width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
14194c8945a0SNathan Whitehorn }
14204c8945a0SNathan Whitehorn 
14214c8945a0SNathan Whitehorn /* End of real_auto_size() */
14224c8945a0SNathan Whitehorn 
14234c8945a0SNathan Whitehorn void
14244c8945a0SNathan Whitehorn dlg_auto_size(const char *title,
14254c8945a0SNathan Whitehorn 	      const char *prompt,
14264c8945a0SNathan Whitehorn 	      int *height,
14274c8945a0SNathan Whitehorn 	      int *width,
14284c8945a0SNathan Whitehorn 	      int boxlines,
14294c8945a0SNathan Whitehorn 	      int mincols)
14304c8945a0SNathan Whitehorn {
1431f4f33ea0SBaptiste Daroussin     DLG_TRACE(("# dlg_auto_size(%d,%d) limits %d,%d\n",
1432f4f33ea0SBaptiste Daroussin 	       *height, *width,
1433f4f33ea0SBaptiste Daroussin 	       boxlines, mincols));
1434f4f33ea0SBaptiste Daroussin 
14354c8945a0SNathan Whitehorn     real_auto_size(title, prompt, height, width, boxlines, mincols);
14364c8945a0SNathan Whitehorn 
14374c8945a0SNathan Whitehorn     if (*width > SCOLS) {
14384c8945a0SNathan Whitehorn 	(*height)++;
14394c8945a0SNathan Whitehorn 	*width = SCOLS;
14404c8945a0SNathan Whitehorn     }
14414c8945a0SNathan Whitehorn 
1442f4f33ea0SBaptiste Daroussin     if (*height > SLINES) {
14434c8945a0SNathan Whitehorn 	*height = SLINES;
14444c8945a0SNathan Whitehorn     }
1445f4f33ea0SBaptiste Daroussin     DLG_TRACE(("# ...dlg_auto_size(%d,%d) also %d,%d\n",
1446f4f33ea0SBaptiste Daroussin 	       *height, *width,
1447f4f33ea0SBaptiste Daroussin 	       dialog_state.text_height, dialog_state.text_width));
1448f4f33ea0SBaptiste Daroussin }
14494c8945a0SNathan Whitehorn 
14504c8945a0SNathan Whitehorn /*
14514c8945a0SNathan Whitehorn  * if (height or width == -1) Maximize()
14524c8945a0SNathan Whitehorn  * if (height or width == 0)
14534c8945a0SNathan Whitehorn  *    height=MIN(SLINES, num.lines in fd+n);
14544c8945a0SNathan Whitehorn  *    width=MIN(SCOLS, MAX(longer line+n, mincols));
14554c8945a0SNathan Whitehorn  */
14564c8945a0SNathan Whitehorn void
14574c8945a0SNathan Whitehorn dlg_auto_sizefile(const char *title,
14584c8945a0SNathan Whitehorn 		  const char *file,
14594c8945a0SNathan Whitehorn 		  int *height,
14604c8945a0SNathan Whitehorn 		  int *width,
14614c8945a0SNathan Whitehorn 		  int boxlines,
14624c8945a0SNathan Whitehorn 		  int mincols)
14634c8945a0SNathan Whitehorn {
14644c8945a0SNathan Whitehorn     int count = 0;
14654c8945a0SNathan Whitehorn     int len = title ? dlg_count_columns(title) : 0;
14664c8945a0SNathan Whitehorn     int nc = 4;
14674c8945a0SNathan Whitehorn     int numlines = 2;
14684c8945a0SNathan Whitehorn     FILE *fd;
14694c8945a0SNathan Whitehorn 
14704c8945a0SNathan Whitehorn     /* Open input file for reading */
14714c8945a0SNathan Whitehorn     if ((fd = fopen(file, "rb")) == NULL)
14724c8945a0SNathan Whitehorn 	dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file);
14734c8945a0SNathan Whitehorn 
14744c8945a0SNathan Whitehorn     if ((*height == -1) || (*width == -1)) {
14754c8945a0SNathan Whitehorn 	*height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
14764c8945a0SNathan Whitehorn 	*width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
14774c8945a0SNathan Whitehorn     }
14784c8945a0SNathan Whitehorn     if ((*height != 0) && (*width != 0)) {
14794c8945a0SNathan Whitehorn 	(void) fclose(fd);
14804c8945a0SNathan Whitehorn 	if (*width > SCOLS)
14814c8945a0SNathan Whitehorn 	    *width = SCOLS;
14824c8945a0SNathan Whitehorn 	if (*height > SLINES)
14834c8945a0SNathan Whitehorn 	    *height = SLINES;
14844c8945a0SNathan Whitehorn 	return;
14854c8945a0SNathan Whitehorn     }
14864c8945a0SNathan Whitehorn 
14874c8945a0SNathan Whitehorn     while (!feof(fd)) {
1488*a96ef450SBaptiste Daroussin 	int ch;
1489*a96ef450SBaptiste Daroussin 	long offset;
1490*a96ef450SBaptiste Daroussin 
1491f4f33ea0SBaptiste Daroussin 	if (ferror(fd))
1492f4f33ea0SBaptiste Daroussin 	    break;
1493*a96ef450SBaptiste Daroussin 
14944c8945a0SNathan Whitehorn 	offset = 0;
1495f4f33ea0SBaptiste Daroussin 	while (((ch = getc(fd)) != '\n') && !feof(fd)) {
1496f4f33ea0SBaptiste Daroussin 	    if ((ch == TAB) && (dialog_vars.tab_correct)) {
14974c8945a0SNathan Whitehorn 		offset += dialog_state.tab_len - (offset % dialog_state.tab_len);
1498f4f33ea0SBaptiste Daroussin 	    } else {
14994c8945a0SNathan Whitehorn 		offset++;
1500f4f33ea0SBaptiste Daroussin 	    }
1501f4f33ea0SBaptiste Daroussin 	}
15024c8945a0SNathan Whitehorn 
15034c8945a0SNathan Whitehorn 	if (offset > len)
15047a1c0d96SNathan Whitehorn 	    len = (int) offset;
15054c8945a0SNathan Whitehorn 
15064c8945a0SNathan Whitehorn 	count++;
15074c8945a0SNathan Whitehorn     }
15084c8945a0SNathan Whitehorn 
15097a1c0d96SNathan Whitehorn     /* now 'count' has the number of lines of fd and 'len' the max length */
15104c8945a0SNathan Whitehorn 
15114c8945a0SNathan Whitehorn     *height = MIN(SLINES, count + numlines + boxlines);
15124c8945a0SNathan Whitehorn     *width = MIN(SCOLS, MAX((len + nc), mincols));
15134c8945a0SNathan Whitehorn     /* here width and height can be maximized if > SCOLS|SLINES because
15144c8945a0SNathan Whitehorn        textbox-like widgets don't put all <file> on the screen.
15154c8945a0SNathan Whitehorn        Msgbox-like widget instead have to put all <text> correctly. */
15164c8945a0SNathan Whitehorn 
15174c8945a0SNathan Whitehorn     (void) fclose(fd);
15184c8945a0SNathan Whitehorn }
15194c8945a0SNathan Whitehorn 
15204c8945a0SNathan Whitehorn /*
15214c8945a0SNathan Whitehorn  * Draw a rectangular box with line drawing characters.
15224c8945a0SNathan Whitehorn  *
15234c8945a0SNathan Whitehorn  * borderchar is used to color the upper/left edges.
15244c8945a0SNathan Whitehorn  *
15254c8945a0SNathan Whitehorn  * boxchar is used to color the right/lower edges.  It also is fill-color used
15264c8945a0SNathan Whitehorn  * for the box contents.
15274c8945a0SNathan Whitehorn  *
15284c8945a0SNathan Whitehorn  * Normally, if you are drawing a scrollable box, use menubox_border_attr for
15294c8945a0SNathan Whitehorn  * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn
15304c8945a0SNathan Whitehorn  * with menubox_attr at the top, and menubox_border_attr at the bottom.  That
15314c8945a0SNathan Whitehorn  * also (given the default color choices) produces a recessed effect.
15324c8945a0SNathan Whitehorn  *
15334c8945a0SNathan Whitehorn  * If you want a raised effect (and are not going to use the scroll-arrows),
15344c8945a0SNathan Whitehorn  * reverse this choice.
15354c8945a0SNathan Whitehorn  */
15364c8945a0SNathan Whitehorn void
15372a3e3873SBaptiste Daroussin dlg_draw_box2(WINDOW *win, int y, int x, int height, int width,
15382a3e3873SBaptiste Daroussin 	      chtype boxchar, chtype borderchar, chtype borderchar2)
15394c8945a0SNathan Whitehorn {
15404c8945a0SNathan Whitehorn     int i, j;
15417a1c0d96SNathan Whitehorn     chtype save = dlg_get_attrs(win);
15424c8945a0SNathan Whitehorn 
1543f4f33ea0SBaptiste Daroussin     dlg_attrset(win, 0);
15444c8945a0SNathan Whitehorn     for (i = 0; i < height; i++) {
15454c8945a0SNathan Whitehorn 	(void) wmove(win, y + i, x);
15464c8945a0SNathan Whitehorn 	for (j = 0; j < width; j++)
15474c8945a0SNathan Whitehorn 	    if (!i && !j)
15484c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER));
15494c8945a0SNathan Whitehorn 	    else if (i == height - 1 && !j)
15504c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER));
15514c8945a0SNathan Whitehorn 	    else if (!i && j == width - 1)
15522a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_URCORNER));
15534c8945a0SNathan Whitehorn 	    else if (i == height - 1 && j == width - 1)
15542a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_LRCORNER));
15554c8945a0SNathan Whitehorn 	    else if (!i)
15564c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE));
15574c8945a0SNathan Whitehorn 	    else if (i == height - 1)
15582a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_HLINE));
15594c8945a0SNathan Whitehorn 	    else if (!j)
15604c8945a0SNathan Whitehorn 		(void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE));
15614c8945a0SNathan Whitehorn 	    else if (j == width - 1)
15622a3e3873SBaptiste Daroussin 		(void) waddch(win, borderchar2 | dlg_boxchar(ACS_VLINE));
15634c8945a0SNathan Whitehorn 	    else
15644c8945a0SNathan Whitehorn 		(void) waddch(win, boxchar | ' ');
15654c8945a0SNathan Whitehorn     }
1566f4f33ea0SBaptiste Daroussin     dlg_attrset(win, save);
15672a3e3873SBaptiste Daroussin }
15682a3e3873SBaptiste Daroussin 
15692a3e3873SBaptiste Daroussin void
15702a3e3873SBaptiste Daroussin dlg_draw_box(WINDOW *win, int y, int x, int height, int width,
15712a3e3873SBaptiste Daroussin 	     chtype boxchar, chtype borderchar)
15722a3e3873SBaptiste Daroussin {
15732a3e3873SBaptiste Daroussin     dlg_draw_box2(win, y, x, height, width, boxchar, borderchar, boxchar);
15744c8945a0SNathan Whitehorn }
15754c8945a0SNathan Whitehorn 
1576*a96ef450SBaptiste Daroussin /*
1577*a96ef450SBaptiste Daroussin  * Search the given 'list' for the given window 'win'.  Typically 'win' is an
1578*a96ef450SBaptiste Daroussin  * input-window, i.e., a window where we might use wgetch.
1579*a96ef450SBaptiste Daroussin  *
1580*a96ef450SBaptiste Daroussin  * The all-windows list has normal- and shadow-windows.  Since we never use the
1581*a96ef450SBaptiste Daroussin  * shadow as an input window, normally we just look for the normal-window.
1582*a96ef450SBaptiste Daroussin  *
1583*a96ef450SBaptiste Daroussin  * However, the all-subwindows list stores parent/child windows rather than
1584*a96ef450SBaptiste Daroussin  * normal/shadow windows.  When searching that list, we look for the child
1585*a96ef450SBaptiste Daroussin  * window (in the .shadow field).
1586*a96ef450SBaptiste Daroussin  */
1587682c9e0fSNathan Whitehorn static DIALOG_WINDOWS *
1588*a96ef450SBaptiste Daroussin find_window(DIALOG_WINDOWS * list, WINDOW *win, bool normal)
1589682c9e0fSNathan Whitehorn {
1590682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *result = 0;
1591682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1592682c9e0fSNathan Whitehorn 
1593*a96ef450SBaptiste Daroussin     for (p = list; p != 0; p = p->next) {
1594*a96ef450SBaptiste Daroussin 	WINDOW *check = normal ? p->normal : p->shadow;
1595*a96ef450SBaptiste Daroussin 	if (check == win) {
1596682c9e0fSNathan Whitehorn 	    result = p;
1597682c9e0fSNathan Whitehorn 	    break;
1598682c9e0fSNathan Whitehorn 	}
1599682c9e0fSNathan Whitehorn     }
1600682c9e0fSNathan Whitehorn     return result;
1601682c9e0fSNathan Whitehorn }
1602682c9e0fSNathan Whitehorn 
1603*a96ef450SBaptiste Daroussin #define SearchTopWindows(win) find_window(dialog_state.all_windows, win, TRUE)
1604*a96ef450SBaptiste Daroussin #define SearchSubWindows(win) find_window(dialog_state.all_subwindows, win, FALSE)
1605*a96ef450SBaptiste Daroussin 
1606*a96ef450SBaptiste Daroussin /*
1607*a96ef450SBaptiste Daroussin  * Check for the existence of a window, e.g., when used for input or updating
1608*a96ef450SBaptiste Daroussin  * the display.  This is used in dlg_getc() and related functions, to guard
1609*a96ef450SBaptiste Daroussin  * against an asynchronous window-deletion that might invalidate the input
1610*a96ef450SBaptiste Daroussin  * window used in dlg_getc().
1611*a96ef450SBaptiste Daroussin  */
1612*a96ef450SBaptiste Daroussin DIALOG_WINDOWS *
1613*a96ef450SBaptiste Daroussin _dlg_find_window(WINDOW *win)
1614*a96ef450SBaptiste Daroussin {
1615*a96ef450SBaptiste Daroussin     DIALOG_WINDOWS *result = 0;
1616*a96ef450SBaptiste Daroussin 
1617*a96ef450SBaptiste Daroussin     if ((result = SearchTopWindows(win)) == NULL)
1618*a96ef450SBaptiste Daroussin 	result = SearchSubWindows(win);
1619*a96ef450SBaptiste Daroussin     return result;
1620*a96ef450SBaptiste Daroussin }
1621*a96ef450SBaptiste Daroussin 
16224c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
16234c8945a0SNathan Whitehorn /*
1624682c9e0fSNathan Whitehorn  * If we have wchgat(), use that for updating shadow attributes, to work with
1625682c9e0fSNathan Whitehorn  * wide-character data.
1626682c9e0fSNathan Whitehorn  */
1627682c9e0fSNathan Whitehorn 
1628682c9e0fSNathan Whitehorn /*
1629682c9e0fSNathan Whitehorn  * Check if the given point is "in" the given window.  If so, return the window
1630682c9e0fSNathan Whitehorn  * pointer, otherwise null.
1631682c9e0fSNathan Whitehorn  */
1632682c9e0fSNathan Whitehorn static WINDOW *
1633682c9e0fSNathan Whitehorn in_window(WINDOW *win, int y, int x)
1634682c9e0fSNathan Whitehorn {
1635682c9e0fSNathan Whitehorn     WINDOW *result = 0;
1636682c9e0fSNathan Whitehorn     int y_base = getbegy(win);
1637682c9e0fSNathan Whitehorn     int x_base = getbegx(win);
1638682c9e0fSNathan Whitehorn     int y_last = getmaxy(win) + y_base;
1639682c9e0fSNathan Whitehorn     int x_last = getmaxx(win) + x_base;
1640682c9e0fSNathan Whitehorn 
1641682c9e0fSNathan Whitehorn     if (y >= y_base && y <= y_last && x >= x_base && x <= x_last)
1642682c9e0fSNathan Whitehorn 	result = win;
1643682c9e0fSNathan Whitehorn     return result;
1644682c9e0fSNathan Whitehorn }
1645682c9e0fSNathan Whitehorn 
1646682c9e0fSNathan Whitehorn static WINDOW *
1647682c9e0fSNathan Whitehorn window_at_cell(DIALOG_WINDOWS * dw, int y, int x)
1648682c9e0fSNathan Whitehorn {
1649682c9e0fSNathan Whitehorn     WINDOW *result = 0;
1650682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1651682c9e0fSNathan Whitehorn     int y_want = y + getbegy(dw->shadow);
1652682c9e0fSNathan Whitehorn     int x_want = x + getbegx(dw->shadow);
1653682c9e0fSNathan Whitehorn 
1654682c9e0fSNathan Whitehorn     for (p = dialog_state.all_windows; p != 0; p = p->next) {
1655682c9e0fSNathan Whitehorn 	if (dw->normal != p->normal
1656682c9e0fSNathan Whitehorn 	    && dw->shadow != p->normal
1657682c9e0fSNathan Whitehorn 	    && (result = in_window(p->normal, y_want, x_want)) != 0) {
1658682c9e0fSNathan Whitehorn 	    break;
1659682c9e0fSNathan Whitehorn 	}
1660682c9e0fSNathan Whitehorn     }
1661682c9e0fSNathan Whitehorn     if (result == 0) {
1662682c9e0fSNathan Whitehorn 	result = stdscr;
1663682c9e0fSNathan Whitehorn     }
1664682c9e0fSNathan Whitehorn     return result;
1665682c9e0fSNathan Whitehorn }
1666682c9e0fSNathan Whitehorn 
1667682c9e0fSNathan Whitehorn static bool
1668682c9e0fSNathan Whitehorn in_shadow(WINDOW *normal, WINDOW *shadow, int y, int x)
1669682c9e0fSNathan Whitehorn {
1670682c9e0fSNathan Whitehorn     bool result = FALSE;
1671682c9e0fSNathan Whitehorn     int ybase = getbegy(normal);
1672682c9e0fSNathan Whitehorn     int ylast = getmaxy(normal) + ybase;
1673682c9e0fSNathan Whitehorn     int xbase = getbegx(normal);
1674682c9e0fSNathan Whitehorn     int xlast = getmaxx(normal) + xbase;
1675682c9e0fSNathan Whitehorn 
1676682c9e0fSNathan Whitehorn     y += getbegy(shadow);
1677682c9e0fSNathan Whitehorn     x += getbegx(shadow);
1678682c9e0fSNathan Whitehorn 
1679682c9e0fSNathan Whitehorn     if (y >= ybase + SHADOW_ROWS
1680682c9e0fSNathan Whitehorn 	&& y < ylast + SHADOW_ROWS
1681682c9e0fSNathan Whitehorn 	&& x >= xlast
1682682c9e0fSNathan Whitehorn 	&& x < xlast + SHADOW_COLS) {
1683682c9e0fSNathan Whitehorn 	/* in the right-side */
1684682c9e0fSNathan Whitehorn 	result = TRUE;
1685682c9e0fSNathan Whitehorn     } else if (y >= ylast
1686682c9e0fSNathan Whitehorn 	       && y < ylast + SHADOW_ROWS
1687682c9e0fSNathan Whitehorn 	       && x >= ybase + SHADOW_COLS
1688682c9e0fSNathan Whitehorn 	       && x < ylast + SHADOW_COLS) {
1689682c9e0fSNathan Whitehorn 	/* check the bottom */
1690682c9e0fSNathan Whitehorn 	result = TRUE;
1691682c9e0fSNathan Whitehorn     }
1692682c9e0fSNathan Whitehorn 
1693682c9e0fSNathan Whitehorn     return result;
1694682c9e0fSNathan Whitehorn }
1695682c9e0fSNathan Whitehorn 
1696682c9e0fSNathan Whitehorn /*
1697682c9e0fSNathan Whitehorn  * When erasing a shadow, check each cell to make sure that it is not part of
1698682c9e0fSNathan Whitehorn  * another box's shadow.  This is a little complicated since most shadows are
1699682c9e0fSNathan Whitehorn  * merged onto stdscr.
1700682c9e0fSNathan Whitehorn  */
1701682c9e0fSNathan Whitehorn static bool
1702682c9e0fSNathan Whitehorn last_shadow(DIALOG_WINDOWS * dw, int y, int x)
1703682c9e0fSNathan Whitehorn {
1704682c9e0fSNathan Whitehorn     DIALOG_WINDOWS *p;
1705682c9e0fSNathan Whitehorn     bool result = TRUE;
1706682c9e0fSNathan Whitehorn 
1707682c9e0fSNathan Whitehorn     for (p = dialog_state.all_windows; p != 0; p = p->next) {
1708682c9e0fSNathan Whitehorn 	if (p->normal != dw->normal
1709682c9e0fSNathan Whitehorn 	    && in_shadow(p->normal, dw->shadow, y, x)) {
1710682c9e0fSNathan Whitehorn 	    result = FALSE;
1711682c9e0fSNathan Whitehorn 	    break;
1712682c9e0fSNathan Whitehorn 	}
1713682c9e0fSNathan Whitehorn     }
1714682c9e0fSNathan Whitehorn     return result;
1715682c9e0fSNathan Whitehorn }
1716682c9e0fSNathan Whitehorn 
1717682c9e0fSNathan Whitehorn static void
1718682c9e0fSNathan Whitehorn repaint_cell(DIALOG_WINDOWS * dw, bool draw, int y, int x)
1719682c9e0fSNathan Whitehorn {
1720682c9e0fSNathan Whitehorn     WINDOW *win = dw->shadow;
1721682c9e0fSNathan Whitehorn     WINDOW *cellwin;
1722682c9e0fSNathan Whitehorn     int y2, x2;
1723682c9e0fSNathan Whitehorn 
1724682c9e0fSNathan Whitehorn     if ((cellwin = window_at_cell(dw, y, x)) != 0
1725682c9e0fSNathan Whitehorn 	&& (draw || last_shadow(dw, y, x))
1726682c9e0fSNathan Whitehorn 	&& (y2 = (y + getbegy(win) - getbegy(cellwin))) >= 0
1727682c9e0fSNathan Whitehorn 	&& (x2 = (x + getbegx(win) - getbegx(cellwin))) >= 0
1728682c9e0fSNathan Whitehorn 	&& wmove(cellwin, y2, x2) != ERR) {
1729682c9e0fSNathan Whitehorn 	chtype the_cell = dlg_get_attrs(cellwin);
1730682c9e0fSNathan Whitehorn 	chtype the_attr = (draw ? shadow_attr : the_cell);
1731682c9e0fSNathan Whitehorn 
1732f4f33ea0SBaptiste Daroussin 	if (winch(cellwin) & A_ALTCHARSET) {
1733682c9e0fSNathan Whitehorn 	    the_attr |= A_ALTCHARSET;
1734682c9e0fSNathan Whitehorn 	}
1735682c9e0fSNathan Whitehorn #if USE_WCHGAT
1736682c9e0fSNathan Whitehorn 	wchgat(cellwin, 1,
1737682c9e0fSNathan Whitehorn 	       the_attr & (chtype) (~A_COLOR),
17382a3e3873SBaptiste Daroussin 	       (short) PAIR_NUMBER(the_attr),
1739682c9e0fSNathan Whitehorn 	       NULL);
1740682c9e0fSNathan Whitehorn #else
1741682c9e0fSNathan Whitehorn 	{
1742682c9e0fSNathan Whitehorn 	    chtype the_char = ((winch(cellwin) & A_CHARTEXT) | the_attr);
1743682c9e0fSNathan Whitehorn 	    (void) waddch(cellwin, the_char);
1744682c9e0fSNathan Whitehorn 	}
1745682c9e0fSNathan Whitehorn #endif
1746682c9e0fSNathan Whitehorn 	wnoutrefresh(cellwin);
1747682c9e0fSNathan Whitehorn     }
1748682c9e0fSNathan Whitehorn }
1749682c9e0fSNathan Whitehorn 
1750682c9e0fSNathan Whitehorn #define RepaintCell(dw, draw, y, x) repaint_cell(dw, draw, y, x)
1751682c9e0fSNathan Whitehorn 
1752682c9e0fSNathan Whitehorn static void
1753682c9e0fSNathan Whitehorn repaint_shadow(DIALOG_WINDOWS * dw, bool draw, int y, int x, int height, int width)
1754682c9e0fSNathan Whitehorn {
1755*a96ef450SBaptiste Daroussin     if (UseShadow(dw)) {
1756682c9e0fSNathan Whitehorn 	int i, j;
1757682c9e0fSNathan Whitehorn 
1758682c9e0fSNathan Whitehorn #if !USE_WCHGAT
1759682c9e0fSNathan Whitehorn 	chtype save = dlg_get_attrs(dw->shadow);
1760f4f33ea0SBaptiste Daroussin 	dlg_attrset(dw->shadow, draw ? shadow_attr : screen_attr);
1761682c9e0fSNathan Whitehorn #endif
1762682c9e0fSNathan Whitehorn 	for (i = 0; i < SHADOW_ROWS; ++i) {
1763682c9e0fSNathan Whitehorn 	    for (j = 0; j < width; ++j) {
1764682c9e0fSNathan Whitehorn 		RepaintCell(dw, draw, i + y + height, j + x + SHADOW_COLS);
1765682c9e0fSNathan Whitehorn 	    }
1766682c9e0fSNathan Whitehorn 	}
1767682c9e0fSNathan Whitehorn 	for (i = 0; i < height; i++) {
1768682c9e0fSNathan Whitehorn 	    for (j = 0; j < SHADOW_COLS; ++j) {
1769682c9e0fSNathan Whitehorn 		RepaintCell(dw, draw, i + y + SHADOW_ROWS, j + x + width);
1770682c9e0fSNathan Whitehorn 	    }
1771682c9e0fSNathan Whitehorn 	}
1772682c9e0fSNathan Whitehorn 	(void) wnoutrefresh(dw->shadow);
1773682c9e0fSNathan Whitehorn #if !USE_WCHGAT
1774f4f33ea0SBaptiste Daroussin 	dlg_attrset(dw->shadow, save);
1775682c9e0fSNathan Whitehorn #endif
1776682c9e0fSNathan Whitehorn     }
1777682c9e0fSNathan Whitehorn }
1778682c9e0fSNathan Whitehorn 
1779682c9e0fSNathan Whitehorn /*
17804c8945a0SNathan Whitehorn  * Draw a shadow on the parent window corresponding to the right- and
17814c8945a0SNathan Whitehorn  * bottom-edge of the child window, to give a 3-dimensional look.
17824c8945a0SNathan Whitehorn  */
17834c8945a0SNathan Whitehorn static void
1784682c9e0fSNathan Whitehorn draw_childs_shadow(DIALOG_WINDOWS * dw)
17854c8945a0SNathan Whitehorn {
1786682c9e0fSNathan Whitehorn     if (UseShadow(dw)) {
1787682c9e0fSNathan Whitehorn 	repaint_shadow(dw,
1788682c9e0fSNathan Whitehorn 		       TRUE,
1789682c9e0fSNathan Whitehorn 		       getbegy(dw->normal) - getbegy(dw->shadow),
1790682c9e0fSNathan Whitehorn 		       getbegx(dw->normal) - getbegx(dw->shadow),
1791682c9e0fSNathan Whitehorn 		       getmaxy(dw->normal),
1792682c9e0fSNathan Whitehorn 		       getmaxx(dw->normal));
1793682c9e0fSNathan Whitehorn     }
1794682c9e0fSNathan Whitehorn }
17954c8945a0SNathan Whitehorn 
1796682c9e0fSNathan Whitehorn /*
1797682c9e0fSNathan Whitehorn  * Erase a shadow on the parent window corresponding to the right- and
1798682c9e0fSNathan Whitehorn  * bottom-edge of the child window.
1799682c9e0fSNathan Whitehorn  */
1800682c9e0fSNathan Whitehorn static void
1801682c9e0fSNathan Whitehorn erase_childs_shadow(DIALOG_WINDOWS * dw)
1802682c9e0fSNathan Whitehorn {
1803682c9e0fSNathan Whitehorn     if (UseShadow(dw)) {
1804682c9e0fSNathan Whitehorn 	repaint_shadow(dw,
1805682c9e0fSNathan Whitehorn 		       FALSE,
1806682c9e0fSNathan Whitehorn 		       getbegy(dw->normal) - getbegy(dw->shadow),
1807682c9e0fSNathan Whitehorn 		       getbegx(dw->normal) - getbegx(dw->shadow),
1808682c9e0fSNathan Whitehorn 		       getmaxy(dw->normal),
1809682c9e0fSNathan Whitehorn 		       getmaxx(dw->normal));
18104c8945a0SNathan Whitehorn     }
18114c8945a0SNathan Whitehorn }
18124c8945a0SNathan Whitehorn 
18134c8945a0SNathan Whitehorn /*
18144c8945a0SNathan Whitehorn  * Draw shadows along the right and bottom edge to give a more 3D look
1815682c9e0fSNathan Whitehorn  * to the boxes.
18164c8945a0SNathan Whitehorn  */
18174c8945a0SNathan Whitehorn void
18184c8945a0SNathan Whitehorn dlg_draw_shadow(WINDOW *win, int y, int x, int height, int width)
18194c8945a0SNathan Whitehorn {
1820*a96ef450SBaptiste Daroussin     repaint_shadow(SearchTopWindows(win), TRUE, y, x, height, width);
18214c8945a0SNathan Whitehorn }
18224c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
18234c8945a0SNathan Whitehorn 
18244c8945a0SNathan Whitehorn /*
18254c8945a0SNathan Whitehorn  * Allow shell scripts to remap the exit codes so they can distinguish ESC
18264c8945a0SNathan Whitehorn  * from ERROR.
18274c8945a0SNathan Whitehorn  */
18284c8945a0SNathan Whitehorn void
18294c8945a0SNathan Whitehorn dlg_exit(int code)
18304c8945a0SNathan Whitehorn {
18314c8945a0SNathan Whitehorn     /* *INDENT-OFF* */
18324c8945a0SNathan Whitehorn     static const struct {
18334c8945a0SNathan Whitehorn 	int code;
18344c8945a0SNathan Whitehorn 	const char *name;
18354c8945a0SNathan Whitehorn     } table[] = {
18364c8945a0SNathan Whitehorn 	{ DLG_EXIT_CANCEL, 	"DIALOG_CANCEL" },
18374c8945a0SNathan Whitehorn 	{ DLG_EXIT_ERROR,  	"DIALOG_ERROR" },
18384c8945a0SNathan Whitehorn 	{ DLG_EXIT_ESC,	   	"DIALOG_ESC" },
18394c8945a0SNathan Whitehorn 	{ DLG_EXIT_EXTRA,  	"DIALOG_EXTRA" },
18404c8945a0SNathan Whitehorn 	{ DLG_EXIT_HELP,   	"DIALOG_HELP" },
18414c8945a0SNathan Whitehorn 	{ DLG_EXIT_OK,	   	"DIALOG_OK" },
18424c8945a0SNathan Whitehorn 	{ DLG_EXIT_ITEM_HELP,	"DIALOG_ITEM_HELP" },
1843*a96ef450SBaptiste Daroussin 	{ DLG_EXIT_TIMEOUT,	"DIALOG_TIMEOUT" },
18444c8945a0SNathan Whitehorn     };
18454c8945a0SNathan Whitehorn     /* *INDENT-ON* */
18464c8945a0SNathan Whitehorn 
18474c8945a0SNathan Whitehorn     unsigned n;
18484c8945a0SNathan Whitehorn     bool overridden = FALSE;
18494c8945a0SNathan Whitehorn 
18504c8945a0SNathan Whitehorn   retry:
1851*a96ef450SBaptiste Daroussin     for (n = 0; n < TableSize(table); n++) {
18524c8945a0SNathan Whitehorn 	if (table[n].code == code) {
1853*a96ef450SBaptiste Daroussin 	    if (dlg_getenv_num(table[n].name, &code)) {
18544c8945a0SNathan Whitehorn 		overridden = TRUE;
18554c8945a0SNathan Whitehorn 	    }
18564c8945a0SNathan Whitehorn 	    break;
18574c8945a0SNathan Whitehorn 	}
18584c8945a0SNathan Whitehorn     }
18594c8945a0SNathan Whitehorn 
18604c8945a0SNathan Whitehorn     /*
18614c8945a0SNathan Whitehorn      * Prior to 2004/12/19, a widget using --item-help would exit with "OK"
18624c8945a0SNathan Whitehorn      * if the help button were selected.  Now we want to exit with "HELP",
18634c8945a0SNathan Whitehorn      * but allow the environment variable to override.
18644c8945a0SNathan Whitehorn      */
18654c8945a0SNathan Whitehorn     if (code == DLG_EXIT_ITEM_HELP && !overridden) {
18664c8945a0SNathan Whitehorn 	code = DLG_EXIT_HELP;
18674c8945a0SNathan Whitehorn 	goto retry;
18684c8945a0SNathan Whitehorn     }
1869682c9e0fSNathan Whitehorn #ifdef HAVE_DLG_TRACE
1870682c9e0fSNathan Whitehorn     dlg_trace((const char *) 0);	/* close it */
1871682c9e0fSNathan Whitehorn #endif
1872682c9e0fSNathan Whitehorn 
18734c8945a0SNathan Whitehorn #ifdef NO_LEAKS
18744c8945a0SNathan Whitehorn     _dlg_inputstr_leaks();
1875*a96ef450SBaptiste Daroussin #if defined(NCURSES_VERSION) && (defined(HAVE_CURSES_EXIT) || defined(HAVE__NC_FREE_AND_EXIT))
1876*a96ef450SBaptiste Daroussin     curses_exit(code);
18774c8945a0SNathan Whitehorn #endif
18784c8945a0SNathan Whitehorn #endif
18794c8945a0SNathan Whitehorn 
18804c8945a0SNathan Whitehorn     if (dialog_state.input == stdin) {
18814c8945a0SNathan Whitehorn 	exit(code);
18824c8945a0SNathan Whitehorn     } else {
18834c8945a0SNathan Whitehorn 	/*
18844c8945a0SNathan Whitehorn 	 * Just in case of using --input-fd option, do not
18854c8945a0SNathan Whitehorn 	 * call atexit functions of ncurses which may hang.
18864c8945a0SNathan Whitehorn 	 */
18874c8945a0SNathan Whitehorn 	if (dialog_state.input) {
18884c8945a0SNathan Whitehorn 	    fclose(dialog_state.input);
18894c8945a0SNathan Whitehorn 	    dialog_state.input = 0;
18904c8945a0SNathan Whitehorn 	}
18914c8945a0SNathan Whitehorn 	if (dialog_state.pipe_input) {
18924c8945a0SNathan Whitehorn 	    if (dialog_state.pipe_input != stdin) {
18934c8945a0SNathan Whitehorn 		fclose(dialog_state.pipe_input);
18944c8945a0SNathan Whitehorn 		dialog_state.pipe_input = 0;
18954c8945a0SNathan Whitehorn 	    }
18964c8945a0SNathan Whitehorn 	}
18974c8945a0SNathan Whitehorn 	_exit(code);
18984c8945a0SNathan Whitehorn     }
18994c8945a0SNathan Whitehorn }
19004c8945a0SNathan Whitehorn 
1901*a96ef450SBaptiste Daroussin #define DATA(name) { DLG_EXIT_ ## name, #name }
1902*a96ef450SBaptiste Daroussin /* *INDENT-OFF* */
1903*a96ef450SBaptiste Daroussin static struct {
1904*a96ef450SBaptiste Daroussin     int code;
1905*a96ef450SBaptiste Daroussin     const char *name;
1906*a96ef450SBaptiste Daroussin } exit_codenames[] = {
1907*a96ef450SBaptiste Daroussin     DATA(ESC),
1908*a96ef450SBaptiste Daroussin     DATA(UNKNOWN),
1909*a96ef450SBaptiste Daroussin     DATA(ERROR),
1910*a96ef450SBaptiste Daroussin     DATA(OK),
1911*a96ef450SBaptiste Daroussin     DATA(CANCEL),
1912*a96ef450SBaptiste Daroussin     DATA(HELP),
1913*a96ef450SBaptiste Daroussin     DATA(EXTRA),
1914*a96ef450SBaptiste Daroussin     DATA(ITEM_HELP),
1915*a96ef450SBaptiste Daroussin };
1916*a96ef450SBaptiste Daroussin #undef DATA
1917*a96ef450SBaptiste Daroussin /* *INDENT-ON* */
1918*a96ef450SBaptiste Daroussin 
1919*a96ef450SBaptiste Daroussin const char *
1920*a96ef450SBaptiste Daroussin dlg_exitcode2s(int code)
1921*a96ef450SBaptiste Daroussin {
1922*a96ef450SBaptiste Daroussin     const char *result = "?";
1923*a96ef450SBaptiste Daroussin     size_t n;
1924*a96ef450SBaptiste Daroussin 
1925*a96ef450SBaptiste Daroussin     for (n = 0; n < TableSize(exit_codenames); ++n) {
1926*a96ef450SBaptiste Daroussin 	if (exit_codenames[n].code == code) {
1927*a96ef450SBaptiste Daroussin 	    result = exit_codenames[n].name;
1928*a96ef450SBaptiste Daroussin 	    break;
1929*a96ef450SBaptiste Daroussin 	}
1930*a96ef450SBaptiste Daroussin     }
1931*a96ef450SBaptiste Daroussin     return result;
1932*a96ef450SBaptiste Daroussin }
1933*a96ef450SBaptiste Daroussin 
1934*a96ef450SBaptiste Daroussin int
1935*a96ef450SBaptiste Daroussin dlg_exitname2n(const char *name)
1936*a96ef450SBaptiste Daroussin {
1937*a96ef450SBaptiste Daroussin     int result = DLG_EXIT_UNKNOWN;
1938*a96ef450SBaptiste Daroussin     size_t n;
1939*a96ef450SBaptiste Daroussin 
1940*a96ef450SBaptiste Daroussin     for (n = 0; n < TableSize(exit_codenames); ++n) {
1941*a96ef450SBaptiste Daroussin 	if (!dlg_strcmp(exit_codenames[n].name, name)) {
1942*a96ef450SBaptiste Daroussin 	    result = exit_codenames[n].code;
1943*a96ef450SBaptiste Daroussin 	    break;
1944*a96ef450SBaptiste Daroussin 	}
1945*a96ef450SBaptiste Daroussin     }
1946*a96ef450SBaptiste Daroussin     return result;
1947*a96ef450SBaptiste Daroussin }
1948*a96ef450SBaptiste Daroussin 
19494c8945a0SNathan Whitehorn /* quit program killing all tailbg */
19504c8945a0SNathan Whitehorn void
19514c8945a0SNathan Whitehorn dlg_exiterr(const char *fmt, ...)
19524c8945a0SNathan Whitehorn {
19534c8945a0SNathan Whitehorn     int retval;
19544c8945a0SNathan Whitehorn     va_list ap;
19554c8945a0SNathan Whitehorn 
19564c8945a0SNathan Whitehorn     end_dialog();
19574c8945a0SNathan Whitehorn 
19584c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
19594c8945a0SNathan Whitehorn     va_start(ap, fmt);
19604c8945a0SNathan Whitehorn     (void) vfprintf(stderr, fmt, ap);
19614c8945a0SNathan Whitehorn     va_end(ap);
19624c8945a0SNathan Whitehorn     (void) fputc('\n', stderr);
19634c8945a0SNathan Whitehorn 
1964*a96ef450SBaptiste Daroussin #ifdef HAVE_DLG_TRACE
1965*a96ef450SBaptiste Daroussin     va_start(ap, fmt);
1966*a96ef450SBaptiste Daroussin     dlg_trace_msg("## Error: ");
1967*a96ef450SBaptiste Daroussin     dlg_trace_va_msg(fmt, ap);
1968*a96ef450SBaptiste Daroussin     va_end(ap);
1969*a96ef450SBaptiste Daroussin #endif
1970*a96ef450SBaptiste Daroussin 
19714c8945a0SNathan Whitehorn     dlg_killall_bg(&retval);
19724c8945a0SNathan Whitehorn 
19734c8945a0SNathan Whitehorn     (void) fflush(stderr);
19744c8945a0SNathan Whitehorn     (void) fflush(stdout);
1975*a96ef450SBaptiste Daroussin     dlg_exit(strcmp(fmt, "timeout") == 0 ? DLG_EXIT_TIMEOUT : DLG_EXIT_ERROR);
1976*a96ef450SBaptiste Daroussin }
1977*a96ef450SBaptiste Daroussin 
1978*a96ef450SBaptiste Daroussin /*
1979*a96ef450SBaptiste Daroussin  * Get a string from the environment, rejecting those which are entirely blank.
1980*a96ef450SBaptiste Daroussin  */
1981*a96ef450SBaptiste Daroussin char *
1982*a96ef450SBaptiste Daroussin dlg_getenv_str(const char *name)
1983*a96ef450SBaptiste Daroussin {
1984*a96ef450SBaptiste Daroussin     char *result = getenv(name);
1985*a96ef450SBaptiste Daroussin     if (result != NULL) {
1986*a96ef450SBaptiste Daroussin 	while (*result != '\0' && isspace(UCH(*result)))
1987*a96ef450SBaptiste Daroussin 	    ++result;
1988*a96ef450SBaptiste Daroussin 	if (*result == '\0')
1989*a96ef450SBaptiste Daroussin 	    result = NULL;
1990*a96ef450SBaptiste Daroussin     }
1991*a96ef450SBaptiste Daroussin     return result;
1992*a96ef450SBaptiste Daroussin }
1993*a96ef450SBaptiste Daroussin 
1994*a96ef450SBaptiste Daroussin /*
1995*a96ef450SBaptiste Daroussin  * Get a number from the environment:
1996*a96ef450SBaptiste Daroussin  * + If the caller provides a pointer in the second parameter, return
1997*a96ef450SBaptiste Daroussin  *   success/failure for the function return, and the actual value via the
1998*a96ef450SBaptiste Daroussin  *   pointer.  Use this for decoding arbitrary numbers, e.g., negative or zero.
1999*a96ef450SBaptiste Daroussin  * + If the caller does not provide a pointer, return the decoded value for
2000*a96ef450SBaptiste Daroussin  *   the function-return.  Use this when only values greater than zero are
2001*a96ef450SBaptiste Daroussin  *   useful.
2002*a96ef450SBaptiste Daroussin  */
2003*a96ef450SBaptiste Daroussin int
2004*a96ef450SBaptiste Daroussin dlg_getenv_num(const char *name, int *value)
2005*a96ef450SBaptiste Daroussin {
2006*a96ef450SBaptiste Daroussin     int result = 0;
2007*a96ef450SBaptiste Daroussin     char *data = getenv(name);
2008*a96ef450SBaptiste Daroussin     if (data != NULL) {
2009*a96ef450SBaptiste Daroussin 	char *temp = NULL;
2010*a96ef450SBaptiste Daroussin 	long check = strtol(data, &temp, 0);
2011*a96ef450SBaptiste Daroussin 	if (temp != 0 && temp != data && *temp == '\0') {
2012*a96ef450SBaptiste Daroussin 	    result = (int) check;
2013*a96ef450SBaptiste Daroussin 	    if (value != NULL) {
2014*a96ef450SBaptiste Daroussin 		*value = result;
2015*a96ef450SBaptiste Daroussin 		result = 1;
2016*a96ef450SBaptiste Daroussin 	    }
2017*a96ef450SBaptiste Daroussin 	}
2018*a96ef450SBaptiste Daroussin     }
2019*a96ef450SBaptiste Daroussin     return result;
20204c8945a0SNathan Whitehorn }
20214c8945a0SNathan Whitehorn 
20224c8945a0SNathan Whitehorn void
20234c8945a0SNathan Whitehorn dlg_beeping(void)
20244c8945a0SNathan Whitehorn {
20254c8945a0SNathan Whitehorn     if (dialog_vars.beep_signal) {
20264c8945a0SNathan Whitehorn 	(void) beep();
20274c8945a0SNathan Whitehorn 	dialog_vars.beep_signal = 0;
20284c8945a0SNathan Whitehorn     }
20294c8945a0SNathan Whitehorn }
20304c8945a0SNathan Whitehorn 
20314c8945a0SNathan Whitehorn void
20324c8945a0SNathan Whitehorn dlg_print_size(int height, int width)
20334c8945a0SNathan Whitehorn {
2034f4f33ea0SBaptiste Daroussin     if (dialog_vars.print_siz) {
20354c8945a0SNathan Whitehorn 	fprintf(dialog_state.output, "Size: %d, %d\n", height, width);
2036f4f33ea0SBaptiste Daroussin 	DLG_TRACE(("# print size: %dx%d\n", height, width));
2037f4f33ea0SBaptiste Daroussin     }
20384c8945a0SNathan Whitehorn }
20394c8945a0SNathan Whitehorn 
20404c8945a0SNathan Whitehorn void
20414c8945a0SNathan Whitehorn dlg_ctl_size(int height, int width)
20424c8945a0SNathan Whitehorn {
20434c8945a0SNathan Whitehorn     if (dialog_vars.size_err) {
20444c8945a0SNathan Whitehorn 	if ((width > COLS) || (height > LINES)) {
20454c8945a0SNathan Whitehorn 	    dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
20464c8945a0SNathan Whitehorn 			height, width, LINES, COLS);
20474c8945a0SNathan Whitehorn 	}
20484c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
20494c8945a0SNathan Whitehorn 	else if ((dialog_state.use_shadow)
20504c8945a0SNathan Whitehorn 		 && ((width > SCOLS || height > SLINES))) {
20514c8945a0SNathan Whitehorn 	    if ((width <= COLS) && (height <= LINES)) {
20524c8945a0SNathan Whitehorn 		/* try again, without shadows */
20534c8945a0SNathan Whitehorn 		dialog_state.use_shadow = 0;
20544c8945a0SNathan Whitehorn 	    } else {
20554c8945a0SNathan Whitehorn 		dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
20564c8945a0SNathan Whitehorn 			    height, width, SLINES, SCOLS);
20574c8945a0SNathan Whitehorn 	    }
20584c8945a0SNathan Whitehorn 	}
20594c8945a0SNathan Whitehorn #endif
20604c8945a0SNathan Whitehorn     }
20614c8945a0SNathan Whitehorn }
20624c8945a0SNathan Whitehorn 
20634c8945a0SNathan Whitehorn /*
20644c8945a0SNathan Whitehorn  * If the --tab-correct was not selected, convert tabs to single spaces.
20654c8945a0SNathan Whitehorn  */
20664c8945a0SNathan Whitehorn void
20674c8945a0SNathan Whitehorn dlg_tab_correct_str(char *prompt)
20684c8945a0SNathan Whitehorn {
20694c8945a0SNathan Whitehorn     char *ptr;
20704c8945a0SNathan Whitehorn 
20714c8945a0SNathan Whitehorn     if (dialog_vars.tab_correct) {
20724c8945a0SNathan Whitehorn 	while ((ptr = strchr(prompt, TAB)) != NULL) {
20734c8945a0SNathan Whitehorn 	    *ptr = ' ';
20744c8945a0SNathan Whitehorn 	    prompt = ptr;
20754c8945a0SNathan Whitehorn 	}
20764c8945a0SNathan Whitehorn     }
20774c8945a0SNathan Whitehorn }
20784c8945a0SNathan Whitehorn 
20794c8945a0SNathan Whitehorn void
20804c8945a0SNathan Whitehorn dlg_calc_listh(int *height, int *list_height, int item_no)
20814c8945a0SNathan Whitehorn {
20824c8945a0SNathan Whitehorn     /* calculate new height and list_height */
20834c8945a0SNathan Whitehorn     int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
20844c8945a0SNathan Whitehorn     if (rows - (*height) > 0) {
20854c8945a0SNathan Whitehorn 	if (rows - (*height) > item_no)
20864c8945a0SNathan Whitehorn 	    *list_height = item_no;
20874c8945a0SNathan Whitehorn 	else
20884c8945a0SNathan Whitehorn 	    *list_height = rows - (*height);
20894c8945a0SNathan Whitehorn     }
20904c8945a0SNathan Whitehorn     (*height) += (*list_height);
20914c8945a0SNathan Whitehorn }
20924c8945a0SNathan Whitehorn 
20934c8945a0SNathan Whitehorn /* obsolete */
20944c8945a0SNathan Whitehorn int
20954c8945a0SNathan Whitehorn dlg_calc_listw(int item_no, char **items, int group)
20964c8945a0SNathan Whitehorn {
2097*a96ef450SBaptiste Daroussin     int i, len1 = 0, len2 = 0;
2098*a96ef450SBaptiste Daroussin 
20994c8945a0SNathan Whitehorn     for (i = 0; i < (item_no * group); i += group) {
2100*a96ef450SBaptiste Daroussin 	int n;
2101*a96ef450SBaptiste Daroussin 
21024c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i])) > len1)
21034c8945a0SNathan Whitehorn 	    len1 = n;
21044c8945a0SNathan Whitehorn 	if ((n = dlg_count_columns(items[i + 1])) > len2)
21054c8945a0SNathan Whitehorn 	    len2 = n;
21064c8945a0SNathan Whitehorn     }
21074c8945a0SNathan Whitehorn     return len1 + len2;
21084c8945a0SNathan Whitehorn }
21094c8945a0SNathan Whitehorn 
21104c8945a0SNathan Whitehorn int
21114c8945a0SNathan Whitehorn dlg_calc_list_width(int item_no, DIALOG_LISTITEM * items)
21124c8945a0SNathan Whitehorn {
21134c8945a0SNathan Whitehorn     int n, i, len1 = 0, len2 = 0;
21142a3e3873SBaptiste Daroussin     int bits = ((dialog_vars.no_tags ? 1 : 0)
21152a3e3873SBaptiste Daroussin 		+ (dialog_vars.no_items ? 2 : 0));
21162a3e3873SBaptiste Daroussin 
21174c8945a0SNathan Whitehorn     for (i = 0; i < item_no; ++i) {
21182a3e3873SBaptiste Daroussin 	switch (bits) {
21192a3e3873SBaptiste Daroussin 	case 0:
21202a3e3873SBaptiste Daroussin 	    /* FALLTHRU */
21212a3e3873SBaptiste Daroussin 	case 1:
21224c8945a0SNathan Whitehorn 	    if ((n = dlg_count_columns(items[i].name)) > len1)
21234c8945a0SNathan Whitehorn 		len1 = n;
21244c8945a0SNathan Whitehorn 	    if ((n = dlg_count_columns(items[i].text)) > len2)
21254c8945a0SNathan Whitehorn 		len2 = n;
21262a3e3873SBaptiste Daroussin 	    break;
21272a3e3873SBaptiste Daroussin 	case 2:
21282a3e3873SBaptiste Daroussin 	    /* FALLTHRU */
21292a3e3873SBaptiste Daroussin 	case 3:
21302a3e3873SBaptiste Daroussin 	    if ((n = dlg_count_columns(items[i].name)) > len1)
21312a3e3873SBaptiste Daroussin 		len1 = n;
21322a3e3873SBaptiste Daroussin 	    break;
21332a3e3873SBaptiste Daroussin 	}
21344c8945a0SNathan Whitehorn     }
21354c8945a0SNathan Whitehorn     return len1 + len2;
21364c8945a0SNathan Whitehorn }
21374c8945a0SNathan Whitehorn 
21384c8945a0SNathan Whitehorn char *
21394c8945a0SNathan Whitehorn dlg_strempty(void)
21404c8945a0SNathan Whitehorn {
21414c8945a0SNathan Whitehorn     static char empty[] = "";
21424c8945a0SNathan Whitehorn     return empty;
21434c8945a0SNathan Whitehorn }
21444c8945a0SNathan Whitehorn 
21454c8945a0SNathan Whitehorn char *
21464c8945a0SNathan Whitehorn dlg_strclone(const char *cprompt)
21474c8945a0SNathan Whitehorn {
2148f4f33ea0SBaptiste Daroussin     char *prompt = 0;
2149f4f33ea0SBaptiste Daroussin     if (cprompt != 0) {
2150f4f33ea0SBaptiste Daroussin 	prompt = dlg_malloc(char, strlen(cprompt) + 1);
21514c8945a0SNathan Whitehorn 	assert_ptr(prompt, "dlg_strclone");
21524c8945a0SNathan Whitehorn 	strcpy(prompt, cprompt);
2153f4f33ea0SBaptiste Daroussin     }
21544c8945a0SNathan Whitehorn     return prompt;
21554c8945a0SNathan Whitehorn }
21564c8945a0SNathan Whitehorn 
21574c8945a0SNathan Whitehorn chtype
21584c8945a0SNathan Whitehorn dlg_asciibox(chtype ch)
21594c8945a0SNathan Whitehorn {
21604c8945a0SNathan Whitehorn     chtype result = 0;
21614c8945a0SNathan Whitehorn 
21624c8945a0SNathan Whitehorn     if (ch == ACS_ULCORNER)
21634c8945a0SNathan Whitehorn 	result = '+';
21644c8945a0SNathan Whitehorn     else if (ch == ACS_LLCORNER)
21654c8945a0SNathan Whitehorn 	result = '+';
21664c8945a0SNathan Whitehorn     else if (ch == ACS_URCORNER)
21674c8945a0SNathan Whitehorn 	result = '+';
21684c8945a0SNathan Whitehorn     else if (ch == ACS_LRCORNER)
21694c8945a0SNathan Whitehorn 	result = '+';
21704c8945a0SNathan Whitehorn     else if (ch == ACS_HLINE)
21714c8945a0SNathan Whitehorn 	result = '-';
21724c8945a0SNathan Whitehorn     else if (ch == ACS_VLINE)
21734c8945a0SNathan Whitehorn 	result = '|';
21744c8945a0SNathan Whitehorn     else if (ch == ACS_LTEE)
21754c8945a0SNathan Whitehorn 	result = '+';
21764c8945a0SNathan Whitehorn     else if (ch == ACS_RTEE)
21774c8945a0SNathan Whitehorn 	result = '+';
21784c8945a0SNathan Whitehorn     else if (ch == ACS_UARROW)
21794c8945a0SNathan Whitehorn 	result = '^';
21804c8945a0SNathan Whitehorn     else if (ch == ACS_DARROW)
21814c8945a0SNathan Whitehorn 	result = 'v';
21824c8945a0SNathan Whitehorn 
21834c8945a0SNathan Whitehorn     return result;
21844c8945a0SNathan Whitehorn }
21854c8945a0SNathan Whitehorn 
21864c8945a0SNathan Whitehorn chtype
21874c8945a0SNathan Whitehorn dlg_boxchar(chtype ch)
21884c8945a0SNathan Whitehorn {
21894c8945a0SNathan Whitehorn     chtype result = dlg_asciibox(ch);
21904c8945a0SNathan Whitehorn 
21914c8945a0SNathan Whitehorn     if (result != 0) {
21924c8945a0SNathan Whitehorn 	if (dialog_vars.ascii_lines)
21934c8945a0SNathan Whitehorn 	    ch = result;
21944c8945a0SNathan Whitehorn 	else if (dialog_vars.no_lines)
21954c8945a0SNathan Whitehorn 	    ch = ' ';
21964c8945a0SNathan Whitehorn     }
21974c8945a0SNathan Whitehorn     return ch;
21984c8945a0SNathan Whitehorn }
21994c8945a0SNathan Whitehorn 
22004c8945a0SNathan Whitehorn int
22014c8945a0SNathan Whitehorn dlg_box_x_ordinate(int width)
22024c8945a0SNathan Whitehorn {
22034c8945a0SNathan Whitehorn     int x;
22044c8945a0SNathan Whitehorn 
22054c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
22064c8945a0SNathan Whitehorn 	x = dialog_vars.begin_x;
22074c8945a0SNathan Whitehorn     } else {
22084c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
22094c8945a0SNathan Whitehorn 	x = (SCOLS - width) / 2;
22104c8945a0SNathan Whitehorn     }
22114c8945a0SNathan Whitehorn     return x;
22124c8945a0SNathan Whitehorn }
22134c8945a0SNathan Whitehorn 
22144c8945a0SNathan Whitehorn int
22154c8945a0SNathan Whitehorn dlg_box_y_ordinate(int height)
22164c8945a0SNathan Whitehorn {
22174c8945a0SNathan Whitehorn     int y;
22184c8945a0SNathan Whitehorn 
22194c8945a0SNathan Whitehorn     if (dialog_vars.begin_set == 1) {
22204c8945a0SNathan Whitehorn 	y = dialog_vars.begin_y;
22214c8945a0SNathan Whitehorn     } else {
22224c8945a0SNathan Whitehorn 	/* center dialog box on screen unless --begin-set */
22234c8945a0SNathan Whitehorn 	y = (SLINES - height) / 2;
22244c8945a0SNathan Whitehorn     }
22254c8945a0SNathan Whitehorn     return y;
22264c8945a0SNathan Whitehorn }
22274c8945a0SNathan Whitehorn 
22284c8945a0SNathan Whitehorn void
22294c8945a0SNathan Whitehorn dlg_draw_title(WINDOW *win, const char *title)
22304c8945a0SNathan Whitehorn {
22314c8945a0SNathan Whitehorn     if (title != NULL) {
22324c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
22337a1c0d96SNathan Whitehorn 	chtype save = dlg_get_attrs(win);
22344c8945a0SNathan Whitehorn 	int x = centered(getmaxx(win), title);
22354c8945a0SNathan Whitehorn 
2236f4f33ea0SBaptiste Daroussin 	dlg_attrset(win, title_attr);
22374c8945a0SNathan Whitehorn 	wmove(win, 0, x);
22384c8945a0SNathan Whitehorn 	dlg_print_text(win, title, getmaxx(win) - x, &attr);
2239f4f33ea0SBaptiste Daroussin 	dlg_attrset(win, save);
2240febdb468SDevin Teske 	dlg_finish_string(title);
22414c8945a0SNathan Whitehorn     }
22424c8945a0SNathan Whitehorn }
22434c8945a0SNathan Whitehorn 
22444c8945a0SNathan Whitehorn void
22452a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(WINDOW *win, chtype on_left, chtype on_right, chtype on_inside)
22464c8945a0SNathan Whitehorn {
22474c8945a0SNathan Whitehorn     int width = getmaxx(win);
22484c8945a0SNathan Whitehorn     int height = getmaxy(win);
22494c8945a0SNathan Whitehorn     int i;
22504c8945a0SNathan Whitehorn 
2251f4f33ea0SBaptiste Daroussin     dlg_attrset(win, on_left);
22524c8945a0SNathan Whitehorn     (void) wmove(win, height - 3, 0);
22534c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_LTEE));
22544c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
22554c8945a0SNathan Whitehorn 	(void) waddch(win, dlg_boxchar(ACS_HLINE));
2256f4f33ea0SBaptiste Daroussin     dlg_attrset(win, on_right);
22574c8945a0SNathan Whitehorn     (void) waddch(win, dlg_boxchar(ACS_RTEE));
2258f4f33ea0SBaptiste Daroussin     dlg_attrset(win, on_inside);
22594c8945a0SNathan Whitehorn     (void) wmove(win, height - 2, 1);
22604c8945a0SNathan Whitehorn     for (i = 0; i < width - 2; i++)
22614c8945a0SNathan Whitehorn 	(void) waddch(win, ' ');
22624c8945a0SNathan Whitehorn }
22634c8945a0SNathan Whitehorn 
22642a3e3873SBaptiste Daroussin void
22652a3e3873SBaptiste Daroussin dlg_draw_bottom_box(WINDOW *win)
22662a3e3873SBaptiste Daroussin {
22672a3e3873SBaptiste Daroussin     dlg_draw_bottom_box2(win, border_attr, dialog_attr, dialog_attr);
22682a3e3873SBaptiste Daroussin }
22692a3e3873SBaptiste Daroussin 
22704c8945a0SNathan Whitehorn /*
22714c8945a0SNathan Whitehorn  * Remove a window, repainting everything else.  This would be simpler if we
22724c8945a0SNathan Whitehorn  * used the panel library, but that is not _always_ available.
22734c8945a0SNathan Whitehorn  */
22744c8945a0SNathan Whitehorn void
22754c8945a0SNathan Whitehorn dlg_del_window(WINDOW *win)
22764c8945a0SNathan Whitehorn {
22774c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p, *q, *r;
22784c8945a0SNathan Whitehorn 
22794c8945a0SNathan Whitehorn     /*
22804c8945a0SNathan Whitehorn      * If --keep-window was set, do not delete/repaint the windows.
22814c8945a0SNathan Whitehorn      */
22824c8945a0SNathan Whitehorn     if (dialog_vars.keep_window)
22834c8945a0SNathan Whitehorn 	return;
22844c8945a0SNathan Whitehorn 
22854c8945a0SNathan Whitehorn     /* Leave the main window untouched if there are no background windows.
22864c8945a0SNathan Whitehorn      * We do this so the current window will not be cleared on exit, allowing
22874c8945a0SNathan Whitehorn      * things like the infobox demo to run without flicker.
22884c8945a0SNathan Whitehorn      */
22894c8945a0SNathan Whitehorn     if (dialog_state.getc_callbacks != 0) {
22904c8945a0SNathan Whitehorn 	touchwin(stdscr);
22914c8945a0SNathan Whitehorn 	wnoutrefresh(stdscr);
22924c8945a0SNathan Whitehorn     }
22934c8945a0SNathan Whitehorn 
22944c8945a0SNathan Whitehorn     for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) {
22954c8945a0SNathan Whitehorn 	if (p->normal == win) {
22964c8945a0SNathan Whitehorn 	    q = p;		/* found a match - should be only one */
22974c8945a0SNathan Whitehorn 	    if (r == 0) {
22984c8945a0SNathan Whitehorn 		dialog_state.all_windows = p->next;
22994c8945a0SNathan Whitehorn 	    } else {
23004c8945a0SNathan Whitehorn 		r->next = p->next;
23014c8945a0SNathan Whitehorn 	    }
23024c8945a0SNathan Whitehorn 	} else {
23034c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
23044c8945a0SNathan Whitehorn 		touchwin(p->shadow);
23054c8945a0SNathan Whitehorn 		wnoutrefresh(p->shadow);
23064c8945a0SNathan Whitehorn 	    }
23074c8945a0SNathan Whitehorn 	    touchwin(p->normal);
23084c8945a0SNathan Whitehorn 	    wnoutrefresh(p->normal);
23094c8945a0SNathan Whitehorn 	}
23104c8945a0SNathan Whitehorn     }
23114c8945a0SNathan Whitehorn 
23124c8945a0SNathan Whitehorn     if (q) {
2313682c9e0fSNathan Whitehorn 	if (dialog_state.all_windows != 0)
2314682c9e0fSNathan Whitehorn 	    erase_childs_shadow(q);
23152a3e3873SBaptiste Daroussin 	del_subwindows(q->normal);
23164c8945a0SNathan Whitehorn 	dlg_unregister_window(q->normal);
23172a3e3873SBaptiste Daroussin 	delwin(q->normal);
23184c8945a0SNathan Whitehorn 	free(q);
23194c8945a0SNathan Whitehorn     }
23204c8945a0SNathan Whitehorn     doupdate();
23214c8945a0SNathan Whitehorn }
23224c8945a0SNathan Whitehorn 
23234c8945a0SNathan Whitehorn /*
23244c8945a0SNathan Whitehorn  * Create a window, optionally with a shadow.
23254c8945a0SNathan Whitehorn  */
23264c8945a0SNathan Whitehorn WINDOW *
23274c8945a0SNathan Whitehorn dlg_new_window(int height, int width, int y, int x)
23284c8945a0SNathan Whitehorn {
2329682c9e0fSNathan Whitehorn     return dlg_new_modal_window(stdscr, height, width, y, x);
23304c8945a0SNathan Whitehorn }
23314c8945a0SNathan Whitehorn 
2332682c9e0fSNathan Whitehorn /*
2333682c9e0fSNathan Whitehorn  * "Modal" windows differ from normal ones by having a shadow in a window
2334682c9e0fSNathan Whitehorn  * separate from the standard screen.
2335682c9e0fSNathan Whitehorn  */
23364c8945a0SNathan Whitehorn WINDOW *
23374c8945a0SNathan Whitehorn dlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x)
23384c8945a0SNathan Whitehorn {
23394c8945a0SNathan Whitehorn     WINDOW *win;
23404c8945a0SNathan Whitehorn     DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
23414c8945a0SNathan Whitehorn 
23424c8945a0SNathan Whitehorn     (void) parent;
23432a3e3873SBaptiste Daroussin     if (p == 0
23442a3e3873SBaptiste Daroussin 	|| (win = newwin(height, width, y, x)) == 0) {
23454c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
23464c8945a0SNathan Whitehorn 		    y, x, height, width);
23474c8945a0SNathan Whitehorn     }
23484c8945a0SNathan Whitehorn     p->next = dialog_state.all_windows;
23494c8945a0SNathan Whitehorn     p->normal = win;
2350*a96ef450SBaptiste Daroussin     p->getc_timeout = WTIMEOUT_OFF;
23514c8945a0SNathan Whitehorn     dialog_state.all_windows = p;
23524c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
23534c8945a0SNathan Whitehorn     if (dialog_state.use_shadow) {
2354682c9e0fSNathan Whitehorn 	p->shadow = parent;
2355682c9e0fSNathan Whitehorn 	draw_childs_shadow(p);
23564c8945a0SNathan Whitehorn     }
23574c8945a0SNathan Whitehorn #endif
23584c8945a0SNathan Whitehorn 
23594c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
23604c8945a0SNathan Whitehorn     return win;
23614c8945a0SNathan Whitehorn }
23624c8945a0SNathan Whitehorn 
23634c8945a0SNathan Whitehorn /*
2364*a96ef450SBaptiste Daroussin  * dlg_getc() uses the return-value to determine how to handle an ERR return
2365*a96ef450SBaptiste Daroussin  * from a non-blocking read:
2366*a96ef450SBaptiste Daroussin  * a) if greater than zero, there was an expired timeout (blocking for a short
2367*a96ef450SBaptiste Daroussin  *    time), or
2368*a96ef450SBaptiste Daroussin  * b) if zero, it was a non-blocking read, or
2369*a96ef450SBaptiste Daroussin  * c) if negative, an error occurred on a blocking read.
2370*a96ef450SBaptiste Daroussin  */
2371*a96ef450SBaptiste Daroussin int
2372*a96ef450SBaptiste Daroussin dlg_set_timeout(WINDOW *win, bool will_getc)
2373*a96ef450SBaptiste Daroussin {
2374*a96ef450SBaptiste Daroussin     DIALOG_WINDOWS *p;
2375*a96ef450SBaptiste Daroussin     int result = 0;
2376*a96ef450SBaptiste Daroussin 
2377*a96ef450SBaptiste Daroussin     if ((p = SearchTopWindows(win)) != NULL) {
2378*a96ef450SBaptiste Daroussin 	int interval = (dialog_vars.timeout_secs * 1000);
2379*a96ef450SBaptiste Daroussin 
2380*a96ef450SBaptiste Daroussin 	if (will_getc || dialog_vars.pause_secs) {
2381*a96ef450SBaptiste Daroussin 	    interval = WTIMEOUT_VAL;
2382*a96ef450SBaptiste Daroussin 	} else {
2383*a96ef450SBaptiste Daroussin 	    result = interval;
2384*a96ef450SBaptiste Daroussin 	    if (interval <= 0) {
2385*a96ef450SBaptiste Daroussin 		interval = WTIMEOUT_OFF;
2386*a96ef450SBaptiste Daroussin 	    }
2387*a96ef450SBaptiste Daroussin 	}
2388*a96ef450SBaptiste Daroussin 	wtimeout(win, interval);
2389*a96ef450SBaptiste Daroussin 	p->getc_timeout = interval;
2390*a96ef450SBaptiste Daroussin     }
2391*a96ef450SBaptiste Daroussin     return result;
2392*a96ef450SBaptiste Daroussin }
2393*a96ef450SBaptiste Daroussin 
2394*a96ef450SBaptiste Daroussin void
2395*a96ef450SBaptiste Daroussin dlg_reset_timeout(WINDOW *win)
2396*a96ef450SBaptiste Daroussin {
2397*a96ef450SBaptiste Daroussin     DIALOG_WINDOWS *p;
2398*a96ef450SBaptiste Daroussin 
2399*a96ef450SBaptiste Daroussin     if ((p = SearchTopWindows(win)) != NULL) {
2400*a96ef450SBaptiste Daroussin 	wtimeout(win, p->getc_timeout);
2401*a96ef450SBaptiste Daroussin     } else {
2402*a96ef450SBaptiste Daroussin 	wtimeout(win, WTIMEOUT_OFF);
2403*a96ef450SBaptiste Daroussin     }
2404*a96ef450SBaptiste Daroussin }
2405*a96ef450SBaptiste Daroussin 
2406*a96ef450SBaptiste Daroussin /*
24074c8945a0SNathan Whitehorn  * Move/Resize a window, optionally with a shadow.
24084c8945a0SNathan Whitehorn  */
24094c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
24104c8945a0SNathan Whitehorn void
24114c8945a0SNathan Whitehorn dlg_move_window(WINDOW *win, int height, int width, int y, int x)
24124c8945a0SNathan Whitehorn {
2413*a96ef450SBaptiste Daroussin     if (win != 0) {
2414682c9e0fSNathan Whitehorn 	DIALOG_WINDOWS *p;
24154c8945a0SNathan Whitehorn 
24164c8945a0SNathan Whitehorn 	dlg_ctl_size(height, width);
24174c8945a0SNathan Whitehorn 
2418*a96ef450SBaptiste Daroussin 	if ((p = SearchTopWindows(win)) != 0) {
24194c8945a0SNathan Whitehorn 	    (void) wresize(win, height, width);
24204c8945a0SNathan Whitehorn 	    (void) mvwin(win, y, x);
24214c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
24224c8945a0SNathan Whitehorn 	    if (p->shadow != 0) {
24234c8945a0SNathan Whitehorn 		if (dialog_state.use_shadow) {
24244c8945a0SNathan Whitehorn 		    (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS);
24254c8945a0SNathan Whitehorn 		} else {
24264c8945a0SNathan Whitehorn 		    p->shadow = 0;
24274c8945a0SNathan Whitehorn 		}
24284c8945a0SNathan Whitehorn 	    }
24294c8945a0SNathan Whitehorn #endif
24304c8945a0SNathan Whitehorn 	    (void) refresh();
24314c8945a0SNathan Whitehorn 
24324c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
2433682c9e0fSNathan Whitehorn 	    draw_childs_shadow(p);
24344c8945a0SNathan Whitehorn #endif
24354c8945a0SNathan Whitehorn 	}
24364c8945a0SNathan Whitehorn     }
24374c8945a0SNathan Whitehorn }
2438f4f33ea0SBaptiste Daroussin 
2439f4f33ea0SBaptiste Daroussin /*
2440f4f33ea0SBaptiste Daroussin  * Having just received a KEY_RESIZE, wait a short time to ignore followup
2441f4f33ea0SBaptiste Daroussin  * KEY_RESIZE events.
2442f4f33ea0SBaptiste Daroussin  */
2443f4f33ea0SBaptiste Daroussin void
2444f4f33ea0SBaptiste Daroussin dlg_will_resize(WINDOW *win)
2445f4f33ea0SBaptiste Daroussin {
2446*a96ef450SBaptiste Daroussin     int n, base;
2447f4f33ea0SBaptiste Daroussin     int caught = 0;
2448f4f33ea0SBaptiste Daroussin 
2449*a96ef450SBaptiste Daroussin     dialog_state.had_resize = TRUE;
2450f4f33ea0SBaptiste Daroussin     dlg_trace_win(win);
2451*a96ef450SBaptiste Daroussin     wtimeout(win, WTIMEOUT_VAL * 5);
2452*a96ef450SBaptiste Daroussin 
2453f4f33ea0SBaptiste Daroussin     for (n = base = 0; n < base + 10; ++n) {
2454*a96ef450SBaptiste Daroussin 	int ch;
2455*a96ef450SBaptiste Daroussin 
2456f4f33ea0SBaptiste Daroussin 	if ((ch = wgetch(win)) != ERR) {
2457f4f33ea0SBaptiste Daroussin 	    if (ch == KEY_RESIZE) {
2458f4f33ea0SBaptiste Daroussin 		base = n;
2459f4f33ea0SBaptiste Daroussin 		++caught;
2460*a96ef450SBaptiste Daroussin 	    } else if (ch != ERR) {
2461f4f33ea0SBaptiste Daroussin 		ungetch(ch);
2462f4f33ea0SBaptiste Daroussin 		break;
2463f4f33ea0SBaptiste Daroussin 	    }
2464f4f33ea0SBaptiste Daroussin 	}
2465f4f33ea0SBaptiste Daroussin     }
2466*a96ef450SBaptiste Daroussin     dlg_reset_timeout(win);
2467*a96ef450SBaptiste Daroussin     DLG_TRACE(("# caught %d KEY_RESIZE key%s\n",
2468f4f33ea0SBaptiste Daroussin 	       1 + caught,
2469*a96ef450SBaptiste Daroussin 	       caught == 1 ? "" : "s"));
2470f4f33ea0SBaptiste Daroussin }
24714c8945a0SNathan Whitehorn #endif /* KEY_RESIZE */
24724c8945a0SNathan Whitehorn 
24734c8945a0SNathan Whitehorn WINDOW *
2474*a96ef450SBaptiste Daroussin dlg_der_window(WINDOW *parent, int height, int width, int y, int x)
2475*a96ef450SBaptiste Daroussin {
2476*a96ef450SBaptiste Daroussin     WINDOW *win;
2477*a96ef450SBaptiste Daroussin 
2478*a96ef450SBaptiste Daroussin     /* existing uses of derwin are (almost) guaranteed to succeed, and the
2479*a96ef450SBaptiste Daroussin      * caller has to allow for failure.
2480*a96ef450SBaptiste Daroussin      */
2481*a96ef450SBaptiste Daroussin     if ((win = derwin(parent, height, width, y, x)) != 0) {
2482*a96ef450SBaptiste Daroussin 	add_subwindow(parent, win);
2483*a96ef450SBaptiste Daroussin 	(void) keypad(win, TRUE);
2484*a96ef450SBaptiste Daroussin     }
2485*a96ef450SBaptiste Daroussin     return win;
2486*a96ef450SBaptiste Daroussin }
2487*a96ef450SBaptiste Daroussin 
2488*a96ef450SBaptiste Daroussin WINDOW *
24894c8945a0SNathan Whitehorn dlg_sub_window(WINDOW *parent, int height, int width, int y, int x)
24904c8945a0SNathan Whitehorn {
24914c8945a0SNathan Whitehorn     WINDOW *win;
24924c8945a0SNathan Whitehorn 
24934c8945a0SNathan Whitehorn     if ((win = subwin(parent, height, width, y, x)) == 0) {
24944c8945a0SNathan Whitehorn 	dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n",
24954c8945a0SNathan Whitehorn 		    y, x, height, width);
24964c8945a0SNathan Whitehorn     }
24974c8945a0SNathan Whitehorn 
24982a3e3873SBaptiste Daroussin     add_subwindow(parent, win);
24994c8945a0SNathan Whitehorn     (void) keypad(win, TRUE);
25004c8945a0SNathan Whitehorn     return win;
25014c8945a0SNathan Whitehorn }
25024c8945a0SNathan Whitehorn 
25034c8945a0SNathan Whitehorn /* obsolete */
25044c8945a0SNathan Whitehorn int
25054c8945a0SNathan Whitehorn dlg_default_item(char **items, int llen)
25064c8945a0SNathan Whitehorn {
25074c8945a0SNathan Whitehorn     int result = 0;
25084c8945a0SNathan Whitehorn 
25094c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
25104c8945a0SNathan Whitehorn 	int count = 0;
25114c8945a0SNathan Whitehorn 	while (*items != 0) {
25124c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, *items)) {
25134c8945a0SNathan Whitehorn 		result = count;
25144c8945a0SNathan Whitehorn 		break;
25154c8945a0SNathan Whitehorn 	    }
25164c8945a0SNathan Whitehorn 	    items += llen;
25174c8945a0SNathan Whitehorn 	    count++;
25184c8945a0SNathan Whitehorn 	}
25194c8945a0SNathan Whitehorn     }
25204c8945a0SNathan Whitehorn     return result;
25214c8945a0SNathan Whitehorn }
25224c8945a0SNathan Whitehorn 
25234c8945a0SNathan Whitehorn int
25244c8945a0SNathan Whitehorn dlg_default_listitem(DIALOG_LISTITEM * items)
25254c8945a0SNathan Whitehorn {
25264c8945a0SNathan Whitehorn     int result = 0;
25274c8945a0SNathan Whitehorn 
25284c8945a0SNathan Whitehorn     if (dialog_vars.default_item != 0) {
25294c8945a0SNathan Whitehorn 	int count = 0;
25304c8945a0SNathan Whitehorn 	while (items->name != 0) {
25314c8945a0SNathan Whitehorn 	    if (!strcmp(dialog_vars.default_item, items->name)) {
25324c8945a0SNathan Whitehorn 		result = count;
25334c8945a0SNathan Whitehorn 		break;
25344c8945a0SNathan Whitehorn 	    }
25354c8945a0SNathan Whitehorn 	    ++items;
25364c8945a0SNathan Whitehorn 	    count++;
25374c8945a0SNathan Whitehorn 	}
25384c8945a0SNathan Whitehorn     }
25394c8945a0SNathan Whitehorn     return result;
25404c8945a0SNathan Whitehorn }
25414c8945a0SNathan Whitehorn 
25424c8945a0SNathan Whitehorn /*
25434c8945a0SNathan Whitehorn  * Draw the string for item_help
25444c8945a0SNathan Whitehorn  */
25454c8945a0SNathan Whitehorn void
25464c8945a0SNathan Whitehorn dlg_item_help(const char *txt)
25474c8945a0SNathan Whitehorn {
25484c8945a0SNathan Whitehorn     if (USE_ITEM_HELP(txt)) {
25494c8945a0SNathan Whitehorn 	chtype attr = A_NORMAL;
25504c8945a0SNathan Whitehorn 
2551f4f33ea0SBaptiste Daroussin 	dlg_attrset(stdscr, itemhelp_attr);
25524c8945a0SNathan Whitehorn 	(void) wmove(stdscr, LINES - 1, 0);
25534c8945a0SNathan Whitehorn 	(void) wclrtoeol(stdscr);
25544c8945a0SNathan Whitehorn 	(void) addch(' ');
25554c8945a0SNathan Whitehorn 	dlg_print_text(stdscr, txt, COLS - 1, &attr);
2556*a96ef450SBaptiste Daroussin 
25574c8945a0SNathan Whitehorn 	if (itemhelp_attr & A_COLOR) {
2558*a96ef450SBaptiste Daroussin 	    int y, x;
25594c8945a0SNathan Whitehorn 	    /* fill the remainder of the line with the window's attributes */
25604c8945a0SNathan Whitehorn 	    getyx(stdscr, y, x);
25612a3e3873SBaptiste Daroussin 	    (void) y;
25624c8945a0SNathan Whitehorn 	    while (x < COLS) {
25634c8945a0SNathan Whitehorn 		(void) addch(' ');
25644c8945a0SNathan Whitehorn 		++x;
25654c8945a0SNathan Whitehorn 	    }
25664c8945a0SNathan Whitehorn 	}
25674c8945a0SNathan Whitehorn 	(void) wnoutrefresh(stdscr);
25684c8945a0SNathan Whitehorn     }
25694c8945a0SNathan Whitehorn }
25704c8945a0SNathan Whitehorn 
25714c8945a0SNathan Whitehorn #ifndef HAVE_STRCASECMP
25724c8945a0SNathan Whitehorn int
25734c8945a0SNathan Whitehorn dlg_strcmp(const char *a, const char *b)
25744c8945a0SNathan Whitehorn {
25754c8945a0SNathan Whitehorn     int ac, bc, cmp;
25764c8945a0SNathan Whitehorn 
25774c8945a0SNathan Whitehorn     for (;;) {
25784c8945a0SNathan Whitehorn 	ac = UCH(*a++);
25794c8945a0SNathan Whitehorn 	bc = UCH(*b++);
25804c8945a0SNathan Whitehorn 	if (isalpha(ac) && islower(ac))
25814c8945a0SNathan Whitehorn 	    ac = _toupper(ac);
25824c8945a0SNathan Whitehorn 	if (isalpha(bc) && islower(bc))
25834c8945a0SNathan Whitehorn 	    bc = _toupper(bc);
25844c8945a0SNathan Whitehorn 	cmp = ac - bc;
25854c8945a0SNathan Whitehorn 	if (ac == 0 || bc == 0 || cmp != 0)
25864c8945a0SNathan Whitehorn 	    break;
25874c8945a0SNathan Whitehorn     }
25884c8945a0SNathan Whitehorn     return cmp;
25894c8945a0SNathan Whitehorn }
25904c8945a0SNathan Whitehorn #endif
25914c8945a0SNathan Whitehorn 
25924c8945a0SNathan Whitehorn /*
25934c8945a0SNathan Whitehorn  * Returns true if 'dst' points to a blank which follows another blank which
25944c8945a0SNathan Whitehorn  * is not a leading blank on a line.
25954c8945a0SNathan Whitehorn  */
25964c8945a0SNathan Whitehorn static bool
25974c8945a0SNathan Whitehorn trim_blank(char *base, char *dst)
25984c8945a0SNathan Whitehorn {
2599*a96ef450SBaptiste Daroussin     int count = !!isblank(UCH(*dst));
26004c8945a0SNathan Whitehorn 
26014c8945a0SNathan Whitehorn     while (dst-- != base) {
26024c8945a0SNathan Whitehorn 	if (*dst == '\n') {
2603f4f33ea0SBaptiste Daroussin 	    break;
2604f4f33ea0SBaptiste Daroussin 	} else if (isblank(UCH(*dst))) {
26054c8945a0SNathan Whitehorn 	    count++;
2606f4f33ea0SBaptiste Daroussin 	} else {
2607f4f33ea0SBaptiste Daroussin 	    break;
26084c8945a0SNathan Whitehorn 	}
26094c8945a0SNathan Whitehorn     }
2610f4f33ea0SBaptiste Daroussin     return (count > 1);
26114c8945a0SNathan Whitehorn }
26124c8945a0SNathan Whitehorn 
26134c8945a0SNathan Whitehorn /*
26144c8945a0SNathan Whitehorn  * Change embedded "\n" substrings to '\n' characters and tabs to single
26154c8945a0SNathan Whitehorn  * spaces.  If there are no "\n"s, it will strip all extra spaces, for
26164c8945a0SNathan Whitehorn  * justification.  If it has "\n"'s, it will preserve extra spaces.  If cr_wrap
26174c8945a0SNathan Whitehorn  * is set, it will preserve '\n's.
26184c8945a0SNathan Whitehorn  */
26194c8945a0SNathan Whitehorn void
26204c8945a0SNathan Whitehorn dlg_trim_string(char *s)
26214c8945a0SNathan Whitehorn {
26224c8945a0SNathan Whitehorn     char *base = s;
26234c8945a0SNathan Whitehorn     char *p1;
26244c8945a0SNathan Whitehorn     char *p = s;
2625682c9e0fSNathan Whitehorn     int has_newlines = !dialog_vars.no_nl_expand && (strstr(s, "\\n") != 0);
26264c8945a0SNathan Whitehorn 
26274c8945a0SNathan Whitehorn     while (*p != '\0') {
26284c8945a0SNathan Whitehorn 	if (*p == TAB && !dialog_vars.nocollapse)
26294c8945a0SNathan Whitehorn 	    *p = ' ';
26304c8945a0SNathan Whitehorn 
26314c8945a0SNathan Whitehorn 	if (has_newlines) {	/* If prompt contains "\n" strings */
26324c8945a0SNathan Whitehorn 	    if (*p == '\\' && *(p + 1) == 'n') {
26334c8945a0SNathan Whitehorn 		*s++ = '\n';
26344c8945a0SNathan Whitehorn 		p += 2;
26354c8945a0SNathan Whitehorn 		p1 = p;
26364c8945a0SNathan Whitehorn 		/*
26374c8945a0SNathan Whitehorn 		 * Handle end of lines intelligently.  If '\n' follows "\n"
26384c8945a0SNathan Whitehorn 		 * then ignore the '\n'.  This eliminates the need to escape
26394c8945a0SNathan Whitehorn 		 * the '\n' character (no need to use "\n\").
26404c8945a0SNathan Whitehorn 		 */
2641f4f33ea0SBaptiste Daroussin 		while (isblank(UCH(*p1)))
26424c8945a0SNathan Whitehorn 		    p1++;
26434c8945a0SNathan Whitehorn 		if (*p1 == '\n')
26444c8945a0SNathan Whitehorn 		    p = p1 + 1;
26454c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
26464c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
26474c8945a0SNathan Whitehorn 		    *s++ = *p++;
26484c8945a0SNathan Whitehorn 		else {
26494c8945a0SNathan Whitehorn 		    /* Replace the '\n' with a space if cr_wrap is not set */
2650f4f33ea0SBaptiste Daroussin 		    if (!trim_blank(base, p))
26514c8945a0SNathan Whitehorn 			*s++ = ' ';
26524c8945a0SNathan Whitehorn 		    p++;
26534c8945a0SNathan Whitehorn 		}
26544c8945a0SNathan Whitehorn 	    } else		/* If *p != '\n' */
26554c8945a0SNathan Whitehorn 		*s++ = *p++;
26564c8945a0SNathan Whitehorn 	} else if (dialog_vars.trim_whitespace) {
2657f4f33ea0SBaptiste Daroussin 	    if (isblank(UCH(*p))) {
2658f4f33ea0SBaptiste Daroussin 		if (!isblank(UCH(*(s - 1)))) {
26594c8945a0SNathan Whitehorn 		    *s++ = ' ';
26604c8945a0SNathan Whitehorn 		    p++;
26614c8945a0SNathan Whitehorn 		} else
26624c8945a0SNathan Whitehorn 		    p++;
26634c8945a0SNathan Whitehorn 	    } else if (*p == '\n') {
26644c8945a0SNathan Whitehorn 		if (dialog_vars.cr_wrap)
26654c8945a0SNathan Whitehorn 		    *s++ = *p++;
2666f4f33ea0SBaptiste Daroussin 		else if (!isblank(UCH(*(s - 1)))) {
26674c8945a0SNathan Whitehorn 		    /* Strip '\n's if cr_wrap is not set. */
26684c8945a0SNathan Whitehorn 		    *s++ = ' ';
26694c8945a0SNathan Whitehorn 		    p++;
26704c8945a0SNathan Whitehorn 		} else
26714c8945a0SNathan Whitehorn 		    p++;
26724c8945a0SNathan Whitehorn 	    } else
26734c8945a0SNathan Whitehorn 		*s++ = *p++;
26744c8945a0SNathan Whitehorn 	} else {		/* If there are no "\n" strings */
2675f4f33ea0SBaptiste Daroussin 	    if (isblank(UCH(*p)) && !dialog_vars.nocollapse) {
2676f4f33ea0SBaptiste Daroussin 		if (!trim_blank(base, p))
26774c8945a0SNathan Whitehorn 		    *s++ = *p;
26784c8945a0SNathan Whitehorn 		p++;
26794c8945a0SNathan Whitehorn 	    } else
26804c8945a0SNathan Whitehorn 		*s++ = *p++;
26814c8945a0SNathan Whitehorn 	}
26824c8945a0SNathan Whitehorn     }
26834c8945a0SNathan Whitehorn 
26844c8945a0SNathan Whitehorn     *s = '\0';
26854c8945a0SNathan Whitehorn }
26864c8945a0SNathan Whitehorn 
26874c8945a0SNathan Whitehorn void
26884c8945a0SNathan Whitehorn dlg_set_focus(WINDOW *parent, WINDOW *win)
26894c8945a0SNathan Whitehorn {
26904c8945a0SNathan Whitehorn     if (win != 0) {
26914c8945a0SNathan Whitehorn 	(void) wmove(parent,
26924c8945a0SNathan Whitehorn 		     getpary(win) + getcury(win),
26934c8945a0SNathan Whitehorn 		     getparx(win) + getcurx(win));
26944c8945a0SNathan Whitehorn 	(void) wnoutrefresh(win);
26954c8945a0SNathan Whitehorn 	(void) doupdate();
26964c8945a0SNathan Whitehorn     }
26974c8945a0SNathan Whitehorn }
26984c8945a0SNathan Whitehorn 
26994c8945a0SNathan Whitehorn /*
27004c8945a0SNathan Whitehorn  * Returns the nominal maximum buffer size.
27014c8945a0SNathan Whitehorn  */
27024c8945a0SNathan Whitehorn int
27034c8945a0SNathan Whitehorn dlg_max_input(int max_len)
27044c8945a0SNathan Whitehorn {
27054c8945a0SNathan Whitehorn     if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN)
27064c8945a0SNathan Whitehorn 	max_len = dialog_vars.max_input;
27074c8945a0SNathan Whitehorn 
27084c8945a0SNathan Whitehorn     return max_len;
27094c8945a0SNathan Whitehorn }
27104c8945a0SNathan Whitehorn 
27114c8945a0SNathan Whitehorn /*
27124c8945a0SNathan Whitehorn  * Free storage used for the result buffer.
27134c8945a0SNathan Whitehorn  */
27144c8945a0SNathan Whitehorn void
27154c8945a0SNathan Whitehorn dlg_clr_result(void)
27164c8945a0SNathan Whitehorn {
27174c8945a0SNathan Whitehorn     if (dialog_vars.input_length) {
27184c8945a0SNathan Whitehorn 	dialog_vars.input_length = 0;
27194c8945a0SNathan Whitehorn 	if (dialog_vars.input_result)
27204c8945a0SNathan Whitehorn 	    free(dialog_vars.input_result);
27214c8945a0SNathan Whitehorn     }
27224c8945a0SNathan Whitehorn     dialog_vars.input_result = 0;
27234c8945a0SNathan Whitehorn }
27244c8945a0SNathan Whitehorn 
27254c8945a0SNathan Whitehorn /*
27264c8945a0SNathan Whitehorn  * Setup a fixed-buffer for the result.
27274c8945a0SNathan Whitehorn  */
27284c8945a0SNathan Whitehorn char *
27294c8945a0SNathan Whitehorn dlg_set_result(const char *string)
27304c8945a0SNathan Whitehorn {
27317a1c0d96SNathan Whitehorn     unsigned need = string ? (unsigned) strlen(string) + 1 : 0;
27324c8945a0SNathan Whitehorn 
27334c8945a0SNathan Whitehorn     /* inputstr.c needs a fixed buffer */
27344c8945a0SNathan Whitehorn     if (need < MAX_LEN)
27354c8945a0SNathan Whitehorn 	need = MAX_LEN;
27364c8945a0SNathan Whitehorn 
27374c8945a0SNathan Whitehorn     /*
27384c8945a0SNathan Whitehorn      * If the buffer is not big enough, allocate a new one.
27394c8945a0SNathan Whitehorn      */
27404c8945a0SNathan Whitehorn     if (dialog_vars.input_length != 0
27414c8945a0SNathan Whitehorn 	|| dialog_vars.input_result == 0
27424c8945a0SNathan Whitehorn 	|| need > MAX_LEN) {
27434c8945a0SNathan Whitehorn 
27444c8945a0SNathan Whitehorn 	dlg_clr_result();
27454c8945a0SNathan Whitehorn 
27464c8945a0SNathan Whitehorn 	dialog_vars.input_length = need;
27474c8945a0SNathan Whitehorn 	dialog_vars.input_result = dlg_malloc(char, need);
27484c8945a0SNathan Whitehorn 	assert_ptr(dialog_vars.input_result, "dlg_set_result");
27494c8945a0SNathan Whitehorn     }
27504c8945a0SNathan Whitehorn 
27514c8945a0SNathan Whitehorn     strcpy(dialog_vars.input_result, string ? string : "");
27524c8945a0SNathan Whitehorn 
27534c8945a0SNathan Whitehorn     return dialog_vars.input_result;
27544c8945a0SNathan Whitehorn }
27554c8945a0SNathan Whitehorn 
27564c8945a0SNathan Whitehorn /*
27574c8945a0SNathan Whitehorn  * Accumulate results in dynamically allocated buffer.
27584c8945a0SNathan Whitehorn  * If input_length is zero, it is a MAX_LEN buffer belonging to the caller.
27594c8945a0SNathan Whitehorn  */
27604c8945a0SNathan Whitehorn void
27614c8945a0SNathan Whitehorn dlg_add_result(const char *string)
27624c8945a0SNathan Whitehorn {
27634c8945a0SNathan Whitehorn     unsigned have = (dialog_vars.input_result
27647a1c0d96SNathan Whitehorn 		     ? (unsigned) strlen(dialog_vars.input_result)
27654c8945a0SNathan Whitehorn 		     : 0);
27667a1c0d96SNathan Whitehorn     unsigned want = (unsigned) strlen(string) + 1 + have;
27674c8945a0SNathan Whitehorn 
27684c8945a0SNathan Whitehorn     if ((want >= MAX_LEN)
27694c8945a0SNathan Whitehorn 	|| (dialog_vars.input_length != 0)
27704c8945a0SNathan Whitehorn 	|| (dialog_vars.input_result == 0)) {
27714c8945a0SNathan Whitehorn 
27724c8945a0SNathan Whitehorn 	if (dialog_vars.input_length == 0
27734c8945a0SNathan Whitehorn 	    || dialog_vars.input_result == 0) {
27744c8945a0SNathan Whitehorn 
27757a1c0d96SNathan Whitehorn 	    char *save_result = dialog_vars.input_result;
27764c8945a0SNathan Whitehorn 
27774c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
27784c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length);
27794c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result malloc");
27807a1c0d96SNathan Whitehorn 	    dialog_vars.input_result[0] = '\0';
27817a1c0d96SNathan Whitehorn 	    if (save_result != 0)
27827a1c0d96SNathan Whitehorn 		strcpy(dialog_vars.input_result, save_result);
27834c8945a0SNathan Whitehorn 	} else if (want >= dialog_vars.input_length) {
27844c8945a0SNathan Whitehorn 	    dialog_vars.input_length = want * 2;
27854c8945a0SNathan Whitehorn 	    dialog_vars.input_result = dlg_realloc(char,
27864c8945a0SNathan Whitehorn 						   dialog_vars.input_length,
27874c8945a0SNathan Whitehorn 						   dialog_vars.input_result);
27884c8945a0SNathan Whitehorn 	    assert_ptr(dialog_vars.input_result, "dlg_add_result realloc");
27894c8945a0SNathan Whitehorn 	}
27904c8945a0SNathan Whitehorn     }
27914c8945a0SNathan Whitehorn     strcat(dialog_vars.input_result, string);
27924c8945a0SNathan Whitehorn }
27934c8945a0SNathan Whitehorn 
27944c8945a0SNathan Whitehorn /*
27954c8945a0SNathan Whitehorn  * These are characters that (aside from the quote-delimiter) will have to
27964c8945a0SNathan Whitehorn  * be escaped in a single- or double-quoted string.
27974c8945a0SNathan Whitehorn  */
27984c8945a0SNathan Whitehorn #define FIX_SINGLE "\n\\"
27994c8945a0SNathan Whitehorn #define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>"
28004c8945a0SNathan Whitehorn 
28014c8945a0SNathan Whitehorn /*
28024c8945a0SNathan Whitehorn  * Returns the quote-delimiter.
28034c8945a0SNathan Whitehorn  */
28044c8945a0SNathan Whitehorn static const char *
28054c8945a0SNathan Whitehorn quote_delimiter(void)
28064c8945a0SNathan Whitehorn {
28074c8945a0SNathan Whitehorn     return dialog_vars.single_quoted ? "'" : "\"";
28084c8945a0SNathan Whitehorn }
28094c8945a0SNathan Whitehorn 
28104c8945a0SNathan Whitehorn /*
28114c8945a0SNathan Whitehorn  * Returns true if we should quote the given string.
28124c8945a0SNathan Whitehorn  */
28134c8945a0SNathan Whitehorn static bool
28144c8945a0SNathan Whitehorn must_quote(char *string)
28154c8945a0SNathan Whitehorn {
28164c8945a0SNathan Whitehorn     bool code = FALSE;
28174c8945a0SNathan Whitehorn 
28184c8945a0SNathan Whitehorn     if (*string != '\0') {
28197a1c0d96SNathan Whitehorn 	size_t len = strlen(string);
28204c8945a0SNathan Whitehorn 	if (strcspn(string, quote_delimiter()) != len)
28214c8945a0SNathan Whitehorn 	    code = TRUE;
28224c8945a0SNathan Whitehorn 	else if (strcspn(string, "\n\t ") != len)
28234c8945a0SNathan Whitehorn 	    code = TRUE;
28244c8945a0SNathan Whitehorn 	else
28254c8945a0SNathan Whitehorn 	    code = (strcspn(string, FIX_DOUBLE) != len);
28264c8945a0SNathan Whitehorn     } else {
28274c8945a0SNathan Whitehorn 	code = TRUE;
28284c8945a0SNathan Whitehorn     }
28294c8945a0SNathan Whitehorn 
28304c8945a0SNathan Whitehorn     return code;
28314c8945a0SNathan Whitehorn }
28324c8945a0SNathan Whitehorn 
28334c8945a0SNathan Whitehorn /*
28344c8945a0SNathan Whitehorn  * Add a quoted string to the result buffer.
28354c8945a0SNathan Whitehorn  */
28364c8945a0SNathan Whitehorn void
28374c8945a0SNathan Whitehorn dlg_add_quoted(char *string)
28384c8945a0SNathan Whitehorn {
28394c8945a0SNathan Whitehorn     char temp[2];
28404c8945a0SNathan Whitehorn     const char *my_quote = quote_delimiter();
28414c8945a0SNathan Whitehorn     const char *must_fix = (dialog_vars.single_quoted
28424c8945a0SNathan Whitehorn 			    ? FIX_SINGLE
28434c8945a0SNathan Whitehorn 			    : FIX_DOUBLE);
28444c8945a0SNathan Whitehorn 
28452a3e3873SBaptiste Daroussin     if (must_quote(string)) {
28464c8945a0SNathan Whitehorn 	temp[1] = '\0';
28474c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
28484c8945a0SNathan Whitehorn 	while (*string != '\0') {
28494c8945a0SNathan Whitehorn 	    temp[0] = *string++;
2850f4f33ea0SBaptiste Daroussin 	    if ((strchr) (my_quote, *temp) || (strchr) (must_fix, *temp))
28514c8945a0SNathan Whitehorn 		dlg_add_result("\\");
28524c8945a0SNathan Whitehorn 	    dlg_add_result(temp);
28534c8945a0SNathan Whitehorn 	}
28544c8945a0SNathan Whitehorn 	dlg_add_result(my_quote);
28554c8945a0SNathan Whitehorn     } else {
28564c8945a0SNathan Whitehorn 	dlg_add_result(string);
28574c8945a0SNathan Whitehorn     }
28584c8945a0SNathan Whitehorn }
28594c8945a0SNathan Whitehorn 
28604c8945a0SNathan Whitehorn /*
28614c8945a0SNathan Whitehorn  * When adding a result, make that depend on whether "--quoted" is used.
28624c8945a0SNathan Whitehorn  */
28634c8945a0SNathan Whitehorn void
28644c8945a0SNathan Whitehorn dlg_add_string(char *string)
28654c8945a0SNathan Whitehorn {
28664c8945a0SNathan Whitehorn     if (dialog_vars.quoted) {
28674c8945a0SNathan Whitehorn 	dlg_add_quoted(string);
28684c8945a0SNathan Whitehorn     } else {
28694c8945a0SNathan Whitehorn 	dlg_add_result(string);
28704c8945a0SNathan Whitehorn     }
28714c8945a0SNathan Whitehorn }
28724c8945a0SNathan Whitehorn 
28734c8945a0SNathan Whitehorn bool
28744c8945a0SNathan Whitehorn dlg_need_separator(void)
28754c8945a0SNathan Whitehorn {
28764c8945a0SNathan Whitehorn     bool result = FALSE;
28774c8945a0SNathan Whitehorn 
28784c8945a0SNathan Whitehorn     if (dialog_vars.output_separator) {
28794c8945a0SNathan Whitehorn 	result = TRUE;
28804c8945a0SNathan Whitehorn     } else if (dialog_vars.input_result && *(dialog_vars.input_result)) {
28814c8945a0SNathan Whitehorn 	result = TRUE;
28824c8945a0SNathan Whitehorn     }
28834c8945a0SNathan Whitehorn     return result;
28844c8945a0SNathan Whitehorn }
28854c8945a0SNathan Whitehorn 
28864c8945a0SNathan Whitehorn void
28874c8945a0SNathan Whitehorn dlg_add_separator(void)
28884c8945a0SNathan Whitehorn {
28894c8945a0SNathan Whitehorn     const char *separator = (dialog_vars.separate_output) ? "\n" : " ";
28904c8945a0SNathan Whitehorn 
28914c8945a0SNathan Whitehorn     if (dialog_vars.output_separator)
28924c8945a0SNathan Whitehorn 	separator = dialog_vars.output_separator;
28934c8945a0SNathan Whitehorn 
28944c8945a0SNathan Whitehorn     dlg_add_result(separator);
28954c8945a0SNathan Whitehorn }
28964c8945a0SNathan Whitehorn 
2897febdb468SDevin Teske #define HELP_PREFIX		"HELP "
2898febdb468SDevin Teske 
2899febdb468SDevin Teske void
2900febdb468SDevin Teske dlg_add_help_listitem(int *result, char **tag, DIALOG_LISTITEM * item)
2901febdb468SDevin Teske {
2902febdb468SDevin Teske     dlg_add_result(HELP_PREFIX);
2903febdb468SDevin Teske     if (USE_ITEM_HELP(item->help)) {
2904febdb468SDevin Teske 	*tag = dialog_vars.help_tags ? item->name : item->help;
2905febdb468SDevin Teske 	*result = DLG_EXIT_ITEM_HELP;
2906febdb468SDevin Teske     } else {
2907febdb468SDevin Teske 	*tag = item->name;
2908febdb468SDevin Teske     }
2909febdb468SDevin Teske }
2910febdb468SDevin Teske 
2911febdb468SDevin Teske void
2912febdb468SDevin Teske dlg_add_help_formitem(int *result, char **tag, DIALOG_FORMITEM * item)
2913febdb468SDevin Teske {
2914febdb468SDevin Teske     dlg_add_result(HELP_PREFIX);
2915febdb468SDevin Teske     if (USE_ITEM_HELP(item->help)) {
2916febdb468SDevin Teske 	*tag = dialog_vars.help_tags ? item->name : item->help;
2917febdb468SDevin Teske 	*result = DLG_EXIT_ITEM_HELP;
2918febdb468SDevin Teske     } else {
2919febdb468SDevin Teske 	*tag = item->name;
2920febdb468SDevin Teske     }
2921febdb468SDevin Teske }
2922febdb468SDevin Teske 
29234c8945a0SNathan Whitehorn /*
29244c8945a0SNathan Whitehorn  * Some widgets support only one value of a given variable - save/restore the
29254c8945a0SNathan Whitehorn  * global dialog_vars so we can override it consistently.
29264c8945a0SNathan Whitehorn  */
29274c8945a0SNathan Whitehorn void
29284c8945a0SNathan Whitehorn dlg_save_vars(DIALOG_VARS * vars)
29294c8945a0SNathan Whitehorn {
29304c8945a0SNathan Whitehorn     *vars = dialog_vars;
29314c8945a0SNathan Whitehorn }
29324c8945a0SNathan Whitehorn 
29337a1c0d96SNathan Whitehorn /*
29347a1c0d96SNathan Whitehorn  * Most of the data in DIALOG_VARS is normally set by command-line options.
29357a1c0d96SNathan Whitehorn  * The input_result member is an exception; it is normally set by the dialog
29367a1c0d96SNathan Whitehorn  * library to return result values.
29377a1c0d96SNathan Whitehorn  */
29384c8945a0SNathan Whitehorn void
29394c8945a0SNathan Whitehorn dlg_restore_vars(DIALOG_VARS * vars)
29404c8945a0SNathan Whitehorn {
29417a1c0d96SNathan Whitehorn     char *save_result = dialog_vars.input_result;
29427a1c0d96SNathan Whitehorn     unsigned save_length = dialog_vars.input_length;
29437a1c0d96SNathan Whitehorn 
29444c8945a0SNathan Whitehorn     dialog_vars = *vars;
29457a1c0d96SNathan Whitehorn     dialog_vars.input_result = save_result;
29467a1c0d96SNathan Whitehorn     dialog_vars.input_length = save_length;
29474c8945a0SNathan Whitehorn }
29484c8945a0SNathan Whitehorn 
29494c8945a0SNathan Whitehorn /*
29504c8945a0SNathan Whitehorn  * Called each time a widget is invoked which may do output, increment a count.
29514c8945a0SNathan Whitehorn  */
29524c8945a0SNathan Whitehorn void
29534c8945a0SNathan Whitehorn dlg_does_output(void)
29544c8945a0SNathan Whitehorn {
29554c8945a0SNathan Whitehorn     dialog_state.output_count += 1;
29564c8945a0SNathan Whitehorn }
29574c8945a0SNathan Whitehorn 
29584c8945a0SNathan Whitehorn /*
29594c8945a0SNathan Whitehorn  * Compatibility for different versions of curses.
29604c8945a0SNathan Whitehorn  */
29614c8945a0SNathan Whitehorn #if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY))
29624c8945a0SNathan Whitehorn int
29632a3e3873SBaptiste Daroussin dlg_getbegx(WINDOW *win)
29644c8945a0SNathan Whitehorn {
29654c8945a0SNathan Whitehorn     int y, x;
29664c8945a0SNathan Whitehorn     getbegyx(win, y, x);
29674c8945a0SNathan Whitehorn     return x;
29684c8945a0SNathan Whitehorn }
29694c8945a0SNathan Whitehorn int
29702a3e3873SBaptiste Daroussin dlg_getbegy(WINDOW *win)
29714c8945a0SNathan Whitehorn {
29724c8945a0SNathan Whitehorn     int y, x;
29734c8945a0SNathan Whitehorn     getbegyx(win, y, x);
29744c8945a0SNathan Whitehorn     return y;
29754c8945a0SNathan Whitehorn }
29764c8945a0SNathan Whitehorn #endif
29774c8945a0SNathan Whitehorn 
29784c8945a0SNathan Whitehorn #if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY))
29794c8945a0SNathan Whitehorn int
29802a3e3873SBaptiste Daroussin dlg_getcurx(WINDOW *win)
29814c8945a0SNathan Whitehorn {
29824c8945a0SNathan Whitehorn     int y, x;
29834c8945a0SNathan Whitehorn     getyx(win, y, x);
29844c8945a0SNathan Whitehorn     return x;
29854c8945a0SNathan Whitehorn }
29864c8945a0SNathan Whitehorn int
29872a3e3873SBaptiste Daroussin dlg_getcury(WINDOW *win)
29884c8945a0SNathan Whitehorn {
29894c8945a0SNathan Whitehorn     int y, x;
29904c8945a0SNathan Whitehorn     getyx(win, y, x);
29914c8945a0SNathan Whitehorn     return y;
29924c8945a0SNathan Whitehorn }
29934c8945a0SNathan Whitehorn #endif
29944c8945a0SNathan Whitehorn 
29954c8945a0SNathan Whitehorn #if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY))
29964c8945a0SNathan Whitehorn int
29972a3e3873SBaptiste Daroussin dlg_getmaxx(WINDOW *win)
29984c8945a0SNathan Whitehorn {
29994c8945a0SNathan Whitehorn     int y, x;
30004c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
30014c8945a0SNathan Whitehorn     return x;
30024c8945a0SNathan Whitehorn }
30034c8945a0SNathan Whitehorn int
30042a3e3873SBaptiste Daroussin dlg_getmaxy(WINDOW *win)
30054c8945a0SNathan Whitehorn {
30064c8945a0SNathan Whitehorn     int y, x;
30074c8945a0SNathan Whitehorn     getmaxyx(win, y, x);
30084c8945a0SNathan Whitehorn     return y;
30094c8945a0SNathan Whitehorn }
30104c8945a0SNathan Whitehorn #endif
30114c8945a0SNathan Whitehorn 
30124c8945a0SNathan Whitehorn #if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY))
30134c8945a0SNathan Whitehorn int
30142a3e3873SBaptiste Daroussin dlg_getparx(WINDOW *win)
30154c8945a0SNathan Whitehorn {
30164c8945a0SNathan Whitehorn     int y, x;
30174c8945a0SNathan Whitehorn     getparyx(win, y, x);
30184c8945a0SNathan Whitehorn     return x;
30194c8945a0SNathan Whitehorn }
30204c8945a0SNathan Whitehorn int
30212a3e3873SBaptiste Daroussin dlg_getpary(WINDOW *win)
30224c8945a0SNathan Whitehorn {
30234c8945a0SNathan Whitehorn     int y, x;
30244c8945a0SNathan Whitehorn     getparyx(win, y, x);
30254c8945a0SNathan Whitehorn     return y;
30264c8945a0SNathan Whitehorn }
30274c8945a0SNathan Whitehorn #endif
30282a3e3873SBaptiste Daroussin 
30292a3e3873SBaptiste Daroussin #ifdef NEED_WGETPARENT
30302a3e3873SBaptiste Daroussin WINDOW *
30312a3e3873SBaptiste Daroussin dlg_wgetparent(WINDOW *win)
30322a3e3873SBaptiste Daroussin {
30332a3e3873SBaptiste Daroussin #undef wgetparent
30342a3e3873SBaptiste Daroussin     WINDOW *result = 0;
30352a3e3873SBaptiste Daroussin     DIALOG_WINDOWS *p;
30362a3e3873SBaptiste Daroussin 
30372a3e3873SBaptiste Daroussin     for (p = dialog_state.all_subwindows; p != 0; p = p->next) {
30382a3e3873SBaptiste Daroussin 	if (p->shadow == win) {
30392a3e3873SBaptiste Daroussin 	    result = p->normal;
30402a3e3873SBaptiste Daroussin 	    break;
30412a3e3873SBaptiste Daroussin 	}
30422a3e3873SBaptiste Daroussin     }
30432a3e3873SBaptiste Daroussin     return result;
30442a3e3873SBaptiste Daroussin }
30452a3e3873SBaptiste Daroussin #endif
3046