1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
const std = @import("std");
const ghostty_vt = @import("ghostty-vt");
/// One text selection (block-shaped), in pane-local coords; the row carries the
/// scrollback offset. .none == nothing selected.
pub const Sel = struct {
state: enum { none, dragging, done } = .none,
c0: i32 = 0,
c1: i32 = 0,
r0: i32 = 0,
r1: i32 = 0,
};
/// Persistent per-terminal state: the pty handle, the ghostty emulator and its
/// (stateful) VT parser, the background reader task, plus its layout weight and
/// text selection.
///
/// Heap-allocate these and never move them: `stream`'s handler holds a pointer
/// back into `term`, so the address must stay stable for parser state split
/// across pty reads to keep working.
pub const Term = @This();
pty: std.Io.File,
term: ghostty_vt.Terminal,
stream: ghostty_vt.TerminalStream,
reader: std.Io.Future(anyerror!void),
/// current emulator grid size; we only push a resize when it actually changes.
cols: u16,
rows: u16,
/// vertical weight within the column (siblings split the column height by this).
vweight: f32 = 1,
/// One independent selection per mouse button: 0=left, 1=middle, 2=right.
sel: [3]Sel = .{ .{}, .{}, .{} },
pub fn deinit(self: *Term, io: std.Io, gpa: std.mem.Allocator) void {
_ = self.reader.cancel(io) catch {};
self.stream.deinit();
self.term.deinit(gpa);
self.pty.close(io);
}
|