Direct mode: invalidate m_bufferData on resize
Also, for efficieny in direct mode, only output the lines that have changed, rather than reprinting all of the lines after the first changed line. Fixes https://github.com/rprichard/winpty/issues/112
This commit is contained in:
parent
d636a1de86
commit
ac33b66172
@ -55,7 +55,7 @@ Scraper::Scraper(
|
||||
{
|
||||
m_consoleBuffer = &buffer;
|
||||
|
||||
resetConsoleTracking(Terminal::OmitClear, buffer.windowRect());
|
||||
resetConsoleTracking(Terminal::OmitClear, buffer.windowRect().top());
|
||||
|
||||
m_bufferData.resize(BUFFER_LINE_COUNT);
|
||||
|
||||
@ -114,13 +114,13 @@ void Scraper::scrapeBuffer(Win32ConsoleBuffer &buffer,
|
||||
}
|
||||
|
||||
void Scraper::resetConsoleTracking(
|
||||
Terminal::SendClearFlag sendClear, const SmallRect &windowRect)
|
||||
Terminal::SendClearFlag sendClear, int64_t scrapedLineCount)
|
||||
{
|
||||
for (ConsoleLine &line : m_bufferData) {
|
||||
line.reset();
|
||||
}
|
||||
m_syncRow = -1;
|
||||
m_scrapedLineCount = windowRect.top();
|
||||
m_scrapedLineCount = scrapedLineCount;
|
||||
m_scrolledCount = 0;
|
||||
m_maxBufferedLine = -1;
|
||||
m_dirtyWindowTop = -1;
|
||||
@ -205,7 +205,11 @@ void Scraper::resizeImpl(const ConsoleScreenBufferInfo &origInfo)
|
||||
const Coord origBufferSize = origInfo.bufferSize();
|
||||
const SmallRect origWindowRect = origInfo.windowRect();
|
||||
|
||||
if (!m_directMode) {
|
||||
if (m_directMode) {
|
||||
for (ConsoleLine &line : m_bufferData) {
|
||||
line.reset();
|
||||
}
|
||||
} else {
|
||||
m_consoleBuffer->clearLines(0, origWindowRect.Top, origInfo);
|
||||
clearBufferLines(0, origWindowRect.Top);
|
||||
if (m_syncRow != -1) {
|
||||
@ -343,7 +347,8 @@ void Scraper::syncConsoleContentAndSize(
|
||||
const bool newDirectMode = (info.bufferSize().Y != BUFFER_LINE_COUNT);
|
||||
if (newDirectMode != m_directMode) {
|
||||
trace("Entering %s mode", newDirectMode ? "direct" : "scrolling");
|
||||
resetConsoleTracking(Terminal::SendClear, info.windowRect());
|
||||
resetConsoleTracking(Terminal::SendClear,
|
||||
newDirectMode ? 0 : info.windowRect().top());
|
||||
m_directMode = newDirectMode;
|
||||
|
||||
// When we switch from direct->scrolling mode, make sure the console is
|
||||
@ -355,6 +360,11 @@ void Scraper::syncConsoleContentAndSize(
|
||||
}
|
||||
|
||||
if (m_directMode) {
|
||||
// In direct-mode, resizing the console redraws the terminal, so do it
|
||||
// before scraping.
|
||||
if (forceResize) {
|
||||
resizeImpl(info);
|
||||
}
|
||||
directScrapeOutput(info, cursorVisible);
|
||||
} else {
|
||||
if (!m_console.frozen()) {
|
||||
@ -365,16 +375,17 @@ void Scraper::syncConsoleContentAndSize(
|
||||
if (m_console.frozen()) {
|
||||
scrollingScrapeOutput(info, cursorVisible, false);
|
||||
}
|
||||
}
|
||||
|
||||
// In scrolling mode, we want to scrape before resizing, because we'll
|
||||
// erase everything in the console buffer up to the top of the console
|
||||
// window.
|
||||
if (forceResize) {
|
||||
resizeImpl(info);
|
||||
finalInfoOut = m_consoleBuffer->bufferInfo();
|
||||
} else {
|
||||
finalInfoOut = info;
|
||||
}
|
||||
}
|
||||
|
||||
finalInfoOut = forceResize ? m_consoleBuffer->bufferInfo() : info;
|
||||
}
|
||||
|
||||
// Try to match Windows' behavior w.r.t. to the LVB attribute flags. In some
|
||||
// situations, Windows ignores the LVB flags on a character cell because of
|
||||
// backwards compatibility -- apparently some programs set the flags without
|
||||
@ -445,17 +456,11 @@ void Scraper::directScrapeOutput(const ConsoleScreenBufferInfo &info,
|
||||
|
||||
largeConsoleRead(m_readBuffer, *m_consoleBuffer, scrapeRect, attributesMask());
|
||||
|
||||
bool sawModifiedLine = false;
|
||||
for (int line = 0; line < h; ++line) {
|
||||
const CHAR_INFO *curLine =
|
||||
const CHAR_INFO *const curLine =
|
||||
m_readBuffer.lineData(scrapeRect.top() + line);
|
||||
ConsoleLine &bufLine = m_bufferData[line];
|
||||
if (sawModifiedLine) {
|
||||
bufLine.setLine(curLine, w);
|
||||
} else {
|
||||
sawModifiedLine = bufLine.detectChangeAndSetLine(curLine, w);
|
||||
}
|
||||
if (sawModifiedLine) {
|
||||
if (bufLine.detectChangeAndSetLine(curLine, w)) {
|
||||
const int lineCursorColumn =
|
||||
line == cursorLine ? cursorColumn : -1;
|
||||
m_terminal->sendLine(line, curLine, w, lineCursorColumn);
|
||||
@ -488,7 +493,7 @@ bool Scraper::scrollingScrapeOutput(const ConsoleScreenBufferInfo &info,
|
||||
trace("Sync marker has disappeared -- resetting the terminal"
|
||||
" (m_syncCounter=%u)",
|
||||
m_syncCounter);
|
||||
resetConsoleTracking(Terminal::SendClear, windowRect);
|
||||
resetConsoleTracking(Terminal::SendClear, windowRect.top());
|
||||
} else if (markerRow != m_syncRow) {
|
||||
ASSERT(markerRow < m_syncRow);
|
||||
m_scrolledCount += (m_syncRow - markerRow);
|
||||
@ -531,7 +536,7 @@ bool Scraper::scrollingScrapeOutput(const ConsoleScreenBufferInfo &info,
|
||||
trace("Window moved upward -- resetting the terminal"
|
||||
" (m_syncCounter=%u)",
|
||||
m_syncCounter);
|
||||
resetConsoleTracking(Terminal::SendClear, windowRect);
|
||||
resetConsoleTracking(Terminal::SendClear, windowRect.top());
|
||||
}
|
||||
}
|
||||
m_dirtyWindowTop = windowRect.top();
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
|
||||
private:
|
||||
void resetConsoleTracking(
|
||||
Terminal::SendClearFlag sendClear, const SmallRect &windowRect);
|
||||
Terminal::SendClearFlag sendClear, int64_t scrapedLineCount);
|
||||
void markEntireWindowDirty(const SmallRect &windowRect);
|
||||
void scanForDirtyLines(const SmallRect &windowRect);
|
||||
void clearBufferLines(int firstRow, int count);
|
||||
|
Loading…
Reference in New Issue
Block a user