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