uv library Ultraviolet

Ultraviolet (UV): High-performance terminal rendering and input.

The UV subsystem provides core rendering primitives, a diffing terminal renderer, structured cell buffers, and fast input decoders to build responsive, visually rich terminal UIs.

Key Components

  • Terminal: Lifecycle, I/O, and orchestration for UV apps.
  • Buffer: A 2D grid of Cells representing screen state.
  • Cell: A single glyph with UvStyle and optional Link.
  • UvTerminalRenderer: Efficient diff-based rendering to the terminal.
  • EventDecoder: Fast ANSI/kitty input decoder for keys and mouse.
  • Screen: High-level convenient API over buffers and rendering.
  • Canvas: Immediate-mode drawing utilities on top of buffers.

Quick Start

import 'package:artisanal/uv.dart';

void main() async {
  final terminal = Terminal();
  await terminal.start();

  // Draw a red "H" at (0, 0).
  terminal.setCell(0, 0, Cell(
    content: 'H',
    style: UvStyle(fg: UvColor.rgb(255, 0, 0)),
  ));

  terminal.draw();
  await terminal.stop();
}

Concepts

UV models the terminal as layers of drawable cells. A Buffer holds the current state, a UvTerminalRenderer diffs and flushes changes, and Terminal manages lifecycle and device capabilities. Use Canvas for immediate-mode drawing, or Screen for a higher-level facade.

Rendering

The UvTerminalRenderer computes minimal diffs between the previous and next Buffer frames and emits optimized ANSI/OSC sequences to the terminal. Combine it with TerminalCapabilities to adapt to device features (kitty, sixel, hyperlinks, etc.). For text drawing, prefer StyledString and the style ops to avoid per-cell overhead.

Example (pseudo-flow):

final screen = Screen(size: Rectangle(0, 0, 80, 24));
final renderer = UvTerminalRenderer();
// mutate screen/buffers
renderer.render(screen.buffer);

Input and Events

Input is decoded by EventDecoder into typed events:

Access mouse modes via MouseMode and buttons via MouseButton.

Performance Tips

  • Batch mutations on buffers to reduce diff churn.
  • Prefer region updates; avoid full-screen rewrites.
  • Use StyledString runs instead of per-cell style objects when possible.
  • Cache geometry and avoid repeated allocations in hot paths.
  • Detect capabilities once; gate feature use via TerminalCapabilities.

Compatibility

UV targets modern terminals with ANSI + extended capabilities (kitty/sixel). Behavior can vary across emulators; query TerminalCapabilities and gracefully degrade. Hyperlinks (Link, LinkState) and RGB (UvRgb) may be unavailable on legacy terminals; fall back to UvBasic16 or UvIndexed256 palettes.

UV models the terminal as layers of drawable cells. A Buffer holds the current state, a UvTerminalRenderer diffs and flushes changes, and Terminal manages lifecycle and device capabilities. Use Canvas for immediate-mode drawing, or Screen for a higher-level facade.

The UvTerminalRenderer computes minimal diffs between the previous and next Buffer frames and emits optimized ANSI/OSC sequences to the terminal. Combine it with TerminalCapabilities to adapt to device features (kitty, sixel, hyperlinks, etc.). For text drawing, prefer StyledString and the style ops to avoid per-cell overhead.

Example (pseudo-flow):

final screen = Screen(size: Rectangle(0, 0, 80, 24));
final renderer = UvTerminalRenderer();
// mutate screen/buffers
renderer.render(screen.buffer);

Input is decoded by EventDecoder into typed events:

Access mouse modes via MouseMode and buttons via MouseButton.

  • Batch mutations on buffers to reduce diff churn.
  • Prefer region updates; avoid full-screen rewrites.
  • Use StyledString runs instead of per-cell style objects when possible.
  • Cache geometry and avoid repeated allocations in hot paths.
  • Detect capabilities once; gate feature use via TerminalCapabilities.

UV targets modern terminals with ANSI + extended capabilities (kitty/sixel). Behavior can vary across emulators; query TerminalCapabilities and gracefully degrade. Hyperlinks (Link, LinkState) and RGB (UvRgb) may be unavailable on legacy terminals; fall back to UvBasic16 or UvIndexed256 palettes.

