75 lines
2.4 KiB
Go
75 lines
2.4 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package reader
|
|
|
|
import (
|
|
"git.stormux.org/storm/fenrir/internal/i18n"
|
|
"git.stormux.org/storm/fenrir/internal/presentation"
|
|
"git.stormux.org/storm/fenrir/internal/screen"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func (r *Reader) Configure_attributes(mode, format string) {
|
|
// Configuration is the saved/quick-menu choice. Reapplying unchanged
|
|
// settings must not overwrite the shortcut's temporary session state.
|
|
if mode != r.attributeConfigured {
|
|
r.attributeConfigured, r.attributeMode = mode, mode
|
|
if mode != "" && mode != "none" {
|
|
r.attributeResumeMode = mode
|
|
}
|
|
}
|
|
r.attributeFormat = format
|
|
r.review.Configure_attributes(format)
|
|
}
|
|
|
|
func (r *Reader) toggle_attributes() string {
|
|
if r.attributeMode == "" || r.attributeMode == "none" {
|
|
r.attributeMode = r.attributeResumeMode
|
|
if r.attributeMode == "" {
|
|
r.attributeMode = "beeps"
|
|
}
|
|
return i18n.T("announcement of attributes enabled")
|
|
}
|
|
r.attributeResumeMode, r.attributeMode = r.attributeMode, "none"
|
|
return i18n.T("announcement of attributes disabled")
|
|
}
|
|
|
|
func (r *Reader) attribute_feedback(announce bool) *presentation.Message {
|
|
attribute, valid := r.review.Attribute()
|
|
if !valid {
|
|
r.attributeKnown = false
|
|
return nil
|
|
}
|
|
changed := r.attributeKnown && attribute != r.lastAttribute
|
|
r.lastAttribute, r.attributeKnown = attribute, true
|
|
if !announce || !changed || r.attributeMode == "" || r.attributeMode == "none" {
|
|
return nil
|
|
}
|
|
// Presence tones describe emphasis; returning to defaults is described by
|
|
// speech modes, but must not play a misleading has-attribute cue.
|
|
if attribute.Default() && r.attributeMode == "beeps" {
|
|
return nil
|
|
}
|
|
message := presentation.Attribute_message(attribute, r.attributeMode, r.attributeFormat)
|
|
if attribute.Default() {
|
|
message.Cue = ""
|
|
}
|
|
if message.Cue == "" && strings.TrimSpace(message.Text) == "" {
|
|
return nil
|
|
}
|
|
return &message
|
|
}
|
|
|
|
func (r *Reader) automatic_attributes(previous, next screen.Snapshot, switched bool) *presentation.Message {
|
|
if switched {
|
|
r.attributeKnown = false
|
|
}
|
|
announce := !switched && next.Active && r.automatic && r.cursorEcho && r.trackingMode == "cursor" && !r.review.Active() && r.region_state().allows(next.X, next.Y, next.Cols, true, true)
|
|
if announce && (previous.X != next.X || previous.Y != next.Y) {
|
|
announce = !r.applicationInputAt.IsZero() && time.Since(r.applicationInputAt) < 300*time.Millisecond
|
|
}
|
|
return r.attribute_feedback(announce)
|
|
}
|