85 lines
2.6 KiB
Go
85 lines
2.6 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package reader
|
|
|
|
import (
|
|
"git.stormux.org/storm/fenrir/internal/presentation"
|
|
"git.stormux.org/storm/fenrir/internal/screen"
|
|
"slices"
|
|
)
|
|
|
|
// Cursor feedback requires unchanged composer text. Comparing masked snapshots
|
|
// allows simultaneous tool/status redraws outside the input field to stay quiet.
|
|
func input_cursor_feedback(previous, next screen.Snapshot) []presentation.Message {
|
|
if !slices.Equal(previous.Cells, next.Cells) {
|
|
return nil
|
|
}
|
|
return changes(previous, next, true)
|
|
}
|
|
|
|
// SessionState preserves shortcut-only state as well as configuration. Screen,
|
|
// input timestamps and detached review positions are deliberately not restored.
|
|
type SessionState struct {
|
|
automatic bool
|
|
mode, attributeConfigured, attributeMode, attributeResumeMode string
|
|
regions *terminalRegions
|
|
}
|
|
|
|
func clone_regions(source *terminalRegions) *terminalRegions {
|
|
if source == nil {
|
|
return nil
|
|
}
|
|
result := *source
|
|
clone := func(region *screen.Region) *screen.Region {
|
|
if region == nil {
|
|
return nil
|
|
}
|
|
value := *region
|
|
return &value
|
|
}
|
|
result.window = clone(source.window)
|
|
for index, region := range source.live {
|
|
result.live[index] = clone(region)
|
|
}
|
|
return &result
|
|
}
|
|
|
|
func (r *Reader) Capture_session() SessionState {
|
|
return r.Capture_terminal_session(r.screen.Terminal)
|
|
}
|
|
|
|
func (r *Reader) Capture_terminal_session(terminal int) SessionState {
|
|
return SessionState{r.automatic, r.trackingMode, r.attributeConfigured, r.attributeMode, r.attributeResumeMode, clone_regions(r.regions[terminal])}
|
|
}
|
|
|
|
func (r *Reader) Restore_session(state SessionState, terminal int) {
|
|
r.automatic = state.automatic
|
|
r.Configure_tracking(state.mode)
|
|
r.attributeConfigured, r.attributeMode, r.attributeResumeMode = state.attributeConfigured, state.attributeMode, state.attributeResumeMode
|
|
if r.regions == nil {
|
|
r.regions = make(map[int]*terminalRegions)
|
|
}
|
|
r.regions[terminal] = clone_regions(state.regions)
|
|
r.regionRevision++
|
|
r.attributeKnown, r.indentKnown = false, false
|
|
r.Reset_progress()
|
|
}
|
|
|
|
func (r *Reader) Clear_session_regions(terminal int) {
|
|
delete(r.regions, terminal)
|
|
r.regionRevision++
|
|
}
|
|
|
|
func input_snapshot(snapshot screen.Snapshot, region screen.Region) screen.Snapshot {
|
|
snapshot.Cells = slices.Clone(snapshot.Cells)
|
|
for row := range snapshot.Rows {
|
|
for col := range snapshot.Cols {
|
|
if !region.Contains(col, row, snapshot.Cols) {
|
|
snapshot.Cells[row*snapshot.Cols+col] = ' '
|
|
}
|
|
}
|
|
}
|
|
return snapshot
|
|
}
|