More work on LibreOffice support.

This commit is contained in:
Storm Dragon committed 2026-10-15 00:50:49 -04:00
1 parent e0c8c6198c
commit 4ac59d4ced
25 files changed
+392 -57

No files matched your search

+19
View File
@@ -4,6 +4,11 @@
package atspi
import (
"strings"
"unicode/utf8"
)
// LibreOfficeContext is bounded, copied metadata from the native owner. It
// describes Calc's cell and temporary editor objects, without native handles.
// Presentation and application policy must not query the provider themselves.
@@ -15,6 +20,7 @@ type LibreOfficeContext struct {
ContainerFocused bool
CellText string
Coordinates string
Formula string
}
// IsLibreOfficeProcess uses /proc identity verified by the adapter. An
@@ -22,3 +28,16 @@ type LibreOfficeContext struct {
func IsLibreOfficeProcess(process string) bool {
return process == "soffice.bin"
}
// Preserve spaces inside formula string literals and keep the beginning when
// bounding long expressions. Text context's default suffix is for caret lines.
func sanitizeLibreOfficeFormula(value string) string {
value = strings.ToValidUTF8(value, "�")
if len(value) > maxSnapshotFieldLength {
value = value[:maxSnapshotFieldLength]
for !utf8.ValidString(value) {
value = value[:len(value)-1]
}
}
return sanitizeTextContext(value)
}
+13
View File
@@ -120,6 +120,9 @@ func captureLibreOfficeContext(source *C.AtspiAccessible, snapshot *Snapshot) {
grandparentRole == C.ATSPI_ROLE_DOCUMENT_SPREADSHEET
if context.Cell {
context.Coordinates = snapshot.Name
// Orca requests uncached attributes: editing can replace a formula
// without replacing the accessible cell.
C.atspi_accessible_clear_cache_single(source)
attributes := C.atspi_accessible_get_attributes(source, nil)
if attributes != nil {
columnKey, rowKey := C.CString("colindextext"), C.CString("rowindextext")
@@ -130,6 +133,16 @@ func captureLibreOfficeContext(source *C.AtspiAccessible, snapshot *Snapshot) {
if column != "" && row != "" {
context.Coordinates = sanitizeSnapshotField(column + row)
}
// Current providers use lowercase; Orca also accepts Formula.
for _, key := range []string{"formula", "Formula"} {
name := C.CString(key)
value := C.g_hash_table_lookup(attributes, C.gconstpointer(name))
C.free(unsafe.Pointer(name))
if value != nil {
context.Formula = sanitizeLibreOfficeFormula(C.GoString((*C.gchar)(value)))
break
}
}
C.g_hash_table_unref(attributes)
}
text := C.atspi_accessible_get_text_iface(source)
+23
View File
@@ -0,0 +1,23 @@
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package atspi
import (
"strings"
"testing"
"unicode/utf8"
)
func TestLibreOfficeFormulaPreservesLiteralSpacesAndBoundedPrefix(t *testing.T) {
formula := `="two spaces"`
if got := sanitizeLibreOfficeFormula(formula); got != formula {
t.Fatalf("formula literal changed: %q", got)
}
formula += strings.Repeat("猫", maxSnapshotFieldLength)
got := sanitizeLibreOfficeFormula(formula)
if len(got) > maxSnapshotFieldLength || !utf8.ValidString(got) || !strings.HasPrefix(formula, got) {
t.Fatalf("invalid bounded formula prefix: bytes=%d", len(got))
}
}