diff options
Diffstat (limited to 'Build/source/utils/dialog/dialog-1.1-20110118/util.c')
-rw-r--r-- | Build/source/utils/dialog/dialog-1.1-20110118/util.c | 2262 |
1 files changed, 0 insertions, 2262 deletions
diff --git a/Build/source/utils/dialog/dialog-1.1-20110118/util.c b/Build/source/utils/dialog/dialog-1.1-20110118/util.c deleted file mode 100644 index 8496330a3db..00000000000 --- a/Build/source/utils/dialog/dialog-1.1-20110118/util.c +++ /dev/null @@ -1,2262 +0,0 @@ -/* - * $Id: util.c,v 1.211 2011/01/19 00:31:43 tom Exp $ - * - * util.c -- miscellaneous utilities for dialog - * - * Copyright 2000-2010,2011 Thomas E. Dickey - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License, version 2.1 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to - * Free Software Foundation, Inc. - * 51 Franklin St., Fifth Floor - * Boston, MA 02110, USA. - * - * An earlier version of this program lists as authors - * Savio Lam (lam836@cs.cuhk.hk) - */ - -#include <dialog.h> -#include <dlg_keys.h> - -#ifdef NCURSES_VERSION -#if defined(HAVE_NCURSESW_TERM_H) -#include <ncursesw/term.h> -#elif defined(HAVE_NCURSES_TERM_H) -#include <ncurses/term.h> -#else -#include <term.h> -#endif -#endif - -/* globals */ -DIALOG_STATE dialog_state; -DIALOG_VARS dialog_vars; - -#define concat(a,b) a##b - -#ifdef HAVE_RC_FILE -#define RC_DATA(name,comment) , #name "_color", comment " color" -#else -#define RC_DATA(name,comment) /*nothing */ -#endif - -#ifdef HAVE_COLOR -#include <dlg_colors.h> -#define COLOR_DATA(upr) , \ - concat(DLGC_FG_,upr), \ - concat(DLGC_BG_,upr), \ - concat(DLGC_HL_,upr) -#else -#define COLOR_DATA(upr) /*nothing */ -#endif - -#define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) } - -/* - * Table of color and attribute values, default is for mono display. - */ -/* *INDENT-OFF* */ -DIALOG_COLORS dlg_color_table[] = -{ - DATA(A_NORMAL, SCREEN, screen, "Screen"), - DATA(A_NORMAL, SHADOW, shadow, "Shadow"), - DATA(A_REVERSE, DIALOG, dialog, "Dialog box"), - DATA(A_REVERSE, TITLE, title, "Dialog box title"), - DATA(A_REVERSE, BORDER, border, "Dialog box border"), - DATA(A_BOLD, BUTTON_ACTIVE, button_active, "Active button"), - DATA(A_DIM, BUTTON_INACTIVE, button_inactive, "Inactive button"), - DATA(A_UNDERLINE, BUTTON_KEY_ACTIVE, button_key_active, "Active button key"), - DATA(A_UNDERLINE, BUTTON_KEY_INACTIVE, button_key_inactive, "Inactive button key"), - DATA(A_NORMAL, BUTTON_LABEL_ACTIVE, button_label_active, "Active button label"), - DATA(A_NORMAL, BUTTON_LABEL_INACTIVE, button_label_inactive, "Inactive button label"), - DATA(A_REVERSE, INPUTBOX, inputbox, "Input box"), - DATA(A_REVERSE, INPUTBOX_BORDER, inputbox_border, "Input box border"), - DATA(A_REVERSE, SEARCHBOX, searchbox, "Search box"), - DATA(A_REVERSE, SEARCHBOX_TITLE, searchbox_title, "Search box title"), - DATA(A_REVERSE, SEARCHBOX_BORDER, searchbox_border, "Search box border"), - DATA(A_REVERSE, POSITION_INDICATOR, position_indicator, "File position indicator"), - DATA(A_REVERSE, MENUBOX, menubox, "Menu box"), - DATA(A_REVERSE, MENUBOX_BORDER, menubox_border, "Menu box border"), - DATA(A_REVERSE, ITEM, item, "Item"), - DATA(A_NORMAL, ITEM_SELECTED, item_selected, "Selected item"), - DATA(A_REVERSE, TAG, tag, "Tag"), - DATA(A_REVERSE, TAG_SELECTED, tag_selected, "Selected tag"), - DATA(A_NORMAL, TAG_KEY, tag_key, "Tag key"), - DATA(A_BOLD, TAG_KEY_SELECTED, tag_key_selected, "Selected tag key"), - DATA(A_REVERSE, CHECK, check, "Check box"), - DATA(A_REVERSE, CHECK_SELECTED, check_selected, "Selected check box"), - DATA(A_REVERSE, UARROW, uarrow, "Up arrow"), - DATA(A_REVERSE, DARROW, darrow, "Down arrow"), - DATA(A_NORMAL, ITEMHELP, itemhelp, "Item help-text"), - DATA(A_BOLD, FORM_ACTIVE_TEXT, form_active_text, "Active form text"), - DATA(A_REVERSE, FORM_TEXT, form_text, "Form text"), - DATA(A_NORMAL, FORM_ITEM_READONLY, form_item_readonly, "Readonly form item"), - DATA(A_REVERSE, GAUGE, gauge, "Dialog box gauge") -}; -/* *INDENT-ON* */ - -/* - * Display background title if it exists ... - */ -void -dlg_put_backtitle(void) -{ - int i; - - if (dialog_vars.backtitle != NULL) { - chtype attr = A_NORMAL; - int backwidth = dlg_count_columns(dialog_vars.backtitle); - - wattrset(stdscr, screen_attr); - (void) wmove(stdscr, 0, 1); - dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr); - for (i = 0; i < COLS - backwidth; i++) - (void) waddch(stdscr, ' '); - (void) wmove(stdscr, 1, 1); - for (i = 0; i < COLS - 2; i++) - (void) waddch(stdscr, dlg_boxchar(ACS_HLINE)); - } - - (void) wnoutrefresh(stdscr); -} - -/* - * Set window to attribute 'attr'. There are more efficient ways to do this, - * but will not work on older/buggy ncurses versions. - */ -void -dlg_attr_clear(WINDOW *win, int height, int width, chtype attr) -{ - int i, j; - - wattrset(win, attr); - for (i = 0; i < height; i++) { - (void) wmove(win, i, 0); - for (j = 0; j < width; j++) - (void) waddch(win, ' '); - } - (void) touchwin(win); -} - -void -dlg_clear(void) -{ - dlg_attr_clear(stdscr, LINES, COLS, screen_attr); -} - -#define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0) - -#define TTY_DEVICE "/dev/tty" - -/* - * If $DIALOG_TTY exists, allow the program to try to open the terminal - * directly when stdout is redirected. By default we require the "--stdout" - * option to be given, but some scripts were written making use of the - * behavior of dialog which tried opening the terminal anyway. - */ -static char * -dialog_tty(void) -{ - char *result = getenv("DIALOG_TTY"); - if (result != 0 && atoi(result) == 0) - result = 0; - return result; -} - -/* - * Open the terminal directly. If one of stdin, stdout or stderr really points - * to a tty, use it. Otherwise give up and open /dev/tty. - */ -static int -open_terminal(char **result, int mode) -{ - const char *device = TTY_DEVICE; - if (!isatty(fileno(stderr)) - || (device = ttyname(fileno(stderr))) == 0) { - if (!isatty(fileno(stdout)) - || (device = ttyname(fileno(stdout))) == 0) { - if (!isatty(fileno(stdin)) - || (device = ttyname(fileno(stdin))) == 0) { - device = TTY_DEVICE; - } - } - } - *result = dlg_strclone(device); - return open(device, mode); -} - -/* - * Do some initialization for dialog. - * - * 'input' is the real tty input of dialog. Usually it is stdin, but if - * --input-fd option is used, it may be anything. - * - * 'output' is where dialog will send its result. Usually it is stderr, but - * if --stdout or --output-fd is used, it may be anything. We are concerned - * mainly with the case where it happens to be the same as stdout. - */ -void -init_dialog(FILE *input, FILE *output) -{ - int fd1, fd2; - char *device = 0; - - dialog_state.output = output; - dialog_state.tab_len = TAB_LEN; - dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO; -#ifdef HAVE_COLOR - dialog_state.use_colors = USE_COLORS; /* use colors by default? */ - dialog_state.use_shadow = USE_SHADOW; /* shadow dialog boxes by default? */ -#endif - -#ifdef HAVE_RC_FILE - if (dlg_parse_rc() == -1) /* Read the configuration file */ - dlg_exiterr("init_dialog: dlg_parse_rc"); -#endif - - /* - * Some widgets (such as gauge) may read from the standard input. Pipes - * only connect stdout/stdin, so there is not much choice. But reading a - * pipe would get in the way of curses' normal reading stdin for getch. - * - * As in the --stdout (see below), reopening the terminal does not always - * work properly. dialog provides a --pipe-fd option for this purpose. We - * test that case first (differing fileno's for input/stdin). If the - * fileno's are equal, but we're not reading from a tty, see if we can open - * /dev/tty. - */ - dialog_state.pipe_input = stdin; - if (fileno(input) != fileno(stdin)) { - if ((fd1 = dup(fileno(input))) >= 0 - && (fd2 = dup(fileno(stdin))) >= 0) { - (void) dup2(fileno(input), fileno(stdin)); - dialog_state.pipe_input = fdopen(fd2, "r"); - if (fileno(stdin) != 0) /* some functions may read fd #0 */ - (void) dup2(fileno(stdin), 0); - } else - dlg_exiterr("cannot open tty-input"); - } else if (!isatty(fileno(stdin))) { - if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0 - && (fd2 = dup(fileno(stdin))) >= 0) { - dialog_state.pipe_input = fdopen(fd2, "r"); - if (freopen(device, "r", stdin) == 0) - dlg_exiterr("cannot open tty-input"); - if (fileno(stdin) != 0) /* some functions may read fd #0 */ - (void) dup2(fileno(stdin), 0); - } - free(device); - } - - /* - * If stdout is not a tty and dialog is called with the --stdout option, we - * have to provide for a way to write to the screen. - * - * The curses library normally writes its output to stdout, leaving stderr - * free for scripting. Scripts are simpler when stdout is redirected. The - * newterm function is useful; it allows us to specify where the output - * goes. Reopening the terminal is not portable since several - * configurations do not allow this to work properly: - * - * a) some getty implementations (and possibly broken tty drivers, e.g., on - * HPUX 10 and 11) cause stdin to act as if it is still in cooked mode - * even though results from ioctl's state that it is successfully - * altered to raw mode. Broken is the proper term. - * - * b) the user may not have permissions on the device, e.g., if one su's - * from the login user to another non-privileged user. - */ - if (!isatty(fileno(stdout)) - && (fileno(stdout) == fileno(output) || dialog_tty())) { - if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0 - && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) { - if (newterm(NULL, dialog_state.screen_output, stdin) == 0) { - dlg_exiterr("cannot initialize curses"); - } - free(device); - } else { - dlg_exiterr("cannot open tty-output"); - } - } else { - dialog_state.screen_output = stdout; - (void) initscr(); - } -#ifdef NCURSES_VERSION - /* - * Cancel xterm's alternate-screen mode. - */ - if (!dialog_vars.keep_tite - && (dialog_state.screen_output != stdout - || isatty(fileno(dialog_state.screen_output))) - && key_mouse != 0 /* xterm and kindred */ - && isprivate(enter_ca_mode) - && isprivate(exit_ca_mode)) { - /* - * initscr() or newterm() already did putp(enter_ca_mode) as a side - * effect of initializing the screen. It would be nice to not even - * do that, but we do not really have access to the correct copy of - * the terminfo description until those functions have been invoked. - */ - (void) putp(exit_ca_mode); - (void) putp(clear_screen); - /* - * Prevent ncurses from switching "back" to the normal screen when - * exiting from dialog. That would move the cursor to the original - * location saved in xterm. Normally curses sets the cursor position - * to the first line after the display, but the alternate screen - * switching is done after that point. - * - * Cancelling the strings altogether also works around the buggy - * implementation of alternate-screen in rxvt, etc., which clear - * more of the display than they should. - */ - enter_ca_mode = 0; - exit_ca_mode = 0; - } -#endif -#ifdef HAVE_FLUSHINP - (void) flushinp(); -#endif - (void) keypad(stdscr, TRUE); - (void) cbreak(); - (void) noecho(); - - if (!dialog_state.no_mouse) { - mouse_open(); - } - - dialog_state.screen_initialized = TRUE; - -#ifdef HAVE_COLOR - if (dialog_state.use_colors || dialog_state.use_shadow) - dlg_color_setup(); /* Set up colors */ -#endif - - /* Set screen to screen attribute */ - dlg_clear(); -} - -#ifdef HAVE_COLOR -static int defined_colors = 1; /* pair-0 is reserved */ -/* - * Setup for color display - */ -void -dlg_color_setup(void) -{ - unsigned i; - - if (has_colors()) { /* Terminal supports color? */ - (void) start_color(); - -#if defined(HAVE_USE_DEFAULT_COLORS) - use_default_colors(); -#endif - -#if defined(__NetBSD__) && defined(_CURSES_) -#define C_ATTR(x,y) (((x) != 0 ? A_BOLD : 0) | COLOR_PAIR((y))) - /* work around bug in NetBSD curses */ - for (i = 0; i < sizeof(dlg_color_table) / - sizeof(dlg_color_table[0]); i++) { - - /* Initialize color pairs */ - (void) init_pair(i + 1, - dlg_color_table[i].fg, - dlg_color_table[i].bg); - - /* Setup color attributes */ - dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1); - } - defined_colors = i + 1; -#else - for (i = 0; i < sizeof(dlg_color_table) / - sizeof(dlg_color_table[0]); i++) { - - /* Initialize color pairs */ - chtype color = dlg_color_pair(dlg_color_table[i].fg, - dlg_color_table[i].bg); - - /* Setup color attributes */ - dlg_color_table[i].atr = ((dlg_color_table[i].hilite - ? A_BOLD - : 0) - | color); - } -#endif - } else { - dialog_state.use_colors = FALSE; - dialog_state.use_shadow = FALSE; - } -} - -int -dlg_color_count(void) -{ - return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]); -} - -/* - * Wrapper for getattrs(), or the more cumbersome X/Open wattr_get(). - */ -chtype -dlg_get_attrs(WINDOW *win) -{ - chtype result; -#ifdef HAVE_GETATTRS - result = getattrs(win); -#else - attr_t my_result; - short my_pair; - wattr_get(win, &my_result, &my_pair, NULL); - result = my_result; -#endif - return result; -} - -/* - * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we - * have (or can) define a pair with the given color as foreground on the - * window's defined background. - */ -chtype -dlg_color_pair(int foreground, int background) -{ - chtype result = 0; - int pair; - short fg, bg; - bool found = FALSE; - - for (pair = 1; pair < defined_colors; ++pair) { - if (pair_content((short) pair, &fg, &bg) != ERR - && fg == foreground - && bg == background) { - result = (chtype) COLOR_PAIR(pair); - found = TRUE; - break; - } - } - if (!found && (defined_colors + 1) < COLOR_PAIRS) { - pair = defined_colors++; - (void) init_pair((short) pair, (short) foreground, (short) background); - result = (chtype) COLOR_PAIR(pair); - } - return result; -} - -/* - * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we - * have (or can) define a pair with the given color as foreground on the - * window's defined background. - */ -static chtype -define_color(WINDOW *win, int foreground) -{ - chtype attrs = dlg_get_attrs(win); - int pair; - short fg, bg, background; - - if ((pair = PAIR_NUMBER(attrs)) != 0 - && pair_content((short) pair, &fg, &bg) != ERR) { - background = bg; - } else { - background = COLOR_BLACK; - } - return dlg_color_pair(foreground, background); -} -#endif - -/* - * End using dialog functions. - */ -void -end_dialog(void) -{ - if (dialog_state.screen_initialized) { - dialog_state.screen_initialized = FALSE; - mouse_close(); - (void) endwin(); - (void) fflush(stdout); - } -} - -#define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0)) - -static int -centered(int width, const char *string) -{ - int len = dlg_count_columns(string); - int left; - int hide = 0; - int n; - - if (dialog_vars.colors) { - for (n = 0; n < len; ++n) { - if (isOurEscape(string + n)) { - hide += 3; - } - } - } - left = (width - (len - hide)) / 2 - 1; - if (left < 0) - left = 0; - return left; -} - -#ifdef USE_WIDE_CURSES -static bool -is_combining(const char *txt, int *combined) -{ - bool result = FALSE; - - if (*combined == 0) { - if (UCH(*txt) >= 128) { - wchar_t wch; - mbstate_t state; - size_t given = strlen(txt); - size_t len; - - memset(&state, 0, sizeof(state)); - len = mbrtowc(&wch, txt, given, &state); - if ((int) len > 0 && wcwidth(wch) == 0) { - *combined = (int) len - 1; - result = TRUE; - } - } - } else { - result = TRUE; - *combined -= 1; - } - return result; -} -#endif - -/* - * Print up to 'cols' columns from 'text', optionally rendering our escape - * sequence for attributes and color. - */ -void -dlg_print_text(WINDOW *win, const char *txt, int cols, chtype *attr) -{ - int y_origin, x_origin; - int y_before, x_before = 0; - int y_after, x_after; - int tabbed = 0; - bool thisTab; - bool ended = FALSE; - chtype useattr; -#ifdef USE_WIDE_CURSES - int combined = 0; -#endif - - getyx(win, y_origin, x_origin); - while (cols > 0 && (*txt != '\0')) { - if (dialog_vars.colors) { - while (isOurEscape(txt)) { - int code; - - txt += 2; - switch (code = CharOf(*txt)) { -#ifdef HAVE_COLOR - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - *attr &= ~A_COLOR; - *attr |= define_color(win, code - '0'); - break; -#endif - case 'B': - *attr &= ~A_BOLD; - break; - case 'b': - *attr |= A_BOLD; - break; - case 'R': - *attr &= ~A_REVERSE; - break; - case 'r': - *attr |= A_REVERSE; - break; - case 'U': - *attr &= ~A_UNDERLINE; - break; - case 'u': - *attr |= A_UNDERLINE; - break; - case 'n': - *attr = A_NORMAL; - break; - } - ++txt; - } - } - if (ended || *txt == '\n' || *txt == '\0') - break; - useattr = (*attr) & A_ATTRIBUTES; -#ifdef HAVE_COLOR - /* - * Prevent this from making text invisible when the foreground and - * background colors happen to be the same, and there's no bold - * attribute. - */ - if ((useattr & A_COLOR) != 0 && (useattr & A_BOLD) == 0) { - short pair = (short) PAIR_NUMBER(useattr); - short fg, bg; - if (pair_content(pair, &fg, &bg) != ERR - && fg == bg) { - useattr &= ~A_COLOR; - useattr |= dlg_color_pair(fg, ((bg == COLOR_BLACK) - ? COLOR_WHITE - : COLOR_BLACK)); - } - } -#endif - /* - * Write the character, using curses to tell exactly how wide it - * is. If it is a tab, discount that, since the caller thinks - * tabs are nonprinting, and curses will expand tabs to one or - * more blanks. - */ - thisTab = (CharOf(*txt) == TAB); - if (thisTab) - getyx(win, y_before, x_before); - (void) waddch(win, CharOf(*txt++) | useattr); - getyx(win, y_after, x_after); - if (thisTab && (y_after == y_origin)) - tabbed += (x_after - x_before); - if ((y_after != y_origin) || - (x_after >= (cols + tabbed + x_origin) -#ifdef USE_WIDE_CURSES - && !is_combining(txt, &combined) -#endif - )) { - ended = TRUE; - } - } -} - -/* - * Print one line of the prompt in the window within the limits of the - * specified right margin. The line will end on a word boundary and a pointer - * to the start of the next line is returned, or a NULL pointer if the end of - * *prompt is reached. - */ -const char * -dlg_print_line(WINDOW *win, - chtype *attr, - const char *prompt, - int lm, int rm, int *x) -{ - const char *wrap_ptr = prompt; - const char *test_ptr = prompt; - const int *cols = dlg_index_columns(prompt); - const int *indx = dlg_index_wchars(prompt); - int wrap_inx = 0; - int test_inx = 0; - int cur_x = lm; - int hidden = 0; - int limit = dlg_count_wchars(prompt); - int n; - int tabbed = 0; - - *x = 1; - - /* - * Set *test_ptr to the end of the line or the right margin (rm), whichever - * is less, and set wrap_ptr to the end of the last word in the line. - */ - for (n = 0; n < limit; ++n) { - test_ptr = prompt + indx[test_inx]; - if (*test_ptr == '\n' || *test_ptr == '\0' || cur_x >= (rm + hidden)) - break; - if (*test_ptr == TAB && n == 0) { - tabbed = 8; /* workaround for leading tabs */ - } else if (*test_ptr == ' ' && n != 0 && prompt[indx[n - 1]] != ' ') { - wrap_inx = n; - *x = cur_x; - } else if (isOurEscape(test_ptr)) { - hidden += 3; - n += 2; - } - cur_x = lm + tabbed + cols[n + 1]; - if (cur_x > (rm + hidden)) - break; - test_inx = n + 1; - } - - /* - * If the line doesn't reach the right margin in the middle of a word, then - * we don't have to wrap it at the end of the previous word. - */ - test_ptr = prompt + indx[test_inx]; - if (*test_ptr == '\n' || *test_ptr == ' ' || *test_ptr == '\0') { - wrap_inx = test_inx; - while (wrap_inx > 0 && prompt[indx[wrap_inx - 1]] == ' ') { - wrap_inx--; - } - *x = lm + indx[wrap_inx]; - } else if (*x == 1 && cur_x >= rm) { - /* - * If the line has no spaces, then wrap it anyway at the right margin - */ - *x = rm; - wrap_inx = test_inx; - } - wrap_ptr = prompt + indx[wrap_inx]; -#ifdef USE_WIDE_CURSES - if (UCH(*wrap_ptr) >= 128) { - int combined = 0; - while (is_combining(wrap_ptr, &combined)) { - ++wrap_ptr; - } - } -#endif - - /* - * Print the line if we have a window pointer. Otherwise this routine - * is just being called for sizing the window. - */ - if (win) { - dlg_print_text(win, prompt, (cols[wrap_inx] - hidden), attr); - } - - /* *x tells the calling function how long the line was */ - if (*x == 1) - *x = rm; - - /* Find the start of the next line and return a pointer to it */ - test_ptr = wrap_ptr; - while (*test_ptr == ' ') - test_ptr++; - if (*test_ptr == '\n') - test_ptr++; - return (test_ptr); -} - -static void -justify_text(WINDOW *win, - const char *prompt, - int limit_y, - int limit_x, - int *high, int *wide) -{ - chtype attr = A_NORMAL; - int x = (2 * MARGIN); - int y = MARGIN; - int max_x = 2; - int lm = (2 * MARGIN); /* left margin (box-border plus a space) */ - int rm = limit_x; /* right margin */ - int bm = limit_y; /* bottom margin */ - int last_y = 0, last_x = 0; - - if (win) { - rm -= (2 * MARGIN); - bm -= (2 * MARGIN); - } - if (prompt == 0) - prompt = ""; - - if (win != 0) - getyx(win, last_y, last_x); - while (y <= bm && *prompt) { - x = lm; - - if (*prompt == '\n') { - while (*prompt == '\n' && y < bm) { - if (*(prompt + 1) != '\0') { - ++y; - if (win != 0) - (void) wmove(win, y, lm); - } - prompt++; - } - } else if (win != 0) - (void) wmove(win, y, lm); - - if (*prompt) { - prompt = dlg_print_line(win, &attr, prompt, lm, rm, &x); - if (win != 0) - getyx(win, last_y, last_x); - } - if (*prompt) { - ++y; - if (win != 0) - (void) wmove(win, y, lm); - } - max_x = MAX(max_x, x); - } - /* Move back to the last position after drawing prompt, for msgbox. */ - if (win != 0) - (void) wmove(win, last_y, last_x); - - /* Set the final height and width for the calling function */ - if (high != 0) - *high = y; - if (wide != 0) - *wide = max_x; -} - -/* - * Print a string of text in a window, automatically wrap around to the next - * line if the string is too long to fit on one line. Note that the string may - * contain embedded newlines. - */ -void -dlg_print_autowrap(WINDOW *win, const char *prompt, int height, int width) -{ - justify_text(win, prompt, - height, - width, - (int *) 0, (int *) 0); -} - -/* - * Display the message in a scrollable window. Actually the way it works is - * that we create a "tall" window of the proper width, let the text wrap within - * that, and copy a slice of the result to the dialog. - * - * It works for ncurses. Other curses implementations show only blanks (Tru64) - * or garbage (NetBSD). - */ -int -dlg_print_scrolled(WINDOW *win, - const char *prompt, - int offset, - int height, - int width, - int pauseopt) -{ - int oldy, oldx; - int last = 0; - - (void) pauseopt; /* used only for ncurses */ - - getyx(win, oldy, oldx); -#ifdef NCURSES_VERSION - if (pauseopt) { - int wide = width - (2 * MARGIN); - int high = LINES; - int y, x; - int len; - int percent; - WINDOW *dummy; - char buffer[5]; - -#if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH >= 20040417 - /* - * If we're not limited by the screensize, allow text to possibly be - * one character per line. - */ - if ((len = dlg_count_columns(prompt)) > high) - high = len; -#endif - dummy = newwin(high, width, 0, 0); - wbkgdset(dummy, dialog_attr | ' '); - wattrset(dummy, dialog_attr); - werase(dummy); - dlg_print_autowrap(dummy, prompt, high, width); - getyx(dummy, y, x); - - copywin(dummy, /* srcwin */ - win, /* dstwin */ - offset + MARGIN, /* sminrow */ - MARGIN, /* smincol */ - MARGIN, /* dminrow */ - MARGIN, /* dmincol */ - height, /* dmaxrow */ - wide, /* dmaxcol */ - FALSE); - - delwin(dummy); - - /* if the text is incomplete, or we have scrolled, show the percentage */ - if (y > 0 && wide > 4) { - percent = (int) ((height + offset) * 100.0 / y); - if (percent < 0) - percent = 0; - if (percent > 100) - percent = 100; - if (offset != 0 || percent != 100) { - (void) wattrset(win, position_indicator_attr); - (void) wmove(win, MARGIN + height, wide - 4); - (void) sprintf(buffer, "%d%%", percent); - (void) waddstr(win, buffer); - if ((len = (int) strlen(buffer)) < 4) { - wattrset(win, border_attr); - whline(win, dlg_boxchar(ACS_HLINE), 4 - len); - } - } - } - last = (y - height); - } else -#endif - { - (void) offset; - wattrset(win, dialog_attr); - dlg_print_autowrap(win, prompt, height + 1 + (3 * MARGIN), width); - last = 0; - } - wmove(win, oldy, oldx); - return last; -} - -int -dlg_check_scrolled(int key, int last, int page, bool * show, int *offset) -{ - int code = 0; - - *show = FALSE; - - switch (key) { - case DLGK_PAGE_FIRST: - if (*offset > 0) { - *offset = 0; - *show = TRUE; - } - break; - case DLGK_PAGE_LAST: - if (*offset < last) { - *offset = last; - *show = TRUE; - } - break; - case DLGK_GRID_UP: - if (*offset > 0) { - --(*offset); - *show = TRUE; - } - break; - case DLGK_GRID_DOWN: - if (*offset < last) { - ++(*offset); - *show = TRUE; - } - break; - case DLGK_PAGE_PREV: - if (*offset > 0) { - *offset -= page; - if (*offset < 0) - *offset = 0; - *show = TRUE; - } - break; - case DLGK_PAGE_NEXT: - if (*offset < last) { - *offset += page; - if (*offset > last) - *offset = last; - *show = TRUE; - } - break; - default: - code = -1; - break; - } - return code; -} - -/* - * Calculate the window size for preformatted text. This will calculate box - * dimensions that are at or close to the specified aspect ratio for the prompt - * string with all spaces and newlines preserved and additional newlines added - * as necessary. - */ -static void -auto_size_preformatted(const char *prompt, int *height, int *width) -{ - int high = 0, wide = 0; - float car; /* Calculated Aspect Ratio */ - float diff; - int max_y = SLINES - 1; - int max_x = SCOLS - 2; - int max_width = max_x; - int ar = dialog_state.aspect_ratio; - - /* Get the initial dimensions */ - justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); - car = (float) (wide / high); - - /* - * If the aspect ratio is greater than it should be, then decrease the - * width proportionately. - */ - if (car > ar) { - diff = car / (float) ar; - max_x = (int) ((float) wide / diff + 4); - justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); - car = (float) wide / (float) high; - } - - /* - * If the aspect ratio is too small after decreasing the width, then - * incrementally increase the width until the aspect ratio is equal to or - * greater than the specified aspect ratio. - */ - while (car < ar && max_x < max_width) { - max_x += 4; - justify_text((WINDOW *) 0, prompt, max_y, max_x, &high, &wide); - car = (float) (wide / high); - } - - *height = high; - *width = wide; -} - -/* - * Find the length of the longest "word" in the given string. By setting the - * widget width at least this long, we can avoid splitting a word on the - * margin. - */ -static int -longest_word(const char *string) -{ - int length, result = 0; - - while (*string != '\0') { - length = 0; - while (*string != '\0' && !isspace(UCH(*string))) { - length++; - string++; - } - result = MAX(result, length); - if (*string != '\0') - string++; - } - return result; -} - -/* - * if (height or width == -1) Maximize() - * if (height or width == 0), justify and return actual limits. - */ -static void -real_auto_size(const char *title, - const char *prompt, - int *height, int *width, - int boxlines, int mincols) -{ - int x = (dialog_vars.begin_set ? dialog_vars.begin_x : 2); - int y = (dialog_vars.begin_set ? dialog_vars.begin_y : 1); - int title_length = title ? dlg_count_columns(title) : 0; - int nc = 4; - int high; - int wide; - int save_high = *height; - int save_wide = *width; - - if (prompt == 0) { - if (*height == 0) - *height = -1; - if (*width == 0) - *width = -1; - } - - if (*height > 0) { - high = *height; - } else { - high = SLINES - y; - } - - if (*width > 0) { - wide = *width; - } else if (prompt != 0) { - wide = MAX(title_length, mincols); - if (strchr(prompt, '\n') == 0) { - double val = dialog_state.aspect_ratio * dlg_count_columns(prompt); - double xxx = sqrt(val); - int tmp = (int) xxx; - wide = MAX(wide, tmp); - wide = MAX(wide, longest_word(prompt)); - justify_text((WINDOW *) 0, prompt, high, wide, height, width); - } else { - auto_size_preformatted(prompt, height, width); - } - } else { - wide = SCOLS - x; - justify_text((WINDOW *) 0, prompt, high, wide, height, width); - } - - if (*width < title_length) { - justify_text((WINDOW *) 0, prompt, high, title_length, height, width); - *width = title_length; - } - - if (*width < mincols && save_wide == 0) - *width = mincols; - if (prompt != 0) { - *width += nc; - *height += boxlines + 2; - } - if (save_high > 0) - *height = save_high; - if (save_wide > 0) - *width = save_wide; -} - -/* End of real_auto_size() */ - -void -dlg_auto_size(const char *title, - const char *prompt, - int *height, - int *width, - int boxlines, - int mincols) -{ - real_auto_size(title, prompt, height, width, boxlines, mincols); - - if (*width > SCOLS) { - (*height)++; - *width = SCOLS; - } - - if (*height > SLINES) - *height = SLINES; -} - -/* - * if (height or width == -1) Maximize() - * if (height or width == 0) - * height=MIN(SLINES, num.lines in fd+n); - * width=MIN(SCOLS, MAX(longer line+n, mincols)); - */ -void -dlg_auto_sizefile(const char *title, - const char *file, - int *height, - int *width, - int boxlines, - int mincols) -{ - int count = 0; - int len = title ? dlg_count_columns(title) : 0; - int nc = 4; - int numlines = 2; - long offset; - int ch; - FILE *fd; - - /* Open input file for reading */ - if ((fd = fopen(file, "rb")) == NULL) - dlg_exiterr("dlg_auto_sizefile: Cannot open input file %s", file); - - if ((*height == -1) || (*width == -1)) { - *height = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0); - *width = SCOLS - (dialog_vars.begin_set ? dialog_vars.begin_x : 0); - } - if ((*height != 0) && (*width != 0)) { - (void) fclose(fd); - if (*width > SCOLS) - *width = SCOLS; - if (*height > SLINES) - *height = SLINES; - return; - } - - while (!feof(fd)) { - offset = 0; - while (((ch = getc(fd)) != '\n') && !feof(fd)) - if ((ch == TAB) && (dialog_vars.tab_correct)) - offset += dialog_state.tab_len - (offset % dialog_state.tab_len); - else - offset++; - - if (offset > len) - len = (int) offset; - - count++; - } - - /* now 'count' has the number of lines of fd and 'len' the max length */ - - *height = MIN(SLINES, count + numlines + boxlines); - *width = MIN(SCOLS, MAX((len + nc), mincols)); - /* here width and height can be maximized if > SCOLS|SLINES because - textbox-like widgets don't put all <file> on the screen. - Msgbox-like widget instead have to put all <text> correctly. */ - - (void) fclose(fd); -} - -/* - * Draw a rectangular box with line drawing characters. - * - * borderchar is used to color the upper/left edges. - * - * boxchar is used to color the right/lower edges. It also is fill-color used - * for the box contents. - * - * Normally, if you are drawing a scrollable box, use menubox_border_attr for - * boxchar, and menubox_attr for borderchar since the scroll-arrows are drawn - * with menubox_attr at the top, and menubox_border_attr at the bottom. That - * also (given the default color choices) produces a recessed effect. - * - * If you want a raised effect (and are not going to use the scroll-arrows), - * reverse this choice. - */ -void -dlg_draw_box(WINDOW *win, int y, int x, int height, int width, - chtype boxchar, chtype borderchar) -{ - int i, j; - chtype save = dlg_get_attrs(win); - - wattrset(win, 0); - for (i = 0; i < height; i++) { - (void) wmove(win, y + i, x); - for (j = 0; j < width; j++) - if (!i && !j) - (void) waddch(win, borderchar | dlg_boxchar(ACS_ULCORNER)); - else if (i == height - 1 && !j) - (void) waddch(win, borderchar | dlg_boxchar(ACS_LLCORNER)); - else if (!i && j == width - 1) - (void) waddch(win, boxchar | dlg_boxchar(ACS_URCORNER)); - else if (i == height - 1 && j == width - 1) - (void) waddch(win, boxchar | dlg_boxchar(ACS_LRCORNER)); - else if (!i) - (void) waddch(win, borderchar | dlg_boxchar(ACS_HLINE)); - else if (i == height - 1) - (void) waddch(win, boxchar | dlg_boxchar(ACS_HLINE)); - else if (!j) - (void) waddch(win, borderchar | dlg_boxchar(ACS_VLINE)); - else if (j == width - 1) - (void) waddch(win, boxchar | dlg_boxchar(ACS_VLINE)); - else - (void) waddch(win, boxchar | ' '); - } - wattrset(win, save); -} - -#ifdef HAVE_COLOR -/* - * Draw a shadow on the parent window corresponding to the right- and - * bottom-edge of the child window, to give a 3-dimensional look. - */ -static void -draw_childs_shadow(WINDOW *parent, WINDOW *child) -{ - if (has_colors()) { /* Whether terminal supports color? */ - chtype save = dlg_get_attrs(parent); - - dlg_draw_shadow(parent, - getbegy(child) - getbegy(parent), - getbegx(child) - getbegx(parent), - getmaxy(child), - getmaxx(child)); - wattrset(parent, save); - } -} - -/* - * Draw shadows along the right and bottom edge to give a more 3D look - * to the boxes - */ -void -dlg_draw_shadow(WINDOW *win, int y, int x, int height, int width) -{ - int i, j; - - if (has_colors()) { /* Whether terminal supports color? */ - wattrset(win, shadow_attr); - for (i = 0; i < SHADOW_ROWS; ++i) { - for (j = 0; j < width; ++j) { - if (wmove(win, i + y + height, j + x + SHADOW_COLS) != ERR) { - (void) waddch(win, winch(win) & (chtype) (~A_COLOR)); - } - } - } - for (i = 0; i < height; i++) { - for (j = 0; j < SHADOW_COLS; ++j) { - if (wmove(win, i + y + SHADOW_ROWS, j + x + width) != ERR) { - (void) waddch(win, winch(win) & (chtype) (~A_COLOR)); - } - } - } - (void) wnoutrefresh(win); - } -} -#endif /* HAVE_COLOR */ - -/* - * Allow shell scripts to remap the exit codes so they can distinguish ESC - * from ERROR. - */ -void -dlg_exit(int code) -{ - /* *INDENT-OFF* */ - static const struct { - int code; - const char *name; - } table[] = { - { DLG_EXIT_CANCEL, "DIALOG_CANCEL" }, - { DLG_EXIT_ERROR, "DIALOG_ERROR" }, - { DLG_EXIT_ESC, "DIALOG_ESC" }, - { DLG_EXIT_EXTRA, "DIALOG_EXTRA" }, - { DLG_EXIT_HELP, "DIALOG_HELP" }, - { DLG_EXIT_OK, "DIALOG_OK" }, - { DLG_EXIT_ITEM_HELP, "DIALOG_ITEM_HELP" }, - }; - /* *INDENT-ON* */ - - unsigned n; - char *name; - char *temp; - long value; - bool overridden = FALSE; - - retry: - for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) { - if (table[n].code == code) { - if ((name = getenv(table[n].name)) != 0) { - value = strtol(name, &temp, 0); - if (temp != 0 && temp != name && *temp == '\0') { - code = (int) value; - overridden = TRUE; - } - } - break; - } - } - - /* - * Prior to 2004/12/19, a widget using --item-help would exit with "OK" - * if the help button were selected. Now we want to exit with "HELP", - * but allow the environment variable to override. - */ - if (code == DLG_EXIT_ITEM_HELP && !overridden) { - code = DLG_EXIT_HELP; - goto retry; - } -#ifdef NO_LEAKS - _dlg_inputstr_leaks(); -#if defined(NCURSES_VERSION) && defined(HAVE__NC_FREE_AND_EXIT) - _nc_free_and_exit(code); -#endif -#endif - - if (dialog_state.input == stdin) { - exit(code); - } else { - /* - * Just in case of using --input-fd option, do not - * call atexit functions of ncurses which may hang. - */ - if (dialog_state.input) { - fclose(dialog_state.input); - dialog_state.input = 0; - } - if (dialog_state.pipe_input) { - if (dialog_state.pipe_input != stdin) { - fclose(dialog_state.pipe_input); - dialog_state.pipe_input = 0; - } - } - _exit(code); - } -} - -/* quit program killing all tailbg */ -void -dlg_exiterr(const char *fmt,...) -{ - int retval; - va_list ap; - - end_dialog(); - - (void) fputc('\n', stderr); - va_start(ap, fmt); - (void) vfprintf(stderr, fmt, ap); - va_end(ap); - (void) fputc('\n', stderr); - - dlg_killall_bg(&retval); - - (void) fflush(stderr); - (void) fflush(stdout); - dlg_exit(DLG_EXIT_ERROR); -} - -void -dlg_beeping(void) -{ - if (dialog_vars.beep_signal) { - (void) beep(); - dialog_vars.beep_signal = 0; - } -} - -void -dlg_print_size(int height, int width) -{ - if (dialog_vars.print_siz) - fprintf(dialog_state.output, "Size: %d, %d\n", height, width); -} - -void -dlg_ctl_size(int height, int width) -{ - if (dialog_vars.size_err) { - if ((width > COLS) || (height > LINES)) { - dlg_exiterr("Window too big. (height, width) = (%d, %d). Max allowed (%d, %d).", - height, width, LINES, COLS); - } -#ifdef HAVE_COLOR - else if ((dialog_state.use_shadow) - && ((width > SCOLS || height > SLINES))) { - if ((width <= COLS) && (height <= LINES)) { - /* try again, without shadows */ - dialog_state.use_shadow = 0; - } else { - dlg_exiterr("Window+Shadow too big. (height, width) = (%d, %d). Max allowed (%d, %d).", - height, width, SLINES, SCOLS); - } - } -#endif - } -} - -/* - * If the --tab-correct was not selected, convert tabs to single spaces. - */ -void -dlg_tab_correct_str(char *prompt) -{ - char *ptr; - - if (dialog_vars.tab_correct) { - while ((ptr = strchr(prompt, TAB)) != NULL) { - *ptr = ' '; - prompt = ptr; - } - } -} - -void -dlg_calc_listh(int *height, int *list_height, int item_no) -{ - /* calculate new height and list_height */ - int rows = SLINES - (dialog_vars.begin_set ? dialog_vars.begin_y : 0); - if (rows - (*height) > 0) { - if (rows - (*height) > item_no) - *list_height = item_no; - else - *list_height = rows - (*height); - } - (*height) += (*list_height); -} - -/* obsolete */ -int -dlg_calc_listw(int item_no, char **items, int group) -{ - int n, i, len1 = 0, len2 = 0; - for (i = 0; i < (item_no * group); i += group) { - if ((n = dlg_count_columns(items[i])) > len1) - len1 = n; - if ((n = dlg_count_columns(items[i + 1])) > len2) - len2 = n; - } - return len1 + len2; -} - -int -dlg_calc_list_width(int item_no, DIALOG_LISTITEM * items) -{ - int n, i, len1 = 0, len2 = 0; - for (i = 0; i < item_no; ++i) { - if ((n = dlg_count_columns(items[i].name)) > len1) - len1 = n; - if ((n = dlg_count_columns(items[i].text)) > len2) - len2 = n; - } - return len1 + len2; -} - -char * -dlg_strempty(void) -{ - static char empty[] = ""; - return empty; -} - -char * -dlg_strclone(const char *cprompt) -{ - char *prompt = dlg_malloc(char, strlen(cprompt) + 1); - assert_ptr(prompt, "dlg_strclone"); - strcpy(prompt, cprompt); - return prompt; -} - -chtype -dlg_asciibox(chtype ch) -{ - chtype result = 0; - - if (ch == ACS_ULCORNER) - result = '+'; - else if (ch == ACS_LLCORNER) - result = '+'; - else if (ch == ACS_URCORNER) - result = '+'; - else if (ch == ACS_LRCORNER) - result = '+'; - else if (ch == ACS_HLINE) - result = '-'; - else if (ch == ACS_VLINE) - result = '|'; - else if (ch == ACS_LTEE) - result = '+'; - else if (ch == ACS_RTEE) - result = '+'; - else if (ch == ACS_UARROW) - result = '^'; - else if (ch == ACS_DARROW) - result = 'v'; - - return result; -} - -chtype -dlg_boxchar(chtype ch) -{ - chtype result = dlg_asciibox(ch); - - if (result != 0) { - if (dialog_vars.ascii_lines) - ch = result; - else if (dialog_vars.no_lines) - ch = ' '; - } - return ch; -} - -int -dlg_box_x_ordinate(int width) -{ - int x; - - if (dialog_vars.begin_set == 1) { - x = dialog_vars.begin_x; - } else { - /* center dialog box on screen unless --begin-set */ - x = (SCOLS - width) / 2; - } - return x; -} - -int -dlg_box_y_ordinate(int height) -{ - int y; - - if (dialog_vars.begin_set == 1) { - y = dialog_vars.begin_y; - } else { - /* center dialog box on screen unless --begin-set */ - y = (SLINES - height) / 2; - } - return y; -} - -void -dlg_draw_title(WINDOW *win, const char *title) -{ - if (title != NULL) { - chtype attr = A_NORMAL; - chtype save = dlg_get_attrs(win); - int x = centered(getmaxx(win), title); - - wattrset(win, title_attr); - wmove(win, 0, x); - dlg_print_text(win, title, getmaxx(win) - x, &attr); - wattrset(win, save); - } -} - -void -dlg_draw_bottom_box(WINDOW *win) -{ - int width = getmaxx(win); - int height = getmaxy(win); - int i; - - wattrset(win, border_attr); - (void) wmove(win, height - 3, 0); - (void) waddch(win, dlg_boxchar(ACS_LTEE)); - for (i = 0; i < width - 2; i++) - (void) waddch(win, dlg_boxchar(ACS_HLINE)); - wattrset(win, dialog_attr); - (void) waddch(win, dlg_boxchar(ACS_RTEE)); - (void) wmove(win, height - 2, 1); - for (i = 0; i < width - 2; i++) - (void) waddch(win, ' '); -} - -/* - * Remove a window, repainting everything else. This would be simpler if we - * used the panel library, but that is not _always_ available. - */ -void -dlg_del_window(WINDOW *win) -{ - DIALOG_WINDOWS *p, *q, *r; - - /* - * If --keep-window was set, do not delete/repaint the windows. - */ - if (dialog_vars.keep_window) - return; - - /* Leave the main window untouched if there are no background windows. - * We do this so the current window will not be cleared on exit, allowing - * things like the infobox demo to run without flicker. - */ - if (dialog_state.getc_callbacks != 0) { - touchwin(stdscr); - wnoutrefresh(stdscr); - } - - for (p = dialog_state.all_windows, q = r = 0; p != 0; r = p, p = p->next) { - if (p->normal == win) { - q = p; /* found a match - should be only one */ - if (r == 0) { - dialog_state.all_windows = p->next; - } else { - r->next = p->next; - } - } else { - if (p->shadow != 0) { - touchwin(p->shadow); - wnoutrefresh(p->shadow); - } - touchwin(p->normal); - wnoutrefresh(p->normal); - } - } - - if (q) { - delwin(q->normal); - dlg_unregister_window(q->normal); - free(q); - } - doupdate(); -} - -/* - * Create a window, optionally with a shadow. - */ -WINDOW * -dlg_new_window(int height, int width, int y, int x) -{ - WINDOW *win; - DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1); - - if ((win = newwin(height, width, y, x)) == 0) { - dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n", - y, x, height, width); - } - p->next = dialog_state.all_windows; - p->normal = win; - dialog_state.all_windows = p; -#ifdef HAVE_COLOR - if (dialog_state.use_shadow) { - draw_childs_shadow(p->shadow = stdscr, win); - } -#endif - - (void) keypad(win, TRUE); - return win; -} - -WINDOW * -dlg_new_modal_window(WINDOW *parent, int height, int width, int y, int x) -{ - WINDOW *win; - DIALOG_WINDOWS *p = dlg_calloc(DIALOG_WINDOWS, 1); - - (void) parent; - if ((win = newwin(height, width, y, x)) == 0) { - dlg_exiterr("Can't make new window at (%d,%d), size (%d,%d).\n", - y, x, height, width); - } - p->next = dialog_state.all_windows; - p->normal = win; - dialog_state.all_windows = p; -#ifdef HAVE_COLOR - if (dialog_state.use_shadow) { - draw_childs_shadow(p->shadow = parent, win); - } -#endif - - (void) keypad(win, TRUE); - return win; -} - -/* - * Move/Resize a window, optionally with a shadow. - */ -#ifdef KEY_RESIZE -void -dlg_move_window(WINDOW *win, int height, int width, int y, int x) -{ - DIALOG_WINDOWS *p, *q; - - if (win != 0) { - dlg_ctl_size(height, width); - - for (p = dialog_state.all_windows; p != 0; p = q) { - q = p->next; - if (p->normal == win) { - break; - } - } - - if (p != 0) { - (void) wresize(win, height, width); - (void) mvwin(win, y, x); -#ifdef HAVE_COLOR - if (p->shadow != 0) { - if (dialog_state.use_shadow) { - (void) mvwin(p->shadow, y + SHADOW_ROWS, x + SHADOW_COLS); - } else { - p->shadow = 0; - } - } -#endif - (void) refresh(); - -#ifdef HAVE_COLOR - if (p->shadow) - draw_childs_shadow(p->shadow, win); -#endif - } - } -} -#endif /* KEY_RESIZE */ - -WINDOW * -dlg_sub_window(WINDOW *parent, int height, int width, int y, int x) -{ - WINDOW *win; - - if ((win = subwin(parent, height, width, y, x)) == 0) { - dlg_exiterr("Can't make sub-window at (%d,%d), size (%d,%d).\n", - y, x, height, width); - } - - (void) keypad(win, TRUE); - return win; -} - -/* obsolete */ -int -dlg_default_item(char **items, int llen) -{ - int result = 0; - - if (dialog_vars.default_item != 0) { - int count = 0; - while (*items != 0) { - if (!strcmp(dialog_vars.default_item, *items)) { - result = count; - break; - } - items += llen; - count++; - } - } - return result; -} - -int -dlg_default_listitem(DIALOG_LISTITEM * items) -{ - int result = 0; - - if (dialog_vars.default_item != 0) { - int count = 0; - while (items->name != 0) { - if (!strcmp(dialog_vars.default_item, items->name)) { - result = count; - break; - } - ++items; - count++; - } - } - return result; -} - -/* - * Draw the string for item_help - */ -void -dlg_item_help(const char *txt) -{ - if (USE_ITEM_HELP(txt)) { - chtype attr = A_NORMAL; - int y, x; - - wattrset(stdscr, itemhelp_attr); - (void) wmove(stdscr, LINES - 1, 0); - (void) wclrtoeol(stdscr); - (void) addch(' '); - dlg_print_text(stdscr, txt, COLS - 1, &attr); - if (itemhelp_attr & A_COLOR) { - /* fill the remainder of the line with the window's attributes */ - getyx(stdscr, y, x); - while (x < COLS) { - (void) addch(' '); - ++x; - } - } - (void) wnoutrefresh(stdscr); - } -} - -#ifndef HAVE_STRCASECMP -int -dlg_strcmp(const char *a, const char *b) -{ - int ac, bc, cmp; - - for (;;) { - ac = UCH(*a++); - bc = UCH(*b++); - if (isalpha(ac) && islower(ac)) - ac = _toupper(ac); - if (isalpha(bc) && islower(bc)) - bc = _toupper(bc); - cmp = ac - bc; - if (ac == 0 || bc == 0 || cmp != 0) - break; - } - return cmp; -} -#endif - -/* - * Returns true if 'dst' points to a blank which follows another blank which - * is not a leading blank on a line. - */ -static bool -trim_blank(char *base, char *dst) -{ - int count = 0; - - while (dst-- != base) { - if (*dst == '\n') { - return FALSE; - } else if (*dst != ' ') { - return (count > 1); - } else { - count++; - } - } - return FALSE; -} - -/* - * Change embedded "\n" substrings to '\n' characters and tabs to single - * spaces. If there are no "\n"s, it will strip all extra spaces, for - * justification. If it has "\n"'s, it will preserve extra spaces. If cr_wrap - * is set, it will preserve '\n's. - */ -void -dlg_trim_string(char *s) -{ - char *base = s; - char *p1; - char *p = s; - int has_newlines = (strstr(s, "\\n") != 0); - - while (*p != '\0') { - if (*p == TAB && !dialog_vars.nocollapse) - *p = ' '; - - if (has_newlines) { /* If prompt contains "\n" strings */ - if (*p == '\\' && *(p + 1) == 'n') { - *s++ = '\n'; - p += 2; - p1 = p; - /* - * Handle end of lines intelligently. If '\n' follows "\n" - * then ignore the '\n'. This eliminates the need to escape - * the '\n' character (no need to use "\n\"). - */ - while (*p1 == ' ') - p1++; - if (*p1 == '\n') - p = p1 + 1; - } else if (*p == '\n') { - if (dialog_vars.cr_wrap) - *s++ = *p++; - else { - /* Replace the '\n' with a space if cr_wrap is not set */ - if (!trim_blank(base, s)) - *s++ = ' '; - p++; - } - } else /* If *p != '\n' */ - *s++ = *p++; - } else if (dialog_vars.trim_whitespace) { - if (*p == ' ') { - if (*(s - 1) != ' ') { - *s++ = ' '; - p++; - } else - p++; - } else if (*p == '\n') { - if (dialog_vars.cr_wrap) - *s++ = *p++; - else if (*(s - 1) != ' ') { - /* Strip '\n's if cr_wrap is not set. */ - *s++ = ' '; - p++; - } else - p++; - } else - *s++ = *p++; - } else { /* If there are no "\n" strings */ - if (*p == ' ' && !dialog_vars.nocollapse) { - if (!trim_blank(base, s)) - *s++ = *p; - p++; - } else - *s++ = *p++; - } - } - - *s = '\0'; -} - -void -dlg_set_focus(WINDOW *parent, WINDOW *win) -{ - if (win != 0) { - (void) wmove(parent, - getpary(win) + getcury(win), - getparx(win) + getcurx(win)); - (void) wnoutrefresh(win); - (void) doupdate(); - } -} - -/* - * Returns the nominal maximum buffer size. - */ -int -dlg_max_input(int max_len) -{ - if (dialog_vars.max_input != 0 && dialog_vars.max_input < MAX_LEN) - max_len = dialog_vars.max_input; - - return max_len; -} - -/* - * Free storage used for the result buffer. - */ -void -dlg_clr_result(void) -{ - if (dialog_vars.input_length) { - dialog_vars.input_length = 0; - if (dialog_vars.input_result) - free(dialog_vars.input_result); - } - dialog_vars.input_result = 0; -} - -/* - * Setup a fixed-buffer for the result. - */ -char * -dlg_set_result(const char *string) -{ - unsigned need = string ? (unsigned) strlen(string) + 1 : 0; - - /* inputstr.c needs a fixed buffer */ - if (need < MAX_LEN) - need = MAX_LEN; - - /* - * If the buffer is not big enough, allocate a new one. - */ - if (dialog_vars.input_length != 0 - || dialog_vars.input_result == 0 - || need > MAX_LEN) { - - dlg_clr_result(); - - dialog_vars.input_length = need; - dialog_vars.input_result = dlg_malloc(char, need); - assert_ptr(dialog_vars.input_result, "dlg_set_result"); - } - - strcpy(dialog_vars.input_result, string ? string : ""); - - return dialog_vars.input_result; -} - -/* - * Accumulate results in dynamically allocated buffer. - * If input_length is zero, it is a MAX_LEN buffer belonging to the caller. - */ -void -dlg_add_result(const char *string) -{ - unsigned have = (dialog_vars.input_result - ? (unsigned) strlen(dialog_vars.input_result) - : 0); - unsigned want = (unsigned) strlen(string) + 1 + have; - - if ((want >= MAX_LEN) - || (dialog_vars.input_length != 0) - || (dialog_vars.input_result == 0)) { - - if (dialog_vars.input_length == 0 - || dialog_vars.input_result == 0) { - - char *save_result = dialog_vars.input_result; - - dialog_vars.input_length = want * 2; - dialog_vars.input_result = dlg_malloc(char, dialog_vars.input_length); - assert_ptr(dialog_vars.input_result, "dlg_add_result malloc"); - dialog_vars.input_result[0] = '\0'; - if (save_result != 0) - strcpy(dialog_vars.input_result, save_result); - } else if (want >= dialog_vars.input_length) { - dialog_vars.input_length = want * 2; - dialog_vars.input_result = dlg_realloc(char, - dialog_vars.input_length, - dialog_vars.input_result); - assert_ptr(dialog_vars.input_result, "dlg_add_result realloc"); - } - } - strcat(dialog_vars.input_result, string); -} - -/* - * These are characters that (aside from the quote-delimiter) will have to - * be escaped in a single- or double-quoted string. - */ -#define FIX_SINGLE "\n\\" -#define FIX_DOUBLE FIX_SINGLE "[]{}?*;`~#$^&()|<>" - -/* - * Returns the quote-delimiter. - */ -static const char * -quote_delimiter(void) -{ - return dialog_vars.single_quoted ? "'" : "\""; -} - -/* - * Returns true if we should quote the given string. - */ -static bool -must_quote(char *string) -{ - bool code = FALSE; - - if (*string != '\0') { - size_t len = strlen(string); - if (strcspn(string, quote_delimiter()) != len) - code = TRUE; - else if (strcspn(string, "\n\t ") != len) - code = TRUE; - else - code = (strcspn(string, FIX_DOUBLE) != len); - } else { - code = TRUE; - } - - return code; -} - -/* - * Add a quoted string to the result buffer. - */ -void -dlg_add_quoted(char *string) -{ - char temp[2]; - const char *my_quote = quote_delimiter(); - const char *must_fix = (dialog_vars.single_quoted - ? FIX_SINGLE - : FIX_DOUBLE); - - if (dialog_vars.quoted || must_quote(string)) { - temp[1] = '\0'; - dlg_add_result(my_quote); - while (*string != '\0') { - temp[0] = *string++; - if (strchr(my_quote, *temp) || strchr(must_fix, *temp)) - dlg_add_result("\\"); - dlg_add_result(temp); - } - dlg_add_result(my_quote); - } else { - dlg_add_result(string); - } -} - -/* - * When adding a result, make that depend on whether "--quoted" is used. - */ -void -dlg_add_string(char *string) -{ - if (dialog_vars.quoted) { - dlg_add_quoted(string); - } else { - dlg_add_result(string); - } -} - -bool -dlg_need_separator(void) -{ - bool result = FALSE; - - if (dialog_vars.output_separator) { - result = TRUE; - } else if (dialog_vars.input_result && *(dialog_vars.input_result)) { - result = TRUE; - } - return result; -} - -void -dlg_add_separator(void) -{ - const char *separator = (dialog_vars.separate_output) ? "\n" : " "; - - if (dialog_vars.output_separator) - separator = dialog_vars.output_separator; - - dlg_add_result(separator); -} - -/* - * Some widgets support only one value of a given variable - save/restore the - * global dialog_vars so we can override it consistently. - */ -void -dlg_save_vars(DIALOG_VARS * vars) -{ - *vars = dialog_vars; -} - -/* - * Most of the data in DIALOG_VARS is normally set by command-line options. - * The input_result member is an exception; it is normally set by the dialog - * library to return result values. - */ -void -dlg_restore_vars(DIALOG_VARS * vars) -{ - char *save_result = dialog_vars.input_result; - unsigned save_length = dialog_vars.input_length; - - dialog_vars = *vars; - dialog_vars.input_result = save_result; - dialog_vars.input_length = save_length; -} - -/* - * Called each time a widget is invoked which may do output, increment a count. - */ -void -dlg_does_output(void) -{ - dialog_state.output_count += 1; -} - -/* - * Compatibility for different versions of curses. - */ -#if !(defined(HAVE_GETBEGX) && defined(HAVE_GETBEGY)) -int -getbegx(WINDOW *win) -{ - int y, x; - getbegyx(win, y, x); - return x; -} -int -getbegy(WINDOW *win) -{ - int y, x; - getbegyx(win, y, x); - return y; -} -#endif - -#if !(defined(HAVE_GETCURX) && defined(HAVE_GETCURY)) -int -getcurx(WINDOW *win) -{ - int y, x; - getyx(win, y, x); - return x; -} -int -getcury(WINDOW *win) -{ - int y, x; - getyx(win, y, x); - return y; -} -#endif - -#if !(defined(HAVE_GETMAXX) && defined(HAVE_GETMAXY)) -int -getmaxx(WINDOW *win) -{ - int y, x; - getmaxyx(win, y, x); - return x; -} -int -getmaxy(WINDOW *win) -{ - int y, x; - getmaxyx(win, y, x); - return y; -} -#endif - -#if !(defined(HAVE_GETPARX) && defined(HAVE_GETPARY)) -int -getparx(WINDOW *win) -{ - int y, x; - getparyx(win, y, x); - return x; -} -int -getpary(WINDOW *win) -{ - int y, x; - getparyx(win, y, x); - return y; -} -#endif |