// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package atspi import ( "sort" "strings" ) // Derive rows from the already captured document. This performs no native // queries and keeps large tables bounded to 32 cells and 4096 bytes per row. func populate_document_rows(document *DocumentSnapshot) { nodes := make(map[ObjectID]int, len(document.Nodes)) for index, node := range document.Nodes { nodes[node.Reference.ID()] = index } type rowKey struct { table ObjectID row int } rows := make(map[rowKey][]int) owners := make(map[int]rowKey) for index, node := range document.Nodes { if node.Hidden || !node.Snapshot.TablePositionKnown || node.Snapshot.Role != "table cell" { continue } current := node.Parent var owner ObjectID spreadsheet := false for depth := 0; depth < 32 && current.Valid(); depth++ { parentIndex, exists := nodes[current] if !exists { break } parent := document.Nodes[parentIndex] if owner == (ObjectID{}) && parent.Snapshot.Role == "table" { owner = current } if parent.Snapshot.Role == "document spreadsheet" { spreadsheet = true } current = parent.Parent } if !owner.Valid() { continue } document.Nodes[index].Snapshot.Spreadsheet = spreadsheet document.Nodes[index].Snapshot.TablePath = owner.Path key := rowKey{owner, node.Snapshot.TableRowIndex} if len(rows[key]) < 32 { rows[key] = append(rows[key], index) } owners[index] = key } texts := make(map[rowKey]string, len(rows)) for key, indices := range rows { sort.SliceStable(indices, func(a, b int) bool { return document.Nodes[indices[a]].Snapshot.TableColumnIndex < document.Nodes[indices[b]].Snapshot.TableColumnIndex }) var parts []string length := 0 for _, index := range indices { snapshot := document.Nodes[index].Snapshot label := strings.TrimSpace(snapshot.Name) if label == "" { label = strings.TrimSpace(snapshot.Text) } if label == "" { label = "blank" } if length+len(label)+2 > 4096 { break } length += len(label) + 2 parts = append(parts, label) } texts[key] = strings.Join(parts, ", ") } for index, key := range owners { document.Nodes[index].Snapshot.TableRowText = texts[key] } }