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

📄 tty_update.c

📁 ncurses-5.4 需要的就来下把 一定会有用的哦
💻 C
📖 第 1 页 / 共 4 页
字号:
/**************************************************************************** * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              * *                                                                          * * Permission is hereby granted, free of charge, to any person obtaining a  * * copy of this software and associated documentation files (the            * * "Software"), to deal in the Software without restriction, including      * * without limitation the rights to use, copy, modify, merge, publish,      * * distribute, distribute with modifications, sublicense, and/or sell       * * copies of the Software, and to permit persons to whom the Software is    * * furnished to do so, subject to the following conditions:                 * *                                                                          * * The above copyright notice and this permission notice shall be included  * * in all copies or substantial portions of the Software.                   * *                                                                          * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    * * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               * *                                                                          * * Except as contained in this notice, the name(s) of the above copyright   * * holders shall not be used in advertising or otherwise to promote the     * * sale, use or other dealings in this Software without prior written       * * authorization.                                                           * ****************************************************************************//**************************************************************************** *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               * *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         * *     and: Thomas E. Dickey 1996-2004                                      * ****************************************************************************//*----------------------------------------------------------------- * *	lib_doupdate.c * * 	The routine doupdate() and its dependents. * 	All physical output is concentrated here (except _nc_outch()  *	in lib_tputs.c). * *-----------------------------------------------------------------*/#include <curses.priv.h>#ifdef __BEOS__#undef false#undef true#include <OS.h>#endif#if defined(TRACE) && HAVE_SYS_TIMES_H && HAVE_TIMES#define USE_TRACE_TIMES 1#else#define USE_TRACE_TIMES 0#endif#if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT#include <sys/time.h>#endif#if USE_TRACE_TIMES#include <sys/times.h>#endif#if USE_FUNC_POLL#elif HAVE_SELECT#if HAVE_SYS_SELECT_H#include <sys/select.h>#endif#endif#include <ctype.h>#include <term.h>MODULE_ID("$Id: tty_update.c,v 1.205 2004/02/07 18:02:42 tom Exp $")/* * This define controls the line-breakout optimization.  Every once in a * while during screen refresh, we want to check for input and abort the * update if there's some waiting.  CHECK_INTERVAL controls the number of * changed lines to be emitted between input checks. * * Note: Input-check-and-abort is no longer done if the screen is being * updated from scratch.  This is a feature, not a bug. */#define CHECK_INTERVAL	5#define FILL_BCE() (SP->_coloron && !SP->_default_color && !back_color_erase)/* * Enable checking to see if doupdate and friends are tracking the true * cursor position correctly.  NOTE: this is a debugging hack which will * work ONLY on ANSI-compatible terminals! *//* #define POSITION_DEBUG */static inline NCURSES_CH_T ClrBlank(WINDOW *win);static int ClrBottom(int total);static void ClearScreen(NCURSES_CH_T blank);static void ClrUpdate(void);static void DelChar(int count);static void InsStr(NCURSES_CH_T * line, int count);static void TransformLine(int const lineno);#ifdef POSITION_DEBUG/**************************************************************************** * * Debugging code.  Only works on ANSI-standard terminals. * ****************************************************************************/static voidposition_check(int expected_y, int expected_x, char *legend)/* check to see if the real cursor position matches the virtual */{    char buf[20];    char *s;    int y, x;    if (!_nc_tracing || (expected_y < 0 && expected_x < 0))	return;    _nc_flush();    memset(buf, '\0', sizeof(buf));    putp("\033[6n");		/* only works on ANSI-compatibles */    _nc_flush();    *(s = buf) = 0;    do {	int ask = sizeof(buf) - 1 - (s - buf);	int got = read(0, s, ask);	if (got == 0)	    break;	s += got;    } while (strchr(buf, 'R') == 0);    _tracef("probe returned %s", _nc_visbuf(buf));    /* try to interpret as a position report */    if (sscanf(buf, "\033[%d;%dR", &y, &x) != 2) {	_tracef("position probe failed in %s", legend);    } else {	if (expected_x < 0)	    expected_x = x - 1;	if (expected_y < 0)	    expected_y = y - 1;	if (y - 1 != expected_y || x - 1 != expected_x) {	    beep();	    tputs(tparm("\033[%d;%dH", expected_y + 1, expected_x + 1), 1, _nc_outch);	    _tracef("position seen (%d, %d) doesn't match expected one (%d, %d) in %s",		    y - 1, x - 1, expected_y, expected_x, legend);	} else {	    _tracef("position matches OK in %s", legend);	}    }}#else#define position_check(expected_y, expected_x, legend)	/* nothing */#endif /* POSITION_DEBUG *//**************************************************************************** * * Optimized update code * ****************************************************************************/static inline voidGoTo(int const row, int const col){    TR(TRACE_MOVE, ("GoTo(%d, %d) from (%d, %d)",		    row, col, SP->_cursrow, SP->_curscol));    position_check(SP->_cursrow, SP->_curscol, "GoTo");    mvcur(SP->_cursrow, SP->_curscol, row, col);    position_check(SP->_cursrow, SP->_curscol, "GoTo2");}static inline voidPutAttrChar(CARG_CH_T ch){    int chlen = 1;    NCURSES_CH_T my_ch;    PUTC_DATA;    NCURSES_CH_T tilde;    NCURSES_ATTR_T attr = AttrOfD(ch);    TR(TRACE_CHARPUT, ("PutAttrChar(%s) at (%d, %d)",		       _tracech_t(ch),		       SP->_cursrow, SP->_curscol));#if USE_WIDEC_SUPPORT    /*     * If this is not a valid character, there is nothing more to do.     */    if (isnac(CHDEREF(ch)))	return;    /*     * Determine the number of character cells which the 'ch' value will use     * on the screen.  It should be at least one.     */    if ((chlen = wcwidth(CharOf(CHDEREF(ch)))) <= 0) {	static NCURSES_CH_T blank = NewChar(BLANK_TEXT);	if (isprint(CharOf(CHDEREF(ch)))	    || (SP->_posix_locale && CharOf(CHDEREF(ch)) >= 160)) {	    ;	} else {	    ch = CHREF(blank);	    TR(TRACE_CHARPUT, ("forced to blank"));	}	chlen = 1;    }#endif    if ((attr & A_ALTCHARSET)	&& SP->_acs_map != 0	&& CharOfD(ch) < ACS_LEN) {	my_ch = CHDEREF(ch);	/* work around const param */#if USE_WIDEC_SUPPORT	/*	 * This is crude & ugly, but works most of the time.  It checks if the	 * acs_chars string specified that we have a mapping for this	 * character, and uses the wide-character mapping when we expect the	 * normal one to be broken (by mis-design ;-).	 */	if (SP->_screen_acs_fix	    && SP->_acs_map[CharOf(my_ch)] & A_ALTCHARSET) {	    attr &= ~(A_ALTCHARSET);	    my_ch = _nc_wacs[CharOf(my_ch)];	}#endif	if (attr & A_ALTCHARSET) {	    chtype temp = UChar(SP->_acs_map[CharOfD(ch)]);	    if (temp != 0)		SetChar(my_ch, temp, attr);	    RemAttr(my_ch, A_ALTCHARSET);	}	ch = CHREF(my_ch);    }    if (tilde_glitch && (CharOfD(ch) == L('~'))) {	SetChar(tilde, L('`'), attr);	ch = CHREF(tilde);    }    UpdateAttrs(attr);#if !USE_WIDEC_SUPPORT    /* FIXME - we do this special case for signal handling, should see how to     * make it work for wide characters.     */    if (SP->_outch != 0) {	SP->_outch(UChar(ch));    } else#endif    {	PUTC(CHDEREF(ch), SP->_ofp);	/* macro's fastest... */	TRACE_OUTCHARS(1);    }    SP->_curscol += chlen;    if (char_padding) {	TPUTS_TRACE("char_padding");	putp(char_padding);    }}static boolcheck_pending(void)/* check for pending input */{    bool have_pending = FALSE;    /*     * Only carry out this check when the flag is zero, otherwise we'll     * have the refreshing slow down drastically (or stop) if there's an     * unread character available.     */    if (SP->_fifohold != 0)	return FALSE;    if (SP->_checkfd >= 0) {#if USE_FUNC_POLL	struct pollfd fds[1];	fds[0].fd = SP->_checkfd;	fds[0].events = POLLIN;	if (poll(fds, 1, 0) > 0) {	    have_pending = TRUE;	}#elif defined(__BEOS__)	/*	 * BeOS's select() is declared in socket.h, so the configure script does	 * not see it.  That's just as well, since that function works only for	 * sockets.  This (using snooze and ioctl) was distilled from Be's patch	 * for ncurses which uses a separate thread to simulate select().	 *	 * FIXME: the return values from the ioctl aren't very clear if we get	 * interrupted.	 */	int n = 0;	int howmany = ioctl(0, 'ichr', &n);	if (howmany >= 0 && n > 0) {	    have_pending = TRUE;	}#elif HAVE_SELECT	fd_set fdset;	struct timeval ktimeout;	ktimeout.tv_sec =	    ktimeout.tv_usec = 0;	FD_ZERO(&fdset);	FD_SET(SP->_checkfd, &fdset);	if (select(SP->_checkfd + 1, &fdset, NULL, NULL, &ktimeout) != 0) {	    have_pending = TRUE;	}#endif    }    if (have_pending) {	SP->_fifohold = 5;	_nc_flush();    }    return FALSE;}/* put char at lower right corner */static voidPutCharLR(const ARG_CH_T ch){    if (!auto_right_margin) {	/* we can put the char directly */	PutAttrChar(ch);    } else if (enter_am_mode && exit_am_mode) {	/* we can suppress automargin */	TPUTS_TRACE("exit_am_mode");	putp(exit_am_mode);	PutAttrChar(ch);	SP->_curscol--;	position_check(SP->_cursrow, SP->_curscol, "exit_am_mode");	TPUTS_TRACE("enter_am_mode");	putp(enter_am_mode);    } else if ((enter_insert_mode && exit_insert_mode)	       || insert_character || parm_ich) {	GoTo(screen_lines - 1, screen_columns - 2);	PutAttrChar(ch);	GoTo(screen_lines - 1, screen_columns - 2);	InsStr(newscr->_line[screen_lines - 1].text + screen_columns - 2, 1);    }}static voidwrap_cursor(void){    if (eat_newline_glitch) {	/*	 * xenl can manifest two different ways.  The vt100	 * way is that, when you'd expect the cursor to wrap,	 * it stays hung at the right margin (on top of the	 * character just emitted) and doesn't wrap until the	 * *next* graphic char is emitted.  The c100 way is	 * to ignore LF received just after an am wrap.	 *	 * An aggressive way to handle this would be to	 * emit CR/LF after the char and then assume the wrap	 * is done, you're on the first position of the next	 * line, and the terminal out of its weird state.	 * Here it's safe to just tell the code that the	 * cursor is in hyperspace and let the next mvcur()	 * call straighten things out.	 */	SP->_curscol = -1;	SP->_cursrow = -1;    } else if (auto_right_margin) {	SP->_curscol = 0;	SP->_cursrow++;    } else {	SP->_curscol--;    }    position_check(SP->_cursrow, SP->_curscol, "wrap_cursor");}static inline voidPutChar(const ARG_CH_T ch)/* insert character, handling automargin stuff */{    if (SP->_cursrow == screen_lines - 1 && SP->_curscol == screen_columns - 1)	PutCharLR(ch);    else	PutAttrChar(ch);    if (SP->_curscol >= screen_columns)	wrap_cursor();    position_check(SP->_cursrow, SP->_curscol, "PutChar");}/* * Check whether the given character can be output by clearing commands.  This * includes test for being a space and not including any 'bad' attributes, such * as A_REVERSE.  All attribute flags which don't affect appearance of a space * or can be output by clearing (A_COLOR in case of bce-terminal) are excluded. */static inline boolcan_clear_with(ARG_CH_T ch){    if (!back_color_erase && SP->_coloron) {#if NCURSES_EXT_FUNCS	if (!SP->_default_color)	    return FALSE;	if (SP->_default_fg != C_MASK || SP->_default_bg != C_MASK)	    return FALSE;	if (AttrOfD(ch) & A_COLOR) {	    short fg, bg;	    pair_content(PAIR_NUMBER(AttrOfD(ch)), &fg, &bg);	    if (fg != C_MASK || bg != C_MASK)		return FALSE;	}#else	if (AttrOfD(ch) & A_COLOR)	    return FALSE;#endif    }    return (ISBLANK(CHDEREF(ch)) &&	    (AttrOfD(ch) & ~(NONBLANK_ATTR | A_COLOR)) == BLANK_ATTR);}/* * Issue a given span of characters from an array. * Must be functionally equivalent to: *	for (i = 0; i < num; i++) *	    PutChar(ntext[i]); * but can leave the cursor positioned at the middle of the interval. * * Returns: 0 - cursor is at the end of interval *	    1 - cursor is somewhere in the middle * * This code is optimized using ech and rep. */static intEmitRange(const NCURSES_CH_T * ntext, int num){    int i;    if (erase_chars || repeat_char) {	while (num > 0) {	    int runcount;	    NCURSES_CH_T ntext0;	    while (num > 1 && !CharEq(ntext[0], ntext[1])) {		PutChar(CHREF(ntext[0]));		ntext++;		num--;	    }	    ntext0 = ntext[0];	    if (num == 1) {		PutChar(CHREF(ntext0));		return 0;	    }	    runcount = 2;	    while (runcount < num && CharEq(ntext[runcount], ntext0))		runcount++;	    /*	     * The cost expression in the middle isn't exactly right.	     * _cup_ch_cost is an upper bound on the cost for moving to the	     * end of the erased area, but not the cost itself (which we	     * can't compute without emitting the move).  This may result	     * in erase_chars not getting used in some situations for	     * which it would be marginally advantageous.	     */	    if (erase_chars		&& runcount > SP->_ech_cost + SP->_cup_ch_cost

⌨️ 快捷键说明

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