2 * $Id: util.c,v 1.201 2010/04/28 21:12:42 tom Exp $
4 * util.c -- miscellaneous utilities for dialog
6 * Copyright 2000-2008,2010 Thomas E. Dickey
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License, version 2.1
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to
19 * Free Software Foundation, Inc.
20 * 51 Franklin St., Fifth Floor
21 * Boston, MA 02110, USA.
23 * An earlier version of this program lists as authors
24 * Savio Lam (lam836@cs.cuhk.hk)
30 #ifdef NCURSES_VERSION
31 #if defined(HAVE_NCURSESW_TERM_H)
32 #include <ncursesw/term.h>
33 #elif defined(HAVE_NCURSES_TERM_H)
34 #include <ncurses/term.h>
41 DIALOG_STATE dialog_state;
42 DIALOG_VARS dialog_vars;
44 #define concat(a,b) a##b
47 #define RC_DATA(name,comment) , #name "_color", comment " color"
49 #define RC_DATA(name,comment) /*nothing */
53 #include <dlg_colors.h>
54 #define COLOR_DATA(upr) , \
55 concat(DLGC_FG_,upr), \
56 concat(DLGC_BG_,upr), \
59 #define COLOR_DATA(upr) /*nothing */
62 #define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }
65 * Table of color and attribute values, default is for mono display.
68 DIALOG_COLORS dlg_color_table[] =
70 DATA(A_NORMAL, SCREEN, screen, "Screen"),
71 DATA(A_NORMAL, SHADOW, shadow, "Shadow"),
72 DATA(A_REVERSE, DIALOG, dialog, "Dialog box"),
73 DATA(A_REVERSE, TITLE, title, "Dialog box title"),
74 DATA(A_REVERSE, BORDER, border, "Dialog box border"),
75 DATA(A_BOLD, BUTTON_ACTIVE, button_active, "Active button"),
76 DATA(A_DIM, BUTTON_INACTIVE, button_inactive, "Inactive button"),
77 DATA(A_UNDERLINE, BUTTON_KEY_ACTIVE, button_key_active, "Active button key"),
78 DATA(A_UNDERLINE, BUTTON_KEY_INACTIVE, button_key_inactive, "Inactive button key"),
79 DATA(A_NORMAL, BUTTON_LABEL_ACTIVE, button_label_active, "Active button label"),
80 DATA(A_NORMAL, BUTTON_LABEL_INACTIVE, button_label_inactive, "Inactive button label"),
81 DATA(A_REVERSE, INPUTBOX, inputbox, "Input box"),
82 DATA(A_REVERSE, INPUTBOX_BORDER, inputbox_border, "Input box border"),
83 DATA(A_REVERSE, SEARCHBOX, searchbox, "Search box"),
84 DATA(A_REVERSE, SEARCHBOX_TITLE, searchbox_title, "Search box title"),
85 DATA(A_REVERSE, SEARCHBOX_BORDER, searchbox_border, "Search box border"),
86 DATA(A_REVERSE, POSITION_INDICATOR, position_indicator, "File position indicator"),
87 DATA(A_REVERSE, MENUBOX, menubox, "Menu box"),
88 DATA(A_REVERSE, MENUBOX_BORDER, menubox_border, "Menu box border"),
89 DATA(A_REVERSE, ITEM, item, "Item"),
90 DATA(A_NORMAL, ITEM_SELECTED, item_selected, "Selected item"),
91 DATA(A_REVERSE, TAG, tag, "Tag"),
92 DATA(A_REVERSE, TAG_SELECTED, tag_selected, "Selected tag"),
93 DATA(A_NORMAL, TAG_KEY, tag_key, "Tag key"),
94 DATA(A_BOLD, TAG_KEY_SELECTED, tag_key_selected, "Selected tag key"),
95 DATA(A_REVERSE, CHECK, check, "Check box"),
96 DATA(A_REVERSE, CHECK_SELECTED, check_selected, "Selected check box"),
97 DATA(A_REVERSE, UARROW, uarrow, "Up arrow"),
98 DATA(A_REVERSE, DARROW, darrow, "Down arrow"),
99 DATA(A_NORMAL, ITEMHELP, itemhelp, "Item help-text"),
100 DATA(A_BOLD, FORM_ACTIVE_TEXT, form_active_text, "Active form text"),
101 DATA(A_REVERSE, FORM_TEXT, form_text, "Form text"),
102 DATA(A_NORMAL, FORM_ITEM_READONLY, form_item_readonly, "Readonly form item")
107 * Display background title if it exists ...
110 dlg_put_backtitle(void)
114 if (dialog_vars.backtitle != NULL) {
115 chtype attr = A_NORMAL;
116 int backwidth = dlg_count_columns(dialog_vars.backtitle);
118 wattrset(stdscr, screen_attr);
119 (void) wmove(stdscr, 0, 1);
120 dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);
121 for (i = 0; i < COLS - backwidth; i++)
122 (void) waddch(stdscr, ' ');
123 (void) wmove(stdscr, 1, 1);
124 for (i = 0; i < COLS - 2; i++)
125 (void) waddch(stdscr, dlg_boxchar(ACS_HLINE));
128 (void) wnoutrefresh(stdscr);
132 * Set window to attribute 'attr'. There are more efficient ways to do this,
133 * but will not work on older/buggy ncurses versions.
136 dlg_attr_clear(WINDOW *win, int height, int width, chtype attr)
141 for (i = 0; i < height; i++) {
142 (void) wmove(win, i, 0);
143 for (j = 0; j < width; j++)
144 (void) waddch(win, ' ');
146 (void) touchwin(win);
152 dlg_attr_clear(stdscr, LINES, COLS, screen_attr);
155 #define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)
157 #define TTY_DEVICE "/dev/tty"
160 * If $DIALOG_TTY exists, allow the program to try to open the terminal
161 * directly when stdout is redirected. By default we require the "--stdout"
162 * option to be given, but some scripts were written making use of the
163 * behavior of dialog which tried opening the terminal anyway.
168 char *result = getenv("DIALOG_TTY");
169 if (result != 0 && atoi(result) == 0)
175 * Open the terminal directly. If one of stdin, stdout or stderr really points
176 * to a tty, use it. Otherwise give up and open /dev/tty.
179 open_terminal(char **result, int mode)
181 const char *device = TTY_DEVICE;
182 if (!isatty(fileno(stderr))
183 || (device = ttyname(fileno(stderr))) == 0) {
184 if (!isatty(fileno(stdout))
185 || (device = ttyname(fileno(stdout))) == 0) {
186 if (!isatty(fileno(stdin))
187 || (device = ttyname(fileno(stdin))) == 0) {
192 *result = dlg_strclone(device);
193 return open(device, mode);
197 * Do some initialization for dialog.
199 * 'input' is the real tty input of dialog. Usually it is stdin, but if
200 * --input-fd option is used, it may be anything.
202 * 'output' is where dialog will send its result. Usually it is stderr, but
203 * if --stdout or --output-fd is used, it may be anything. We are concerned
204 * mainly with the case where it happens to be the same as stdout.
207 init_dialog(FILE *input, FILE *output)
212 dialog_state.output = output;
213 dialog_state.tab_len = TAB_LEN;
214 dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;
216 dialog_state.use_colors = USE_COLORS; /* use colors by default? */
217 dialog_state.use_shadow = USE_SHADOW; /* shadow dialog boxes by default? */
221 if (dlg_parse_rc() == -1) /* Read the configuration file */
222 dlg_exiterr("init_dialog: dlg_parse_rc");
226 * Some widgets (such as gauge) may read from the standard input. Pipes
227 * only connect stdout/stdin, so there is not much choice. But reading a
228 * pipe would get in the way of curses' normal reading stdin for getch.
230 * As in the --stdout (see below), reopening the terminal does not always
231 * work properly. dialog provides a --pipe-fd option for this purpose. We
232 * test that case first (differing fileno's for input/stdin). If the
233 * fileno's are equal, but we're not reading from a tty, see if we can open
236 dialog_state.pipe_input = stdin;
237 if (fileno(input) != fileno(stdin)) {
238 if ((fd1 = dup(fileno(input))) >= 0
239 && (fd2 = dup(fileno(stdin))) >= 0) {
240 (void) dup2(fileno(input), fileno(stdin));
241 dialog_state.pipe_input = fdopen(fd2, "r");
242 if (fileno(stdin) != 0) /* some functions may read fd #0 */
243 (void) dup2(fileno(stdin), 0);
245 dlg_exiterr("cannot open tty-input");
246 } else if (!isatty(fileno(stdin))) {
247 if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0
248 && (fd2 = dup(fileno(stdin))) >= 0) {
249 dialog_state.pipe_input = fdopen(fd2, "r");
250 if (freopen(device, "r", stdin) == 0)
251 dlg_exiterr("cannot open tty-input");
252 if (fileno(stdin) != 0) /* some functions may read fd #0 */
253 (void) dup2(fileno(stdin), 0);
259 * If stdout is not a tty and dialog is called with the --stdout option, we
260 * have to provide for a way to write to the screen.
262 * The curses library normally writes its output to stdout, leaving stderr
263 * free for scripting. Scripts are simpler when stdout is redirected. The
264 * newterm function is useful; it allows us to specify where the output
265 * goes. Reopening the terminal is not portable since several
266 * configurations do not allow this to work properly:
268 * a) some getty implementations (and possibly broken tty drivers, e.g., on
269 * HPUX 10 and 11) cause stdin to act as if it is still in cooked mode
270 * even though results from ioctl's state that it is successfully
271 * altered to raw mode. Broken is the proper term.
273 * b) the user may not have permissions on the device, e.g., if one su's
274 * from the login user to another non-privileged user.
276 if (!isatty(fileno(stdout))
277 && (fileno(stdout) == fileno(output) || dialog_tty())) {
278 if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0
279 && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {
280 if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {
281 dlg_exiterr("cannot initialize curses");
285 dlg_exiterr("cannot open tty-output");
288 dialog_state.screen_output = stdout;
291 #ifdef NCURSES_VERSION
293 * Cancel xterm's alternate-screen mode.
295 if (!dialog_vars.keep_tite
296 && (dialog_state.screen_output != stdout
297 || isatty(fileno(dialog_state.screen_output)))
298 && key_mouse != 0 /* xterm and kindred */
299 && isprivate(enter_ca_mode)
300 && isprivate(exit_ca_mode)) {
302 * initscr() or newterm() already did putp(enter_ca_mode) as a side
303 * effect of initializing the screen. It would be nice to not even
304 * do that, but we do not really have access to the correct copy of
305 * the terminfo description until those functions have been invoked.
307 (void) putp(exit_ca_mode);
308 (void) putp(clear_screen);
310 * Prevent ncurses from switching "back" to the normal screen when
311 * exiting from dialog. That would move the cursor to the original
312 * location saved in xterm. Normally curses sets the cursor position
313 * to the first line after the display, but the alternate screen
314 * switching is done after that point.
316 * Cancelling the strings altogether also works around the buggy
317 * implementation of alternate-screen in rxvt, etc., which clear
318 * more of the display than they should.
327 (void) keypad(stdscr, TRUE);
331 dialog_state.screen_initialized = TRUE;
334 if (dialog_state.use_colors || dialog_state.use_shadow)
335 dlg_color_setup(); /* Set up colors */
338 /* Set screen to screen attribute */
343 static int defined_colors = 1; /* pair-0 is reserved */
345 * Setup for color display
348 dlg_color_setup(void)
352 if (has_colors()) { /* Terminal supports color? */
353 (void) start_color();
355 #if defined(HAVE_USE_DEFAULT_COLORS)
356 use_default_colors();
359 #if defined(__NetBSD__) && defined(_CURSES_)
360 #define C_ATTR(x,y) (((x) != 0 ? A_BOLD : 0) | COLOR_PAIR((y)))
361 /* work around bug in NetBSD curses */
362 for (i = 0; i < sizeof(dlg_color_table) /
363 sizeof(dlg_color_table[0]); i++) {
365 /* Initialize color pairs */
366 (void) init_pair(i + 1,
367 dlg_color_table[i].fg,
368 dlg_color_table[i].bg);
370 /* Setup color attributes */
371 dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);
373 defined_colors = i + 1;
375 for (i = 0; i < sizeof(dlg_color_table) /
376 sizeof(dlg_color_table[0]); i++) {
378 /* Initialize color pairs */
379 chtype color = dlg_color_pair(dlg_color_table[i].fg,
380 dlg_color_table[i].bg);
382 /* Setup color attributes */
383 dlg_color_table[i].atr = ((dlg_color_table[i].hilite
390 dialog_state.use_colors = FALSE;
391 dialog_state.use_shadow = FALSE;
396 dlg_color_count(void)
398 return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]);
402 * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
403 * have (or can) define a pair with the given color as foreground on the
404 * window's defined background.
407 dlg_color_pair(int foreground, int background)
414 for (pair = 1; pair < defined_colors; ++pair) {
415 if (pair_content((short) pair, &fg, &bg) != ERR
417 && bg == background) {
418 result = (chtype) COLOR_PAIR(pair);
423 if (!found && (defined_colors + 1) < COLOR_PAIRS) {
424 pair = defined_colors++;
425 (void) init_pair((short) pair, (short) foreground, (short) background);
426 result = (chtype) COLOR_PAIR(pair);
432 * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we
433 * have (or can) define a pair with the given color as foreground on the
434 * window's defined background.
437 define_color(WINDOW *win, int foreground)
439 chtype attrs = getattrs(win);
441 short fg, bg, background;
443 if ((pair = PAIR_NUMBER(attrs)) != 0
444 && pair_content((short) pair, &fg, &bg) != ERR) {
447 background = COLOR_BLACK;
449 return dlg_color_pair(foreground, background);
454 * End using dialog functions.
459 if (dialog_state.screen_initialized) {
460 dialog_state.screen_initialized = FALSE;
463 (void) fflush(stdout);
467 #define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))
470 centered(int width, const char *string)
472 int len = dlg_count_columns(string);
477 if (dialog_vars.colors) {
478 for (n = 0; n < len; ++n) {
479 if (isOurEscape(string + n)) {
484 left = (width - (len - hide)) / 2 - 1;
491 * Print up to 'cols' columns from 'text', optionally rendering our escape
492 * sequence for attributes and color.
495 dlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr)
497 int y_origin, x_origin;
498 int y_before, x_before = 0;
499 int y_after, x_after;
505 getyx(win, y_origin, x_origin);
506 while (cols > 0 && (*txt != '\0')) {
507 if (dialog_vars.colors) {
508 while (isOurEscape(txt)) {
512 switch (code = CharOf(*txt)) {
523 *attr |= define_color(win, code - '0');
539 *attr &= ~A_UNDERLINE;
542 *attr |= A_UNDERLINE;
551 if (ended || *txt == '\n' || *txt == '\0')
553 useattr = (*attr) & A_ATTRIBUTES;
556 * Prevent this from making text invisible when the foreground and
557 * background colors happen to be the same, and there's no bold
560 if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) {
561 short pair = (short) PAIR_NUMBER(useattr);
563 if (pair_content(pair, &fg, &bg) != ERR
566 useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK)
573 * Write the character, using curses to tell exactly how wide it
574 * is. If it is a tab, discount that, since the caller thinks
575 * tabs are nonprinting, and curses will expand tabs to one or
578 thisTab = (CharOf(*txt) == TAB);
580 getyx(win, y_before, x_before);
581 (void) waddch(win, CharOf(*txt++) | useattr);
582 getyx(win, y_after, x_after);
583 if (thisTab && (y_after == y_origin))
584 tabbed += (x_after - x_before);
585 if (y_after != y_origin || x_after >= cols + tabbed + x_origin) {
592 * Print one line of the prompt in the window within the limits of the
593 * specified right margin. The line will end on a word boundary and a pointer
594 * to the start of the next line is returned, or a NULL pointer if the end of
595 * *prompt is reached.
598 dlg_print_line(WINDOW *win,
601 int lm, int rm, int *x)
603 const char *wrap_ptr = prompt;
604 const char *test_ptr = prompt;
605 const int *cols = dlg_index_columns(prompt);
606 const int *indx = dlg_index_wchars(prompt);
611 int limit = dlg_count_wchars(prompt);
618 * Set *test_ptr to the end of the line or the right margin (rm), whichever
619 * is less, and set wrap_ptr to the end of the last word in the line.
621 for (n = 0; n < limit; ++n) {
622 test_ptr = prompt + indx[test_inx];
623 if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden))
625 if (*test_ptr == TAB && n == 0) {
626 tabbed = 8; /* workaround for leading tabs */
627 } else if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') {
630 } else if (isOurEscape(test_ptr)) {
634 cur_x = lm + tabbed + cols[n + 1];
635 if (cur_x > (rm + hidden))
641 * If the line doesn't reach the right margin in the middle of a word, then
642 * we don't have to wrap it at the end of the previous word.
644 test_ptr = prompt + indx[test_inx];
645 if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') {
647 while (wrap_inx > 0 && prompt[indx[wrap_inx - 1]] == ' ') {
650 *x = lm + indx[wrap_inx];
651 } else if (*x == 1 && cur_x >= rm) {
653 * If the line has no spaces, then wrap it anyway at the right margin
658 wrap_ptr = prompt + indx[wrap_inx];
661 * Print the line if we have a window pointer. Otherwise this routine
662 * is just being called for sizing the window.
665 dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr);
668 /* *x tells the calling function how long the line was */
672 /* Find the start of the next line and return a pointer to it */
674 while (*test_ptr == ' ')
676 if (*test_ptr == '\n')
682 justify_text(WINDOW *win,
686 int *high, int *wide)
688 chtype attr = A_NORMAL;
689 int x = (2 * MARGIN);
692 int lm = (2 * MARGIN); /* left margin (box-border plus a space) */
693 int rm = limit_x; /* right margin */
694 int bm = limit_y; /* bottom margin */
695 int last_y = 0, last_x = 0;
705 getyx(win, last_y, last_x);
706 while (y <= bm && *prompt) {
709 if (*prompt == '\n') {
710 while (*prompt == '\n' && y < bm) {
711 if (*(prompt + 1) != '\0') {
714 (void) wmove(win, y, lm);
719 (void) wmove(win, y, lm);
722 prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x);
724 getyx(win, last_y, last_x);
729 (void) wmove(win, y, lm);
731 max_x = MAX(max_x, x);
733 /* Move back to the last position after drawing prompt, for msgbox. */
735 (void) wmove(win, last_y, last_x);
737 /* Set the final height and width for the calling function */
745 * Print a string of text in a window, automatically wrap around to the next
746 * line if the string is too long to fit on one line. Note that the string may
747 * contain embedded newlines.
750 dlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width)
752 justify_text(win, prompt,
755 (int *) 0, (int *) 0);
759 * Display the message in a scrollable window. Actually the way it works is
760 * that we create a "tall" window of the proper width, let the text wrap within
761 * that, and copy a slice of the result to the dialog.
763 * It works for ncurses. Other curses implementations show only blanks (Tru64)
764 * or garbage (NetBSD).
767 dlg_print_scrolled(WINDOW *win,
777 getyx(win, oldy, oldx);
778 #ifdef NCURSES_VERSION
780 int wide = width - (2 * MARGIN);
788 #if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417
790 * If we're not limited by the screensize, allow text to possibly be
791 * one character per line.
793 if ((len = dlg_count_columns(prompt)) > high)
796 dummy = newwin(high, width, 0, 0);
797 wbkgdset(dummy, dialog_attr | ' ');
798 wattrset(dummy, dialog_attr);
800 dlg_print_autowrap(dummy, prompt, high, width);
803 copywin(dummy, /* srcwin */
805 offset + MARGIN, /* sminrow */
806 MARGIN, /* smincol */
807 MARGIN, /* dminrow */
808 MARGIN, /* dmincol */
809 height, /* dmaxrow */
815 /* if the text is incomplete, or we have scrolled, show the percentage */
816 if (y > 0 && wide > 4) {
817 percent = (int) ((height + offset) * 100.0 / y);
822 if (offset != 0 || percent != 100) {
823 (void) wattrset(win, position_indicator_attr);
824 (void) wmove(win, MARGIN + height, wide - 4);
825 (void) sprintf(buffer, "%d%%", percent);
826 (void) waddstr(win, buffer);
827 if ((len = (int) strlen(buffer)) < 4) {
828 wattrset(win, border_attr);
829 whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
838 wattrset(win, dialog_attr);
839 dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width);
842 wmove(win, oldy, oldx);
847 dlg_check_scrolled(int key, int last, int page, bool * show, int *offset)
854 case DLGK_PAGE_FIRST:
861 if (*offset < last) {
873 if (*offset < last) {
887 if (*offset < last) {
902 * Calculate the window size for preformatted text. This will calculate box
903 * dimensions that are at or close to the specified aspect ratio for the prompt
904 * string with all spaces and newlines preserved and additional newlines added
908 auto_size_preformatted(const char *prompt, int *height, int *width)
910 int high = 0, wide = 0;
911 float car; /* Calculated Aspect Ratio */
913 int max_y = SLINES - 1;
914 int max_x = SCOLS - 2;
915 int max_width = max_x;
916 int ar = dialog_state.aspect_ratio;
918 /* Get the initial dimensions */
919 justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
920 car = (float) (wide / high);
923 * If the aspect ratio is greater than it should be, then decrease the
924 * width proportionately.
927 diff = car / (float) ar;
928 max_x = (int) ((float) wide / diff + 4);
929 justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
930 car = (float) wide / (float) high;
934 * If the aspect ratio is too small after decreasing the width, then
935 * incrementally increase the width until the aspect ratio is equal to or
936 * greater than the specified aspect ratio.
938 while (car < ar && max_x < max_width) {
940 justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide);
941 car = (float) (wide / high);
949 * Find the length of the longest "word" in the given string. By setting the
950 * widget width at least this long, we can avoid splitting a word on the
954 longest_word(const char *string)
956 int length, result = 0;
958 while (*string != '\0') {
960 while (*string != '\0' && !isspace(UCH(*string))) {
964 result = MAX(result, length);
972 * if (height or width == -1) Maximize()
973 * if (height or width == 0), justify and return actual limits.
976 real_auto_size(const char *title,
978 int *height, int *width,
979 int boxlines, int mincols)
981 int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2);
982 int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1);
983 int title_length = title ? dlg_count_columns(title) : 0;
987 int save_high = *height;
988 int save_wide = *width;
1005 } else if (prompt != 0) {
1006 wide = MAX(title_length, mincols);
1007 if (strchr(prompt, '\n') == 0) {
1008 double val = dialog_state.aspect_ratio * dlg_count_columns(prompt);
1009 double xxx = sqrt(val);
1010 int tmp = (int) xxx;
1011 wide = MAX(wide, tmp);
1012 wide = MAX(wide, longest_word(prompt));
1013 justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1015 auto_size_preformatted(prompt, height, width);
1019 justify_text((WINDOW *) 0, prompt, high, wide, height, width);
1022 if (*width < title_length) {
1023 justify_text((WINDOW *) 0, prompt, high, title_length, height, width);
1024 *width = title_length;
1027 if (*width < mincols && save_wide == 0)
1031 *height += boxlines + 2;
1034 *height = save_high;
1039 /* End of real_auto_size() */
1042 dlg_auto_size(const char *title,
1049 real_auto_size(title, prompt, height, width, boxlines, mincols);
1051 if (*width > SCOLS) {
1056 if (*height > SLINES)
1061 * if (height or width == -1) Maximize()
1062 * if (height or width == 0)
1063 * height=MIN(SLINES, num.lines in fd+n);
1064 * width=MIN(SCOLS, MAX(longer line+n, mincols));
1067 dlg_auto_sizefile(const char *title,
1075 int len = title ? dlg_count_columns(title) : 0;
1082 /* Open input file for reading */
1083 if ((fd = fopen(file, "rb")) == NULL)
1084 dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file);
1086 if ((*height == -1) || (*width == -1)) {
1087 *height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1088 *width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0);
1090 if ((*height != 0) && (*width != 0)) {
1094 if (*height > SLINES)
1101 while (((ch = getc(fd)) != '\n') && !feof(fd))
1102 if ((ch == TAB) && (dialog_vars.tab_correct))
1103 offset += dialog_state.tab_len - (offset % dialog_state.tab_len);
1113 /* now 'count' has the number of lines of fd and 'len' the max lenght */
1115 *height = MIN(SLINES, count + numlines + boxlines);
1116 *width = MIN(SCOLS, MAX((len + nc), mincols));
1117 /* here width and height can be maximized if > SCOLS|SLINES because
1118 textbox-like widgets don't put all <file> on the screen.
1119 Msgbox-like widget instead have to put all <text> correctly. */
1125 * Draw a rectangular box with line drawing characters.
1127 * borderchar is used to color the upper/left edges.
1129 * boxchar is used to color the right/lower edges. It also is fill-color used
1130 * for the box contents.
1132 * Normally, if you are drawing a scrollable box, use menubox_border_attr for
1133 * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn
1134 * with menubox_attr at the top, and menubox_border_attr at the bottom. That
1135 * also (given the default color choices) produces a recessed effect.
1137 * If you want a raised effect (and are not going to use the scroll-arrows),
1138 * reverse this choice.
1141 dlg_draw_box(WINDOW *win, int y, int x, int height, int width,
1142 chtype boxchar, chtype borderchar)
1145 chtype save = getattrs(win);
1148 for (i = 0; i < height; i++) {
1149 (void) wmove(win, y + i, x);
1150 for (j = 0; j < width; j++)
1152 (void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER));
1153 else if (i == height - 1 && !j)
1154 (void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER));
1155 else if (!i && j == width - 1)
1156 (void) waddch(win, boxchar | dlg_boxchar(ACS_URCORNER));
1157 else if (i == height - 1 && j == width - 1)
1158 (void) waddch(win, boxchar | dlg_boxchar(ACS_LRCORNER));
1160 (void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE));
1161 else if (i == height - 1)
1162 (void) waddch(win, boxchar | dlg_boxchar(ACS_HLINE));
1164 (void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE));
1165 else if (j == width - 1)
1166 (void) waddch(win, boxchar | dlg_boxchar(ACS_VLINE));
1168 (void) waddch(win, boxchar | ' ');
1170 wattrset(win, save);
1175 * Draw a shadow on the parent window corresponding to the right- and
1176 * bottom-edge of the child window, to give a 3-dimensional look.
1179 draw_childs_shadow(WINDOW *parent, WINDOW *child)
1181 if (has_colors()) { /* Whether terminal supports color? */
1182 chtype save = getattrs(parent);
1184 dlg_draw_shadow(parent,
1185 getbegy(child) - getbegy(parent),
1186 getbegx(child) - getbegx(parent),
1189 wattrset(parent, save);
1194 * Draw shadows along the right and bottom edge to give a more 3D look
1198 dlg_draw_shadow(WINDOW *win, int y, int x, int height, int width)
1202 if (has_colors()) { /* Whether terminal supports color? */
1203 wattrset(win, shadow_attr);
1204 for (i = 0; i < SHADOW_ROWS; ++i) {
1205 for (j = 0; j < width; ++j) {
1206 if (wmove(win, i + y + height, j + x + SHADOW_COLS) != ERR) {
1207 (void) waddch(win, winch(win) & (chtype) (~A_COLOR));
1211 for (i = 0; i < height; i++) {
1212 for (j = 0; j < SHADOW_COLS; ++j) {
1213 if (wmove(win, i + y + SHADOW_ROWS, j + x + width) != ERR) {
1214 (void) waddch(win, winch(win) & (chtype) (~A_COLOR));
1218 (void) wnoutrefresh(win);
1221 #endif /* HAVE_COLOR */
1224 * Allow shell scripts to remap the exit codes so they can distinguish ESC
1231 static const struct {
1235 { DLG_EXIT_CANCEL, "DIALOG_CANCEL" },
1236 { DLG_EXIT_ERROR, "DIALOG_ERROR" },
1237 { DLG_EXIT_ESC, "DIALOG_ESC" },
1238 { DLG_EXIT_EXTRA, "DIALOG_EXTRA" },
1239 { DLG_EXIT_HELP, "DIALOG_HELP" },
1240 { DLG_EXIT_OK, "DIALOG_OK" },
1241 { DLG_EXIT_ITEM_HELP, "DIALOG_ITEM_HELP" },
1249 bool overridden = FALSE;
1252 for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) {
1253 if (table[n].code == code) {
1254 if ((name = getenv(table[n].name)) != 0) {
1255 value = strtol(name, &temp, 0);
1256 if (temp != 0 && temp != name && *temp == '\0') {
1266 * Prior to 2004/12/19, a widget using --item-help would exit with "OK"
1267 * if the help button were selected. Now we want to exit with "HELP",
1268 * but allow the environment variable to override.
1270 if (code == DLG_EXIT_ITEM_HELP && !overridden) {
1271 code = DLG_EXIT_HELP;
1275 _dlg_inputstr_leaks();
1276 #if defined(NCURSES_VERSION) && defined(HAVE__NC_FREE_AND_EXIT)
1277 _nc_free_and_exit(code);
1281 if (dialog_state.input == stdin) {
1285 * Just in case of using --input-fd option, do not
1286 * call atexit functions of ncurses which may hang.
1288 if (dialog_state.input) {
1289 fclose(dialog_state.input);
1290 dialog_state.input = 0;
1292 if (dialog_state.pipe_input) {
1293 if (dialog_state.pipe_input != stdin) {
1294 fclose(dialog_state.pipe_input);
1295 dialog_state.pipe_input = 0;
1302 /* quit program killing all tailbg */
1304 dlg_exiterr(const char *fmt,...)
1311 (void) fputc('\n', stderr);
1313 (void) vfprintf(stderr, fmt, ap);
1315 (void) fputc('\n', stderr);
1317 dlg_killall_bg(&retval);
1319 (void) fflush(stderr);
1320 (void) fflush(stdout);
1321 dlg_exit(DLG_EXIT_ERROR);
1327 if (dialog_vars.beep_signal) {
1329 dialog_vars.beep_signal = 0;
1334 dlg_print_size(int height, int width)
1336 if (dialog_vars.print_siz)
1337 fprintf(dialog_state.output, "Size: %d, %d\n", height, width);
1341 dlg_ctl_size(int height, int width)
1343 if (dialog_vars.size_err) {
1344 if ((width > COLS) || (height > LINES)) {
1345 dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1346 height, width, LINES, COLS);
1349 else if ((dialog_state.use_shadow)
1350 && ((width > SCOLS || height > SLINES))) {
1351 if ((width <= COLS) && (height <= LINES)) {
1352 /* try again, without shadows */
1353 dialog_state.use_shadow = 0;
1355 dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).",
1356 height, width, SLINES, SCOLS);
1364 * If the --tab-correct was not selected, convert tabs to single spaces.
1367 dlg_tab_correct_str(char *prompt)
1371 if (dialog_vars.tab_correct) {
1372 while ((ptr = strchr(prompt, TAB)) != NULL) {
1380 dlg_calc_listh(int *height, int *list_height, int item_no)
1382 /* calculate new height and list_height */
1383 int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0);
1384 if (rows - (*height) > 0) {
1385 if (rows - (*height) > item_no)
1386 *list_height = item_no;
1388 *list_height = rows - (*height);
1390 (*height) += (*list_height);
1395 dlg_calc_listw(int item_no, char **items, int group)
1397 int n, i, len1 = 0, len2 = 0;
1398 for (i = 0; i < (item_no * group); i += group) {
1399 if ((n = dlg_count_columns(items[i])) > len1)
1401 if ((n = dlg_count_columns(items[i + 1])) > len2)
1408 dlg_calc_list_width(int item_no, DIALOG_LISTITEM * items)
1410 int n, i, len1 = 0, len2 = 0;
1411 for (i = 0; i < item_no; ++i) {
1412 if ((n = dlg_count_columns(items[i].name)) > len1)
1414 if ((n = dlg_count_columns(items[i].text)) > len2)
1423 static char empty[] = "";
1428 dlg_strclone(const char *cprompt)
1430 char *prompt = dlg_malloc(char, strlen(cprompt) + 1);
1431 assert_ptr(prompt, "dlg_strclone");
1432 strcpy(prompt, cprompt);
1437 dlg_asciibox(chtype ch)
1441 if (ch == ACS_ULCORNER)
1443 else if (ch == ACS_LLCORNER)
1445 else if (ch == ACS_URCORNER)
1447 else if (ch == ACS_LRCORNER)
1449 else if (ch == ACS_HLINE)
1451 else if (ch == ACS_VLINE)
1453 else if (ch == ACS_LTEE)
1455 else if (ch == ACS_RTEE)
1457 else if (ch == ACS_UARROW)
1459 else if (ch == ACS_DARROW)
1466 dlg_boxchar(chtype ch)
1468 chtype result = dlg_asciibox(ch);
1471 if (dialog_vars.ascii_lines)
1473 else if (dialog_vars.no_lines)
1480 dlg_box_x_ordinate(int width)
1484 if (dialog_vars.begin_set == 1) {
1485 x = dialog_vars.begin_x;
1487 /* center dialog box on screen unless --begin-set */
1488 x = (SCOLS - width) / 2;
1494 dlg_box_y_ordinate(int height)
1498 if (dialog_vars.begin_set == 1) {
1499 y = dialog_vars.begin_y;
1501 /* center dialog box on screen unless --begin-set */
1502 y = (SLINES - height) / 2;
1508 dlg_draw_title(WINDOW *win, const char *title)
1510 if (title != NULL) {
1511 chtype attr = A_NORMAL;
1512 chtype save = getattrs(win);
1513 int x = centered(getmaxx(win), title);
1515 wattrset(win, title_attr);
1517 dlg_print_text(win, title, getmaxx(win) - x, &attr);
1518 wattrset(win, save);
1523 dlg_draw_bottom_box(WINDOW *win)
1525 int width = getmaxx(win);
1526 int height = getmaxy(win);
1529 wattrset(win, border_attr);
1530 (void) wmove(win, height - 3, 0);
1531 (void) waddch(win, dlg_boxchar(ACS_LTEE));
1532 for (i = 0; i < width - 2; i++)
1533 (void) waddch(win, dlg_boxchar(ACS_HLINE));
1534 wattrset(win, dialog_attr);
1535 (void) waddch(win, dlg_boxchar(ACS_RTEE));
1536 (void) wmove(win, height - 2, 1);
1537 for (i = 0; i < width - 2; i++)
1538 (void) waddch(win, ' ');
1542 * Remove a window, repainting everything else. This would be simpler if we
1543 * used the panel library, but that is not _always_ available.
1546 dlg_del_window(WINDOW *win)
1548 DIALOG_WINDOWS *p, *q, *r;
1551 * If --keep-window was set, do not delete/repaint the windows.
1553 if (dialog_vars.keep_window)
1556 /* Leave the main window untouched if there are no background windows.
1557 * We do this so the current window will not be cleared on exit, allowing
1558 * things like the infobox demo to run without flicker.
1560 if (dialog_state.getc_callbacks != 0) {
1562 wnoutrefresh(stdscr);
1565 for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) {
1566 if (p->normal == win) {
1567 q = p; /* found a match - should be only one */
1569 dialog_state.all_windows = p->next;
1574 if (p->shadow != 0) {
1575 touchwin(p->shadow);
1576 wnoutrefresh(p->shadow);
1578 touchwin(p->normal);
1579 wnoutrefresh(p->normal);
1585 dlg_unregister_window(q->normal);
1592 * Create a window, optionally with a shadow.
1595 dlg_new_window(int height, int width, int y, int x)
1598 DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
1600 if ((win = newwin(height, width, y, x)) == 0) {
1601 dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
1602 y, x, height, width);
1604 p->next = dialog_state.all_windows;
1606 dialog_state.all_windows = p;
1608 if (dialog_state.use_shadow) {
1609 draw_childs_shadow(p->shadow = stdscr, win);
1613 (void) keypad(win, TRUE);
1618 dlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x)
1621 DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1);
1624 if ((win = newwin(height, width, y, x)) == 0) {
1625 dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n",
1626 y, x, height, width);
1628 p->next = dialog_state.all_windows;
1630 dialog_state.all_windows = p;
1632 if (dialog_state.use_shadow) {
1633 draw_childs_shadow(p->shadow = parent, win);
1637 (void) keypad(win, TRUE);
1642 * Move/Resize a window, optionally with a shadow.
1646 dlg_move_window(WINDOW *win, int height, int width, int y, int x)
1648 DIALOG_WINDOWS *p, *q;
1651 dlg_ctl_size(height, width);
1653 for (p = dialog_state.all_windows; p != 0; p = q) {
1655 if (p->normal == win) {
1661 (void) wresize(win, height, width);
1662 (void) mvwin(win, y, x);
1664 if (p->shadow != 0) {
1665 if (dialog_state.use_shadow) {
1666 (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS);
1676 draw_childs_shadow(p->shadow, win);
1681 #endif /* KEY_RESIZE */
1684 dlg_sub_window(WINDOW *parent, int height, int width, int y, int x)
1688 if ((win = subwin(parent, height, width, y, x)) == 0) {
1689 dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n",
1690 y, x, height, width);
1693 (void) keypad(win, TRUE);
1699 dlg_default_item(char **items, int llen)
1703 if (dialog_vars.default_item != 0) {
1705 while (*items != 0) {
1706 if (!strcmp(dialog_vars.default_item, *items)) {
1718 dlg_default_listitem(DIALOG_LISTITEM * items)
1722 if (dialog_vars.default_item != 0) {
1724 while (items->name != 0) {
1725 if (!strcmp(dialog_vars.default_item, items->name)) {
1737 * Draw the string for item_help
1740 dlg_item_help(const char *txt)
1742 if (USE_ITEM_HELP(txt)) {
1743 chtype attr = A_NORMAL;
1746 wattrset(stdscr, itemhelp_attr);
1747 (void) wmove(stdscr, LINES - 1, 0);
1748 (void) wclrtoeol(stdscr);
1750 dlg_print_text(stdscr, txt, COLS - 1, &attr);
1751 if (itemhelp_attr & A_COLOR) {
1752 /* fill the remainder of the line with the window's attributes */
1753 getyx(stdscr, y, x);
1759 (void) wnoutrefresh(stdscr);
1763 #ifndef HAVE_STRCASECMP
1765 dlg_strcmp(const char *a, const char *b)
1772 if (isalpha(ac) && islower(ac))
1774 if (isalpha(bc) && islower(bc))
1777 if (ac == 0 || bc == 0 || cmp != 0)
1785 * Returns true if 'dst' points to a blank which follows another blank which
1786 * is not a leading blank on a line.
1789 trim_blank(char *base, char *dst)
1793 while (dst-- != base) {
1796 } else if (*dst != ' ') {
1806 * Change embedded "\n" substrings to '\n' characters and tabs to single
1807 * spaces. If there are no "\n"s, it will strip all extra spaces, for
1808 * justification. If it has "\n"'s, it will preserve extra spaces. If cr_wrap
1809 * is set, it will preserve '\n's.
1812 dlg_trim_string(char *s)
1817 int has_newlines = (strstr(s, "\\n") != 0);
1819 while (*p != '\0') {
1820 if (*p == TAB && !dialog_vars.nocollapse)
1823 if (has_newlines) { /* If prompt contains "\n" strings */
1824 if (*p == '\\' && *(p + 1) == 'n') {
1829 * Handle end of lines intelligently. If '\n' follows "\n"
1830 * then ignore the '\n'. This eliminates the need to escape
1831 * the '\n' character (no need to use "\n\").
1837 } else if (*p == '\n') {
1838 if (dialog_vars.cr_wrap)
1841 /* Replace the '\n' with a space if cr_wrap is not set */
1842 if (!trim_blank(base, s))
1846 } else /* If *p != '\n' */
1848 } else if (dialog_vars.trim_whitespace) {
1850 if (*(s - 1) != ' ') {
1855 } else if (*p == '\n') {
1856 if (dialog_vars.cr_wrap)
1858 else if (*(s - 1) != ' ') {
1859 /* Strip '\n's if cr_wrap is not set. */
1866 } else { /* If there are no "\n" strings */
1867 if (*p == ' ' && !dialog_vars.nocollapse) {
1868 if (!trim_blank(base, s))
1880 dlg_set_focus(WINDOW *parent, WINDOW *win)
1883 (void) wmove(parent,
1884 getpary(win) + getcury(win),
1885 getparx(win) + getcurx(win));
1886 (void) wnoutrefresh(win);
1892 * Returns the nominal maximum buffer size.
1895 dlg_max_input(int max_len)
1897 if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN)
1898 max_len = dialog_vars.max_input;
1904 * Free storage used for the result buffer.
1907 dlg_clr_result(void)
1909 if (dialog_vars.input_length) {
1910 dialog_vars.input_length = 0;
1911 if (dialog_vars.input_result)
1912 free(dialog_vars.input_result);
1914 dialog_vars.input_result = 0;
1918 * Setup a fixed-buffer for the result.
1921 dlg_set_result(const char *string)
1923 unsigned need = string ? strlen(string) + 1 : 0;
1925 /* inputstr.c needs a fixed buffer */
1930 * If the buffer is not big enough, allocate a new one.
1932 if (dialog_vars.input_length != 0
1933 || dialog_vars.input_result == 0
1934 || need > MAX_LEN) {
1938 dialog_vars.input_length = need;
1939 dialog_vars.input_result = dlg_malloc(char, need);
1940 assert_ptr(dialog_vars.input_result, "dlg_set_result");
1943 strcpy(dialog_vars.input_result, string ? string : "");
1945 return dialog_vars.input_result;
1949 * Accumulate results in dynamically allocated buffer.
1950 * If input_length is zero, it is a MAX_LEN buffer belonging to the caller.
1953 dlg_add_result(const char *string)
1955 unsigned have = (dialog_vars.input_result
1956 ? strlen(dialog_vars.input_result)
1958 unsigned want = strlen(string) + 1 + have;
1960 if ((want >= MAX_LEN)
1961 || (dialog_vars.input_length != 0)
1962 || (dialog_vars.input_result == 0)) {
1964 if (dialog_vars.input_length == 0
1965 || dialog_vars.input_result == 0) {
1967 char *save = dialog_vars.input_result;
1969 dialog_vars.input_length = want * 2;
1970 dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length);
1971 assert_ptr(dialog_vars.input_result, "dlg_add_result malloc");
1972 dialog_vars.input_result[0] = 0;
1974 strcpy(dialog_vars.input_result, save);
1975 } else if (want >= dialog_vars.input_length) {
1976 dialog_vars.input_length = want * 2;
1977 dialog_vars.input_result = dlg_realloc(char,
1978 dialog_vars.input_length,
1979 dialog_vars.input_result);
1980 assert_ptr(dialog_vars.input_result, "dlg_add_result realloc");
1983 strcat(dialog_vars.input_result, string);
1987 * These are characters that (aside from the quote-delimiter) will have to
1988 * be escaped in a single- or double-quoted string.
1990 #define FIX_SINGLE "\n\\"
1991 #define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>"
1994 * Returns the quote-delimiter.
1997 quote_delimiter(void)
1999 return dialog_vars.single_quoted ? "'" : "\"";
2003 * Returns true if we should quote the given string.
2006 must_quote(char *string)
2010 if (*string != '\0') {
2011 unsigned len = strlen(string);
2012 if (strcspn(string, quote_delimiter()) != len)
2014 else if (strcspn(string, "\n\t ") != len)
2017 code = (strcspn(string, FIX_DOUBLE) != len);
2026 * Add a quoted string to the result buffer.
2029 dlg_add_quoted(char *string)
2032 const char *my_quote = quote_delimiter();
2033 const char *must_fix = (dialog_vars.single_quoted
2037 if (dialog_vars.quoted || must_quote(string)) {
2039 dlg_add_result(my_quote);
2040 while (*string != '\0') {
2041 temp[0] = *string++;
2042 if (strchr(my_quote, *temp) || strchr(must_fix, *temp))
2043 dlg_add_result("\\");
2044 dlg_add_result(temp);
2046 dlg_add_result(my_quote);
2048 dlg_add_result(string);
2053 * When adding a result, make that depend on whether "--quoted" is used.
2056 dlg_add_string(char *string)
2058 if (dialog_vars.quoted) {
2059 dlg_add_quoted(string);
2061 dlg_add_result(string);
2066 dlg_need_separator(void)
2068 bool result = FALSE;
2070 if (dialog_vars.output_separator) {
2072 } else if (dialog_vars.input_result && *(dialog_vars.input_result)) {
2079 dlg_add_separator(void)
2081 const char *separator = (dialog_vars.separate_output) ? "\n" : " ";
2083 if (dialog_vars.output_separator)
2084 separator = dialog_vars.output_separator;
2086 dlg_add_result(separator);
2090 * Some widgets support only one value of a given variable - save/restore the
2091 * global dialog_vars so we can override it consistently.
2094 dlg_save_vars(DIALOG_VARS * vars)
2096 *vars = dialog_vars;
2100 dlg_restore_vars(DIALOG_VARS * vars)
2102 dialog_vars = *vars;
2106 * Called each time a widget is invoked which may do output, increment a count.
2109 dlg_does_output(void)
2111 dialog_state.output_count += 1;
2115 * Compatibility for different versions of curses.
2117 #if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY))
2119 getbegx(WINDOW *win)
2122 getbegyx(win, y, x);
2126 getbegy(WINDOW *win)
2129 getbegyx(win, y, x);
2134 #if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY))
2136 getcurx(WINDOW *win)
2143 getcury(WINDOW *win)
2151 #if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY))
2153 getmaxx(WINDOW *win)
2156 getmaxyx(win, y, x);
2160 getmaxy(WINDOW *win)
2163 getmaxyx(win, y, x);
2168 #if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY))
2170 getparx(WINDOW *win)
2173 getparyx(win, y, x);
2177 getpary(WINDOW *win)
2180 getparyx(win, y, x);