Classes

AmberTerminalFilter
Amber monochrome display preset built from the UV filter primitives.
AmberTrailFilter
Warm monochrome preset with a short-lived persistence trail.
AtmosphereFilter
Soft atmosphere-style preset for shimmer/backdrop motion.
Attr
Text attributes (bitmask).
BackgroundColorEvent
Background color report.
BlurEvent
Terminal focus lost event.
Buffer
A 2D buffer of Lines representing a terminal screen or a portion of it.
BufferFilter
Base class for buffer filters.
BufferRenderSink
A render sink that owns double-buffered render targets.
CancelReader
CancelReader provides a cancelable reader interface.
Canvas
Canvas is a cell-buffer that can be used to compose and draw Drawables.
CapabilityEvent
Capability string event (e.g., terminal features).
Cell
A single cell in a terminal Buffer.
CellSizeEvent
Reports terminal cell size in pixels.
ClearableScreen
Optional fast-path: clear the entire screen.
ClearAreaScreen
Optional fast-path: clear an area of the screen.
ClipboardEvent
Clipboard selection and content (OSC 52).
ClipboardSelection
CloneableScreen
Optional fast-path: clone the entire screen into a buffer.
CloneAreaScreen
Optional fast-path: clone a screen area into a buffer.
ColorMatrix
A 4x5 RGBA color matrix.
ColorMatrixFilter
A BufferFilter that applies a ColorMatrix to cell style colors.
ColorPaletteEvent
Palette color report for an index.
CompositeFilter
Runs multiple filters as one reusable filter.
Compositor
Compositor manages layer composition, drawing and hit testing.
Constraint
Layout constraints.
CrtFilter
Opinionated CRT-style preset built from the UV filter primitives.
CrtTrailFilter
CRT-style preset with a short temporal persistence trail.
Cursor
Represents a cursor on the terminal screen.
CursorColorEvent
Cursor color report.
CursorPositionEvent
Reports cursor position.
DarkColorSchemeEvent
Terminal reports dark color scheme preference.
DirtyDensityMap
Metadata for a touched line.
DirtySpan
Drawable
Drawable can draw itself into a Screen.
EmptyDrawable
A no-op drawable with a fixed size.
Environ
An environment snapshot represented as KEY=value strings.
Event
Base type for UV-style input events.
EventDecoder
A high-performance ANSI input decoder.
FillableScreen
Optional fast-path: fill the entire screen.
FillAreaScreen
Optional fast-path: fill an area of the screen.
Fixed
A constraint that represents a fixed size.
FocusEvent
Terminal focus gained event.
ForegroundColorEvent
Foreground color report.
GhostingFilter
Preserves a fading afterimage of recent glyphs.
HalfBlockImageDrawable
A Drawable that renders an image using half-block characters.
IgnoredEvent
Internal marker for sequences intentionally ignored.
ITerm2ImageDrawable
A Drawable that renders an image using the iTerm2 Image Protocol.
Key
UV-style key event.
KeyboardEnhancementsEvent
Kitty keyboard enhancements support report.
KeyEvent
Base type for key press/release events.
KeyMod
Modifier keys.
KeyPressEvent
Key press event.
KeyReleaseEvent
Key release event.
KittyGraphicsEvent
Kitty graphics payload (APC G ... ST).
KittyImageDrawable
A Drawable that renders an image using the Kitty Graphics Protocol.
KittyOptions
Options parsed from a Kitty graphics report.
Layer
Layer represents a visual layer with content and positioning.
LayerHit
LegacyKeyEncoding
Legacy key encoding behavior flags.
LightColorSchemeEvent
Terminal reports light color scheme preference.
Line
A line is a fixed-width list of cells.
LineData
Metadata for one dirty line.
Terminal hyperlink metadata (OSC 8).
LinkState
Holds the parsed hyperlink URL from an OSC 8 sequence.
LiquifyFilter
A simple velocity-field liquify filter.
Logger
Logger is a simple logger interface for Ultraviolet internals.
ModeReportEvent
Terminal mode report.
ModifyOtherKeysEvent
Xterm ModifyOtherKeys mode report.
Mouse
Mouse event payload.
MouseButton
Mouse button codes (X11-style).
MouseClickEvent
Mouse click event.
MouseEvent
Base type for mouse click/release/wheel/motion events.
MouseMotionEvent
Mouse motion (move/drag) event.
MouseReleaseEvent
Mouse button release event.
MouseWheelEvent
Mouse wheel (scroll) event.
MultiEvent
Aggregates multiple events decoded from a single input.
NullLogger
A logger that does nothing.
OwnedCellScreen
Optional fast-path: set a cell that the caller will not reuse.
PackedCell
Fixed-size packed representation of a Cell.
PasteEndEvent
Bracketed paste end.
PasteEvent
Bracketed paste content.
PasteStartEvent
Bracketed paste start.
Percent
A constraint that represents a percentage of the available size.
PhosphorFilter
Green phosphor display preset with a stronger CRT feel.
PhosphorTrailFilter
Green phosphor preset with a temporal afterimage trail.
Position
A 2D integer coordinate in terminal cell space.
PrimaryDeviceAttributesEvent
Primary device attributes (DA1) report.
ProgressBar
A progress bar state + value.
Rectangle
Rectangle with inclusive-exclusive bounds: [min, max).
RenderMetrics
Tracks render performance metrics including FPS, frame times, and render durations.
ScanlineFilter
Adds alternating scanline attenuation with an optional animated rolling bar.
Screen
Screen is a 2D surface of cells.
ScreenBuffer
A screen buffer that implements Screen operations and carries a width method for calculating cell widths.
SecondaryDeviceAttributesEvent
Secondary device attributes (DA2) report.
SgrParam
Represents a parsed SGR (Select Graphic Rendition) parameter.
Side
UvBorder primitives.
SixelImageDrawable
A Drawable that renders an image using Sixel Graphics.
Size
Reports terminal size in cells and optional pixels.
SizeNotifier
Stub SizeNotifier for platforms without SIGWINCH.
StyledString
StyledString is a string that can be decomposed into a series of styled lines and cells.
StyleState
Holds the result of parsing an SGR sequence.
TabStops
Tab stop management.
Terminal
Terminal represents a terminal screen that can be manipulated and drawn to.
TerminalCapabilities
Terminal capabilities discovered via ANSI queries.
TerminalGraphicsControl
One parsed terminal graphics control sequence.
TerminalGraphicsFrame
Retained graphics state visible in a rendered frame.
TerminalReader
TerminalReader represents an input event loop that reads input events from a reader and parses them into human-readable events.
TerminalRenderer
Abstract base class for UV terminal renderers.
TerminalVersionEvent
Terminal version string (e.g., xterm-kitty 0.32.0).
TertiaryDeviceAttributesEvent
Tertiary device attributes (DA3) report.
UnknownApcEvent
Unknown APC event with raw payload.
UnknownCsiEvent
Unknown CSI event with raw payload.
UnknownDcsEvent
Unknown DCS event with raw payload.
UnknownEvent
Unknown event with raw payload.
UnknownOscEvent
Unknown OSC event with raw payload.
UnknownPmEvent
Unknown PM event with raw payload.
UnknownSosEvent
Unknown SOS event with raw payload.
UnknownSs3Event
Unknown SS3 event with raw payload.
UvAnsi
A collection of ANSI escape sequence constants and utilities.
UvBasic16
16-color palette index (optionally bright).
UvBorder
A drawable border composed of Sides and corner glyphs.
UvColor
Color representation sufficient for Ultraviolet parity tests.
UvEventStreamParser
Streaming UV event scanner with ESC-timeout compatibility.
UvIndexed256
256-color indexed palette entry.
UvRgb
24-bit RGBA color.
UvStyle
Style attributes for a terminal Cell.
UvTerminalRenderer
Low-level terminal renderer for the Ultraviolet engine.
UvTuiInputParser
Adapts Ultraviolet-style input events to the current TUI message types.
VignetteFilter
Darkens the edges of the frame while preserving the center.
WaveDistortionFilter
Applies a deterministic sine-wave distortion across the buffer.
Win32ControlKeyState
WindowOpEvent
Window operation report (OSC 7/11/… payloads).
WindowPixelSizeEvent
Reports window size in pixels.
WindowSizeEvent
Reports window size in cells and optional pixels.

