From 17068f44602c481341b3171e6b47e547d0f34828 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Tue, 27 Jul 2021 13:35:09 -0500 Subject: [PATCH] HAX: high water mark, remove Copy functions, fix reflow --- src/buffer/out/Row.cpp | 10 +++++ src/buffer/out/Row.hpp | 5 ++- src/buffer/out/textBuffer.cpp | 78 ++++++++++++++++++----------------- src/buffer/out/textBuffer.hpp | 2 - 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/buffer/out/Row.cpp b/src/buffer/out/Row.cpp index 5b0a49d5fb..890e122428 100644 --- a/src/buffer/out/Row.cpp +++ b/src/buffer/out/Row.cpp @@ -24,6 +24,7 @@ ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute f _lineRendition{ LineRendition::SingleWidth }, _wrapForced{ false }, _doubleBytePadded{ false }, + _highWaterMark{ 0 }, _pParent{ pParent } { } @@ -39,6 +40,7 @@ bool ROW::Reset(const TextAttribute Attr) _lineRendition = LineRendition::SingleWidth; _wrapForced = false; _doubleBytePadded = false; + _highWaterMark = 0; _charRow.Reset(); try { @@ -196,5 +198,13 @@ OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, co _attrRow.Replace(colorStarts, currentIndex, currentColor); } + //_highWaterMark = std::max(currentIndex, _highWaterMark); + return it; } + +size_t ROW::MeasureRight() const noexcept +{ + return _charRow.MeasureRight(); + //return _highWaterMark; +} diff --git a/src/buffer/out/Row.hpp b/src/buffer/out/Row.hpp index cee3b53bd8..9bf89d9eea 100644 --- a/src/buffer/out/Row.hpp +++ b/src/buffer/out/Row.hpp @@ -42,8 +42,10 @@ public: void SetDoubleBytePadded(const bool doubleBytePadded) noexcept { _doubleBytePadded = doubleBytePadded; } bool WasDoubleBytePadded() const noexcept { return _doubleBytePadded; } - const CharRow& GetCharRow() const noexcept { return _charRow; } + size_t MeasureRight() const noexcept; + CharRow& GetCharRow() noexcept { return _charRow; } + const CharRow& GetCharRow() const noexcept { return _charRow; } const ATTR_ROW& GetAttrRow() const noexcept { return _attrRow; } ATTR_ROW& GetAttrRow() noexcept { return _attrRow; } @@ -76,6 +78,7 @@ private: LineRendition _lineRendition; SHORT _id; unsigned short _rowWidth; + unsigned short _highWaterMark; // Occurs when the user runs out of text in a given row and we're forced to wrap the cursor to the next line bool _wrapForced; // Occurs when the user runs out of text to support a double byte character and we're forced to the next line diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 701b5285a0..0bf35e5f0c 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -58,9 +58,14 @@ TextBuffer::TextBuffer(const COORD screenBufferSize, // - OtherBuffer - The text buffer to copy properties from // Return Value: // - -void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer) noexcept +void TextBuffer::CopyProperties(const TextBuffer& other) noexcept { - GetCursor().CopyProperties(OtherBuffer.GetCursor()); + _cursor.CopyProperties(other._cursor); + _hyperlinkMap = other._hyperlinkMap; + _hyperlinkCustomIdMap = other._hyperlinkCustomIdMap; + _currentHyperlinkId = other._currentHyperlinkId; + _idsAndPatterns = other._idsAndPatterns; + _currentPatternId = other._currentPatternId; } // Routine Description: @@ -226,7 +231,10 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt, { // Attempt to write as much data as possible onto this line. // NOTE: if wrap = true/false, we want to set the line's wrap to true/false (respectively) if we reach the end of the line + auto oldIt = it; + OutputDebugStringW(fmt::format(L"Write starting at {},{}\n", lineTarget.X, lineTarget.Y).c_str()); it = WriteLine(it, lineTarget, wrap); + OutputDebugStringW(fmt::format(L"--- done line {}; distance moved {} CEL {} INP\n", lineTarget.Y, it.GetCellDistance(oldIt), it.GetInputDistance(oldIt)).c_str()); // Move to the next line down. lineTarget.X = 0; @@ -419,7 +427,7 @@ COORD TextBuffer::GetLastNonSpaceCharacter(std::optional(currRow.GetCharRow().MeasureRight()) - 1; + coordEndOfText.X = gsl::narrow(currRow.MeasureRight()) - 1; // If the X coordinate turns out to be -1, the row was empty, we need to search backwards for the real end of text. const auto viewportTop = viewport.Top(); @@ -430,7 +438,7 @@ COORD TextBuffer::GetLastNonSpaceCharacter(std::optional(backupRow.GetCharRow().MeasureRight()) - 1; + coordEndOfText.X = gsl::narrow(backupRow.MeasureRight()) - 1; fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > viewportTop); } @@ -787,7 +795,7 @@ void TextBuffer::_RefreshRowIDs(std::optional newRowWidth) it.SetId(i++); // Also update the char row parent pointers as they can get shuffled up in the rotates. - it.GetCharRow().UpdateParent(&it); + const_cast(it.GetCharRow()).UpdateParent(&it); // Resize the rows in the X dimension if we have a new width if (newRowWidth.has_value()) @@ -1951,11 +1959,10 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, // Fetch the row and its "right" which is the last printable character. const ROW& row = oldBuffer.GetRowByOffset(iOldRow); const short cOldColsTotal = oldBuffer.GetLineWidth(iOldRow); - const CharRow& charRow = row.GetCharRow(); - short iRight = gsl::narrow_cast(charRow.MeasureRight()); + //const CharRow& charRow = row.GetCharRow(); + short iRight = gsl::narrow_cast(row.MeasureRight()); if (iRight == 0 && !row.WasWrapForced()) { - // don't beef it if iRight=0 on iterator newBuffer.NewlineCursor(); continue; } @@ -1994,9 +2001,28 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, } OutputCellIterator it{ oldBuffer.GetCellDataAt({ 0, iOldRow }, Viewport::FromDimensions({ 0, iOldRow }, iRight, 1)) }; + const auto first = it; auto preCurPos{ newBuffer.GetCursor().GetPosition() }; - const auto last = newBuffer.Write(it, preCurPos, true); // true - wrap if we don't fit! - const auto distance = last.GetCellDistance(it); + auto postCurPos{ preCurPos }; + OutputDebugStringW(fmt::format(L"+++ CURSOR STARTED AT {},{}\n", preCurPos.X, preCurPos.Y).c_str()); + //const auto last = newBuffer.Write(it, preCurPos, true); // true - wrap if we don't fit! + ptrdiff_t totalDistance{}; + while (it) + { + auto last = it; + it = newBuffer.Write(it, postCurPos, true); + auto distance = it.GetCellDistance(last); + totalDistance += distance; + if (it) + { + // The iterator is still valid, but we stopped for some reason. + // Likely, we ran out of space. + newBuffer.IncrementCircularBuffer(); + postCurPos.Y--; // adjust new write head location + preCurPos.Y--; // adjust original origin location (for future cursor repositioning) + } + newBuffer.GetSize().MoveInBounds(distance, postCurPos); + } if (iOldRow == cOldCursorPos.Y) { @@ -2006,8 +2032,8 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, fFoundCursorPos = true; } - newBuffer.GetSize().MoveInBounds(distance, preCurPos); - newBuffer.GetCursor().SetPosition(preCurPos); + OutputDebugStringW(fmt::format(L"+++ AFTER MOVING {}, CURSOR ENDED AT {},{}\n", totalDistance, preCurPos.X, preCurPos.Y).c_str()); + newBuffer.GetCursor().SetPosition(postCurPos); // If we found the old row that the caller was interested in, set the // out value of that parameter to the cursor's current Y position (the @@ -2040,7 +2066,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, // Only do so if we were not forced to wrap. If we did // force a word wrap, then the existing line break was // only because we ran out of space. - if (distance < cOldColsTotal && !row.WasWrapForced()) + if (totalDistance < cOldColsTotal && !row.WasWrapForced()) { if (iRight == cOldCursorPos.X && iOldRow == cOldCursorPos.Y) { @@ -2097,8 +2123,6 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, { // Finish copying remaining parameters from the old text buffer to the new one newBuffer.CopyProperties(oldBuffer); - newBuffer.CopyHyperlinkMaps(oldBuffer); - newBuffer.CopyPatterns(oldBuffer); // If we found where to put the cursor while placing characters into the buffer, // just put the cursor there. Otherwise we have to advance manually. @@ -2162,6 +2186,8 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer, newCursor.SetSize(ulSize); } + OutputDebugStringW(fmt::format(L"+++ REFLOW DONE\n\n\n").c_str()); + return hr; } @@ -2259,18 +2285,6 @@ std::wstring TextBuffer::GetCustomIdFromId(uint16_t id) const return {}; } -// Method Description: -// - Copies the hyperlink/customID maps of the old buffer into this one, -// also copies currentHyperlinkId -// Arguments: -// - The other buffer -void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other) -{ - _hyperlinkMap = other._hyperlinkMap; - _hyperlinkCustomIdMap = other._hyperlinkCustomIdMap; - _currentHyperlinkId = other._currentHyperlinkId; -} - // Method Description: // - Adds a regex pattern we should search for // - The searching does not happen here, we only search when asked to by TerminalCore @@ -2293,16 +2307,6 @@ void TextBuffer::ClearPatternRecognizers() noexcept _currentPatternId = 0; } -// Method Description: -// - Copies the patterns the other buffer knows about into this one -// Arguments: -// - The other buffer -void TextBuffer::CopyPatterns(const TextBuffer& OtherBuffer) -{ - _idsAndPatterns = OtherBuffer._idsAndPatterns; - _currentPatternId = OtherBuffer._currentPatternId; -} - // Method Description: // - Finds patterns within the requested region of the text buffer // Arguments: diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index 0237b1e150..45059303f9 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -156,7 +156,6 @@ public: uint16_t GetHyperlinkId(std::wstring_view uri, std::wstring_view id); void RemoveHyperlinkFromMap(uint16_t id) noexcept; std::wstring GetCustomIdFromId(uint16_t id) const; - void CopyHyperlinkMaps(const TextBuffer& OtherBuffer); class TextAndColor { @@ -195,7 +194,6 @@ public: const size_t AddPatternRecognizer(const std::wstring_view regexString); void ClearPatternRecognizers() noexcept; - void CopyPatterns(const TextBuffer& OtherBuffer); interval_tree::IntervalTree GetPatterns(const size_t firstRow, const size_t lastRow) const; private: