61 lines
1.8 KiB
Go
61 lines
1.8 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package review
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
|
)
|
|
|
|
func named_link_label(snapshot atspi.Snapshot) string {
|
|
if snapshot.Role == "link" && snapshot.ExplicitName && !snapshot.Editable {
|
|
return strings.TrimSpace(snapshot.Name)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func caret_text_count(snapshot atspi.Snapshot) int {
|
|
if label := named_link_label(snapshot); label != "" {
|
|
return utf8.RuneCountInString(label)
|
|
}
|
|
return snapshot.CharacterCount
|
|
}
|
|
|
|
// Named links can expose no Text interface, or only a badge/embedded object.
|
|
// Review the label used by line speech, retaining the link for activation.
|
|
// These offsets belong to the label and must never become native text offsets.
|
|
func read_caret_text(ctx context.Context, reader DocumentCaretReader, node atspi.DocumentNode, offset int, unit atspi.DocumentCaretUnit) (atspi.DocumentCaretText, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return atspi.DocumentCaretText{}, err
|
|
}
|
|
label := named_link_label(node.Snapshot)
|
|
if label == "" {
|
|
return reader.ReadDocumentCaret(ctx, node.Reference, offset, unit)
|
|
}
|
|
characters := []rune(label)
|
|
result := atspi.DocumentCaretText{CharacterCount: len(characters)}
|
|
if offset < 0 || offset >= len(characters) {
|
|
return result, nil
|
|
}
|
|
start, end := offset, offset+1
|
|
if unit == atspi.DocumentCaretWord {
|
|
for start > 0 && !unicode.IsSpace(characters[start-1]) {
|
|
start--
|
|
}
|
|
for end < len(characters) && !unicode.IsSpace(characters[end]) {
|
|
end++
|
|
}
|
|
for end < len(characters) && unicode.IsSpace(characters[end]) {
|
|
end++
|
|
}
|
|
}
|
|
result.Start, result.End, result.Text = start, end, string(characters[start:end])
|
|
return result, nil
|
|
}
|