apprt: add ghostty_surface_read_text_styled to the embedding API
Same as ghostty_surface_read_text but formats with emit=.vt so SGR sequences (colors/styles) are preserved. Palette indices are resolved to direct RGB via the terminal's current palette (mirroring the styled clipboard path in Surface.zig), soft-wrapped lines are not unwrapped so one output line == one grid row, and trailing whitespace is preserved. Motivation: embedders rendering an overview/minimap of the scrollback need per-cell color, which the plain read_text strips. The formatter already supports this; this just exposes it through the C API.pull/12909/head
parent
46d54ed673
commit
b68e1a2926
|
|
@ -1160,6 +1160,9 @@ GHOSTTY_API bool ghostty_surface_read_selection(ghostty_surface_t, ghostty_text_
|
|||
GHOSTTY_API bool ghostty_surface_read_text(ghostty_surface_t,
|
||||
ghostty_selection_s,
|
||||
ghostty_text_s*);
|
||||
GHOSTTY_API bool ghostty_surface_read_text_styled(ghostty_surface_t,
|
||||
ghostty_selection_s,
|
||||
ghostty_text_s*);
|
||||
GHOSTTY_API void ghostty_surface_free_text(ghostty_surface_t, ghostty_text_s*);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
|
|
|||
|
|
@ -1677,6 +1677,76 @@ pub const CAPI = struct {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Same as ghostty_surface_read_text but emits VT escape sequences
|
||||
/// (predominantly SGR) so colors and styles are preserved. Differences
|
||||
/// from the plain variant:
|
||||
///
|
||||
/// - Palette-indexed colors are resolved to direct RGB using the
|
||||
/// terminal's current palette, so the output is self-contained.
|
||||
/// - Soft-wrapped lines are NOT unwrapped: one emitted line always
|
||||
/// corresponds to one grid row, which lets callers map output rows
|
||||
/// to scrollback rows (e.g. for overview/minimap rendering).
|
||||
/// - Trailing whitespace is preserved.
|
||||
///
|
||||
/// Free the result with ghostty_surface_free_text. The viewport fields
|
||||
/// of the result are not populated by this function.
|
||||
///
|
||||
/// Like ghostty_surface_read_text, this is an expensive operation, so
|
||||
/// callers should cache results and throttle calls.
|
||||
export fn ghostty_surface_read_text_styled(
|
||||
surface: *Surface,
|
||||
sel: Selection,
|
||||
result: *Text,
|
||||
) bool {
|
||||
const core_surface = &surface.core_surface;
|
||||
core_surface.renderer_state.mutex.lock();
|
||||
defer core_surface.renderer_state.mutex.unlock();
|
||||
|
||||
const core_sel = sel.core(
|
||||
core_surface.renderer_state.terminal.screens.active,
|
||||
) orelse return false;
|
||||
|
||||
// Mirror the styled-clipboard configuration from
|
||||
// Surface.completeClipboardReadWrite: resolve palette colors to
|
||||
// direct RGB and carry the terminal's default fg/bg.
|
||||
const term = &core_surface.io.terminal;
|
||||
var formatter: terminal.formatter.ScreenFormatter = .init(
|
||||
term.screens.active,
|
||||
.{
|
||||
.emit = .vt,
|
||||
.unwrap = false,
|
||||
.trim = false,
|
||||
.background = term.colors.background.get(),
|
||||
.foreground = term.colors.foreground.get(),
|
||||
.palette = &term.colors.palette.current,
|
||||
},
|
||||
);
|
||||
formatter.content = .{ .selection = core_sel };
|
||||
|
||||
var aw: std.Io.Writer.Allocating = .init(global.alloc);
|
||||
defer aw.deinit();
|
||||
formatter.format(&aw.writer) catch |err| {
|
||||
log.warn("error reading styled text err={}", .{err});
|
||||
return false;
|
||||
};
|
||||
|
||||
const text = aw.toOwnedSliceSentinel(0) catch |err| {
|
||||
log.warn("error reading styled text err={}", .{err});
|
||||
return false;
|
||||
};
|
||||
|
||||
result.* = .{
|
||||
.tl_px_x = -1,
|
||||
.tl_px_y = -1,
|
||||
.offset_start = 0,
|
||||
.offset_len = 0,
|
||||
.text = text.ptr,
|
||||
.text_len = text.len,
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export fn ghostty_surface_free_text(_: *Surface, ptr: *Text) void {
|
||||
ptr.deinit();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue