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