Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/atk/nsMaiInterfaceTable.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "InterfaceInitFuncs.h"
8
9
#include "Accessible-inl.h"
10
#include "AccessibleWrap.h"
11
#include "nsAccUtils.h"
12
#include "TableAccessible.h"
13
#include "TableCellAccessible.h"
14
#include "nsMai.h"
15
#include "ProxyAccessible.h"
16
#include "nsArrayUtils.h"
17
18
#include "mozilla/Likely.h"
19
20
using namespace mozilla::a11y;
21
22
extern "C" {
23
static AtkObject*
24
refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
25
0
{
26
0
  if (aRowIdx < 0 || aColIdx < 0) {
27
0
    return nullptr;
28
0
  }
29
0
30
0
  AtkObject* cellAtkObj = nullptr;
31
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
32
0
  if (accWrap) {
33
0
    Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
34
0
    if (!cell) {
35
0
      return nullptr;
36
0
    }
37
0
38
0
    cellAtkObj = AccessibleWrap::GetAtkObject(cell);
39
0
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
40
0
    ProxyAccessible* cell = proxy->TableCellAt(aRowIdx, aColIdx);
41
0
    if (!cell) {
42
0
      return nullptr;
43
0
    }
44
0
45
0
    cellAtkObj = GetWrapperFor(cell);
46
0
  }
47
0
48
0
  if (cellAtkObj) {
49
0
    g_object_ref(cellAtkObj);
50
0
  }
51
0
52
0
  return cellAtkObj;
53
0
}
54
55
static gint
56
getIndexAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
57
0
{
58
0
  if (aRowIdx < 0 || aColIdx < 0) {
59
0
    return -1;
60
0
  }
61
0
62
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
63
0
  if (accWrap) {
64
0
    return static_cast<gint>(accWrap->AsTable()->CellIndexAt(aRowIdx, aColIdx));
65
0
  }
66
0
67
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
68
0
    return static_cast<gint>(proxy->TableCellIndexAt(aRowIdx, aColIdx));
69
0
  }
70
0
71
0
  return -1;
72
0
}
73
74
static gint
75
getColumnAtIndexCB(AtkTable *aTable, gint aIdx)
76
0
{
77
0
  if (aIdx < 0) {
78
0
    return -1;
79
0
  }
80
0
81
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
82
0
  if (accWrap) {
83
0
    return static_cast<gint>(accWrap->AsTable()->ColIndexAt(aIdx));
84
0
  }
85
0
86
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
87
0
    return static_cast<gint>(proxy->TableColumnIndexAt(aIdx));
88
0
  }
89
0
90
0
  return -1;
91
0
}
92
93
static gint
94
getRowAtIndexCB(AtkTable *aTable, gint aIdx)
95
0
{
96
0
  if (aIdx < 0) {
97
0
    return -1;
98
0
  }
99
0
100
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
101
0
  if (accWrap) {
102
0
    return static_cast<gint>(accWrap->AsTable()->RowIndexAt(aIdx));
103
0
  }
104
0
105
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
106
0
    return static_cast<gint>(proxy->TableRowIndexAt(aIdx));
107
0
  }
108
0
109
0
  return -1;
110
0
}
111
112
static gint
113
getColumnCountCB(AtkTable *aTable)
114
0
{
115
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
116
0
  if (accWrap) {
117
0
    return static_cast<gint>(accWrap->AsTable()->ColCount());
118
0
  }
119
0
120
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
121
0
    return static_cast<gint>(proxy->TableColumnCount());
122
0
  }
123
0
124
0
  return -1;
125
0
}
126
127
static gint
128
getRowCountCB(AtkTable *aTable)
129
0
{
130
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
131
0
  if (accWrap) {
132
0
    return static_cast<gint>(accWrap->AsTable()->RowCount());
133
0
  }
134
0
135
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
136
0
    return static_cast<gint>(proxy->TableRowCount());
137
0
  }
138
0
139
0
  return -1;
140
0
}
141
142
static gint
143
getColumnExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
144
0
{
145
0
  if (aRowIdx < 0 || aColIdx < 0) {
146
0
    return -1;
147
0
  }
148
0
149
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
150
0
  if (accWrap) {
151
0
    return static_cast<gint>(accWrap->AsTable()->ColExtentAt(aRowIdx, aColIdx));
152
0
  }
153
0
154
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
155
0
    return static_cast<gint>(proxy->TableColumnExtentAt(aRowIdx, aColIdx));
156
0
  }
157
0
158
0
  return -1;
159
0
}
160
161
static gint
162
getRowExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
163
0
{
164
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
165
0
  if (accWrap) {
166
0
    return static_cast<gint>(accWrap->AsTable()->RowExtentAt(aRowIdx, aColIdx));
167
0
  }
168
0
169
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
170
0
    return static_cast<gint>(proxy->TableRowExtentAt(aRowIdx, aColIdx));
171
0
  }
172
0
173
0
  return -1;
174
0
}
175
176
static AtkObject*
177
getCaptionCB(AtkTable* aTable)
178
0
{
179
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
180
0
  if (accWrap) {
181
0
    Accessible* caption = accWrap->AsTable()->Caption();
182
0
    return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
183
0
  }
184
0
185
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
186
0
    ProxyAccessible* caption = proxy->TableCaption();
187
0
    return caption ? GetWrapperFor(caption) : nullptr;
188
0
  }
189
0
190
0
  return nullptr;
191
0
}
192
193
static const gchar*
194
getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
195
0
{
196
0
  nsAutoString autoStr;
197
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
198
0
  if (accWrap) {
199
0
    accWrap->AsTable()->ColDescription(aColumn, autoStr);
200
0
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
201
0
    proxy->TableColumnDescription(aColumn, autoStr);
202
0
  } else {
203
0
    return nullptr;
204
0
  }
205
0
206
0
  return AccessibleWrap::ReturnString(autoStr);
207
0
}
208
209
static AtkObject*
210
getColumnHeaderCB(AtkTable *aTable, gint aColIdx)
211
0
{
212
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
213
0
  if (accWrap) {
214
0
    Accessible* header =
215
0
      AccessibleWrap::GetColumnHeader(accWrap->AsTable(), aColIdx);
216
0
    return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
217
0
  }
218
0
219
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
220
0
    ProxyAccessible* header = proxy->AtkTableColumnHeader(aColIdx);
221
0
    return header ? GetWrapperFor(header) : nullptr;
222
0
  }
223
0
224
0
  return nullptr;
225
0
}
226
227
static const gchar*
228
getRowDescriptionCB(AtkTable *aTable, gint aRow)
229
0
{
230
0
  nsAutoString autoStr;
231
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
232
0
  if (accWrap) {
233
0
    accWrap->AsTable()->RowDescription(aRow, autoStr);
234
0
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
235
0
    proxy->TableRowDescription(aRow, autoStr);
236
0
  } else {
237
0
    return nullptr;
238
0
  }
239
0
240
0
  return AccessibleWrap::ReturnString(autoStr);
241
0
}
242
243
static AtkObject*
244
getRowHeaderCB(AtkTable *aTable, gint aRowIdx)
245
0
{
246
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
247
0
  if (accWrap) {
248
0
    Accessible* header =
249
0
      AccessibleWrap::GetRowHeader(accWrap->AsTable(), aRowIdx);
250
0
    return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
251
0
  }
252
0
253
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
254
0
    ProxyAccessible* header = proxy->AtkTableRowHeader(aRowIdx);
255
0
    return header ? GetWrapperFor(header) : nullptr;
256
0
  }
257
0
258
0
  return nullptr;
259
0
}
260
261
static AtkObject*
262
getSummaryCB(AtkTable *aTable)
263
0
{
264
0
  // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
265
0
  // link an accessible object to specify a summary. There is closes method
266
0
  // in TableAccessible::summary to get a summary as a string which is not
267
0
  // mapped directly to ATK.
268
0
  return nullptr;
269
0
}
270
271
static gint
272
getSelectedColumnsCB(AtkTable *aTable, gint** aSelected)
273
0
{
274
0
  *aSelected = nullptr;
275
0
276
0
  AutoTArray<uint32_t, 10> cols;
277
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
278
0
  if (accWrap) {
279
0
    accWrap->AsTable()->SelectedColIndices(&cols);
280
0
   } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
281
0
    proxy->TableSelectedColumnIndices(&cols);
282
0
  } else {
283
0
    return 0;
284
0
  }
