HAX: high water mark, remove Copy functions, fix reflow

This commit is contained in:
Dustin Howett 2021-07-27 13:35:09 -05:00
parent 227ce8ff20
commit 17068f4460
4 changed files with 55 additions and 40 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -58,9 +58,14 @@ TextBuffer::TextBuffer(const COORD screenBufferSize,
// - OtherBuffer - The text buffer to copy properties from
// Return Value:
// - <none>
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<const Microsoft::Consol
const auto& currRow = GetRowByOffset(coordEndOfText.Y);
// The X position of the end of the valid text is the Right draw boundary (which is one beyond the final valid character)
coordEndOfText.X = gsl::narrow<short>(currRow.GetCharRow().MeasureRight()) - 1;
coordEndOfText.X = gsl::narrow<short>(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<const Microsoft::Consol
const auto& backupRow = GetRowByOffset(coordEndOfText.Y);
// We need to back up to the previous row if this line is empty, AND there are more rows
coordEndOfText.X = gsl::narrow<short>(backupRow.GetCharRow().MeasureRight()) - 1;
coordEndOfText.X = gsl::narrow<short>(backupRow.MeasureRight()) - 1;
fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > viewportTop);
}
@ -787,7 +795,7 @@ void TextBuffer::_RefreshRowIDs(std::optional<SHORT> 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<CharRow&>(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<short>(charRow.MeasureRight());
//const CharRow& charRow = row.GetCharRow();
short iRight = gsl::narrow_cast<short>(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:

View file

@ -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<til::point, size_t> GetPatterns(const size_t firstRow, const size_t lastRow) const;
private: