// 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 }