285
0
286
0
  if (cols.IsEmpty())
287
0
    return 0;
288
0
289
0
  gint* atkColumns = g_new(gint, cols.Length());
290
0
  if (!atkColumns) {
291
0
    NS_WARNING("OUT OF MEMORY");
292
0
    return 0;
293
0
  }
294
0
295
0
  memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t));
296
0
  *aSelected = atkColumns;
297
0
  return cols.Length();
298
0
}
299
300
static gint
301
getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
302
0
{
303
0
  AutoTArray<uint32_t, 10> rows;
304
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
305
0
  if (accWrap) {
306
0
    accWrap->AsTable()->SelectedRowIndices(&rows);
307
0
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
308
0
    proxy->TableSelectedRowIndices(&rows);
309
0
  } else {
310
0
    return 0;
311
0
  }
312
0
313
0
  gint* atkRows = g_new(gint, rows.Length());
314
0
  if (!atkRows) {
315
0
    NS_WARNING("OUT OF MEMORY");
316
0
    return 0;
317
0
  }
318
0
319
0
  memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t));
320
0
  *aSelected = atkRows;
321
0
  return rows.Length();
322
0
}
323
324
static gboolean
325
isColumnSelectedCB(AtkTable *aTable, gint aColIdx)
326
0
{
327
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
328
0
  if (accWrap) {
329
0
    return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
330
0
  }
331
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
332
0
    return static_cast<gboolean>(proxy->TableColumnSelected(aColIdx));
333
0
  }
334
0
335
0
  return FALSE;
336
0
}
337
338
static gboolean
339
isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
340
0
{
341
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
342
0
  if (accWrap) {
343
0
    return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
344
0
  }
345
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
346
0
    return static_cast<gboolean>(proxy->TableRowSelected(aRowIdx));
347
0
  }
348
0
349
0
  return FALSE;
350
0
}
351
352
static gboolean
353
isCellSelectedCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
354
0
{
355
0
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
356
0
  if (accWrap) {
357
0
    return static_cast<gboolean>(accWrap->AsTable()->
358
0
      IsCellSelected(aRowIdx, aColIdx));
359
0
  }
360
0
  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
361
0
    return static_cast<gboolean>(proxy->TableCellSelected(aRowIdx, aColIdx));
362
0
  }
363
0
364
0
  return FALSE;
365
0
}
366
}
367
368
void
369
tableInterfaceInitCB(AtkTableIface* aIface)
370
0
{
371
0
  NS_ASSERTION(aIface, "no interface!");
372
0
  if (MOZ_UNLIKELY(!aIface))
373
0
    return;
374
0
375
0
  aIface->ref_at = refAtCB;
376
0
  aIface->get_index_at = getIndexAtCB;
377
0
  aIface->get_column_at_index = getColumnAtIndexCB;
378
0
  aIface->get_row_at_index = getRowAtIndexCB;
379
0
  aIface->get_n_columns = getColumnCountCB;
380
0
  aIface->get_n_rows = getRowCountCB;
381
0
  aIface->get_column_extent_at = getColumnExtentAtCB;
382
0
  aIface->get_row_extent_at = getRowExtentAtCB;
383
0
  aIface->get_caption = getCaptionCB;
384
0
  aIface->get_column_description = getColumnDescriptionCB;
385
0
  aIface->get_column_header = getColumnHeaderCB;
386
0
  aIface->get_row_description = getRowDescriptionCB;
387
0
  aIface->get_row_header = getRowHeaderCB;
388
0
  aIface->get_summary = getSummaryCB;
389
0
  aIface->get_selected_columns = getSelectedColumnsCB;
390
0
  aIface->get_selected_rows = getSelectedRowsCB;
391
0
  aIface->is_column_selected = isColumnSelectedCB;
392
0
  aIface->is_row_selected = isRowSelectedCB;
393
0
  aIface->is_selected = isCellSelectedCB;
394
0
}