package vt import ( renderer "github.com/bnema/vev-vt/core" "github.com/bnema/vev-vt/graphics" ) // CursorSnapshot is the cursor state captured with a visible screen snapshot. type CursorSnapshot struct { Row int Col int Visible bool Style int StyleSet bool } // ModeSnapshot is the renderer-relevant VT mode state captured with a screen. type ModeSnapshot struct { AlternateScreen bool BracketedPaste bool SynchronizedUpdate bool ColorSchemeMode bool MouseTracking int MouseSGR bool } // ScreenSnapshot is an owned immutable capture of the active terminal // viewport. It implements core.CellSource, and Row returns caller-owned storage. type ScreenSnapshot struct { frame renderer.Frame bounds []LineBound rowIDs []RowID cursor CursorSnapshot modes ModeSnapshot title string graphics *graphics.Snapshot nextRowID RowID } // Snapshot captures the active visible viewport without mutating Screen, // history, or pending damage. Screen remains single-owner; callers must // serialize Snapshot with Write, Resize, and host mutations. func (s *Screen) Snapshot() ScreenSnapshot { if s == nil { return ScreenSnapshot{} } cursorStyle, cursorStyleSet := s.CursorStyle() mouseTracking, mouseSGR := s.MouseMode() nextRowID := s.nextRowID if nextRowID < ^RowID(0) { nextRowID++ } return ScreenSnapshot{ frame: s.frame.Clone(), bounds: s.LineBounds(), rowIDs: s.RowIDs(), nextRowID: nextRowID, cursor: CursorSnapshot{ Row: s.CursorRow(), Col: s.CursorCol(), Visible: s.CursorVisible(), Style: cursorStyle, StyleSet: cursorStyleSet, }, modes: ModeSnapshot{ AlternateScreen: s.AltScreenActive(), BracketedPaste: s.BracketedPasteMode(), SynchronizedUpdate: s.SyncUpdateActive(), ColorSchemeMode: s.ColorSchemeMode(), MouseTracking: mouseTracking, MouseSGR: mouseSGR, }, title: s.TerminalTitle(), graphics: s.GraphicsSnapshot(), } } func (s ScreenSnapshot) Columns() int { return s.frame.Width } func (s ScreenSnapshot) Rows() int { return s.frame.Height } // Cell returns the semantic cell at x, y. func (s ScreenSnapshot) Cell(x, y int) renderer.Cell { return s.frame.Cell(x, y) } // Row returns an owned copy of row y, or nil when y is out of range. func (s ScreenSnapshot) Row(y int) []renderer.Cell { if y < 0 || y >= s.frame.Height { return nil } return s.frame.Row(y) } func (s ScreenSnapshot) Bound(y int) LineBound { if y < 0 || y >= len(s.bounds) { return LineBound{} } return s.bounds[y] } // RowIDs returns an owned copy of the visible physical-row identities. func (s ScreenSnapshot) RowIDs() []RowID { return append([]RowID(nil), s.rowIDs...) } // RowID returns the identity of visible row y, or zero when out of range. func (s ScreenSnapshot) RowID(y int) RowID { if y < 0 || y >= len(s.rowIDs) { return 0 } return s.rowIDs[y] } // NextRowID returns the next identity allocated by the captured screen. func (s ScreenSnapshot) NextRowID() RowID { if s.nextRowID == 0 { return 1 } return s.nextRowID } func (s ScreenSnapshot) Cursor() CursorSnapshot { return s.cursor } func (s ScreenSnapshot) Modes() ModeSnapshot { return s.modes } func (s ScreenSnapshot) Title() string { return s.title } // Graphics returns the immutable graphics scene snapshot for the active // screen buffer, or nil when that buffer has not used Kitty graphics. func (s ScreenSnapshot) Graphics() *graphics.Snapshot { return s.graphics }