Enums

CursorShape
Cursor shape primitives.
ModeSetting
MouseMode
Mouse mode.
ProgressBarState
Progress bar states.
TerminalGraphicsProtocol
Terminal graphics protocols that can appear as display payloads.
UnderlineStyle
Underline style for terminal cells.
WidthMethod
Specifies the method used to calculate character display width.

Extensions

CursorShapeEncode on CursorShape
WidthMethodX on WidthMethod
Extension on WidthMethod providing string width calculation.

Constants

defaultEscTimeout → const Duration
Default timeout at which the TerminalReader will process ESC sequences.
keyBackspace → const int
keyBegin → const int
keyCapsLock → const int
keyDelete → const int
keyDown → const int
keyEnd → const int
keyEnter → const int
keyEscape → const int
keyExtended → const int
keyF1 → const int
keyF10 → const int
keyF11 → const int
keyF12 → const int
keyF13 → const int
keyF14 → const int
keyF15 → const int
keyF16 → const int
keyF17 → const int
keyF18 → const int
keyF19 → const int
keyF2 → const int
keyF20 → const int
keyF21 → const int
keyF22 → const int
keyF23 → const int
keyF24 → const int
keyF25 → const int
keyF26 → const int
keyF27 → const int
keyF28 → const int
keyF29 → const int
keyF3 → const int
keyF30 → const int
keyF31 → const int
keyF32 → const int
keyF33 → const int
keyF34 → const int
keyF35 → const int
keyF36 → const int
keyF37 → const int
keyF38 → const int
keyF39 → const int
keyF4 → const int
keyF40 → const int
keyF41 → const int
keyF42 → const int
keyF43 → const int
keyF44 → const int
keyF45 → const int
keyF46 → const int
keyF47 → const int
keyF48 → const int
keyF49 → const int
keyF5 → const int
keyF50 → const int
keyF51 → const int
keyF52 → const int
keyF53 → const int
keyF54 → const int
keyF55 → const int
keyF56 → const int
keyF57 → const int
keyF58 → const int
keyF59 → const int
keyF6 → const int
keyF60 → const int
keyF61 → const int
keyF62 → const int
keyF63 → const int
keyF7 → const int
keyF8 → const int
keyF9 → const int
keyFind → const int
keyHome → const int
keyInsert → const int
keyIsoLevel3Shift → const int
keyIsoLevel5Shift → const int
keyKp0 → const int
keyKp1 → const int
keyKp2 → const int
keyKp3 → const int
keyKp4 → const int
keyKp5 → const int
keyKp6 → const int
keyKp7 → const int
keyKp8 → const int
keyKp9 → const int
keyKpBegin → const int
keyKpComma → const int
keyKpDecimal → const int
keyKpDelete → const int
keyKpDivide → const int
keyKpDown → const int
keyKpEnd → const int
keyKpEnter → const int
keyKpEqual → const int
keyKpHome → const int
keyKpInsert → const int
keyKpLeft → const int
keyKpMinus → const int
keyKpMultiply → const int
keyKpPgDown → const int
keyKpPgUp → const int
keyKpPlus → const int
keyKpRight → const int
keyKpSep → const int
keyKpUp → const int
keyLeft → const int
keyLeftAlt → const int
keyLeftCtrl → const int
keyLeftHyper → const int
keyLeftMeta → const int
keyLeftShift → const int
keyLeftSuper → const int
keyLowerVol → const int
keyMediaFastForward → const int
keyMediaNext → const int
keyMediaPause → const int
keyMediaPlay → const int
keyMediaPlayPause → const int
keyMediaPrev → const int
keyMediaRecord → const int
keyMediaReverse → const int
keyMediaRewind → const int
keyMediaStop → const int
keyMenu → const int
keyMute → const int
keyNumLock → const int
keyPause → const int
keyPgDown → const int
keyPgUp → const int
keyPrintScreen → const int
keyRaiseVol → const int
keyRight → const int
keyRightAlt → const int
keyRightCtrl → const int
keyRightHyper → const int
keyRightMeta → const int
keyRightShift → const int
keyRightSuper → const int
keyScrollLock → const int
keySelect → const int
keySpace → const int
keyTab → const int
keyUp → const int

