mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-31 03:13:40 +00:00
vt: add ghostty_terminal_cell for point-based cell lookup
Add a new C API function ghostty_terminal_cell that retrieves the opaque cell and row values at a given point in the terminal grid. The point is a tagged union supporting active, viewport, screen, and history coordinate systems.
This commit is contained in:
@@ -196,6 +196,7 @@ comptime {
|
||||
@export(&c.terminal_mode_get, .{ .name = "ghostty_terminal_mode_get" });
|
||||
@export(&c.terminal_mode_set, .{ .name = "ghostty_terminal_mode_set" });
|
||||
@export(&c.terminal_get, .{ .name = "ghostty_terminal_get" });
|
||||
@export(&c.terminal_cell, .{ .name = "ghostty_terminal_cell" });
|
||||
|
||||
// On Wasm we need to export our allocator convenience functions.
|
||||
if (builtin.target.cpu.arch.isWasm()) {
|
||||
|
||||
@@ -109,6 +109,7 @@ pub const terminal_scroll_viewport = terminal.scroll_viewport;
|
||||
pub const terminal_mode_get = terminal.mode_get;
|
||||
pub const terminal_mode_set = terminal.mode_set;
|
||||
pub const terminal_get = terminal.get;
|
||||
pub const terminal_cell = terminal.cell;
|
||||
|
||||
test {
|
||||
_ = cell;
|
||||
|
||||
@@ -7,7 +7,10 @@ const ScreenSet = @import("../ScreenSet.zig");
|
||||
const PageList = @import("../PageList.zig");
|
||||
const kitty = @import("../kitty/key.zig");
|
||||
const modes = @import("../modes.zig");
|
||||
const point = @import("../point.zig");
|
||||
const size = @import("../size.zig");
|
||||
const cell_c = @import("cell.zig");
|
||||
const row_c = @import("row.zig");
|
||||
const style_c = @import("style.zig");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
@@ -207,6 +210,26 @@ fn getTyped(
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn cell(
|
||||
terminal_: Terminal,
|
||||
pt: point.Point.C,
|
||||
out_cell: ?*cell_c.CCell,
|
||||
out_row: ?*row_c.CRow,
|
||||
) callconv(.c) Result {
|
||||
const t = terminal_ orelse return .invalid_value;
|
||||
const zig_pt: point.Point = switch (pt.tag) {
|
||||
.active => .{ .active = pt.value.active },
|
||||
.viewport => .{ .viewport = pt.value.viewport },
|
||||
.screen => .{ .screen = pt.value.screen },
|
||||
.history => .{ .history = pt.value.history },
|
||||
};
|
||||
const result = t.screens.active.pages.getCell(zig_pt) orelse
|
||||
return .invalid_value;
|
||||
if (out_cell) |p| p.* = @bitCast(result.cell.*);
|
||||
if (out_row) |p| p.* = @bitCast(result.row.*);
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn free(terminal_: Terminal) callconv(.c) void {
|
||||
const t = terminal_ orelse return;
|
||||
|
||||
@@ -612,3 +635,61 @@ test "get invalid" {
|
||||
|
||||
try testing.expectEqual(Result.invalid_value, get(t, .invalid, null));
|
||||
}
|
||||
|
||||
test "cell" {
|
||||
var t: Terminal = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib_alloc.test_allocator,
|
||||
&t,
|
||||
.{
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
},
|
||||
));
|
||||
defer free(t);
|
||||
|
||||
vt_write(t, "Hello", 5);
|
||||
|
||||
var out_cell: cell_c.CCell = undefined;
|
||||
var out_row: row_c.CRow = undefined;
|
||||
try testing.expectEqual(Result.success, cell(t, .{
|
||||
.tag = .active,
|
||||
.value = .{ .active = .{ .x = 0, .y = 0 } },
|
||||
}, &out_cell, &out_row));
|
||||
|
||||
// Verify the cell contains 'H'
|
||||
var cp: u32 = 0;
|
||||
try testing.expectEqual(Result.success, cell_c.get(out_cell, .codepoint, @ptrCast(&cp)));
|
||||
try testing.expectEqual(@as(u32, 'H'), cp);
|
||||
}
|
||||
|
||||
test "cell null terminal" {
|
||||
var out_cell: cell_c.CCell = undefined;
|
||||
var out_row: row_c.CRow = undefined;
|
||||
try testing.expectEqual(Result.invalid_value, cell(null, .{
|
||||
.tag = .active,
|
||||
.value = .{ .active = .{ .x = 0, .y = 0 } },
|
||||
}, &out_cell, &out_row));
|
||||
}
|
||||
|
||||
test "cell out of bounds" {
|
||||
var t: Terminal = null;
|
||||
try testing.expectEqual(Result.success, new(
|
||||
&lib_alloc.test_allocator,
|
||||
&t,
|
||||
.{
|
||||
.cols = 80,
|
||||
.rows = 24,
|
||||
.max_scrollback = 0,
|
||||
},
|
||||
));
|
||||
defer free(t);
|
||||
|
||||
var out_cell: cell_c.CCell = undefined;
|
||||
var out_row: row_c.CRow = undefined;
|
||||
try testing.expectEqual(Result.invalid_value, cell(t, .{
|
||||
.tag = .active,
|
||||
.value = .{ .active = .{ .x = 100, .y = 0 } },
|
||||
}, &out_cell, &out_row));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user