⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 This version of dialog, formerly known as cdialog is based on the Debian package for dialog 0.9a (se
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  $Id: util.c,v 1.118 2003/12/01 00:32:44 tom Exp $ * *  util.c -- miscellaneous utilities for dialog * *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk) *     and: Thomas E. Dickey * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version 2 *  of the License, or (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "dialog.h"#include <stdarg.h>#include <sys/types.h>#include <sys/stat.h>#include <time.h>#ifdef NCURSES_VERSION#if defined(HAVE_NCURSESW_TERM_H)#include <ncursesw/term.h>#elif defined(HAVE_NCURSES_TERM_H)#include <ncurses/term.h>#else#include <term.h>#endif#endif#ifndef O_BINARY#define O_BINARY 0#endif#ifndef S_IRUSR#define S_IRUSR 0400#endif#ifndef S_IWUSR#define S_IWUSR 0200#endif#ifndef DIALOG_TMPDIR#define DIALOG_TMPDIR NULL#endif#define LOCK_PERMITS (S_IRUSR | S_IWUSR)#define LOCK_TIMEOUT 10		/* timeout for locking, in seconds *//* globals */DIALOG_STATE dialog_state;DIALOG_VARS dialog_vars;#define concat(a,b) a##b#ifdef HAVE_RC_FILE#define RC_DATA(name,comment) , #name "_color", comment " color"#else#define RC_DATA(name,comment)	/*nothing */#endif#ifdef HAVE_COLOR#include <colors.h>#define COLOR_DATA(upr) , concat(upr,_FG), concat(upr,_BG), concat(upr,_HL)#else#define COLOR_DATA(upr)		/*nothing */#endif#define DATA(atr,upr,lwr,cmt) { atr COLOR_DATA(upr) RC_DATA(lwr,cmt) }/* * Table of color and attribute values, default is for mono display. *//* *INDENT-OFF* */DIALOG_COLORS dlg_color_table[] ={    DATA(A_NORMAL,	SCREEN,			screen, "Screen"),    DATA(A_NORMAL,	SHADOW,			shadow, "Shadow"),    DATA(A_REVERSE,	DIALOG,			dialog, "Dialog box"),    DATA(A_REVERSE,	TITLE,			title, "Dialog box title"),    DATA(A_REVERSE,	BORDER,			border, "Dialog box border"),    DATA(A_BOLD,	BUTTON_ACTIVE,		button_active, "Active button"),    DATA(A_DIM,		BUTTON_INACTIVE,	button_inactive, "Inactive button"),    DATA(A_UNDERLINE,	BUTTON_KEY_ACTIVE,	button_key_active, "Active button key"),    DATA(A_UNDERLINE,	BUTTON_KEY_INACTIVE,	button_key_inactive, "Inactive button key"),    DATA(A_NORMAL,	BUTTON_LABEL_ACTIVE,	button_label_active, "Active button label"),    DATA(A_NORMAL,	BUTTON_LABEL_INACTIVE,	button_label_inactive, "Inactive button label"),    DATA(A_REVERSE,	INPUTBOX,		inputbox, "Input box"),    DATA(A_REVERSE,	INPUTBOX_BORDER,	inputbox_border, "Input box border"),    DATA(A_REVERSE,	SEARCHBOX,		searchbox, "Search box"),    DATA(A_REVERSE,	SEARCHBOX_TITLE,	searchbox_title, "Search box title"),    DATA(A_REVERSE,	SEARCHBOX_BORDER,	searchbox_border, "Search box border"),    DATA(A_REVERSE,	POSITION_INDICATOR,	position_indicator, "File position indicator"),    DATA(A_REVERSE,	MENUBOX,		menubox, "Menu box"),    DATA(A_REVERSE,	MENUBOX_BORDER,		menubox_border, "Menu box border"),    DATA(A_REVERSE,	ITEM,			item, "Item"),    DATA(A_NORMAL,	ITEM_SELECTED,		item_selected, "Selected item"),    DATA(A_REVERSE,	TAG,			tag, "Tag"),    DATA(A_REVERSE,	TAG_SELECTED,		tag_selected, "Selected tag"),    DATA(A_NORMAL,	TAG_KEY,		tag_key, "Tag key"),    DATA(A_BOLD,	TAG_KEY_SELECTED,	tag_key_selected, "Selected tag key"),    DATA(A_REVERSE,	CHECK,			check, "Check box"),    DATA(A_REVERSE,	CHECK_SELECTED,		check_selected, "Selected check box"),    DATA(A_REVERSE,	UARROW,			uarrow, "Up arrow"),    DATA(A_REVERSE,	DARROW,			darrow, "Down arrow"),    DATA(A_NORMAL,	ITEMHELP,		itemhelp, "Item help-text"),    DATA(A_BOLD,	FORM_ACTIVE_TEXT,	form_active_text, "Active form text"),    DATA(A_REVERSE,	FORM_TEXT,		form_text, "Form text"),};/* *INDENT-ON* *//* * Display background title if it exists ... */voiddlg_put_backtitle(void){    int i;    if (dialog_vars.backtitle != NULL) {	chtype attr = A_NORMAL;	wattrset(stdscr, screen_attr);	(void) wmove(stdscr, 0, 1);	dlg_print_text(stdscr, dialog_vars.backtitle, COLS - 2, &attr);	for (i = 0; i < COLS - (int) strlen(dialog_vars.backtitle); i++)	    (void) waddch(stdscr, ' ');	(void) wmove(stdscr, 1, 1);	for (i = 0; i < COLS - 2; i++)	    (void) waddch(stdscr, ACS_HLINE);    }    (void) wnoutrefresh(stdscr);}/* * Set window to attribute 'attr'.  There are more efficient ways to do this, * but will not work on older/buggy ncurses versions. */voiddlg_attr_clear(WINDOW *win, int height, int width, chtype attr){    int i, j;    wattrset(win, attr);    for (i = 0; i < height; i++) {	(void) wmove(win, i, 0);	for (j = 0; j < width; j++)	    (void) waddch(win, ' ');    }    (void) touchwin(win);}voiddlg_clear(void){    dlg_attr_clear(stdscr, LINES, COLS, screen_attr);}#define isprivate(s) ((s) != 0 && strstr(s, "\033[?") != 0)#define TTY_DEVICE "/dev/tty"/* * If $DIALOG_TTY exists, allow the program to try to open the terminal * directly when stdout is redirected.  By default we require the "--stdout" * option to be given, but some scripts were written making use of the * behavior of dialog which tried opening the terminal anyway.  */static char *dialog_tty(void){    char *result = getenv("DIALOG_TTY");    if (result != 0 && atoi(result))	result = 0;    return result;}/* * Open the terminal directly.  If one of stdin, stdout or stderr really points * to a tty, use it.  Otherwise give up and open /dev/tty. */static intopen_terminal(char **result, int mode){    const char *device = TTY_DEVICE;    if (!isatty(fileno(stderr))	|| (device = ttyname(fileno(stderr))) == 0) {	if (!isatty(fileno(stdout))	    || (device = ttyname(fileno(stdout))) == 0) {	    if (!isatty(fileno(stdin))		|| (device = ttyname(fileno(stdin))) == 0) {		device = TTY_DEVICE;	    }	}    }    *result = dlg_strclone(device);    return open(device, mode);}/* * Do some initialization for dialog. * * 'input' is the real tty input of dialog.  Usually it is stdin, but if * --input-fd option is used, it may be anything. * * 'output' is where dialog will send its result.  Usually it is stderr, but * if --stdout or --output-fd is used, it may be anything.  We are concerned * mainly with the case where it happens to be the same as stdout. */voidinit_dialog(FILE *input, FILE *output){    int fd1, fd2;    char *device = 0;    dialog_state.output = output;    dialog_state.tab_len = TAB_LEN;    dialog_state.aspect_ratio = DEFAULT_ASPECT_RATIO;#ifdef HAVE_COLOR    dialog_state.use_colors = USE_COLORS;	/* use colors by default? */    dialog_state.use_shadow = USE_SHADOW;	/* shadow dialog boxes by default? */#endif#ifdef HAVE_RC_FILE    if (dlg_parse_rc() == -1)	/* Read the configuration file */	dlg_exiterr("init_dialog: dlg_parse_rc");#endif    /*     * Some widgets (such as gauge) may read from the standard input.  Pipes     * only connect stdout/stdin, so there is not much choice.  But reading a     * pipe would get in the way of curses' normal reading stdin for getch.     *     * As in the --stdout (see below), reopening the terminal does not always     * work properly.  dialog provides a --pipe-fd option for this purpose.  We     * test that case first (differing fileno's for input/stdin).  If the     * fileno's are equal, but we're not reading from a tty, see if we can open     * /dev/tty.     */    dialog_state.pipe_input = stdin;    if (fileno(input) != fileno(stdin)) {	if ((fd1 = dup(fileno(input))) >= 0	    && (fd2 = dup(fileno(stdin))) >= 0) {	    *stdin = *fdopen(fd1, "r");	    dialog_state.pipe_input = fdopen(fd2, "r");	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */		(void) dup2(fileno(stdin), 0);	} else	    dlg_exiterr("cannot open tty-input");    } else if (!isatty(fileno(stdin))) {	if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0	    && (fd2 = dup(fileno(stdin))) >= 0) {	    dialog_state.pipe_input = fdopen(fd2, "r");	    *stdin = *freopen(device, "r", stdin);	    if (fileno(stdin) != 0)	/* some functions may read fd #0 */		(void) dup2(fileno(stdin), 0);	}	free(device);    }    /*     * If stdout is not a tty and dialog is called with the --stdout option, we     * have to provide for a way to write to the screen.     *     * The curses library normally writes its output to stdout, leaving stderr     * free for scripting.  Scripts are simpler when stdout is redirected.  The     * newterm function is useful; it allows us to specify where the output     * goes.  Reopening the terminal is not portable since several     * configurations do not allow this to work properly:     *     * a) some getty implementations (and possibly broken tty drivers, e.g., on     *    HPUX 10 and 11) cause stdin to act as if it is still in cooked mode     *    even though results from ioctl's state that it is successfully     *    altered to raw mode.  Broken is the proper term.     *     * b) the user may not have permissions on the device, e.g., if one su's     *    from the login user to another non-privileged user.     */    if (!isatty(fileno(stdout))	&& (fileno(stdout) == fileno(output) || dialog_tty())) {	if ((fd1 = open_terminal(&device, O_WRONLY)) >= 0	    && (dialog_state.screen_output = fdopen(fd1, "w")) != 0) {	    if (newterm(NULL, dialog_state.screen_output, stdin) == 0) {		dlg_exiterr("cannot initialize curses");	    }	    free(device);	} else {	    dlg_exiterr("cannot open tty-output");	}    } else {	dialog_state.screen_output = stdout;	(void) initscr();    }#ifdef NCURSES_VERSION    /*     * Cancel xterm's alternate-screen mode.     */    if ((dialog_state.screen_output != stdout || isatty(fileno(dialog_state.screen_output)))	&& key_mouse != 0	/* xterm and kindred */	&& isprivate(enter_ca_mode)	&& isprivate(exit_ca_mode)) {	/*	 * initscr() or newterm() already did putp(enter_ca_mode) as a side	 * effect of initializing the screen.  It would be nice to not even	 * do that, but we do not really have access to the correct copy of	 * the terminfo description until those functions have been invoked.	 */	(void) putp(exit_ca_mode);	(void) putp(clear_screen);	/*	 * Prevent ncurses from switching "back" to the normal screen when	 * exiting from dialog.  That would move the cursor to the original	 * location saved in xterm.  Normally curses sets the cursor position	 * to the first line after the display, but the alternate screen	 * switching is done after that point.	 *	 * Cancelling the strings altogether also works around the buggy	 * implementation of alternate-screen in rxvt, etc., which clear	 * more of the display than they should.	 */	enter_ca_mode = 0;	exit_ca_mode = 0;    }#endif    (void) keypad(stdscr, TRUE);    (void) cbreak();    (void) noecho();    mouse_open();    dialog_state.screen_initialized = 1;#ifdef HAVE_COLOR    if (dialog_state.use_colors || dialog_state.use_shadow)	dlg_color_setup();	/* Set up colors */#endif    /* Set screen to screen attribute */    dlg_clear();}#ifdef HAVE_COLORstatic int defined_colors = 0;/* * Setup for color display */voiddlg_color_setup(void){    unsigned i;    if (has_colors()) {		/* Terminal supports color? */	(void) start_color();	for (i = 0; i < sizeof(dlg_color_table) /	     sizeof(dlg_color_table[0]); i++) {	    /* Initialize color pairs */	    (void) init_pair(i + 1, dlg_color_table[i].fg,			     dlg_color_table[i].bg);	    /* Setup color attributes */	    dlg_color_table[i].atr = C_ATTR(dlg_color_table[i].hilite, i + 1);	}	defined_colors = i + 1;    }}intdlg_color_count(void){    return sizeof(dlg_color_table) / sizeof(dlg_color_table[0]);}/* * Reuse color pairs (they are limited), returning a COLOR_PAIR() value if we * have (or can) define a pair with the given color as foreground on the * window's defined background. */static chtypedefine_color(WINDOW *win, int foreground){    chtype result = 0;    chtype attrs = getattrs(win);    int pair;    short fg, bg, background;    bool found = FALSE;    if ((pair = PAIR_NUMBER(attrs)) != 0	&& pair_content(pair, &fg, &bg) != ERR	&& bg != foreground) {	background = bg;    } else {	background = COLOR_BLACK;    }    for (pair = 0; pair < defined_colors; ++pair) {	if (pair_content(pair, &fg, &bg) != ERR	    && fg == foreground	    && bg == background) {	    result = COLOR_PAIR(pair);	    found = TRUE;	    break;	}    }    if (!found && (defined_colors + 1) < COLOR_PAIRS) {	pair = defined_colors++;	(void) init_pair(pair, foreground, background);	result = COLOR_PAIR(pair);    }    return result;}#endif/* * End using dialog functions. */voidend_dialog(void){    if (dialog_state.screen_initialized) {	dialog_state.screen_initialized = 0;	mouse_close();	(void) endwin();	(void) fflush(stdout);    }}#define isOurEscape(p) (((p)[0] == '\\') && ((p)[1] == 'Z') && ((p)[2] != 0))static intcentered(int width, const char *string){    int len = strlen(string);    int left;    int hide = 0;    int n;    if (dialog_vars.colors) {	for (n = 0; n < len; ++n) {	    if (isOurEscape(string + n)) {		hide += 3;	    }	}    }    left = (width - (len - hide)) / 2 - 1;    if (left < 0)	left = 0;    return left;}/* * Print up to 'len' bytes from 'text', optionally rendering our escape * sequence for attributes and color. */voiddlg_print_text(WINDOW *win, const char *txt, int len, chtype *attr){    while (len > 0 && (*txt != '\0')) {	if (dialog_vars.colors) {	    while (isOurEscape(txt)) {		int code;		txt += 2;		switch (code = CharOf(*txt)) {#ifdef HAVE_COLOR		case '0':		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		    *attr &= ~A_COLOR;		    *attr |= define_color(win, code - '0');		    break;#endif		case 'B':		    *attr &= ~A_BOLD;		    break;		case 'b':		    *attr = A_BOLD;		    break;		case 'R':		    *attr &= ~A_REVERSE;		    break;		case 'r':		    *attr = A_REVERSE;		    break;		case 'U':		    *attr &= ~A_UNDERLINE;		    break;		case 'u':		    *attr = A_UNDERLINE;		    break;		case 'n':		    *attr = A_NORMAL;		    break;		}		++txt;	    }	    if (*txt == '\n')		break;	}	(void) waddch(win, CharOf(*txt++) | *attr);	--len;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -