1/*
2 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "WebKitAccessibleInterfaceTableCell.h"
22
23#if HAVE(ACCESSIBILITY)
24#if ATK_CHECK_VERSION(2,11,90)
25#include "AccessibilityObject.h"
26#include "AccessibilityTable.h"
27#include "AccessibilityTableCell.h"
28#include "WebKitAccessible.h"
29#include "WebKitAccessibleUtil.h"
30
31using namespace WebCore;
32
33static GPtrArray* convertToGPtrArray(const AccessibilityObject::AccessibilityChildrenVector& children)
34{
35 GPtrArray* array = g_ptr_array_new();
36 for (const auto& child : children) {
37 if (auto* atkObject = child->wrapper())
38 g_ptr_array_add(array, atkObject);
39 }
40 return array;
41}
42
43static AccessibilityObject* core(AtkTableCell* cell)
44{
45 if (!WEBKIT_IS_ACCESSIBLE(cell))
46 return nullptr;
47
48 return &webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(cell));
49}
50
51GPtrArray* webkitAccessibleTableCellGetColumnHeaderCells(AtkTableCell* cell)
52{
53 g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr);
54 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr);
55
56 AccessibilityObject* axObject = core(cell);
57 if (!is<AccessibilityTableCell>(axObject))
58 return nullptr;
59
60 AccessibilityObject::AccessibilityChildrenVector columnHeaders;
61 downcast<AccessibilityTableCell>(*axObject).columnHeaders(columnHeaders);
62
63 return convertToGPtrArray(columnHeaders);
64}
65
66GPtrArray* webkitAccessibleTableCellGetRowHeaderCells(AtkTableCell* cell)
67{
68 g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr);
69 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr);
70
71 AccessibilityObject* axObject = core(cell);
72 if (!is<AccessibilityTableCell>(axObject))
73 return nullptr;
74
75 AccessibilityObject::AccessibilityChildrenVector rowHeaders;
76 downcast<AccessibilityTableCell>(*axObject).rowHeaders(rowHeaders);
77
78 return convertToGPtrArray(rowHeaders);
79}
80
81gint webkitAccessibleTableCellGetColumnSpan(AtkTableCell* cell)
82{
83 g_return_val_if_fail(ATK_TABLE_CELL(cell), 0);
84 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), 0);
85
86 AccessibilityObject* axObject = core(cell);
87 if (!is<AccessibilityTableCell>(axObject))
88 return 0;
89
90 std::pair<unsigned, unsigned> columnRange;
91 downcast<AccessibilityTableCell>(*axObject).columnIndexRange(columnRange);
92
93 return columnRange.second;
94}
95
96gint webkitAccessibleTableCellGetRowSpan(AtkTableCell* cell)
97{
98 g_return_val_if_fail(ATK_TABLE_CELL(cell), 0);
99 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), 0);
100
101 AccessibilityObject* axObject = core(cell);
102 if (!is<AccessibilityTableCell>(axObject))
103 return 0;
104
105 std::pair<unsigned, unsigned> rowRange;
106 downcast<AccessibilityTableCell>(*axObject).rowIndexRange(rowRange);
107
108 return rowRange.second;
109}
110
111gboolean webkitAccessibleTableCellGetPosition(AtkTableCell* cell, gint* row, gint* column)
112{
113 g_return_val_if_fail(ATK_TABLE_CELL(cell), false);
114 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), false);
115
116 AccessibilityObject* axObject = core(cell);
117 if (!is<AccessibilityTableCell>(axObject))
118 return false;
119
120 std::pair<unsigned, unsigned> columnRowRange;
121 if (row) {
122 // aria-rowindex is 1-based.
123 int rowIndex = downcast<AccessibilityTableCell>(*axObject).axRowIndex() - 1;
124 if (rowIndex <= -1) {
125 downcast<AccessibilityTableCell>(*axObject).rowIndexRange(columnRowRange);
126 rowIndex = columnRowRange.first;
127 }
128 *row = rowIndex;
129 }
130 if (column) {
131 // aria-colindex is 1-based.
132 int columnIndex = downcast<AccessibilityTableCell>(*axObject).axColumnIndex() - 1;
133 if (columnIndex <= -1) {
134 downcast<AccessibilityTableCell>(*axObject).columnIndexRange(columnRowRange);
135 columnIndex = columnRowRange.first;
136 }
137 *column = columnIndex;
138 }
139
140 return true;
141}
142
143AtkObject* webkitAccessibleTableCellGetTable(AtkTableCell* cell)
144{
145 g_return_val_if_fail(ATK_TABLE_CELL(cell), nullptr);
146 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(cell), nullptr);
147
148 AccessibilityObject* axObject = core(cell);
149 if (!axObject || !axObject->isTableCell())
150 return nullptr;
151
152 auto* table = atk_object_get_parent(ATK_OBJECT(axObject->wrapper()));
153 if (!table || !ATK_IS_TABLE(table))
154 return nullptr;
155
156 return ATK_OBJECT(g_object_ref(table));
157}
158
159void webkitAccessibleTableCellInterfaceInit(AtkTableCellIface* iface)
160{
161 iface->get_column_header_cells = webkitAccessibleTableCellGetColumnHeaderCells;
162 iface->get_row_header_cells = webkitAccessibleTableCellGetRowHeaderCells;
163 iface->get_column_span = webkitAccessibleTableCellGetColumnSpan;
164 iface->get_row_span = webkitAccessibleTableCellGetRowSpan;
165 iface->get_position = webkitAccessibleTableCellGetPosition;
166 iface->get_table = webkitAccessibleTableCellGetTable;
167}
168
169#endif // ATK_CHECK_VERSION(2,11,90)
170#endif // HAVE(ACCESSIBILITY)
171