Properties

emojiPresentationWidth int
Runtime configuration for width calculations that depend on terminal behavior.
getter/setter pair

Functions

asciiBorder() UvBorder
Creates a plain ASCII border style.
blockBorder() UvBorder
Creates a solid block border style.
bottomCenterRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the bottom-center of area with width and height.
bottomLeftRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the bottom-left of area with width and height.
bottomRightRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the bottom-right of area with width and height.
buildKeysTable(LegacyKeyEncoding flags, String term, {bool useTerminfo = false}) Map<String, Key>
Builds a table of key sequences and their corresponding key events.
centerRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle centered within area with width and height.
clampRgbChannel(int x) int
Clamps a color component to the byte range required by SGR truecolor.
clear(Screen screen) → void
Screen helpers for clearing/filling/cloning.
clearArea(Screen screen, Rectangle area) → void
Clears area of screen to empty cells.
clone(Screen screen) Buffer
Returns a copy of screen as a Buffer.
cloneArea(Screen screen, Rectangle area) Buffer?
Returns a copy of area from screen, or null when empty.
colorToHex(UvRgb? c) String
Formats c as a #RRGGBB hex string, or empty if null.
containsRetainedTerminalGraphics(String value) bool
Whether value contains retained graphics.
containsSixelDisplay(String value) bool
Whether value contains a Sixel display payload.
containsTerminalGraphicsDisplay(String value) bool
Whether value contains any terminal graphics display sequence.
Converts a Link to respect the given terminal color profile.
convertStyle(UvStyle style, Profile profile) UvStyle
Converts a UvStyle to respect the given terminal color profile.
cutAnsiByCells(String s, int start, int end) String
Cuts an ANSI string by visible cell indices, preserving any active SGR/OSC 8 state at the start boundary.
debugDirectRelativeMoveSeq(UvTerminalRenderer renderer, Buffer newbuf, int fx, int fy, int tx, int ty, {bool useTabs = false, bool useBackspace = false}) String
Returns the direct relative move sequence used as the DP baseline.
debugDpOverwriteMoveSeq(UvTerminalRenderer renderer, Buffer newbuf, int fx, int fy, int tx, int ty, {bool useTabs = false, bool useBackspace = false}) String?
Returns the same-row DP overwrite/move sequence used by the renderer.
debugGraphemeGeneration(int id) int
Returns the encoded grapheme generation for id.
debugGraphemeRefCount(int id) int
Returns the pooled grapheme refcount for id.
debugGraphemeSlot(int id) int
Returns the encoded grapheme slot index for id.
debugGraphemeWidth(int id) int
Returns the encoded grapheme width for id.
debugLinkGeneration(int id) int
Returns the pooled link generation for id.
debugLinkRefCount(int id) int
Returns the pooled link refcount for id.
debugLinkSlot(int id) int
Returns the pooled link slot index for id.
deleteAllRetainedGraphics({int quiet = 2}) String
Returns the retained-graphics delete-all sequence.
deleteRetainedGraphic(int imageId, {int quiet = 2}) String
Returns the retained-graphics delete sequence for imageId.
doubleBorder() UvBorder
Creates a double line border style.
ensureKeyCase(Key key, int cks) Key
fill(Screen screen, Cell? cell) → void
Fills the entire screen with cell.
fillArea(Screen screen, Cell? cell, Rectangle area) → void
Fills area of screen with cell.
getMaxMin(double a, double b, double c) → (double, double)
Returns the max and min of three values.
hiddenBorder() UvBorder
Creates an invisible border style (spaces for all sides).
innerHalfBlockBorder() UvBorder
Creates an inner half-block border style.
isDarkColor(UvRgb? c) bool
Returns whether c is considered dark using HSL lightness.
keyModFromXTerm(int xtermModMinus1) int
Converts a 1-based XTerm modifier value to a UV KeyMod bitmask.
leftCenterRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the left-center of area with width and height.
markdownBorder() UvBorder
Creates a markdown-style border using | for verticals.
maxLineWidth(String s) int
Returns the maximum display width across all lines in s.
mayContainTerminalGraphics(String value) bool
Whether value can contain one of the graphics protocols handled here.
newLayer(Object content, [List<Layer> layers = const []]) Layer
Creates a new Layer from a String or Drawable.
newStyledString(String str) StyledString
Factory function to create a StyledString from str.
normalBorder() UvBorder
outerHalfBlockBorder() UvBorder
Creates an outer half-block border style.
parsePrimaryDevAttrs(List<int> params) Event
parseSecondaryDevAttrs(List<int> params) Event
parseTermcap(List<int> data) CapabilityEvent
parseTerminalGraphicsControls(String value) Iterable<TerminalGraphicsControl>
Parses terminal graphics controls in value.
parseTertiaryDevAttrs(List<int> data) Event
parseWin32InputKeyEvent(int vkc, int sc, int uc, bool keyDown, int cks, int repeatCount) Event?
ratio(int numerator, int denominator) Percent
Syntactic sugar for Percent.
Parses an OSC 8 hyperlink sequence from data into out.
readStyle(List<SgrParam> params, StyleState out) → void
Parses SGR params and applies them to the style in out.
rect(int x, int y, int width, int height) Rectangle
Creates a rectangle from origin (x, y) and size (width, height).
rgbToHsl(int r, int g, int b) → (double, double, double)
Returns (h, s, l) where h is degrees [0, 360).
rightCenterRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the right-center of area with width and height.
roundedBorder() UvBorder
Creates a rounded border style.
runeWidth(int rune) int
Returns the display width of a single Unicode code point.
setEmojiPresentationWidth(int width) → void
Sets the display width used for emoji presentation characters.
shift(int x) int
Shifts a 16-bit color component down to 8-bit.
sourceOver(UvColor? src, UvColor? dst) UvColor?
Composites src over dst using Porter-Duff SourceOver.
splitByLargestRemainder(int size, List<int> weights, {List<int> previous = const []}) List<int>
Splits size cells across weights using Largest Remainder Method.
splitHorizontal(Rectangle area, Constraint c) → ({Rectangle left, Rectangle right})
Splits area horizontally into left/right.
splitHorizontalByLargestRemainder(Rectangle area, List<int> weights, {List<int> previousAllocations = const []}) → ({List<Rectangle> columns})
Splits area into horizontal segments using stable largest-remainder sizing.
splitVertical(Rectangle area, Constraint c) → ({Rectangle bottom, Rectangle top})
Splits area vertically into top/bottom.
splitVerticalByLargestRemainder(Rectangle area, List<int> weights, {List<int> previousAllocations = const []}) → ({List<Rectangle> rows})
Splits area into vertical segments using stable largest-remainder sizing.
stringWidth(String s) int
Returns the terminal display width of s, counting per grapheme cluster.
styleDiff(UvStyle? from, UvStyle? to) String
Returns the SGR diff needed to transition from from to to.
styledStringBounds(String text, WidthMethod method) Rectangle
Parses a string and returns its bounds (width/height) using a width method.
styleToSgr(UvStyle style) String
Returns the SGR sequence for style.
styleTransitionSgr(UvStyle? from, UvStyle? to) String
Returns the cheaper SGR transition from from to to.
suppressOverflowingTerminalGraphics(String text, int viewportHeight) String
Removes graphics displays that would paint outside viewportHeight.
terminalGraphicsCellWidth(String line) int
Additional cell width contributed by graphics controls embedded in line.
terminalGraphicsControlCellWidth(String controls) int
Cell width for a pending control sequence group.
terminalGraphicsControlsDisplayImage(String controls) bool
Whether a pending control sequence group displays graphics.
terminalGraphicsSuppressesCursorMovement(String value) bool
Whether value displays graphics while suppressing terminal cursor motion.
thickBorder() UvBorder
Creates a thick line border style.
topCenterRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the top-center of area with width and height.
topLeftRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the top-left of area with width and height.
topRightRect(Rectangle area, int width, int height) Rectangle
Returns a new Rectangle at the top-right of area with width and height.
translateControlKeyState(int cks) int
truncateLeftAnsiByCells(String s, int start) String
Truncates an ANSI string from the left by visible cell indices.
wrapAnsiPreserving(String input, int width, {String breakpoints = ''}) String
Wraps a string to width while preserving ANSI pen state (SGR + OSC 8) across inserted and existing newlines.