1package vt
2
3import (
4 renderer "github.com/bnema/vev-vt/core"
5 "github.com/bnema/vev-vt/graphics"
6)
7
8// CursorSnapshot is the cursor state captured with a visible screen snapshot.
9type CursorSnapshot struct {
10 Row int
11 Col int
12 Visible bool
13 Style int
14 StyleSet bool
15}
16
17// ModeSnapshot is the renderer-relevant VT mode state captured with a screen.
18type ModeSnapshot struct {
19 AlternateScreen bool
20 BracketedPaste bool
21 SynchronizedUpdate bool
22 ColorSchemeMode bool
23 MouseTracking int
24 MouseSGR bool
25}
26
27// ScreenSnapshot is an owned immutable-by-convention capture of the active
28// terminal viewport. Row returns caller-owned storage; BorrowedRow must not be
29// mutated and remains valid while the snapshot is retained.
30type ScreenSnapshot struct {
31 frame renderer.Frame
32 bounds []LineBound
33 rowIDs []RowID
34 cursor CursorSnapshot
35 modes ModeSnapshot
36 title string
37 graphics *graphics.Snapshot
38 nextRowID RowID
39}
40
41// Snapshot captures the active visible viewport without mutating Screen,
42// history, or pending damage. Screen remains single-owner; callers must
43// serialize Snapshot with Write, Resize, and host mutations.
44func (s *Screen) Snapshot() ScreenSnapshot {
45 if s == nil {
46 return ScreenSnapshot{}
47 }
48 cursorStyle, cursorStyleSet := s.CursorStyle()
49 mouseTracking, mouseSGR := s.MouseMode()
50 nextRowID := s.nextRowID
51 if nextRowID < ^RowID(0) {
52 nextRowID++
53 }
54 return ScreenSnapshot{
55 frame: s.Frame.Clone(),
56 bounds: s.LineBounds(),
57 rowIDs: s.RowIDs(),
58 nextRowID: nextRowID,
59 cursor: CursorSnapshot{
60 Row: s.CursorRow(),
61 Col: s.CursorCol(),
62 Visible: s.CursorVisible(),
63 Style: cursorStyle,
64 StyleSet: cursorStyleSet,
65 },
66 modes: ModeSnapshot{
67 AlternateScreen: s.AltScreenActive(),
68 BracketedPaste: s.BracketedPasteMode(),
69 SynchronizedUpdate: s.SyncUpdateActive(),
70 ColorSchemeMode: s.ColorSchemeMode(),
71 MouseTracking: mouseTracking,
72 MouseSGR: mouseSGR,
73 },
74 title: s.TerminalTitle(),
75 graphics: s.GraphicsSnapshot(),
76 }
77}
78
79func (s ScreenSnapshot) Columns() int { return s.frame.Width }
80func (s ScreenSnapshot) Rows() int { return s.frame.Height }
81
82func (s ScreenSnapshot) Row(y int) []renderer.Cell {
83 return append([]renderer.Cell(nil), s.BorrowedRow(y)...)
84}
85
86func (s ScreenSnapshot) BorrowedRow(y int) []renderer.Cell {
87 if y < 0 || y >= s.frame.Height {
88 return nil
89 }
90 return s.frame.Row(y)
91}
92
93func (s ScreenSnapshot) Bound(y int) LineBound {
94 if y < 0 || y >= len(s.bounds) {
95 return LineBound{}
96 }
97 return s.bounds[y]
98}
99
100// RowIDs returns an owned copy of the visible physical-row identities.
101func (s ScreenSnapshot) RowIDs() []RowID { return append([]RowID(nil), s.rowIDs...) }
102
103// RowID returns the identity of visible row y, or zero when out of range.
104func (s ScreenSnapshot) RowID(y int) RowID {
105 if y < 0 || y >= len(s.rowIDs) {
106 return 0
107 }
108 return s.rowIDs[y]
109}
110
111// NextRowID returns the next identity allocated by the captured screen.
112func (s ScreenSnapshot) NextRowID() RowID {
113 if s.nextRowID == 0 {
114 return 1
115 }
116 return s.nextRowID
117}
118
119func (s ScreenSnapshot) Cursor() CursorSnapshot { return s.cursor }
120func (s ScreenSnapshot) Modes() ModeSnapshot { return s.modes }
121func (s ScreenSnapshot) Title() string { return s.title }
122
123// Graphics returns the immutable graphics scene snapshot for the active
124// screen buffer, or nil when that buffer has not used Kitty graphics.
125func (s ScreenSnapshot) Graphics() *graphics.Snapshot { return s.graphics }