[GTK] Missing call to g_object_ref while retrieving accessible table cells
[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 "HTMLSelectElement.h"
41 #include "HTMLTableCaptionElement.h"
42 #include "HTMLTableElement.h"
43 #include "RenderObject.h"
44 #include "WebKitAccessibleInterfaceText.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 0;
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 (accTable->isAccessibilityRenderObject())
61         return static_cast<AccessibilityTable*>(accTable)->cellForColumnAndRow(column, row);
62     return 0;
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 (accTable->isAccessibilityRenderObject()) {
82         AccessibilityObject::AccessibilityChildrenVector allCells;
83         static_cast<AccessibilityTable*>(accTable)->cells(allCells);
84         if (0 <= index && static_cast<unsigned>(index) < allCells.size()) {
85             AccessibilityObject* accCell = allCells.at(index).get();
86             return static_cast<AccessibilityTableCell*>(accCell);
87         }
88     }
89     return 0;
90 }
91
92 static AtkObject* webkitAccessibleTableRefAt(AtkTable* table, gint row, gint column)
93 {
94     AccessibilityTableCell* axCell = cell(table, row, column);
95     if (!axCell)
96         return 0;
97
98     AtkObject* cell = axCell->wrapper();
99     if (!cell)
100         return 0;
101
102     // This method transfers full ownership over the returned
103     // AtkObject, so an extra reference is needed here.
104     return ATK_OBJECT(g_object_ref(cell));
105 }
106
107 static gint webkitAccessibleTableGetIndexAt(AtkTable* table, gint row, gint column)
108 {
109     AccessibilityTableCell* axCell = cell(table, row, column);
110     AccessibilityTable* axTable = static_cast<AccessibilityTable*>(core(table));
111     return cellIndex(axCell, axTable);
112 }
113
114 static gint webkitAccessibleTableGetColumnAtIndex(AtkTable* table, gint index)
115 {
116     AccessibilityTableCell* axCell = cellAtIndex(table, index);
117     if (axCell) {
118         pair<int, int> columnRange;
119         axCell->columnIndexRange(columnRange);
120         return columnRange.first;
121     }
122     return -1;
123 }
124
125 static gint webkitAccessibleTableGetRowAtIndex(AtkTable* table, gint index)
126 {
127     AccessibilityTableCell* axCell = cellAtIndex(table, index);
128     if (axCell) {
129         pair<int, int> rowRange;
130         axCell->rowIndexRange(rowRange);
131         return rowRange.first;
132     }
133     return -1;
134 }
135
136 static gint webkitAccessibleTableGetNColumns(AtkTable* table)
137 {
138     AccessibilityObject* accTable = core(table);
139     if (accTable->isAccessibilityRenderObject())
140         return static_cast<AccessibilityTable*>(accTable)->columnCount();
141     return 0;
142 }
143
144 static gint webkitAccessibleTableGetNRows(AtkTable* table)
145 {
146     AccessibilityObject* accTable = core(table);
147     if (accTable->isAccessibilityRenderObject())
148         return static_cast<AccessibilityTable*>(accTable)->rowCount();
149     return 0;
150 }
151
152 static gint webkitAccessibleTableGetColumnExtentAt(AtkTable* table, gint row, gint column)
153 {
154     AccessibilityTableCell* axCell = cell(table, row, column);
155     if (axCell) {
156         pair<int, int> columnRange;
157         axCell->columnIndexRange(columnRange);
158         return columnRange.second;
159     }
160     return 0;
161 }
162
163 static gint webkitAccessibleTableGetRowExtentAt(AtkTable* table, gint row, gint column)
164 {
165     AccessibilityTableCell* axCell = cell(table, row, column);
166     if (axCell) {
167         pair<int, int> rowRange;
168         axCell->rowIndexRange(rowRange);
169         return rowRange.second;
170     }
171     return 0;
172 }
173
174 static AtkObject* webkitAccessibleTableGetColumnHeader(AtkTable* table, gint column)
175 {
176     AccessibilityObject* accTable = core(table);
177     if (accTable->isAccessibilityRenderObject()) {
178         AccessibilityObject::AccessibilityChildrenVector allColumnHeaders;
179         static_cast<AccessibilityTable*>(accTable)->columnHeaders(allColumnHeaders);
180         unsigned columnCount = allColumnHeaders.size();
181         for (unsigned k = 0; k < columnCount; ++k) {
182             pair<int, int> columnRange;
183             AccessibilityTableCell* cell = static_cast<AccessibilityTableCell*>(allColumnHeaders.at(k).get());
184             cell->columnIndexRange(columnRange);
185             if (columnRange.first <= column && column < columnRange.first + columnRange.second)
186                 return allColumnHeaders[k]->wrapper();
187         }
188     }
189     return 0;
190 }
191
192 static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
193 {
194     AccessibilityObject* accTable = core(table);
195     if (accTable->isAccessibilityRenderObject()) {
196         AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
197         static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders);
198         unsigned rowCount = allRowHeaders.size();
199         for (unsigned k = 0; k < rowCount; ++k) {
200             pair<int, int> rowRange;
201             AccessibilityTableCell* cell = static_cast<AccessibilityTableCell*>(allRowHeaders.at(k).get());
202             cell->rowIndexRange(rowRange);
203             if (rowRange.first <= row && row < rowRange.first + rowRange.second)
204                 return allRowHeaders[k]->wrapper();
205         }
206     }
207     return 0;
208 }
209
210 static AtkObject* webkitAccessibleTableGetCaption(AtkTable* table)
211 {
212     AccessibilityObject* accTable = core(table);
213     if (accTable->isAccessibilityRenderObject()) {
214         Node* node = accTable->node();
215         if (node && node->hasTagName(HTMLNames::tableTag)) {
216             HTMLTableCaptionElement* caption = static_cast<HTMLTableElement*>(node)->caption();
217             if (caption)
218                 return AccessibilityObject::firstAccessibleObjectFromNode(caption->renderer()->node())->wrapper();
219         }
220     }
221     return 0;
222 }
223
224 static const gchar* webkitAccessibleTableGetColumnDescription(AtkTable* table, gint column)
225 {
226     AtkObject* columnHeader = atk_table_get_column_header(table, column);
227     if (columnHeader && ATK_IS_TEXT(columnHeader))
228         return atk_text_get_text(ATK_TEXT(columnHeader), 0, -1);
229
230     return 0;
231 }
232
233 static const gchar* webkitAccessibleTableGetRowDescription(AtkTable* table, gint row)
234 {
235     AtkObject* rowHeader = atk_table_get_row_header(table, row);
236     if (rowHeader && ATK_IS_TEXT(rowHeader))
237         return atk_text_get_text(ATK_TEXT(rowHeader), 0, -1);
238
239     return 0;
240 }
241
242 void webkitAccessibleTableInterfaceInit(AtkTableIface* iface)
243 {
244     iface->ref_at = webkitAccessibleTableRefAt;
245     iface->get_index_at = webkitAccessibleTableGetIndexAt;
246     iface->get_column_at_index = webkitAccessibleTableGetColumnAtIndex;
247     iface->get_row_at_index = webkitAccessibleTableGetRowAtIndex;
248     iface->get_n_columns = webkitAccessibleTableGetNColumns;
249     iface->get_n_rows = webkitAccessibleTableGetNRows;
250     iface->get_column_extent_at = webkitAccessibleTableGetColumnExtentAt;
251     iface->get_row_extent_at = webkitAccessibleTableGetRowExtentAt;
252     iface->get_column_header = webkitAccessibleTableGetColumnHeader;
253     iface->get_row_header = webkitAccessibleTableGetRowHeader;
254     iface->get_caption = webkitAccessibleTableGetCaption;
255     iface->get_column_description = webkitAccessibleTableGetColumnDescription;
256     iface->get_row_description = webkitAccessibleTableGetRowDescription;
257 }
258
259 #endif