📄 tty_update.c
字号:
} }}/*** ClrToEOS(blank)**** Clear to end of screen, starting at the cursor position*/static voidClrToEOS(NCURSES_CH_T blank){ int row, col; row = SP->_cursrow; col = SP->_curscol; UpdateAttrs(blank); TPUTS_TRACE("clr_eos"); tputs(clr_eos, screen_lines - row, _nc_outch); while (col < screen_columns) curscr->_line[row].text[col++] = blank; for (row++; row < screen_lines; row++) { for (col = 0; col < screen_columns; col++) curscr->_line[row].text[col] = blank; }}/* * ClrBottom(total) * * Test if clearing the end of the screen would satisfy part of the * screen-update. Do this by scanning backwards through the lines in the * screen, checking if each is blank, and one or more are changed. */static intClrBottom(int total){ int row; int col; int top = total; int last = min(screen_columns, newscr->_maxx + 1); NCURSES_CH_T blank = newscr->_line[total - 1].text[last - 1]; bool ok; if (clr_eos && can_clear_with(CHREF(blank))) { for (row = total - 1; row >= 0; row--) { for (col = 0, ok = TRUE; ok && col < last; col++) { ok = (CharEq(newscr->_line[row].text[col], blank)); } if (!ok) break; for (col = 0; ok && col < last; col++) { ok = (CharEq(curscr->_line[row].text[col], blank)); } if (!ok) top = row; } /* don't use clr_eos for just one line if clr_eol available */ if (top < total) { GoTo(top, 0); ClrToEOS(blank); if (SP->oldhash && SP->newhash) { for (row = top; row < screen_lines; row++) SP->oldhash[row] = SP->newhash[row]; } } } return top;}#if USE_XMC_SUPPORT#if USE_WIDEC_SUPPORTstatic inline boolcheck_xmc_transition(NCURSES_CH_T * a, NCURSES_CH_T * b){ if (((a->attr ^ b->attr) & ~(a->attr) & SP->_xmc_triggers) != 0) { return TRUE; } return FALSE;}#define xmc_turn_on(a,b) check_xmc_transition(&(a), &(b))#else#define xmc_turn_on(a,b) ((((a)^(b)) & ~(a) & SP->_xmc_triggers) != 0)#endif#define xmc_new(r,c) newscr->_line[r].text[c]#define xmc_turn_off(a,b) xmc_turn_on(b,a)#endif /* USE_XMC_SUPPORT *//*** TransformLine(lineno)**** Transform the given line in curscr to the one in newscr, using** Insert/Delete Character if _nc_idcok && has_ic().**** firstChar = position of first different character in line** oLastChar = position of last different character in old line** nLastChar = position of last different character in new line**** move to firstChar** overwrite chars up to min(oLastChar, nLastChar)** if oLastChar < nLastChar** insert newLine[oLastChar+1..nLastChar]** else** delete oLastChar - nLastChar spaces*/static voidTransformLine(int const lineno){ int firstChar, oLastChar, nLastChar; NCURSES_CH_T *newLine = newscr->_line[lineno].text; NCURSES_CH_T *oldLine = curscr->_line[lineno].text; int n; bool attrchanged = FALSE; TR(TRACE_UPDATE, (T_CALLED("TransformLine(%d)"), lineno)); /* copy new hash value to old one */ if (SP->oldhash && SP->newhash) SP->oldhash[lineno] = SP->newhash[lineno]; /* * If we have colors, there is the possibility of having two color pairs * that display as the same colors. For instance, Lynx does this. Check * for this case, and update the old line with the new line's colors when * they are equivalent. */ if (SP->_coloron) { int oldPair; int newPair; for (n = 0; n < screen_columns; n++) { if (!CharEq(newLine[n], oldLine[n])) { oldPair = GetPair(oldLine[n]); newPair = GetPair(newLine[n]); if (oldPair != newPair && unColor(oldLine[n]) == unColor(newLine[n])) { if (oldPair < COLOR_PAIRS && newPair < COLOR_PAIRS && SP->_color_pairs[oldPair] == SP->_color_pairs[newPair]) { SetPair(oldLine[n], GetPair(newLine[n])); } } } } } if (ceol_standout_glitch && clr_eol) { firstChar = 0; while (firstChar < screen_columns) { if (!SameAttrOf(newLine[firstChar], oldLine[firstChar])) { attrchanged = TRUE; break; } firstChar++; } } firstChar = 0; if (attrchanged) { /* we may have to disregard the whole line */ GoTo(lineno, firstChar); ClrToEOL(ClrBlank(curscr), FALSE); PutRange(oldLine, newLine, lineno, 0, (screen_columns - 1));#if USE_XMC_SUPPORT /* * This is a very simple loop to paint characters which may have the * magic cookie glitch embedded. It doesn't know much about video * attributes which are continued from one line to the next. It * assumes that we have filtered out requests for attribute changes * that do not get mapped to blank positions. * * FIXME: we are not keeping track of where we put the cookies, so this * will work properly only once, since we may overwrite a cookie in a * following operation. */ } else if (magic_cookie_glitch > 0) { GoTo(lineno, firstChar); for (n = 0; n < screen_columns; n++) { int m = n + magic_cookie_glitch; /* check for turn-on: * If we are writing an attributed blank, where the * previous cell is not attributed. */ if (ISBLANK(newLine[n]) && ((n > 0 && xmc_turn_on(newLine[n - 1], newLine[n])) || (n == 0 && lineno > 0 && xmc_turn_on(xmc_new(lineno - 1, screen_columns - 1), newLine[n])))) { n = m; } PutChar(CHREF(newLine[n])); /* check for turn-off: * If we are writing an attributed non-blank, where the * next cell is blank, and not attributed. */ if (!ISBLANK(newLine[n]) && ((n + 1 < screen_columns && xmc_turn_off(newLine[n], newLine[n + 1])) || (n + 1 >= screen_columns && lineno + 1 < screen_lines && xmc_turn_off(newLine[n], xmc_new(lineno + 1, 0))))) { n = m; } }#endif } else { NCURSES_CH_T blank; /* it may be cheap to clear leading whitespace with clr_bol */ blank = newLine[0]; if (clr_bol && can_clear_with(CHREF(blank))) { int oFirstChar, nFirstChar; for (oFirstChar = 0; oFirstChar < screen_columns; oFirstChar++) if (!CharEq(oldLine[oFirstChar], blank)) break; for (nFirstChar = 0; nFirstChar < screen_columns; nFirstChar++) if (!CharEq(newLine[nFirstChar], blank)) break; if (nFirstChar == oFirstChar) { firstChar = nFirstChar; /* find the first differing character */ while (firstChar < screen_columns && CharEq(newLine[firstChar], oldLine[firstChar])) firstChar++; } else if (oFirstChar > nFirstChar) { firstChar = nFirstChar; } else { /* oFirstChar < nFirstChar */ firstChar = oFirstChar; if (SP->_el1_cost < nFirstChar - oFirstChar) { if (nFirstChar >= screen_columns && SP->_el_cost <= SP->_el1_cost) { GoTo(lineno, 0); UpdateAttrs(blank); TPUTS_TRACE("clr_eol"); putp(clr_eol); } else { GoTo(lineno, nFirstChar - 1); UpdateAttrs(blank); TPUTS_TRACE("clr_bol"); putp(clr_bol); } while (firstChar < nFirstChar) oldLine[firstChar++] = blank; } } } else { /* find the first differing character */ while (firstChar < screen_columns && CharEq(newLine[firstChar], oldLine[firstChar])) firstChar++; } /* if there wasn't one, we're done */ if (firstChar >= screen_columns) { TR(TRACE_UPDATE, (T_RETURN(""))); return; } blank = newLine[screen_columns - 1]; if (!can_clear_with(CHREF(blank))) { /* find the last differing character */ nLastChar = screen_columns - 1; while (nLastChar > firstChar && CharEq(newLine[nLastChar], oldLine[nLastChar])) nLastChar--; if (nLastChar >= firstChar) { GoTo(lineno, firstChar); PutRange(oldLine, newLine, lineno, firstChar, nLastChar); memcpy(oldLine + firstChar, newLine + firstChar, (nLastChar - firstChar + 1) * sizeof(NCURSES_CH_T)); } TR(TRACE_UPDATE, (T_RETURN(""))); return; } /* find last non-blank character on old line */ oLastChar = screen_columns - 1; while (oLastChar > firstChar && CharEq(oldLine[oLastChar], blank)) oLastChar--; /* find last non-blank character on new line */ nLastChar = screen_columns - 1; while (nLastChar > firstChar && CharEq(newLine[nLastChar], blank)) nLastChar--; if ((nLastChar == firstChar) && (SP->_el_cost < (oLastChar - nLastChar))) { GoTo(lineno, firstChar); if (!CharEq(newLine[firstChar], blank)) PutChar(CHREF(newLine[firstChar])); ClrToEOL(blank, FALSE); } else if ((nLastChar != oLastChar) && (!CharEq(newLine[nLastChar], oldLine[oLastChar]) || !(_nc_idcok && has_ic()))) { GoTo(lineno, firstChar); if ((oLastChar - nLastChar) > SP->_el_cost) { if (PutRange(oldLine, newLine, lineno, firstChar, nLastChar)) GoTo(lineno, nLastChar + 1); ClrToEOL(blank, FALSE); } else { n = max(nLastChar, oLastChar); PutRange(oldLine, newLine, lineno, firstChar, n); } } else { int nLastNonblank = nLastChar; int oLastNonblank = oLastChar; /* find the last characters that really differ */ /* can be -1 if no characters differ */ while (CharEq(newLine[nLastChar], oldLine[oLastChar])) { /* don't split a wide char */ if (isWidecExt(newLine[nLastChar]) && !CharEq(newLine[nLastChar - 1], oldLine[oLastChar - 1])) break; nLastChar--; oLastChar--; if (nLastChar == -1 || oLastChar == -1) break; } n = min(oLastChar, nLastChar); if (n >= firstChar) { GoTo(lineno, firstChar); PutRange(oldLine, newLine, lineno, firstChar, n); } if (oLastChar < nLastChar) { int m = max(nLastNonblank, oLastNonblank);#if USE_WIDEC_SUPPORT while (isWidecExt(newLine[n + 1]) && n) { --n; --oLastChar; }#endif GoTo(lineno, n + 1); if ((nLastChar < nLastNonblank) || InsCharCost(nLastChar - oLastChar) > (m - n)) { PutRange(oldLine, newLine, lineno, n + 1, m); } else { InsStr(&newLine[n + 1], nLastChar - oLastChar); } } else if (oLastChar > nLastChar) { GoTo(lineno, n + 1); if (DelCharCost(oLastChar - nLastChar) > SP->_el_cost + nLastNonblank - (n + 1)) { if (PutRange(oldLine, newLine, lineno, n + 1, nLastNonblank)) GoTo(lineno, nLastNonblank + 1); ClrToEOL(blank, FALSE); } else { /* * The delete-char sequence will * effectively shift in blanks from the * right margin of the screen. Ensure * that they are the right color by * setting the video attributes from * the last character on the row. */ UpdateAttrs(blank); DelChar(oLastChar - nLastChar); } } } } /* update the code's internal representation */ if (screen_columns > firstChar) memcpy(oldLine + firstChar, newLine + firstChar, (screen_columns - firstChar) * sizeof(NCURSES_CH_T)); TR(TRACE_UPDATE, (T_RETURN(""))); return;}/*** ClearScreen(blank)**** Clear the physical screen and put cursor at home***/static voidClearScreen(NCURSES_CH_T blank){ int i, j; bool fast_clear = (clear_screen || clr_eos || clr_eol); TR(TRACE_UPDATE, ("ClearScreen() called"));#if NCURSES_EXT_FUNCS if (SP->_coloron && !SP->_default_color) { _nc_do_color(GET_SCREEN_PAIR(SP), 0, FALSE, _nc_outch); if (!back_color_erase) { fast_clear = FALSE; } }#endif if (fast_clear) { if (clear_screen) { UpdateAttrs(blank); TPUTS_TRACE("clear_screen"); putp(clear_screen); SP->_cursrow = SP->_curscol = 0; position_check(SP->_cursrow, SP->_curscol, "ClearScreen"); } else if (clr_eos) { SP->_cursrow = SP->_curscol = -1; GoTo(0, 0); UpdateAttrs(blank); TPUTS_TRACE("clr_eos"); tputs(clr_eos, screen_lines, _nc_outch); } else if (clr_eol) { SP->_cursrow = SP->_curscol = -1; UpdateAttrs(blank); for (i = 0; i < screen_lines; i++) { GoTo(i, 0); TPUTS_TRACE("clr_eol"); putp(clr_eol); } GoTo(0, 0); } } else { UpdateAttrs(blank); for (i = 0; i < screen_lines; i++) { GoTo(i, 0); for (j = 0; j < screen_columns; j++) PutChar(CHREF(blank)); } GoTo(0, 0); } for (i = 0; i < screen_lines; i++) { for (j = 0; j < screen_columns; j++) curscr->_line[i].text[j] = blank; } TR(TRACE_UPDATE, ("screen cleared"));}/*** InsStr(line, count)**** Insert the count characters pointed to by line.***/static voidInsStr(NCURSES_CH_T * line, int count){ TR(TRACE_UPDATE, ("InsStr(%p,%d) called", line, count)); /* Prefer parm_ich as it has the smallest cost - no need to shift
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -