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 // KittyKeyboard is the active screen's kitty keyboard enhancement flags.
26 KittyKeyboard int
27}
28
29// ScreenSnapshot is an owned immutable capture of the active terminal
30// viewport. It implements core.CellSource, and Row returns caller-owned storage.
31type ScreenSnapshot struct {
32 frame renderer.Frame
33 bounds []LineBound
34 rowIDs []RowID
35 cursor CursorSnapshot
36 modes ModeSnapshot
37 autoWrap bool
38 applicationCursor bool
39 title string
40 graphics *graphics.Snapshot
41 nextRowID RowID
42}
43
44// Snapshot captures the active visible viewport without mutating Screen,
45// history, or pending damage. Screen remains single-owner; callers must
46// serialize Snapshot with Write, Resize, and host mutations.
47func (s *Screen) Snapshot() ScreenSnapshot {
48 if s == nil {
49 return ScreenSnapshot{}
50 }
51 cursorStyle, cursorStyleSet := s.CursorStyle()
52 mouseTracking, mouseSGR := s.MouseMode()
53 nextRowID := s.nextRowID
54 if nextRowID < ^RowID(0) {
55 nextRowID++
56 }
57 return ScreenSnapshot{
58 frame: s.frame.Clone(),
59 bounds: s.LineBounds(),
60 rowIDs: s.RowIDs(),
61 nextRowID: nextRowID,
62 autoWrap: s.AutoWrapMode(),
63 applicationCursor: s.ApplicationCursorMode(),
64 cursor: CursorSnapshot{
65 Row: s.CursorRow(),
66 Col: s.CursorCol(),
67 Visible: s.CursorVisible(),
68 Style: cursorStyle,
69 StyleSet: cursorStyleSet,
70 },
71 modes: ModeSnapshot{
72 AlternateScreen: s.AltScreenActive(),
73 BracketedPaste: s.BracketedPasteMode(),
74 SynchronizedUpdate: s.SyncUpdateActive(),
75 ColorSchemeMode: s.ColorSchemeMode(),
76 MouseTracking: mouseTracking,
77 MouseSGR: mouseSGR,
78 KittyKeyboard: s.KittyKeyboardFlags(),
79 },
80 title: s.TerminalTitle(),
81 graphics: s.GraphicsSnapshot(),
82 }
83}
84
85func (s ScreenSnapshot) Columns() int { return s.frame.Width }
86func (s ScreenSnapshot) Rows() int { return s.frame.Height }
87
88// Cell returns the semantic cell at x, y.
89func (s ScreenSnapshot) Cell(x, y int) renderer.Cell { return s.frame.Cell(x, y) }
90
91// Row returns an owned copy of row y, or nil when y is out of range.
92func (s ScreenSnapshot) Row(y int) []renderer.Cell {
93 if y < 0 || y >= s.frame.Height {
94 return nil
95 }
96 return s.frame.Row(y)
97}
98
99func (s ScreenSnapshot) Bound(y int) LineBound {
100 if y < 0 || y >= len(s.bounds) {
101 return LineBound{}
102 }
103 return s.bounds[y]
104}
105
106// RowIDs returns an owned copy of the visible physical-row identities.
107func (s ScreenSnapshot) RowIDs() []RowID { return append([]RowID(nil), s.rowIDs...) }
108
109// RowID returns the identity of visible row y, or zero when out of range.
110func (s ScreenSnapshot) RowID(y int) RowID {
111 if y < 0 || y >= len(s.rowIDs) {
112 return 0
113 }
114 return s.rowIDs[y]
115}
116
117// NextRowID returns the next identity allocated by the captured screen.
118func (s ScreenSnapshot) NextRowID() RowID {
119 if s.nextRowID == 0 {
120 return 1
121 }
122 return s.nextRowID
123}
124
125func (s ScreenSnapshot) Cursor() CursorSnapshot { return s.cursor }
126func (s ScreenSnapshot) Modes() ModeSnapshot { return s.modes }
127
128// AutoWrapMode reports whether DEC private mode 7 (DECAWM) was enabled in the
129// captured screen.
130func (s ScreenSnapshot) AutoWrapMode() bool { return s.autoWrap }
131
132// ApplicationCursorMode reports whether DEC private mode 1 (DECCKM) was enabled
133// in the captured screen.
134func (s ScreenSnapshot) ApplicationCursorMode() bool { return s.applicationCursor }
135
136func (s ScreenSnapshot) Title() string { return s.title }
137
138// Graphics returns the immutable graphics scene snapshot for the active
139// screen buffer, or nil when that buffer has not used Kitty graphics.
140func (s ScreenSnapshot) Graphics() *graphics.Snapshot { return s.graphics }