TermBuf::Buffer
Stability: stable — changes only in a major release.
The in-memory terminal screen.
The buffer holds one grid: back, what the application has drawn. What a
terminal is believed to be showing lives in a Sink, one per output, along
with the painter and encoder that put it there. Attaching a second sink is
what lets the same buffer drive two displays that paint at different times
and know different things about what they can do.
A single dirty-flag scheme would be smaller, but it leaves nothing to diff against after a forced repaint or a resize, and nothing for the scroll detector to verify a shift against.
Not fibre-safe, and deliberately so: one fibre owns the buffer and every mutation reaches it as a command.
Constructors
Instance methods
Starts painting this buffer to sink. Called by Sink itself, so an
application builds a sink rather than attaching one.
Copies cells out of source, its top left landing at (x, y), taking from of it or all of it. Whatever falls outside this buffer is cut.
For compositing an off-screen panel: draw into a Buffer of its own
through a BufferSurface, then blit it into place. Styles and clusters
are interned per buffer, so the ids a source cell carries mean nothing
here and are translated on the way in. Stored widths are copied rather
than remeasured, so a panel keeps the layout it was drawn with even if
the two buffers measure clusters differently.
A cluster only partly inside the copied rectangle arrives as a blank, since part of one cannot be drawn.
What no attached sink has painted yet. Each sink keeps its own record as well, since they paint at different moments; this one is cleared once every one of them has caught up.
Sets every cell of rect to char.
With a blend, each cell gets the style the blend answers for it rather than style, which is what a wash over what is already painted wants: a faded rectangle, or a tint that leaves the colours under it showing. The rectangle is read before any of it is written, so a blend sees the cells as they were rather than as this fill is leaving them.
What sits at (x, y), or nil when that is off the grid.
A continuation resolves to the cluster it belongs to, so the hit's x
can be to the left of the column asked about and Hit#lead says whether
it moved. Read from the back grid: what the application has drawn, which
is what it wants to reason about, rather than what the terminal is
believed to be showing.
hit = buffer.hit column, row
puts hit.text if hit
Coordinates are 0-based buffer cells. An SGR mouse report is 1-based and carries its own columns; converting one is the mouse decoder's job, not this method's. Turning a hit into an index within a line editor's text belongs to whoever owns that text, which is the widget shard.
Marks the whole screen dirty and has every sink forget what its terminal was showing, so the next paint rewrites every cell.
Interns a hyperlink and returns the id a Style carries it by.
style = Style::DEFAULT.linked buffer.link("https://example.com")
See Link for what id groups.
How clusters are measured. Set by the driver from what the terminal said
when it was asked, because how many cells an emoji takes is a question
about the terminal rather than about Unicode. See Unicode::WidthPolicy.
Changing it does not remeasure what is already written: cells carry the width they were placed with. Invalidate and redraw after changing it.
How clusters are measured. Set by the driver from what the terminal said
when it was asked, because how many cells an emoji takes is a question
about the terminal rather than about Unicode. See Unicode::WidthPolicy.
Changing it does not remeasure what is already written: cells carry the width they were placed with. Invalidate and redraw after changing it.
Registers a region. Regions are for scrolling and scrollback; they do not clip writes, and the buffer does not stop them overlapping.
Declares a region over bounds, keeping up to scrollback rows of what scrolls off the top.
Resizes the back grid and every attached sink, keeping whatever content still fits anchored at the top left. Leaves everything dirty and drops any scroll hints, since the next paint has to redraw the screen outright.
Scrolls rect by lines rows, positive moving content up. Records a hint for the painter.
The hints recorded after serial, oldest first.
Scrolls a region, keeping the rows that leave the top if the region has scrollback capacity.
The serial given to the last scroll recorded. A sink that has read up to this has nothing left to catch up on.
Writes text starting at (x, y), one grapheme cluster per cell, stopping at the right edge of the row. Returns the columns consumed.
Zero width clusters are skipped: a combining mark with no base character in front of it has nothing to attach to, and a control character is never stored in the buffer.
With a blend, each cell gets the style the blend answers for it from
what is already there and style — text over something already painted,
a label across a progress bar, without the caller working out where the
bar's colours change. Style::KEEP_BACKGROUND is that blend. A cluster
covering several cells takes the style its first one lands on.
Writes a single character at (x, y). Returns the columns it consumed: zero if it is zero width, if it is a control character, or if it takes more columns than are left before the right edge.
With a blend, the style placed is what it answers for the cell rather
than style itself. See #write.