Buffer
The buffer classes represent rendered terminal content in memory before it is written to the screen.
ReadableBuffer provides a read-only inspection API,
WritableBuffer extends this with mutation and drawing operations, and
Buffer is the concrete 2D storage type used in most applications.
For more specialized use cases, RemappedBuffer adds efficient
row- and column-based reordering. This is ideal for editors, scrollback views, or any workload that frequently inserts,
deletes, or moves whole lines.
Building on top of that, CursorBuffer provides a VT-style
cursor-writing interface via CursorWriter.
Use these types whenever you want to build frames off-screen, compare frames, copy content between buffers, or derive masks from rendered characters.
Usage
Reading and Writing Through Buffer Interfaces
ReadableBuffer and WritableBuffer
allow helper functions to operate on terminal content without depending on a specific implementation.
auto renderStatusPanel(WritableBuffer &target, Rectangle panel) -> void {
target.fill(panel, Char{" ", Color{fg::Inherited, bg::Blue}});
target.drawText(
"Status",
panel.insetBy(Margins{1}),
Alignment::TopLeft,
Color{fg::BrightWhite, bg::Blue});
}
auto screen = Buffer{Size{80, 24}};
renderStatusPanel(screen, Rectangle{2, 2, 24, 8});
Use ReadableBuffer when your function only needs to inspect content,
count differences, or derive masks.
Use WritableBuffer when your function should modify the target buffer
without caring whether it operates on a standalone Buffer or another writable implementation.
Cloning, Copying, and Resizing
Buffer supports the typical frame-management tasks required by interactive
terminal applications: creating new frames, cloning the current state, and resizing buffers when the terminal size changes.
auto current = Buffer{Size{80, 24}};
current.fill(Char{" ", Color{fg::Inherited, bg::Black}});
const auto previous = current.clone();
current.resize(Size{100, 30}, true, Char::space());
current.setFrom(*previous, Char{" ", Color{fg::Inherited, bg::Black}});
clone() returns a writable copy through the abstract interface. This makes it easy to store previous frames for
diffing, animation steps, or rollback logic.
When resizing a concrete Buffer, use the reorder overload if you want to preserve
existing content while expanding or cropping the canvas.
Working with Remapped Buffers
RemappedBuffer is designed for workloads where the content remains
logically grid-based, but rows or columns are frequently reshuffled.
Instead of rewriting every affected cell, the buffer maintains remapping tables and only updates rows or columns that become newly visible. This keeps operations like scrolling or line insertion efficient, even for large buffers.
auto history = RemappedBuffer{Size{80, 2'000}, Orientation::Vertical};
history.fill(Char::space());
history.eraseRows(0, Char::space(), 1); // Scroll everything up by one row.
history.set(Position{0, 1'999}, String{"new log line"});
history.resize(Size{100, 2'000}, true, Char::space());
Use the plain RemappedBuffer::resize() overload when you want
maximum performance and plan to redraw the content anyway.
Use the reorder overload when the visible order must remain stable while expanding or cropping the buffer.
Streaming Scrollback with CursorBuffer
CursorBuffer is the right choice when text is appended over time, as if it
were written directly to a terminal.
It tracks a cursor position, maintains an active color, and supports streaming writes via
CursorWriter. When the cursor reaches the bottom edge, it can wrap, scroll,
or grow vertically depending on the configured overflow mode.
Newly created cells are initialized using fillChar(), allowing you to keep a consistent background color or
placeholder glyph as the buffer grows.
auto logHistory = CursorBuffer{
Size{120, 10},
CursorBuffer::OverflowMode::ExpandThenShift,
Size{120, 500},
Char{" ", Color{fg::Default, bg::Black}}};
logHistory.setColor(Color{fg::BrightBlue, bg::Black});
logHistory.printParagraph("2026-03-26 09:02:23 INF Request completed in 43 ms");
logHistory.setColor(Color{fg::BrightYellow, bg::Black});
logHistory.printParagraph("2026-03-26 09:03:04 WRN Cache refresh is still pending");
const auto visibleTop = std::max(0, logHistory.size().height() - 20);
auto view = BufferConstRefView{logHistory, Rectangle{0, visibleTop, 120, 20}};
terminal.updateScreen(view);
This pattern works especially well for log viewers, REPL-style tools, dashboards, or any application that needs a growing history buffer with a live viewport onto the most recent content.
If your fill strategy changes later, update it with
CursorBuffer::setFillChar.
For details about the streaming API itself—such as print(), printLine(), and cursor movement—see
Cursor Output.
Important
For an efficient render loop, keep a persistent instance of Buffer and
simply resize it when the terminal size changes.
Reusing the same buffer avoids unnecessary memory allocations and helps keep rendering predictable and fast.
A typical render loop might look like this:
struct MyApp {
void renderLoop() {
for (;;) {
_terminal.testScreenSize();
_buffer.resize(_terminal.size());
// Render the current frame into the buffer.
_terminal.updateScreen(_buffer);
// Handle key presses or other input.
}
}
Terminal _terminal;
Buffer _buffer;
};
Building Buffers from Text Lines
For status panels, generated reports, or static UI elements,
Buffer can be constructed directly from line-oriented text.
const auto help = Buffer::fromLinesInString(String{
"Q Quit\n"
"R Refresh\n"
"H Toggle help"});
auto screen = Buffer{Size{40, 12}};
screen.setFrom(help, Char::space());
This is often the fastest way to turn preformatted terminal text into a buffer that can later be positioned within a larger layout.
Comparing Frames and Deriving Masks
ReadableBuffer also provides analysis helpers that are useful for tests,
animation pipelines, and bitmap-based effects.
const auto changedCells = previous->countDifferencesTo(current);
const auto frameMask = current.toMask({U'|', U'-', U'+', U'┌', U'┐', U'└', U'┘'});
if (changedCells > 0 && frameMask.size().contains(Position{0, 0})) {
// React to the changed frame content.
}
Use toMask() when you want to reason about the structure of rendered content (for example, line art or borders)
instead of raw character or color data.
Interface
-
class ReadableBuffer
A readable buffer.
Subclassed by erbsland::cterm::BufferViewBase, erbsland::cterm::WritableBuffer
Public Functions
-
virtual Size size() const noexcept = 0
Get the configured size of the buffer.
- Returns:
The width and height of the buffer.
-
virtual Rectangle rect() const noexcept = 0
Get a rectangle representing this buffer.
- Returns:
The rectangle for this buffer.
-
virtual const Char &get(Position pos) const noexcept = 0
Read the block stored at the given position.
- Parameters:
pos – The coordinates within the buffer.
- Returns:
A reference to the stored block.
-
virtual WritableBufferPtr clone() const = 0
Create a writeable copy of this buffer.
This will copy every block from this buffer into a new independent instance.
-
virtual std::size_t countDifferencesTo(const ReadableBuffer &other) const noexcept
Count the differences from this to another buffer.
If the size of
otheris smaller or larger than this buffer, the size change counts to the difference.- Parameters:
other – The other buffer to compare with.
- Returns:
The number of blocks that differ between the two buffers.
-
Bitmap toMask(const std::u32string &characters, bool invert = false)
Create a mask from this buffer.
All characters that match one of the given characters result in a pixel set in the mask.
- Parameters:
characters – The characters to match. Only one code-point characters are supported.
invert – If true, not-matching characters result in a pixel set in the mask.
- Returns:
A bitmap mask with the same size as this buffer.
-
virtual Size size() const noexcept = 0
-
class WritableBuffer : public erbsland::cterm::ReadableBuffer
Abstract writable terminal buffer interface.
This base class combines the read-only
ReadableBufferAPI with mutation and higher-level drawing helpers such as frames, text, and bitmap rendering. Concrete implementations likeBufferprovide the actual storage.Subclassed by erbsland::cterm::Buffer, erbsland::cterm::RemappedBuffer
Public Functions
-
virtual void resize(Size newSize) = 0
Resize this buffer in a memory-efficient way.
The content of the resized buffer is undefined and must be filled with new content.
- Parameters:
newSize – The new size for the buffer.
-
virtual void set(Position pos, const Char &block) noexcept = 0
Write a block at the given position.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
-
virtual void setAndResizeFrom(const ReadableBuffer &other)
Copy the content from another buffer and match its size.
This buffer is completely overwritten and resized to the size of
other.- Parameters:
other – The buffer to copy from.
-
virtual void set(Position pos, const Char &block, const CharCombinationStylePtr &combinationStyle) noexcept
Write a block at the given position using a combination style.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
combinationStyle – The combination style for overwriting existing characters.
-
virtual void set(Position pos, const String &str) noexcept
Write a string at the given position.
NL jumps to the next row. Other control and zero-width characters are ignored. Color (even inherited) overwrites the existing characters. Use
drawText(pos, text)for a color overlay.- Parameters:
pos – The coordinates within the buffer.
str – The string to write.
-
void setFrom(const ReadableBuffer &other, Char fillChar = Char::space())
Copy the content from another buffer into this one.
This buffer is completely overwritten but not resized. If there is a size mismatch, the contents are either cut off or filled using
fillChar.- Parameters:
other – The buffer to copy from.
fillChar – The character to use for filling if the sizes differ.
-
virtual void fill(const Char &fillBlock) noexcept
Fill/clear the buffer with the given character.
- Parameters:
fillBlock – The block to use to fill the buffer.
-
void fill(Rectangle rect, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
-
void fill(Rectangle rect, const Tile9StylePtr &style, Color baseColor = {}, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle using a repeating 9-tile style.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
style – The tile style to repeat across the rectangle.
baseColor – The base color underneath the style colors.
combinationStyle – The combination style for overwriting existing characters.
-
void drawFrame(Rectangle rect, const Char &frameBlock, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Draw a frame inside a given rectangle This will set all blocks at the edge, inside the given rectangle.
- Parameters:
rect – The rectangle for the frame.
frameBlock – The block for the frame.
combinationStyle – The combination style for overwriting existing characters.
-
void drawFrame(Rectangle rect, const Char16StylePtr &frameStyle, const CharCombinationStylePtr &combinationStyle = {}, Color frameColor = {}) noexcept
Draw a frame inside a given rectangle This will set all blocks at the edge, inside the given rectangle.
- Parameters:
rect – The rectangle for the frame.
frameStyle – A custom frame style.
combinationStyle – The combination style for overwriting existing characters.
frameColor – The base frame color. Any color from the frame style overlays this base color.
-
void drawFrame(Rectangle rect, const Tile9StylePtr &style, Color frameColor = {}, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Draw a frame inside a given rectangle using a repeating 9-tile style.
This will set all blocks at the edge, inside the given rectangle.
- Parameters:
rect – The rectangle for the frame.
style – The tile style for the frame.
frameColor – The base frame color. Any color from the style overlays this base color.
combinationStyle – The combination style for overwriting existing characters.
-
void drawFrame(Rectangle rect, FrameStyle frameStyle, Color frameColor = {}) noexcept
Draw a frame inside a given rectangle This will set all blocks at the edge, inside the given rectangle.
- Parameters:
rect – The rectangle for the frame.
frameStyle – The predefined frame style.
frameColor – The base frame color. Any color from the frame style overlays this base color.
-
void drawFrame(Rectangle rect, const FrameDrawOptions &options = FrameDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a frame inside a given rectangle with configurable style, fill, and animated colors.
This will set all blocks at the edge, inside the given rectangle. If
options.fillBlock()is empty and noTile9Styleis active, the interior is left unchanged.- Parameters:
rect – The rectangle for the frame.
options – Frame drawing options.
animationCycle – Animation cycle for frame and fill color animations.
-
void drawFilledFrame(Rectangle rect, const Char &frameBlock, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Draw a box and fill it.
- Parameters:
rect – The rectangle for the frame.
frameBlock – The block for the frame.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
-
void drawFilledFrame(Rectangle rect, const Char16StylePtr &frameStyle, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}, Color frameColor = {}) noexcept
Draw a box and fill it.
- Parameters:
rect – The rectangle for the frame.
frameStyle – A custom frame style.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
frameColor – The base frame color. Any color from the frame style overlays this base color.
-
void drawFilledFrame(Rectangle rect, const Tile9StylePtr &style, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}, Color frameColor = {}) noexcept
Draw a box and fill it using a repeating 9-tile style for the frame.
- Parameters:
rect – The rectangle for the frame.
style – The tile style for the frame.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
frameColor – The base frame color. Any color from the style overlays this base color.
-
void drawFilledFrame(Rectangle rect, FrameStyle frameStyle, const Char &fillBlock, Color frameColor = {}) noexcept
Draw a box and fill it.
- Parameters:
rect – The rectangle for the frame.
frameStyle – The predefined frame style.
fillBlock – The block for filling.
frameColor – The base frame color. Any color from the frame style overlays this base color.
-
virtual void drawText(Position pos, const String &str)
Draw a text without warping from the given position.
A newline breaks to the next line, starting at
pos.x. Characters outside this buffer are cut off.- Parameters:
pos – The start position (top-left corner).
str – The text to draw on this buffer.
-
void drawText(const Text &text, std::size_t animationCycle = 0)
If fg or bg is set to
Inherited, the current color from the buffer is used.Draw simple text into a rectangle. If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text description.
animationCycle – Animation cycle for animated text.
-
void drawText(std::string_view text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
Draw simple text into a rectangle.
If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text to render.
rect – The target rectangle.
alignment – The alignment inside the rectangle.
color – The text color.
animationCycle – Animation cycle for animated text.
-
void drawText(String text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void drawBitmap(const Bitmap &bitmap, Position pos, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap at a given position.
The bitmap is rendered according to
options.scaleMode(). Ifoptions.char16Style()is set, it overrides the scale mode and renders one terminal cell per bitmap pixel. Pixels or rendered cells outside the buffer are ignored.- Parameters:
bitmap – The bitmap to draw.
pos – The position of the top left corner.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
void drawBitmap(const Bitmap &bitmap, Rectangle rect, Alignment alignment = Alignment::TopLeft, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap into the given rectangle.
The rendered bitmap is aligned inside
rect. If it is larger thanrect, it is cropped according to the alignment.Note
For half-block drawing mode, alignment and cropping happen at rendered cell boundaries, not per pixel.
- Parameters:
bitmap – The bitmap to draw.
rect – The rectangle to draw the bitmap into.
alignment – Alignment of the bitmap within the rectangle.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
void drawBuffer(const ReadableBuffer &buffer, Position targetPos = Position{})
Draw the contents of another buffer into this one.
Resulting positions outside the target rectangle are clipped.
- Parameters:
buffer – The buffer to draw.
targetPos – The target position where to draw the top-left corner of the buffer.
- Throws:
std::invalid_argument – if
bufferis this buffer.
-
void drawBuffer(const ReadableBuffer &buffer, Rectangle targetRect, Alignment alignment = Alignment::TopLeft)
Draw the contents of another buffer into this one.
Resulting positions outside the target rectangle are clipped.
- Parameters:
buffer – The buffer to draw.
targetRect – The target rectangle where to draw the buffer. Clips
bufferif larger.alignment – The alignment of the buffer within the target rectangle.
- Throws:
std::invalid_argument – if
bufferis this buffer.
-
virtual void drawBuffer(const ReadableBuffer &buffer, const BufferDrawOptions &options)
Draw the contents of another buffer into this one.
- Parameters:
buffer – The buffer to draw.
options – The options for drawing the buffer.
- Throws:
std::invalid_argument – if
bufferis this buffer.
-
virtual void resize(Size newSize) = 0
-
class Buffer : public erbsland::cterm::WritableBuffer
A mutable 2D buffer storing characters and colors for rendering.
Handling of non-1-width blocks:
Blocks with zero display width are ignored.
Blocks with a display width of 2 will overwrite two adjacent cells.
The first cell will contain the set character, the next cell a zero-width (empty) character.
Both cells will have the same color.
A 2-width block at the right edge is ignored.
Blocks with a display width > 2 are ignored.
Public Functions
-
Buffer()
Creates a 1x1 buffer filled with a space.
Usually only used as a placeholder until resized.
-
explicit Buffer(Size size, Char fillChar = Char::space())
Construct a buffer with the given size and fill it with an initial block.
- Parameters:
size – The dimensions of the buffer. Size must be at least 1x1.
fillChar – The optional fill character for the buffer.
- Throws:
std::invalid_argument – if size is invalid
-
virtual Size size() const noexcept override
Get the configured size of the buffer.
- Returns:
The width and height of the buffer.
-
virtual Rectangle rect() const noexcept override
Get a rectangle representing this buffer.
- Returns:
The rectangle for this buffer.
-
virtual const Char &get(Position pos) const noexcept override
Read the block stored at the given position.
- Parameters:
pos – The coordinates within the buffer.
- Returns:
A reference to the stored block.
-
virtual WritableBufferPtr clone() const override
Create a writeable copy of this buffer.
This will copy every block from this buffer into a new independent instance.
-
virtual void resize(Size newSize) override
Resize this buffer in a memory-efficient way.
The content of the resized buffer is undefined and must be filled with new content.
- Parameters:
newSize – The new size for the buffer.
-
virtual void set(Position pos, const Char &block) noexcept override
Write a block at the given position.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
-
virtual void setAndResizeFrom(const ReadableBuffer &other) override
Copy the content from another buffer and match its size.
This buffer is completely overwritten and resized to the size of
other.- Parameters:
other – The buffer to copy from.
-
void resize(Size size, bool reorder, Char fillChar = Char::space())
Resize this buffer.
Resizing the buffer will not clear it. If
reorderistrue, the content will either be expanded with space blocks or cropped. Ifreorderisfalse, the state of the resized buffer is undefined (you must clear it yourself).- Parameters:
size – The new size.
reorder – Whether to reorder the content when resizing.
fillChar – The character to fill the new space with.
- Throws:
std::invalid_argument – if size is invalid
-
virtual void fill(const Char &fillBlock) noexcept override
Fill/clear the buffer with the given character.
- Parameters:
fillBlock – The block to use to fill the buffer.
-
void drawText(std::string_view text, Alignment alignment, Rectangle rect, Color color = {}, std::size_t animationCycle = 0)
Draw text into a rectangle using the legacy parameter order.
- Deprecated:
Use
drawText(std::string_view, Rectangle, ...)instead.
- Parameters:
text – The text to render.
alignment – The alignment inside the rectangle.
rect – The target rectangle.
color – The text color.
animationCycle – Animation cycle for animated text.
-
void drawBitmap(const Bitmap &bitmap, Position pos, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap at a given position.
The bitmap is rendered according to
options.scaleMode(). Ifoptions.char16Style()is set, it overrides the scale mode and renders one terminal cell per bitmap pixel. Pixels or rendered cells outside the buffer are ignored.- Parameters:
bitmap – The bitmap to draw.
pos – The position of the top left corner.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
void drawBitmap(const Bitmap &bitmap, Rectangle rect, Alignment alignment = Alignment::TopLeft, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap into the given rectangle.
The rendered bitmap is aligned inside
rect. If it is larger thanrect, it is cropped according to the alignment.Note
For half-block drawing mode, alignment and cropping happen at rendered cell boundaries, not per pixel.
- Parameters:
bitmap – The bitmap to draw.
rect – The rectangle to draw the bitmap into.
alignment – Alignment of the bitmap within the rectangle.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
virtual void drawText(Position pos, const String &str)
Draw a text without warping from the given position.
A newline breaks to the next line, starting at
pos.x. Characters outside this buffer are cut off.- Parameters:
pos – The start position (top-left corner).
str – The text to draw on this buffer.
-
void drawText(const Text &text, std::size_t animationCycle = 0)
If fg or bg is set to
Inherited, the current color from the buffer is used.Draw simple text into a rectangle. If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text description.
animationCycle – Animation cycle for animated text.
-
void drawText(std::string_view text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
Draw simple text into a rectangle.
If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text to render.
rect – The target rectangle.
alignment – The alignment inside the rectangle.
color – The text color.
animationCycle – Animation cycle for animated text.
-
void drawText(String text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
virtual void fill(const Char &fillBlock) noexcept
Fill/clear the buffer with the given character.
- Parameters:
fillBlock – The block to use to fill the buffer.
-
void fill(Rectangle rect, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
-
void fill(Rectangle rect, const Tile9StylePtr &style, Color baseColor = {}, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle using a repeating 9-tile style.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
style – The tile style to repeat across the rectangle.
baseColor – The base color underneath the style colors.
combinationStyle – The combination style for overwriting existing characters.
-
virtual void resize(Size newSize) = 0
Resize this buffer in a memory-efficient way.
The content of the resized buffer is undefined and must be filled with new content.
- Parameters:
newSize – The new size for the buffer.
-
virtual void set(Position pos, const Char &block) noexcept = 0
Write a block at the given position.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
-
virtual void set(Position pos, const Char &block, const CharCombinationStylePtr &combinationStyle) noexcept
Write a block at the given position using a combination style.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
combinationStyle – The combination style for overwriting existing characters.
-
virtual void set(Position pos, const String &str) noexcept
Write a string at the given position.
NL jumps to the next row. Other control and zero-width characters are ignored. Color (even inherited) overwrites the existing characters. Use
drawText(pos, text)for a color overlay.- Parameters:
pos – The coordinates within the buffer.
str – The string to write.
Public Static Functions
-
static Buffer fromLinesInString(const String &text)
Creates a buffer from the lines in a string.
This function splits the given string into lines and creates a buffer with a matching size.
- Parameters:
text – The string to split into lines and create a buffer from. Must not be empty.
- Returns:
A buffer containing the lines from the input string.
-
static Buffer fromLines(const StringLines &lines)
Creates a buffer from the lines in a string.
- Parameters:
lines – The lines to create the buffer from. Must not be empty.
- Returns:
A buffer containing the lines from the input string.
-
class RemappedBuffer : public erbsland::cterm::WritableBuffer
A buffer that allows fast remapping/shifting/inserting/deleting of rows and columns.
This buffer is useful if you have a large buffer that requires frequent row- or column-based manipulations. It is designed for fast insert/delete/move and shift operations.
This buffer also knows two orientations: vertical and horizontal.
In the vertical orientation, the buffer can efficiently grow vertically, keeping the existing data intact.
In the horizontal orientation, the buffer can efficiently grow horizontally, keeping the existing data intact.
When growing the buffer, memory reallocation may be necessary. Use
reserveto reserve enough memory to avoid frequent reallocations.Use
resize(size, true, fillChar)when you need to preserve the visible order while resizing.
Subclassed by erbsland::cterm::CursorBuffer
Public Types
-
using CoordinateMap = std::vector<Coordinate>
A vector mapping one coordinate to another.
Public Functions
-
RemappedBuffer()
Creates a 1x1 vertical buffer filled with a space.
Usually only used as a placeholder until resized.
-
explicit RemappedBuffer(Size size, Orientation orientation = Orientation::Vertical, Char fillChar = Char::space())
Construct a buffer with the given size and fill it with an initial block.
- Parameters:
size – The dimensions of the buffer. Size must be at least 1x1.
orientation – The orientation of the buffer. Cannot be changed after creation.
fillChar – The optional fill character for the buffer.
- Throws:
std::invalid_argument – if size is invalid
-
virtual Size size() const noexcept override
Get the current size of the buffer.
- Returns:
The configured width and height.
-
virtual Rectangle rect() const noexcept override
Get the rectangle covering the whole buffer.
- Returns:
A rectangle with origin
(0,0)and the current size.
-
virtual const Char &get(Position pos) const noexcept override
Read the block stored at the given logical position.
- Parameters:
pos – The logical coordinates inside the buffer.
- Returns:
A reference to the stored block, or a shared space block for invalid positions.
-
virtual WritableBufferPtr clone() const override
Create an independent writable copy of this buffer.
- Returns:
A shared pointer to the cloned buffer.
-
virtual void resize(Size newSize) override
Resize this buffer.
This is the fast resize path. The internal mapping is rebuilt and the visible content order is undefined after the operation. Use
resize(size, true, fillChar)if you need to preserve the visible order.- Parameters:
newSize – The new size of the buffer.
- Throws:
std::invalid_argument – if
newSizeis invalid.
-
virtual void set(Position pos, const Char &block) noexcept override
Write a block at the given logical position.
This mirrors the wide-character handling from
Buffer: zero-width blocks are ignored, width-2 blocks occupy the next logical cell as an empty continuation cell, and width-2 blocks at the right edge are ignored.- Parameters:
pos – The logical coordinates within the buffer.
block – The block to write.
-
void resize(Size size, bool reorder, Char fillChar = Char::space())
Resize this buffer and optionally keep the visible content order.
- Parameters:
size – The new size.
reorder – If
true, keep the visible order and fill new cells withfillChar. Iffalse, resize using the fast path and leave the visible order undefined.fillChar – The fill character for newly created cells in reordered mode. In fast mode it is only used to initialize newly appended storage cells.
- Throws:
std::invalid_argument – if
sizeis invalid.
-
void reserve(Size size) noexcept
Reserve memory for the given buffer size.
- Parameters:
size – The size whose capacity should be reserved.
-
void shift(Direction direction, Char fillChar, int count = 1)
Shift the buffer in the given direction, fill new cells with a given character.
- Parameters:
direction – The direction of the shift.
fillChar – The character to fill new cells with.
count – The number of cells to shift.
- Throws:
std::invalid_argument – if
countis negative or exceeds buffer size.
-
inline void shift(const Direction direction, const int count = 1)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void rotate(Direction direction, int count = 1)
Rotate the buffer in the given direction.
Cells are shifted in a circular manner, wrapping around to the other end of the buffer.
- Parameters:
direction – The direction in which to rotate.
count – The number of cells to rotate.
- Throws:
std::invalid_argument – if
countis negative or exceeds buffer size.
-
void eraseRows(Coordinate startRow, Char fillChar, int count = 1)
Erase rows in the buffer.
This will erase
countrows, starting fromstartRow, and insert empty ones at the end. If you like to actually shrink the buffer, useresizeafter this call.- Parameters:
startRow – The first row to delete.
fillChar – The character to fill new cells with.
count – The number of rows to delete.
- Throws:
std::invalid_argument – if
startRowis out of bounds orcountis negative or exceeds buffer size.
-
inline void eraseRows(const Coordinate startRow, const int count = 1)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void eraseColumns(Coordinate startColumn, Char fillChar, int count = 1)
Erase columns in the buffer.
This will erase
countcolumns, starting fromstartColumn, and insert empty ones at the end. If you like to actually shrink the buffer, useresizeafter this call.- Parameters:
startColumn – The first column to delete.
fillChar – The character to fill new cells with.
count – The number of columns to delete.
- Throws:
std::invalid_argument – if
startColumnis out of bounds orcountis negative or exceeds buffer size.
-
inline void eraseColumns(const Coordinate startColumn, const int count = 1)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void insertRows(Coordinate startRow, Char fillChar, int count = 1)
Insert rows in the buffer.
The rows at the bottom of the buffer will be erased to make room for the new rows. If you like to actually grow the buffer, use
resizebefore this call.- Parameters:
startRow – The first row to insert.
fillChar – The character to fill the new rows with.
count – The number of rows to insert.
- Throws:
std::invalid_argument – if
startRowis out of bounds orcountis negative or exceeds buffer size.
-
inline void insertRows(const Coordinate startRow, const int count = 1)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void insertColumns(Coordinate startColumn, Char fillChar, int count = 1)
Insert columns in the buffer.
The columns on the right side of the buffer will be erased to make room for the new columns. If you like to actually grow the buffer, use
resizebefore this call.- Parameters:
startColumn – The first column to insert.
fillChar – The character to fill the new columns with.
count – The number of columns to insert.
- Throws:
std::invalid_argument – if
startColumnis out of bounds orcountis negative or exceeds buffer size.
-
inline void insertColumns(const Coordinate startColumn, const int count = 1)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void moveRows(Coordinate startRow, int count, Coordinate delta, Char fillChar)
Move rows in the buffer by a given delta.
A positive delta moves rows down, a negative delta moves rows up. This reshuffles the moved rows, but rows that get moved out of the buffer area are deleted and replaced by empty cells using the
fillChar.- Parameters:
startRow – The first row to move.
count – The number of rows to move.
delta – The number of positions to move (positive = down, negative = up).
fillChar – The character to fill vacated cells with.
- Throws:
std::invalid_argument – if
startRowis out of bounds orcountis negative or exceeds buffer size.
-
inline void moveRows(const Coordinate startRow, const int count, const Coordinate delta)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
void moveColumns(Coordinate startColumn, int count, Coordinate delta, Char fillChar)
Move columns in the buffer by a given delta.
A positive delta moves columns right, a negative delta moves columns left. This reshuffles the moved columns, but columns that get moved out of the buffer area are deleted and replaced by empty cells using the
fillChar.- Parameters:
startColumn – The first column to move.
count – The number of columns to move.
delta – The number of positions to move (positive = right, negative = left).
fillChar – The character to fill vacated cells with.
- Throws:
std::invalid_argument – if
startColumnis out of bounds orcountis negative or exceeds buffer size.
-
inline void moveColumns(const Coordinate startColumn, const int count, const Coordinate delta)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
virtual void fill(const Char &fillBlock) noexcept override
Fill/clear the buffer with the given character.
Note
This will also reset the internal remapping indexes.
- Parameters:
fillBlock – The block to use to fill the buffer.
-
void drawBitmap(const Bitmap &bitmap, Position pos, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap at a given position.
The bitmap is rendered according to
options.scaleMode(). Ifoptions.char16Style()is set, it overrides the scale mode and renders one terminal cell per bitmap pixel. Pixels or rendered cells outside the buffer are ignored.- Parameters:
bitmap – The bitmap to draw.
pos – The position of the top left corner.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
void drawBitmap(const Bitmap &bitmap, Rectangle rect, Alignment alignment = Alignment::TopLeft, const BitmapDrawOptions &options = BitmapDrawOptions::defaultOptions(), std::size_t animationCycle = 0) noexcept
Draw a bitmap into the given rectangle.
The rendered bitmap is aligned inside
rect. If it is larger thanrect, it is cropped according to the alignment.Note
For half-block drawing mode, alignment and cropping happen at rendered cell boundaries, not per pixel.
- Parameters:
bitmap – The bitmap to draw.
rect – The rectangle to draw the bitmap into.
alignment – Alignment of the bitmap within the rectangle.
options – Bitmap drawing options.
animationCycle – Animation cycle for color animations.
-
virtual void drawText(Position pos, const String &str)
Draw a text without warping from the given position.
A newline breaks to the next line, starting at
pos.x. Characters outside this buffer are cut off.- Parameters:
pos – The start position (top-left corner).
str – The text to draw on this buffer.
-
void drawText(const Text &text, std::size_t animationCycle = 0)
If fg or bg is set to
Inherited, the current color from the buffer is used.Draw simple text into a rectangle. If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text description.
animationCycle – Animation cycle for animated text.
-
void drawText(std::string_view text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
Draw simple text into a rectangle.
If fg or bg is set to
Inherited, the current color from the buffer is used.- Parameters:
text – The text to render.
rect – The target rectangle.
alignment – The alignment inside the rectangle.
color – The text color.
animationCycle – Animation cycle for animated text.
-
void drawText(String text, Rectangle rect, Alignment alignment = Alignment::TopLeft, Color color = {}, std::size_t animationCycle = 0)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
virtual void fill(const Char &fillBlock) noexcept
Fill/clear the buffer with the given character.
- Parameters:
fillBlock – The block to use to fill the buffer.
-
void fill(Rectangle rect, const Char &fillBlock, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
fillBlock – The block for filling.
combinationStyle – The combination style for overwriting existing characters.
-
void fill(Rectangle rect, const Tile9StylePtr &style, Color baseColor = {}, const CharCombinationStylePtr &combinationStyle = {}) noexcept
Fill the given rectangle using a repeating 9-tile style.
Positions outside the buffer are ignored.
- Parameters:
rect – The rectangle to be filled.
style – The tile style to repeat across the rectangle.
baseColor – The base color underneath the style colors.
combinationStyle – The combination style for overwriting existing characters.
-
virtual void resize(Size newSize) = 0
Resize this buffer in a memory-efficient way.
The content of the resized buffer is undefined and must be filled with new content.
- Parameters:
newSize – The new size for the buffer.
-
virtual void set(Position pos, const Char &block) noexcept = 0
Write a block at the given position.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
-
virtual void set(Position pos, const Char &block, const CharCombinationStylePtr &combinationStyle) noexcept
Write a block at the given position using a combination style.
Note
Writes outside the buffer are ignored.
- Parameters:
pos – The coordinates within the buffer.
block – The block value to store.
combinationStyle – The combination style for overwriting existing characters.
-
virtual void set(Position pos, const String &str) noexcept
Write a string at the given position.
NL jumps to the next row. Other control and zero-width characters are ignored. Color (even inherited) overwrites the existing characters. Use
drawText(pos, text)for a color overlay.- Parameters:
pos – The coordinates within the buffer.
str – The string to write.
-
class CursorBuffer : public erbsland::cterm::RemappedBuffer, public erbsland::cterm::CursorWriter
A buffer that can be used to write text using a cursor.
Cursor movement emulates VT100 terminals:
Cursor movements are bound to the buffer (they do not wrap around).
Printing characters do wrap around if wrap mode is enabled (it’s enabled by default.)
Printing a character in the last column is special:
A 1-width character is printed in the last column, but the cursor isn’t moved yet. A
wrapOnNextCharis set instead of the cursor movement.As soon as the next character is printed, the cursor is moved to the next line first; then the character is printed.
When a 2-width character is printed in the last column, the cursor is moved to the next line first; then the character is printed (not VT100, it didn’t have 2-width characters).
If the
wrapOnNextCharis set, and the cursor is moved, the flag is cleared.If the
wrapOnNextCharis set, and a line-break is printed, the flag is cleared first before moving the cursor to the next line.
Public Types
-
enum class OverflowMode : uint8_t
The overflow mode determines what happens when the cursor gets a line-break in the last line.
Values:
-
enumerator Shift
Shift the buffer content one line up, exposing a new blank line at the bottom.
-
enumerator Wrap
The cursor wraps back to the first line of the buffer.
-
enumerator ExpandThenShift
Expand the buffer by one line, keeping the content. Up to maximumSize(), then scroll.
-
enumerator ExpandThenWrap
Expand the buffer by one line, keeping the content. Up to maximumSize(), then wrap.
-
enumerator Shift
Public Functions
-
inline explicit CursorBuffer(const Size startSize, const OverflowMode overflowMode = OverflowMode::Shift, const Size maximumSize = cMaximumSize, const Char fillChar = Char::space())
Create a new cursor buffer with the given startSize.
- Parameters:
startSize – The start size of the buffer.
overflowMode – The overflow mode of the buffer.
maximumSize – The maximum size of the buffer. Only
heightis used.fillChar – The character used to initialize and refill empty cells.
- Throws:
std::invalid_argument – if startSize exceeds the maximum or fillChar is not a single-width character.
-
inline CursorBuffer()
Create a new cursor buffer with a default size of 80x25 and overflow mode
Shift.
-
void setMaximumSize(Size maximumSize) noexcept
Change the maximum size.
Changing the maximum size will not affect the current content.
- Parameters:
maximumSize – The new maximum size.
-
OverflowMode overflowMode() const noexcept
Get the overflow mode for this buffer.
-
void setOverflowMode(OverflowMode mode) noexcept
Set the overflow mode for this buffer.
- Parameters:
mode – The new overflow mode.
-
const Char &fillChar() const noexcept
Get the character used for newly exposed or empty cells.
- Returns:
The current fill character.
-
void setFillChar(Char fillChar)
Set the character used for newly exposed or empty cells.
The character should have a display width of one cell.
- Parameters:
fillChar – The new fill character.
- Throws:
std::invalid_argument – if fillChar is not a single-width character.
-
inline virtual Size size() const noexcept override
Get the configured size of the buffer.
- Returns:
The width and height of the buffer.
-
virtual Color color() const noexcept override
Get the current color.
- Returns:
The currently tracked terminal color state.
-
virtual CharAttributes charAttributes() const noexcept override
Get the current character attributes.
- Returns:
The currently tracked character attribute state.
-
virtual void setColor(Color color) noexcept override
Set foreground and background color.
Note
Inheritedcolors are converted toDefaultcolors.- Parameters:
color – The new combined color.
-
virtual void setCharAttributes(CharAttributes attributes) noexcept override
Set all character attributes.
Unspecified attributes are treated as disabled.
- Parameters:
attributes – The new character attributes.
-
virtual void setForeground(Foreground color) noexcept override
Set the foreground color.
Note
Inheritedcolors are converted toDefaultcolors.- Parameters:
color – The new foreground color.
-
virtual void setBackground(Background color) noexcept override
Set the background color.
Note
Inheritedcolors are converted toDefaultcolors.- Parameters:
color – The new background color.
-
virtual CharAttributes supportedCharAttributes() const noexcept override
Get the character attributes supported by this writer.
- Returns:
The supported character attributes.
-
virtual void moveCursor(Position posOrDelta, MoveMode mode) noexcept override
Move the cursor absolute or relative.
If the resulting position is out of bounds, the result is undefined.
- Parameters:
posOrDelta – The absolute position or delta for the move.
mode – The move mode, either absolute or relative.
-
virtual void setAutoWrap(bool enabled) noexcept override
Enabled/disable auto-wrap.
Auto wrap controls if the cursor automatically wraps to the next line when reaching the right margin. This is a feature that can be enabled or disabled. Do not confuse this with line wrapping, which is a different feature.
- Parameters:
enabled – Whether to enable or disable auto-wrap.
-
virtual void clearScreen() noexcept override
Clears the screen/writing area.
-
virtual void write(const Char &character) noexcept override
Write a character at the current cursor position.
Inherited color components resolve against the currently active color. Overwrites the character under the cursor.
- Parameters:
character – The character to write.
-
virtual void write(const String &str) noexcept override
Write a string at the current cursor position.
Inherited color components in each character resolve against the currently active color. Overwrites the characters under the cursor.
- Parameters:
str – The string to write.
-
virtual void write(const ReadableBuffer &buffer) noexcept override
Write a buffer at the current cursor position.
This will not perform any additional formatting, clipping, or processing. Each line of the buffer will be written, and a line-break added after each line.
- Parameters:
buffer – The buffer to write.
-
virtual void writeLineBreak() noexcept override
Write a line-break.
This will move the cursor to the beginning of the next line.
-
virtual void setColor(Color color) noexcept = 0
Set foreground and background color.
Note
Inheritedcolors are converted toDefaultcolors.- Parameters:
color – The new combined color.
-
inline void setColor(const Foreground foregroundColor, const Background backgroundColor) noexcept
Set foreground and background color.
Note
Inheritedcolors are converted toDefaultcolors.- Parameters:
foregroundColor – The new foreground color.
backgroundColor – The new background color.
-
virtual void write(const Char &character) noexcept = 0
Write a character at the current cursor position.
Inherited color components resolve against the currently active color. Overwrites the character under the cursor.
- Parameters:
character – The character to write.
-
virtual void write(const String &str) noexcept = 0
Write a string at the current cursor position.
Inherited color components in each character resolve against the currently active color. Overwrites the characters under the cursor.
- Parameters:
str – The string to write.
-
inline void write(std::string_view text) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
virtual void write(const ReadableBuffer &buffer) noexcept = 0
Write a buffer at the current cursor position.
This will not perform any additional formatting, clipping, or processing. Each line of the buffer will be written, and a line-break added after each line.
- Parameters:
buffer – The buffer to write.
-
virtual void writeLineBreak() noexcept = 0
Write a line-break.
This will move the cursor to the beginning of the next line.