/*++ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: - textBuffer.hpp Abstract: - This module contains structures and functions for manipulating a text based buffer within the console host window. Author(s): - Michael Niksa (miniksa) 10-Apr-2014 - Paul Campbell (paulcam) 10-Apr-2014 Revision History: - From components of output.h/.c by Therese Stowell (ThereseS) 1990-1991 Notes: ScreenBuffer data structure overview: each screen buffer has an array of ROW structures. each ROW structure contains the data for one row of text. the data stored for one row of text is a character array and an attribute array. the character array is allocated the full length of the row from the heap, regardless of the non-space length. we also maintain the non-space length. the character array is initialized to spaces. the attribute array is run length encoded (i.e 5 BLUE, 3 RED). if there is only one attribute for the whole row (the normal case), it is stored in the ATTR_ROW structure. otherwise the attr string is allocated from the heap. ROW - CHAR_ROW - CHAR string \ \ length of char string \ ATTR_ROW - ATTR_PAIR string \ length of attr pair string ROW ROW ROW ScreenInfo->Rows points to the ROW array. ScreenInfo->Rows[0] is not necessarily the top row. ScreenInfo->BufferInfo.TextInfo->FirstRow contains the index of the top row. That means scrolling (if scrolling entire screen) merely involves changing the FirstRow index, filling in the last row, and updating the screen. --*/ #pragma once #include "cursor.h" #include "Row.hpp" #include "TextAttribute.hpp" #include "UnicodeStorage.hpp" #include "../types/inc/Viewport.hpp" #include "../buffer/out/textBufferCellIterator.hpp" #include "../buffer/out/textBufferTextIterator.hpp" #include "../renderer/inc/IRenderTarget.hpp" class TextBuffer final { public: TextBuffer(const COORD screenBufferSize, const TextAttribute defaultAttributes, const UINT cursorSize, Microsoft::Console::Render::IRenderTarget& renderTarget); TextBuffer(const TextBuffer& a) = delete; ~TextBuffer() = default; // Used for duplicating properties to another text buffer void CopyProperties(const TextBuffer& OtherBuffer); // row manipulation const ROW& GetRowByOffset(const size_t index) const; ROW& GetRowByOffset(const size_t index); TextBufferCellIterator GetCellDataAt(const COORD at) const; TextBufferCellIterator GetCellLineDataAt(const COORD at) const; TextBufferCellIterator GetCellDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const; TextBufferTextIterator GetTextDataAt(const COORD at) const; TextBufferTextIterator GetTextLineDataAt(const COORD at) const; TextBufferTextIterator GetTextDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const; // Text insertion functions OutputCellIterator Write(const OutputCellIterator givenIt); OutputCellIterator Write(const OutputCellIterator givenIt, const COORD target); OutputCellIterator WriteLine(const OutputCellIterator givenIt, const COORD target, const bool setWrap = false, const std::optional limitRight = std::nullopt); bool InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr); bool InsertCharacter(const std::wstring_view chars, const DbcsAttribute dbcsAttribute, const TextAttribute attr); bool IncrementCursor(); bool NewlineCursor(); // Scroll needs access to this to quickly rotate around the buffer. bool IncrementCircularBuffer(); COORD GetLastNonSpaceCharacter() const; Cursor& GetCursor(); const Cursor& GetCursor() const; const SHORT GetFirstRowIndex() const; const Microsoft::Console::Types::Viewport GetSize() const; void ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta); UINT TotalRowCount() const; [[nodiscard]] TextAttribute GetCurrentAttributes() const noexcept; void SetCurrentAttributes(const TextAttribute currentAttributes) noexcept; void Reset(); [[nodiscard]] HRESULT ResizeTraditional(const COORD newSize) noexcept; const UnicodeStorage& GetUnicodeStorage() const; UnicodeStorage& GetUnicodeStorage(); Microsoft::Console::Render::IRenderTarget& GetRenderTarget(); class TextAndColor { public: std::vector text; std::vector> FgAttr; std::vector> BkAttr; }; const TextAndColor GetTextForClipboard(const bool lineSelection, const bool trimTrailingWhitespace, const std::vector& selectionRects, std::function GetForegroundColor, std::function GetBackgroundColor) const; private: std::deque _storage; Cursor _cursor; SHORT _firstRow; // indexes top row (not necessarily 0) TextAttribute _currentAttributes; // storage location for glyphs that can't fit into the buffer normally UnicodeStorage _unicodeStorage; void _RefreshRowIDs(std::optional newRowWidth); Microsoft::Console::Render::IRenderTarget& _renderTarget; void _SetFirstRowIndex(const SHORT FirstRowIndex); COORD _GetPreviousFromCursor() const; void _SetWrapOnCurrentRow(); void _AdjustWrapOnCurrentRow(const bool fSet); void _NotifyPaint(const Microsoft::Console::Types::Viewport& viewport) const; // Assist with maintaining proper buffer state for Double Byte character sequences bool _PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute); bool _AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribute); ROW& _GetFirstRow(); ROW& _GetPrevRowNoWrap(const ROW& row); #ifdef UNIT_TESTING friend class TextBufferTests; friend class UiaTextRangeTests; #endif };