diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 03570cf526d..34af621074f 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -373,38 +373,6 @@ TextBufferCellIterator TextBuffer::GetCellDataAt(const til::point at, const View return TextBufferCellIterator(*this, at, limit); } -//Routine Description: -// - Call before inserting a character into the buffer. -// - This will ensure a consistent double byte state (KAttrs line) within the text buffer -// - It will attempt to correct the buffer if we're inserting an unexpected double byte character type -// and it will pad out the buffer if we're going to split a double byte sequence across two rows. -//Arguments: -// - dbcsAttribute - Double byte information associated with the character about to be inserted into the buffer -//Return Value: -// - true if we successfully prepared the buffer and moved the cursor -// - false otherwise (out of memory) -void TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute) -{ - // Now compensate if we don't have enough space for the upcoming double byte sequence - // We only need to compensate for leading bytes - if (dbcsAttribute == DbcsAttribute::Leading) - { - const auto cursorPosition = GetCursor().GetPosition(); - const auto lineWidth = GetLineWidth(cursorPosition.y); - - // If we're about to lead on the last column in the row, we need to add a padding space - if (cursorPosition.x == lineWidth - 1) - { - // set that we're wrapping for double byte reasons - auto& row = GetMutableRowByOffset(cursorPosition.y); - row.SetDoubleBytePadded(true); - - // then move the cursor forward and onto the next row - IncrementCursor(); - } - } -} - // Given the character offset `position` in the `chars` string, this function returns the starting position of the next grapheme. // For instance, given a `chars` of L"x\uD83D\uDE42y" and a `position` of 1 it'll return 3. // GraphemePrev would do the exact inverse of this operation. @@ -740,144 +708,6 @@ OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt, return newIt; } -//Routine Description: -// - Inserts one codepoint into the buffer at the current cursor position and advances the cursor as appropriate. -//Arguments: -// - chars - The codepoint to insert -// - dbcsAttribute - Double byte information associated with the codepoint -// - bAttr - Color data associated with the character -//Return Value: -// - true if we successfully inserted the character -// - false otherwise (out of memory) -void TextBuffer::InsertCharacter(const std::wstring_view chars, - const DbcsAttribute dbcsAttribute, - const TextAttribute attr) -{ - // Ensure consistent buffer state for double byte characters based on the character type we're about to insert - _PrepareForDoubleByteSequence(dbcsAttribute); - - // Get the current cursor position - const auto iRow = GetCursor().GetPosition().y; // row stored as logical position, not array position - const auto iCol = GetCursor().GetPosition().x; // column logical and array positions are equal. - - // Get the row associated with the given logical position - auto& Row = GetMutableRowByOffset(iRow); - - // Store character and double byte data - switch (dbcsAttribute) - { - case DbcsAttribute::Leading: - Row.ReplaceCharacters(iCol, 2, chars); - break; - case DbcsAttribute::Trailing: - Row.ReplaceCharacters(iCol - 1, 2, chars); - break; - default: - Row.ReplaceCharacters(iCol, 1, chars); - break; - } - - // Store color data - Row.SetAttrToEnd(iCol, attr); - IncrementCursor(); -} - -//Routine Description: -// - Inserts one ucs2 codepoint into the buffer at the current cursor position and advances the cursor as appropriate. -//Arguments: -// - wch - The codepoint to insert -// - dbcsAttribute - Double byte information associated with the codepoint -// - bAttr - Color data associated with the character -//Return Value: -// - true if we successfully inserted the character -// - false otherwise (out of memory) -void TextBuffer::InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr) -{ - InsertCharacter({ &wch, 1 }, dbcsAttribute, attr); -} - -//Routine Description: -// - Finds the current row in the buffer (as indicated by the cursor position) -// and specifies that we have forced a line wrap on that row -//Arguments: -// - - Always sets to wrap -//Return Value: -// - -void TextBuffer::_SetWrapOnCurrentRow() -{ - _AdjustWrapOnCurrentRow(true); -} - -//Routine Description: -// - Finds the current row in the buffer (as indicated by the cursor position) -// and specifies whether or not it should have a line wrap flag. -//Arguments: -// - fSet - True if this row has a wrap. False otherwise. -//Return Value: -// - -void TextBuffer::_AdjustWrapOnCurrentRow(const bool fSet) -{ - // The vertical position of the cursor represents the current row we're manipulating. - const auto uiCurrentRowOffset = GetCursor().GetPosition().y; - - // Set the wrap status as appropriate - GetMutableRowByOffset(uiCurrentRowOffset).SetWrapForced(fSet); -} - -//Routine Description: -// - Increments the cursor one position in the buffer as if text is being typed into the buffer. -// - NOTE: Will introduce a wrap marker if we run off the end of the current row -//Arguments: -// - -//Return Value: -// - true if we successfully moved the cursor. -// - false otherwise (out of memory) -void TextBuffer::IncrementCursor() -{ - // Cursor position is stored as logical array indices (starts at 0) for the window - // Buffer Size is specified as the "length" of the array. It would say 80 for valid values of 0-79. - // So subtract 1 from buffer size in each direction to find the index of the final column in the buffer - const auto iFinalColumnIndex = GetLineWidth(GetCursor().GetPosition().y) - 1; - - // Move the cursor one position to the right - GetCursor().IncrementXPosition(1); - - // If we've passed the final valid column... - if (GetCursor().GetPosition().x > iFinalColumnIndex) - { - // Then mark that we've been forced to wrap - _SetWrapOnCurrentRow(); - - // Then move the cursor to a new line - NewlineCursor(); - } -} - -//Routine Description: -// - Increments the cursor one line down in the buffer and to the beginning of the line -//Arguments: -// - -//Return Value: -// - true if we successfully moved the cursor. -void TextBuffer::NewlineCursor() -{ - const auto iFinalRowIndex = GetSize().BottomInclusive(); - - // Reset the cursor position to 0 and move down one line - GetCursor().SetXPosition(0); - GetCursor().IncrementYPosition(1); - - // If we've passed the final valid row... - if (GetCursor().GetPosition().y > iFinalRowIndex) - { - // Stay on the final logical/offset row of the buffer. - GetCursor().SetYPosition(iFinalRowIndex); - - // Instead increment the circular buffer to move us into the "oldest" row of the backing buffer - IncrementCircularBuffer(); - } -} - //Routine Description: // - Increments the circular buffer by one. Circular buffer is represented by FirstRow variable. //Arguments: @@ -954,38 +784,6 @@ til::point TextBuffer::GetLastNonSpaceCharacter(const Viewport* viewOptional) co return coordEndOfText; } -// Routine Description: -// - Retrieves the position of the previous character relative to the current cursor position -// Arguments: -// - -// Return Value: -// - Coordinate position in screen coordinates of the character just before the cursor. -// - NOTE: Will return 0,0 if already in the top left corner -til::point TextBuffer::_GetPreviousFromCursor() const -{ - auto coordPosition = GetCursor().GetPosition(); - - // If we're not at the left edge, simply move the cursor to the left by one - if (coordPosition.x > 0) - { - coordPosition.x--; - } - else - { - // Otherwise, only if we're not on the top row (e.g. we don't move anywhere in the top left corner. there is no previous) - if (coordPosition.y > 0) - { - // move the cursor up one line - coordPosition.y--; - - // and to the right edge - coordPosition.x = GetLineWidth(coordPosition.y) - 1; - } - } - - return coordPosition; -} - const til::CoordType TextBuffer::GetFirstRowIndex() const noexcept { return _firstRow; diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index 6f21ad41cb4..6bcb8e10692 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -121,11 +121,6 @@ class TextBuffer final const std::optional setWrap = std::nullopt, const std::optional limitRight = std::nullopt); - void InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr); - void InsertCharacter(const std::wstring_view chars, const DbcsAttribute dbcsAttribute, const TextAttribute attr); - void IncrementCursor(); - void NewlineCursor(); - // Scroll needs access to this to quickly rotate around the buffer. void IncrementCircularBuffer(const TextAttribute& fillAttributes = {}); @@ -322,11 +317,6 @@ class TextBuffer final til::CoordType _estimateOffsetOfLastCommittedRow() const noexcept; void _SetFirstRowIndex(const til::CoordType FirstRowIndex) noexcept; - til::point _GetPreviousFromCursor() const; - void _SetWrapOnCurrentRow(); - void _AdjustWrapOnCurrentRow(const bool fSet); - // Assist with maintaining proper buffer state for Double Byte character sequences - void _PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute); void _ExpandTextRow(til::inclusive_rect& selectionRow) const; DelimiterClass _GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const; til::point _GetWordStartForAccessibility(const til::point target, const std::wstring_view wordDelimiters) const; diff --git a/src/host/ut_host/TextBufferTests.cpp b/src/host/ut_host/TextBufferTests.cpp index f70f5c6b8ec..0b9155cfb13 100644 --- a/src/host/ut_host/TextBufferTests.cpp +++ b/src/host/ut_host/TextBufferTests.cpp @@ -94,18 +94,10 @@ class TextBufferTests TEST_METHOD(TestCopyProperties); - TEST_METHOD(TestInsertCharacter); - - TEST_METHOD(TestIncrementCursor); - - TEST_METHOD(TestNewlineCursor); - void TestLastNonSpace(const til::CoordType cursorPosY); TEST_METHOD(TestGetLastNonSpaceCharacter); - TEST_METHOD(TestSetWrapOnCurrentRow); - TEST_METHOD(TestIncrementCircularBuffer); TEST_METHOD(TestMixedRgbAndLegacyForeground); @@ -145,7 +137,6 @@ class TextBufferTests TEST_METHOD(ResizeTraditionalHighUnicodeRowRemoval); TEST_METHOD(ResizeTraditionalHighUnicodeColumnRemoval); - TEST_METHOD(TestBurrito); TEST_METHOD(TestOverwriteChars); TEST_METHOD(TestReplace); TEST_METHOD(TestInsert); @@ -400,129 +391,6 @@ void TextBufferTests::TestCopyProperties() VERIFY_IS_TRUE(testTextBuffer->GetCursor().GetDelay()); } -void TextBufferTests::TestInsertCharacter() -{ - auto& textBuffer = GetTbi(); - - // get starting cursor position - const auto coordCursorBefore = textBuffer.GetCursor().GetPosition(); - - // Get current row from the buffer - auto& Row = textBuffer.GetRowByOffset(coordCursorBefore.y); - - // create some sample test data - const auto wch = L'Z'; - const std::wstring_view wchTest(&wch, 1); - const auto dbcsAttribute = DbcsAttribute::Leading; - const auto wAttrTest = BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE; - auto TestAttributes = TextAttribute(wAttrTest); - - // ensure that the buffer didn't start with these fields - VERIFY_ARE_NOT_EQUAL(Row.GlyphAt(coordCursorBefore.x), wchTest); - VERIFY_ARE_NOT_EQUAL(Row.DbcsAttrAt(coordCursorBefore.x), dbcsAttribute); - - auto attr = Row.GetAttrByColumn(coordCursorBefore.x); - - VERIFY_ARE_NOT_EQUAL(attr, TestAttributes); - - // now apply the new data to the buffer - textBuffer.InsertCharacter(wchTest, dbcsAttribute, TestAttributes); - - // ensure that the buffer position where the cursor WAS contains the test items - VERIFY_ARE_EQUAL(Row.GlyphAt(coordCursorBefore.x), wchTest); - VERIFY_ARE_EQUAL(Row.DbcsAttrAt(coordCursorBefore.x), dbcsAttribute); - - attr = Row.GetAttrByColumn(coordCursorBefore.x); - VERIFY_ARE_EQUAL(attr, TestAttributes); - - // ensure that the cursor moved to a new position (X or Y or both have changed) - VERIFY_IS_TRUE((coordCursorBefore.x != textBuffer.GetCursor().GetPosition().x) || - (coordCursorBefore.y != textBuffer.GetCursor().GetPosition().y)); - // the proper advancement of the cursor (e.g. which position it goes to) is validated in other tests -} - -void TextBufferTests::TestIncrementCursor() -{ - auto& textBuffer = GetTbi(); - - // only checking X increments here - // Y increments are covered in the NewlineCursor test - - const auto sBufferWidth = textBuffer.GetSize().Width(); - - const auto sBufferHeight = textBuffer.GetSize().Height(); - VERIFY_IS_TRUE(sBufferWidth > 1 && sBufferHeight > 1); - - Log::Comment(L"Test normal case of moving once to the right within a single line"); - textBuffer.GetCursor().SetXPosition(0); - textBuffer.GetCursor().SetYPosition(0); - - auto coordCursorBefore = textBuffer.GetCursor().GetPosition(); - - textBuffer.IncrementCursor(); - - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().x, 1); // X should advance by 1 - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().y, coordCursorBefore.y); // Y shouldn't have moved - - Log::Comment(L"Test line wrap case where cursor is on the right edge of the line"); - textBuffer.GetCursor().SetXPosition(sBufferWidth - 1); - textBuffer.GetCursor().SetYPosition(0); - - coordCursorBefore = textBuffer.GetCursor().GetPosition(); - - textBuffer.IncrementCursor(); - - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().x, 0); // position should be reset to the left edge when passing right edge - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().y - 1, coordCursorBefore.y); // the cursor should be moved one row down from where it used to be -} - -void TextBufferTests::TestNewlineCursor() -{ - auto& textBuffer = GetTbi(); - - const auto sBufferHeight = textBuffer.GetSize().Height(); - - const auto sBufferWidth = textBuffer.GetSize().Width(); - // width and height are sufficiently large for upcoming math - VERIFY_IS_TRUE(sBufferWidth > 4 && sBufferHeight > 4); - - Log::Comment(L"Verify standard row increment from somewhere in the buffer"); - - // set cursor X position to non zero, any position in buffer - textBuffer.GetCursor().SetXPosition(3); - - // set cursor Y position to not-the-final row in the buffer - textBuffer.GetCursor().SetYPosition(3); - - auto coordCursorBefore = textBuffer.GetCursor().GetPosition(); - - // perform operation - textBuffer.NewlineCursor(); - - // verify - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().x, 0); // move to left edge of buffer - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().y, coordCursorBefore.y + 1); // move down one row - - Log::Comment(L"Verify increment when already on last row of buffer"); - - // X position still doesn't matter - textBuffer.GetCursor().SetXPosition(3); - - // Y position needs to be on the last row of the buffer - textBuffer.GetCursor().SetYPosition(sBufferHeight - 1); - - coordCursorBefore = textBuffer.GetCursor().GetPosition(); - - // perform operation - textBuffer.NewlineCursor(); - - // verify - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().x, 0); // move to left edge - VERIFY_ARE_EQUAL(textBuffer.GetCursor().GetPosition().y, coordCursorBefore.y); // cursor Y position should not have moved. stays on same logical final line of buffer - - // This is okay because the backing circular buffer changes, not the logical screen position (final visible line of the buffer) -} - void TextBufferTests::TestLastNonSpace(const til::CoordType cursorPosY) { auto& textBuffer = GetTbi(); @@ -568,37 +436,6 @@ void TextBufferTests::TestGetLastNonSpaceCharacter() TestLastNonSpace(14); } -void TextBufferTests::TestSetWrapOnCurrentRow() -{ - auto& textBuffer = GetTbi(); - - auto sCurrentRow = textBuffer.GetCursor().GetPosition().y; - - auto& Row = textBuffer.GetMutableRowByOffset(sCurrentRow); - - Log::Comment(L"Testing off to on"); - - // turn wrap status off first - Row.SetWrapForced(false); - - // trigger wrap - textBuffer._SetWrapOnCurrentRow(); - - // ensure this row was flipped - VERIFY_IS_TRUE(Row.WasWrapForced()); - - Log::Comment(L"Testing on stays on"); - - // make sure wrap status is on - Row.SetWrapForced(true); - - // trigger wrap - textBuffer._SetWrapOnCurrentRow(); - - // ensure row is still on - VERIFY_IS_TRUE(Row.WasWrapForced()); -} - void TextBufferTests::TestIncrementCircularBuffer() { auto& textBuffer = GetTbi(); @@ -1929,27 +1766,6 @@ void TextBufferTests::ResizeTraditionalHighUnicodeColumnRemoval() _buffer->ResizeTraditional(trimmedBufferSize); } -void TextBufferTests::TestBurrito() -{ - til::size bufferSize{ 80, 9001 }; - UINT cursorSize = 12; - TextAttribute attr{ 0x7f }; - auto _buffer = std::make_unique(bufferSize, attr, cursorSize, false, _renderer); - - // This is the burrito emoji: 🌯 - // It's encoded in UTF-16, as needed by the buffer. - const auto burrito = L"\xD83C\xDF2F"; - OutputCellIterator burriter{ burrito }; - - auto afterFIter = _buffer->Write({ L"F" }); - _buffer->IncrementCursor(); - - auto afterBurritoIter = _buffer->Write(burriter); - _buffer->IncrementCursor(); - _buffer->IncrementCursor(); - VERIFY_IS_FALSE(afterBurritoIter); -} - void TextBufferTests::TestOverwriteChars() { til::size bufferSize{ 10, 3 };