Replace some auto* with RefPtr within WebCore/html
[WebKit-https.git] / Source / WebCore / accessibility / atk / WebKitAccessibleInterfaceTable.cpp
1 /*
2  * Copyright (C) 2008 Nuanti Ltd.
3  * Copyright (C) 2009 Jan Alonzo
4  * Copyright (C) 2009, 2010, 2011, 2012 Igalia S.L.
5  *
6  * Portions from Mozilla a11y, copyright as follows:
7  *
8  * The Original Code is mozilla.org code.
9  *
10  * The Initial Developer of the Original Code is
11  * Sun Microsystems, Inc.
12  * Portions created by the Initial Developer are Copyright (C) 2002
13  * the Initial Developer. All Rights Reserved.
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Library General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Library General Public License for more details.
24  *
25  * You should have received a copy of the GNU Library General Public License
26  * along with this library; see the file COPYING.LIB.  If not, write to
27  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28  * Boston, MA 02110-1301, USA.
29  */
30
31 #include "config.h"
32 #include "WebKitAccessibleInterfaceTable.h"
33
34 #if HAVE(ACCESSIBILITY)
35
36 #include "AccessibilityListBox.h"
37 #include "AccessibilityObject.h"
38 #include "AccessibilityTable.h"
39 #include "AccessibilityTableCell.h"
40 #include "HTMLTableCaptionElement.h"
41 #include "HTMLTableElement.h"
42 #include "RenderElement.h"
43 #include "WebKitAccessibleInterfaceText.h"
44 #include "WebKitAccessibleUtil.h"
45 #include "WebKitAccessibleWrapperAtk.h"
46
47 using namespace WebCore;
48
49 static AccessibilityObject* core(AtkTable* table)
50 {
51     if (!WEBKIT_IS_ACCESSIBLE(table))
52         return nullptr;
53
54     return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(table));
55 }
56
57 static AccessibilityTableCell* cell(AtkTable* table, guint row, guint column)
58 {
59     AccessibilityObject* accTable = core(table);
60     if (is<AccessibilityTable>(*accTable))
61         return downcast<AccessibilityTable>(*accTable).cellForColumnAndRow(column, row);
62     return nullptr;
63 }
64
65 static gint cellIndex(AccessibilityTableCell* axCell, AccessibilityTable* axTable)
66 {
67     // Calculate the cell's index as if we had a traditional Gtk+ table in
68     // which cells are all direct children of the table, arranged row-first.
69     AccessibilityObject::AccessibilityChildrenVector allCells;
70     axTable->cells(allCells);
71     AccessibilityObject::AccessibilityChildrenVector::iterator position;
72     position = std::find(allCells.begin(), allCells.end(), axCell);
73     if (position == allCells.end())
74         return -1;
75     return position - allCells.begin();
76 }
77
78 static AccessibilityTableCell* cellAtIndex(AtkTable* table, gint index)
79 {
80     AccessibilityObject* accTable = core(table);
81     if (is<AccessibilityTable>(*accTable)) {
82         AccessibilityObject::AccessibilityChildrenVector allCells;
83         downcast<AccessibilityTable>(*accTable).cells(allCells);
84         if (0 <= index && static_cast<unsigned>(index) < allCells.size())
85             return downcast<AccessibilityTableCell>(allCells[index].get());
86     }
87     return nullptr;
88 }
89
90 static AtkObject* webkitAccessibleTableRefAt(AtkTable* table, gint row, gint column)
91 {
92     g_return_val_if_fail(ATK_TABLE(table), 0);
93     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
94
95     AccessibilityTableCell* axCell = cell(table, row, column);
96     if (!axCell)
97         return 0;
98
99     AtkObject* cell = axCell->wrapper();
100     if (!cell)
101         return 0;
102
103     // This method transfers full ownership over the returned
104     // AtkObject, so an extra reference is needed here.
105     return ATK_OBJECT(g_object_ref(cell));
106 }
107
108 static gint webkitAccessibleTableGetIndexAt(AtkTable* table, gint row, gint column)
109 {
110     g_return_val_if_fail(ATK_TABLE(table), -1);
111     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), -1);
112
113     AccessibilityTableCell* axCell = cell(table, row, column);
114     AccessibilityTable* axTable = downcast<AccessibilityTable>(core(table));
115     return cellIndex(axCell, axTable);
116 }
117
118 static gint webkitAccessibleTableGetColumnAtIndex(AtkTable* table, gint index)
119 {
120     g_return_val_if_fail(ATK_TABLE(table), -1);
121     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), -1);
122
123     AccessibilityTableCell* axCell = cellAtIndex(table, index);
124     if (axCell) {
125         std::pair<unsigned, unsigned> columnRange;
126         axCell->columnIndexRange(columnRange);
127         return columnRange.first;
128     }
129     return -1;
130 }
131
132 static gint webkitAccessibleTableGetRowAtIndex(AtkTable* table, gint index)
133 {
134     g_return_val_if_fail(ATK_TABLE(table), -1);
135     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), -1);
136
137     AccessibilityTableCell* axCell = cellAtIndex(table, index);
138     if (axCell) {
139         std::pair<unsigned, unsigned> rowRange;
140         axCell->rowIndexRange(rowRange);
141         return rowRange.first;
142     }
143     return -1;
144 }
145
146 static gint webkitAccessibleTableGetNColumns(AtkTable* table)
147 {
148     g_return_val_if_fail(ATK_TABLE(table), 0);
149     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
150
151     AccessibilityObject* accTable = core(table);
152     if (!is<AccessibilityTable>(*accTable))
153         return 0;
154
155     if (int columnCount = downcast<AccessibilityTable>(*accTable).ariaColumnCount())
156         return columnCount;
157
158     return downcast<AccessibilityTable>(*accTable).columnCount();
159 }
160
161 static gint webkitAccessibleTableGetNRows(AtkTable* table)
162 {
163     g_return_val_if_fail(ATK_TABLE(table), 0);
164     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
165
166     AccessibilityObject* accTable = core(table);
167     if (!is<AccessibilityTable>(*accTable))
168         return 0;
169
170     if (int rowCount = downcast<AccessibilityTable>(*accTable).ariaRowCount())
171         return rowCount;
172
173     return downcast<AccessibilityTable>(*accTable).rowCount();
174 }
175
176 static gint webkitAccessibleTableGetColumnExtentAt(AtkTable* table, gint row, gint column)
177 {
178     g_return_val_if_fail(ATK_TABLE(table), 0);
179     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
180
181     AccessibilityTableCell* axCell = cell(table, row, column);
182     if (axCell) {
183         std::pair<unsigned, unsigned> columnRange;
184         axCell->columnIndexRange(columnRange);
185         return columnRange.second;
186     }
187     return 0;
188 }
189
190 static gint webkitAccessibleTableGetRowExtentAt(AtkTable* table, gint row, gint column)
191 {
192     g_return_val_if_fail(ATK_TABLE(table), 0);
193     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
194
195     AccessibilityTableCell* axCell = cell(table, row, column);
196     if (axCell) {
197         std::pair<unsigned, unsigned> rowRange;
198         axCell->rowIndexRange(rowRange);
199         return rowRange.second;
200     }
201     return 0;
202 }
203
204 static AtkObject* webkitAccessibleTableGetColumnHeader(AtkTable* table, gint column)
205 {
206     g_return_val_if_fail(ATK_TABLE(table), 0);
207     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
208
209     AccessibilityObject* accTable = core(table);
210     if (is<AccessibilityTable>(*accTable)) {
211         AccessibilityObject::AccessibilityChildrenVector columnHeaders;
212         downcast<AccessibilityTable>(*accTable).columnHeaders(columnHeaders);
213
214         for (const auto& columnHeader : columnHeaders) {
215             std::pair<unsigned, unsigned> columnRange;
216             downcast<AccessibilityTableCell>(*columnHeader).columnIndexRange(columnRange);
217             if (columnRange.first <= static_cast<unsigned>(column) && static_cast<unsigned>(column) < columnRange.first + columnRange.second)
218                 return columnHeader->wrapper();
219         }
220     }
221     return nullptr;
222 }
223
224 static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
225 {
226     g_return_val_if_fail(ATK_TABLE(table), 0);
227     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
228
229     AccessibilityObject* accTable = core(table);
230     if (is<AccessibilityTable>(*accTable)) {
231         AccessibilityObject::AccessibilityChildrenVector rowHeaders;
232         downcast<AccessibilityTable>(*accTable).rowHeaders(rowHeaders);
233
234         for (const auto& rowHeader : rowHeaders) {
235             std::pair<unsigned, unsigned> rowRange;
236             downcast<AccessibilityTableCell>(*rowHeader).rowIndexRange(rowRange);
237             if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second)
238                 return rowHeader->wrapper();
239         }
240     }
241     return nullptr;
242 }
243
244 static AtkObject* webkitAccessibleTableGetCaption(AtkTable* table)
245 {
246     g_return_val_if_fail(ATK_TABLE(table), nullptr);
247     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), nullptr);
248
249     AccessibilityObject* accTable = core(table);
250     if (accTable->isAccessibilityRenderObject()) {
251         Node* node = accTable->node();
252         if (is<HTMLTableElement>(node)) {
253             auto caption = downcast<HTMLTableElement>(*node).caption();
254             if (caption)
255                 return AccessibilityObject::firstAccessibleObjectFromNode(caption->renderer()->element())->wrapper();
256         }
257     }
258     return nullptr;
259 }
260
261 static const gchar* webkitAccessibleTableGetColumnDescription(AtkTable* table, gint column)
262 {
263     g_return_val_if_fail(ATK_TABLE(table), 0);
264     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
265
266     AtkObject* columnHeader = atk_table_get_column_header(table, column);
267     if (columnHeader && ATK_IS_TEXT(columnHeader))
268         return atk_text_get_text(ATK_TEXT(columnHeader), 0, -1);
269
270     return 0;
271 }
272
273 static const gchar* webkitAccessibleTableGetRowDescription(AtkTable* table, gint row)
274 {
275     g_return_val_if_fail(ATK_TABLE(table), 0);
276     returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);
277
278     AtkObject* rowHeader = atk_table_get_row_header(table, row);
279     if (rowHeader && ATK_IS_TEXT(rowHeader))
280         return atk_text_get_text(ATK_TEXT(rowHeader), 0, -1);
281
282     return 0;
283 }
284
285 void webkitAccessibleTableInterfaceInit(AtkTableIface* iface)
286 {
287     iface->ref_at = webkitAccessibleTableRefAt;
288     iface->get_index_at = webkitAccessibleTableGetIndexAt;
289     iface->get_column_at_index = webkitAccessibleTableGetColumnAtIndex;
290     iface->get_row_at_index = webkitAccessibleTableGetRowAtIndex;
291     iface->get_n_columns = webkitAccessibleTableGetNColumns;
292     iface->get_n_rows = webkitAccessibleTableGetNRows;
293     iface->get_column_extent_at = webkitAccessibleTableGetColumnExtentAt;
294     iface->get_row_extent_at = webkitAccessibleTableGetRowExtentAt;
295     iface->get_column_header = webkitAccessibleTableGetColumnHeader;
296     iface->get_row_header = webkitAccessibleTableGetRowHeader;
297     iface->get_caption = webkitAccessibleTableGetCaption;
298     iface->get_column_description = webkitAccessibleTableGetColumnDescription;
299     iface->get_row_description = webkitAccessibleTableGetRowDescription;
300 }
301
302 #endif