📄 tty_update.c
字号:
&& can_clear_with(CHREF(ntext0))) { UpdateAttrs(AttrOf(ntext0)); putp(tparm(erase_chars, runcount)); /* * If this is the last part of the given interval, * don't bother moving cursor, since it can be the * last update on the line. */ if (runcount < num) { GoTo(SP->_cursrow, SP->_curscol + runcount); } else { return 1; /* cursor stays in the middle */ } } else if (repeat_char && runcount > SP->_rep_cost) { bool wrap_possible = (SP->_curscol + runcount >= screen_columns); int rep_count = runcount; if (wrap_possible) rep_count--; UpdateAttrs(AttrOf(ntext0)); tputs(tparm(repeat_char, CharOf(ntext0), rep_count), rep_count, _nc_outch); SP->_curscol += rep_count; if (wrap_possible) PutChar(CHREF(ntext0)); } else { for (i = 0; i < runcount; i++) PutChar(CHREF(ntext[i])); } ntext += runcount; num -= runcount; } return 0; } for (i = 0; i < num; i++) PutChar(CHREF(ntext[i])); return 0;}/* * Output the line in the given range [first .. last] * * If there's a run of identical characters that's long enough to justify * cursor movement, use that also. * * Returns: same as EmitRange */static intPutRange(const NCURSES_CH_T * otext, const NCURSES_CH_T * ntext, int row, int first, int last){ int i, j, same; TR(TRACE_CHARPUT, ("PutRange(%p, %p, %d, %d, %d)", otext, ntext, row, first, last)); if (otext != ntext && (last - first + 1) > SP->_inline_cost) { for (j = first, same = 0; j <= last; j++) { if (!same && isnac(otext[j])) continue; if (CharEq(otext[j], ntext[j])) { same++; } else { if (same > SP->_inline_cost) { EmitRange(ntext + first, j - same - first); GoTo(row, first = j); } same = 0; } } i = EmitRange(ntext + first, j - same - first); /* * Always return 1 for the next GoTo() after a PutRange() if we found * identical characters at end of interval */ return (same == 0 ? i : 1); } return EmitRange(ntext + first, last - first + 1);}/* leave unbracketed here so 'indent' works */#define MARK_NOCHANGE(win,row) \ win->_line[row].firstchar = _NOCHANGE; \ win->_line[row].lastchar = _NOCHANGE; \ if_USE_SCROLL_HINTS(win->_line[row].oldindex = row)NCURSES_EXPORT(int)doupdate(void){ int i; int nonempty;#if USE_TRACE_TIMES struct tms before, after;#endif /* USE_TRACE_TIMES */ T((T_CALLED("doupdate()")));#ifdef TRACE if (_nc_tracing & TRACE_UPDATE) { if (curscr->_clear) _tracef("curscr is clear"); else _tracedump("curscr", curscr); _tracedump("newscr", newscr); }#endif /* TRACE */ _nc_signal_handler(FALSE); if (SP->_fifohold) SP->_fifohold--;#if USE_SIZECHANGE if (SP->_endwin || SP->_sig_winch) { /* * This is a transparent extension: XSI does not address it, * and applications need not know that ncurses can do it. * * Check if the terminal size has changed while curses was off * (this can happen in an xterm, for example), and resize the * ncurses data structures accordingly. */ _nc_update_screensize(); }#endif if (SP->_endwin) { T(("coming back from shell mode")); reset_prog_mode(); _nc_mvcur_resume(); _nc_screen_resume(); SP->_mouse_resume(SP); SP->_endwin = FALSE; }#if USE_TRACE_TIMES /* zero the metering machinery */ _nc_outchars = 0; (void) times(&before);#endif /* USE_TRACE_TIMES */ /* * This is the support for magic-cookie terminals. The * theory: we scan the virtual screen looking for attribute * turnons. Where we find one, check to make sure it's * realizable by seeing if the required number of * un-attributed blanks are present before and after the * attributed range; try to shift the range boundaries over * blanks (not changing the screen display) so this becomes * true. If it is, shift the beginning attribute change * appropriately (the end one, if we've gotten this far, is * guaranteed room for its cookie). If not, nuke the added * attributes out of the span. */#if USE_XMC_SUPPORT if (magic_cookie_glitch > 0) { int j, k; attr_t rattr = A_NORMAL; for (i = 0; i < screen_lines; i++) { for (j = 0; j < screen_columns; j++) { bool failed = FALSE; attr_t turnon = AttrOf(newscr->_line[i].text[j]) & ~rattr; /* is an attribute turned on here? */ if (turnon == 0) { rattr = AttrOf(newscr->_line[i].text[j]); continue; } TR(TRACE_ATTRS, ("At (%d, %d): from %s...", i, j, _traceattr(rattr))); TR(TRACE_ATTRS, ("...to %s", _traceattr(turnon))); /* * If the attribute change location is a blank with a * "safe" attribute, undo the attribute turnon. This may * ensure there's enough room to set the attribute before * the first non-blank in the run. */#define SAFE(a) (!((a) & (attr_t)~NONBLANK_ATTR)) if (ISBLANK(newscr->_line[i].text[j]) && SAFE(turnon)) { RemAttr(newscr->_line[i].text[j], turnon); continue; } /* check that there's enough room at start of span */ for (k = 1; k <= magic_cookie_glitch; k++) { if (j - k < 0 || !ISBLANK(newscr->_line[i].text[j - k]) || !SAFE(AttrOf(newscr->_line[i].text[j - k]))) failed = TRUE; } if (!failed) { bool end_onscreen = FALSE; int m, n = j; /* find end of span, if it's onscreen */ for (m = i; m < screen_lines; m++) { for (; n < screen_columns; n++) { if (AttrOf(newscr->_line[m].text[n]) == rattr) { end_onscreen = TRUE; TR(TRACE_ATTRS, ("Range attributed with %s ends at (%d, %d)", _traceattr(turnon), m, n)); goto foundit; } } n = 0; } TR(TRACE_ATTRS, ("Range attributed with %s ends offscreen", _traceattr(turnon))); foundit:; if (end_onscreen) { NCURSES_CH_T *lastline = newscr->_line[m].text; /* * If there are safely-attributed blanks at the * end of the range, shorten the range. This will * help ensure that there is enough room at end * of span. */ while (n >= 0 && ISBLANK(lastline[n]) && SAFE(AttrOf(lastline[n]))) RemAttr(lastline[n--], turnon); /* check that there's enough room at end of span */ for (k = 1; k <= magic_cookie_glitch; k++) if (n + k >= screen_columns || !ISBLANK(lastline[n + k]) || !SAFE(AttrOf(lastline[n + k]))) failed = TRUE; } } if (failed) { int p, q = j; TR(TRACE_ATTRS, ("Clearing %s beginning at (%d, %d)", _traceattr(turnon), i, j)); /* turn off new attributes over span */ for (p = i; p < screen_lines; p++) { for (; q < screen_columns; q++) { if (AttrOf(newscr->_line[p].text[q]) == rattr) goto foundend; RemAttr(newscr->_line[p].text[q], turnon); } q = 0; } foundend:; } else { TR(TRACE_ATTRS, ("Cookie space for %s found before (%d, %d)", _traceattr(turnon), i, j)); /* * back up the start of range so there's room * for cookies before the first nonblank character */ for (k = 1; k <= magic_cookie_glitch; k++) AddAttr(newscr->_line[i].text[j - k], turnon); } rattr = AttrOf(newscr->_line[i].text[j]); } }#ifdef TRACE /* show altered highlights after magic-cookie check */ if (_nc_tracing & TRACE_UPDATE) { _tracef("After magic-cookie check..."); _tracedump("newscr", newscr); }#endif /* TRACE */ }#endif /* USE_XMC_SUPPORT */ nonempty = 0; if (curscr->_clear || newscr->_clear) { /* force refresh ? */ TR(TRACE_UPDATE, ("clearing and updating from scratch")); ClrUpdate(); curscr->_clear = FALSE; /* reset flag */ newscr->_clear = FALSE; /* reset flag */ } else { int changedlines = CHECK_INTERVAL; if (check_pending()) goto cleanup; nonempty = min(screen_lines, newscr->_maxy + 1); if (SP->_scrolling) { _nc_scroll_optimize(); } nonempty = ClrBottom(nonempty); TR(TRACE_UPDATE, ("Transforming lines, nonempty %d", nonempty)); for (i = 0; i < nonempty; i++) { /* * Here is our line-breakout optimization. */ if (changedlines == CHECK_INTERVAL) { if (check_pending()) goto cleanup; changedlines = 0; } /* * newscr->line[i].firstchar is normally set * by wnoutrefresh. curscr->line[i].firstchar * is normally set by _nc_scroll_window in the * vertical-movement optimization code, */ if (newscr->_line[i].firstchar != _NOCHANGE || curscr->_line[i].firstchar != _NOCHANGE) { TransformLine(i); changedlines++; } /* mark line changed successfully */ if (i <= newscr->_maxy) { MARK_NOCHANGE(newscr, i); } if (i <= curscr->_maxy) { MARK_NOCHANGE(curscr, i); } } } /* put everything back in sync */ for (i = nonempty; i <= newscr->_maxy; i++) { MARK_NOCHANGE(newscr, i); } for (i = nonempty; i <= curscr->_maxy; i++) { MARK_NOCHANGE(curscr, i); } if (!newscr->_leaveok) { curscr->_curx = newscr->_curx; curscr->_cury = newscr->_cury; GoTo(curscr->_cury, curscr->_curx); } cleanup: /* * Keep the physical screen in normal mode in case we get other * processes writing to the screen. */ UpdateAttrs(A_NORMAL); _nc_flush(); curscr->_attrs = newscr->_attrs;#if USE_TRACE_TIMES (void) times(&after); TR(TRACE_TIMES, ("Update cost: %ld chars, %ld clocks system time, %ld clocks user time", _nc_outchars, (long) (after.tms_stime - before.tms_stime), (long) (after.tms_utime - before.tms_utime)));#endif /* USE_TRACE_TIMES */ _nc_signal_handler(TRUE); returnCode(OK);}/* * ClrBlank(win) * * Returns the attributed character that corresponds to the "cleared" * screen. If the terminal has the back-color-erase feature, this will be * colored according to the wbkgd() call. * * We treat 'curscr' specially because it isn't supposed to be set directly * in the wbkgd() call. Assume 'stdscr' for this case. */#define BCE_ATTRS (A_NORMAL|A_COLOR)#define BCE_BKGD(win) (((win) == curscr ? stdscr : (win))->_nc_bkgd)static inline NCURSES_CH_TClrBlank(WINDOW *win){ NCURSES_CH_T blank = NewChar(BLANK_TEXT); if (back_color_erase) AddAttr(blank, (AttrOf(BCE_BKGD(win)) & BCE_ATTRS)); return blank;}/*** ClrUpdate()**** Update by clearing and redrawing the entire screen.***/static voidClrUpdate(void){ int i; NCURSES_CH_T blank = ClrBlank(stdscr); int nonempty = min(screen_lines, newscr->_maxy + 1); TR(TRACE_UPDATE, ("ClrUpdate() called")); ClearScreen(blank); TR(TRACE_UPDATE, ("updating screen from scratch")); nonempty = ClrBottom(nonempty); for (i = 0; i < nonempty; i++) TransformLine(i);}/*** ClrToEOL(blank)**** Clear to end of current line, starting at the cursor position*/static voidClrToEOL(NCURSES_CH_T blank, bool needclear){ int j; if (curscr != 0 && SP->_cursrow >= 0) { for (j = SP->_curscol; j < screen_columns; j++) { if (j >= 0) { NCURSES_CH_T *cp = &(curscr->_line[SP->_cursrow].text[j]); if (!CharEq(*cp, blank)) { *cp = blank; needclear = TRUE; } } } } else { needclear = TRUE; } if (needclear) { UpdateAttrs(AttrOf(blank)); TPUTS_TRACE("clr_eol"); if (clr_eol && SP->_el_cost <= (screen_columns - SP->_curscol)) { putp(clr_eol); } else { int count = (screen_columns - SP->_curscol); while (count-- > 0) PutChar(CHREF(blank)); } }}/*** ClrToEOS(blank)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -