ia2AccessibleTable.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim:expandtab:shiftwidth=2:tabstop=2:
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  7. #include "ia2AccessibleTable.h"
  8. #include "Accessible2.h"
  9. #include "AccessibleTable_i.c"
  10. #include "AccessibleTable2_i.c"
  11. #include "AccessibleWrap.h"
  12. #include "IUnknownImpl.h"
  13. #include "TableAccessible.h"
  14. #include "nsCOMPtr.h"
  15. #include "nsString.h"
  16. using namespace mozilla::a11y;
  17. // IUnknown
  18. STDMETHODIMP
  19. ia2AccessibleTable::QueryInterface(REFIID iid, void** ppv)
  20. {
  21. if (!ppv)
  22. return E_INVALIDARG;
  23. *ppv = nullptr;
  24. if (IID_IAccessibleTable == iid) {
  25. *ppv = static_cast<IAccessibleTable*>(this);
  26. (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
  27. return S_OK;
  28. }
  29. if (IID_IAccessibleTable2 == iid) {
  30. *ppv = static_cast<IAccessibleTable2*>(this);
  31. (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
  32. return S_OK;
  33. }
  34. return E_NOINTERFACE;
  35. }
  36. ////////////////////////////////////////////////////////////////////////////////
  37. // IAccessibleTable
  38. STDMETHODIMP
  39. ia2AccessibleTable::get_accessibleAt(long aRowIdx, long aColIdx,
  40. IUnknown** aAccessible)
  41. {
  42. return get_cellAt(aRowIdx, aColIdx, aAccessible);
  43. }
  44. STDMETHODIMP
  45. ia2AccessibleTable::get_caption(IUnknown** aAccessible)
  46. {
  47. if (!aAccessible)
  48. return E_INVALIDARG;
  49. *aAccessible = nullptr;
  50. if (!mTable)
  51. return CO_E_OBJNOTCONNECTED;
  52. AccessibleWrap* caption = static_cast<AccessibleWrap*>(mTable->Caption());
  53. if (!caption)
  54. return S_FALSE;
  55. (*aAccessible = static_cast<IAccessible*>(caption))->AddRef();
  56. return S_OK;
  57. }
  58. STDMETHODIMP
  59. ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
  60. long* aChildIdx)
  61. {
  62. if (!aChildIdx)
  63. return E_INVALIDARG;
  64. *aChildIdx = 0;
  65. if (!mTable)
  66. return CO_E_OBJNOTCONNECTED;
  67. if (aRowIdx < 0 || aColIdx < 0 ||
  68. static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
  69. static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  70. return E_INVALIDARG;
  71. *aChildIdx = mTable->CellIndexAt(aRowIdx, aColIdx);
  72. return S_OK;
  73. }
  74. STDMETHODIMP
  75. ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
  76. {
  77. if (!aDescription)
  78. return E_INVALIDARG;
  79. *aDescription = nullptr;
  80. if (!mTable)
  81. return CO_E_OBJNOTCONNECTED;
  82. if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  83. return E_INVALIDARG;
  84. nsAutoString descr;
  85. mTable->ColDescription(aColIdx, descr);
  86. if (descr.IsEmpty())
  87. return S_FALSE;
  88. *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
  89. return *aDescription ? S_OK : E_OUTOFMEMORY;
  90. }
  91. STDMETHODIMP
  92. ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
  93. long* aSpan)
  94. {
  95. if (!aSpan)
  96. return E_INVALIDARG;
  97. *aSpan = 0;
  98. if (!mTable)
  99. return CO_E_OBJNOTCONNECTED;
  100. if (aRowIdx < 0 || aColIdx < 0 ||
  101. static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
  102. static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  103. return E_INVALIDARG;
  104. *aSpan = mTable->ColExtentAt(aRowIdx, aColIdx);
  105. return S_OK;
  106. }
  107. STDMETHODIMP
  108. ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
  109. long* aStartingRowIndex)
  110. {
  111. if (!aAccessibleTable || !aStartingRowIndex)
  112. return E_INVALIDARG;
  113. *aAccessibleTable = nullptr;
  114. *aStartingRowIndex = -1;
  115. return E_NOTIMPL;
  116. }
  117. STDMETHODIMP
  118. ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
  119. {
  120. if (!aColIdx)
  121. return E_INVALIDARG;
  122. *aColIdx = 0;
  123. if (!mTable)
  124. return CO_E_OBJNOTCONNECTED;
  125. if (aCellIdx < 0 ||
  126. static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
  127. return E_INVALIDARG;
  128. *aColIdx = mTable->ColIndexAt(aCellIdx);
  129. return S_OK;
  130. }
  131. STDMETHODIMP
  132. ia2AccessibleTable::get_nColumns(long* aColCount)
  133. {
  134. if (!aColCount)
  135. return E_INVALIDARG;
  136. *aColCount = 0;
  137. if (!mTable)
  138. return CO_E_OBJNOTCONNECTED;
  139. *aColCount = mTable->ColCount();
  140. return S_OK;
  141. }
  142. STDMETHODIMP
  143. ia2AccessibleTable::get_nRows(long* aRowCount)
  144. {
  145. if (!aRowCount)
  146. return E_INVALIDARG;
  147. *aRowCount = 0;
  148. if (!mTable)
  149. return CO_E_OBJNOTCONNECTED;
  150. *aRowCount = mTable->RowCount();
  151. return S_OK;
  152. }
  153. STDMETHODIMP
  154. ia2AccessibleTable::get_nSelectedChildren(long* aChildCount)
  155. {
  156. return get_nSelectedCells(aChildCount);
  157. }
  158. STDMETHODIMP
  159. ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
  160. {
  161. if (!aColCount)
  162. return E_INVALIDARG;
  163. *aColCount = 0;
  164. if (!mTable)
  165. return CO_E_OBJNOTCONNECTED;
  166. *aColCount = mTable->SelectedColCount();
  167. return S_OK;
  168. }
  169. STDMETHODIMP
  170. ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
  171. {
  172. if (!aRowCount)
  173. return E_INVALIDARG;
  174. *aRowCount = 0;
  175. if (!mTable)
  176. return CO_E_OBJNOTCONNECTED;
  177. *aRowCount = mTable->SelectedRowCount();
  178. return S_OK;
  179. }
  180. STDMETHODIMP
  181. ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
  182. {
  183. if (!aDescription)
  184. return E_INVALIDARG;
  185. *aDescription = nullptr;
  186. if (!mTable)
  187. return CO_E_OBJNOTCONNECTED;
  188. if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
  189. return E_INVALIDARG;
  190. nsAutoString descr;
  191. mTable->RowDescription(aRowIdx, descr);
  192. if (descr.IsEmpty())
  193. return S_FALSE;
  194. *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
  195. return *aDescription ? S_OK : E_OUTOFMEMORY;
  196. }
  197. STDMETHODIMP
  198. ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
  199. {
  200. if (!aSpan)
  201. return E_INVALIDARG;
  202. *aSpan = 0;
  203. if (!mTable)
  204. return CO_E_OBJNOTCONNECTED;
  205. if (aRowIdx < 0 || aColIdx < 0 ||
  206. static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
  207. static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  208. return E_INVALIDARG;
  209. *aSpan = mTable->RowExtentAt(aRowIdx, aColIdx);
  210. return S_OK;
  211. }
  212. STDMETHODIMP
  213. ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
  214. long* aStartingColumnIndex)
  215. {
  216. if (!aAccessibleTable || !aStartingColumnIndex)
  217. return E_INVALIDARG;
  218. *aAccessibleTable = nullptr;
  219. *aStartingColumnIndex = -1;
  220. return E_NOTIMPL;
  221. }
  222. STDMETHODIMP
  223. ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
  224. {
  225. if (!aRowIdx)
  226. return E_INVALIDARG;
  227. *aRowIdx = 0;
  228. if (!mTable)
  229. return CO_E_OBJNOTCONNECTED;
  230. if (aCellIdx < 0 ||
  231. static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
  232. return E_INVALIDARG;
  233. *aRowIdx = mTable->RowIndexAt(aCellIdx);
  234. return S_OK;
  235. }
  236. STDMETHODIMP
  237. ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
  238. long* aNChildren)
  239. {
  240. if (!aChildren || !aNChildren)
  241. return E_INVALIDARG;
  242. *aChildren = nullptr;
  243. *aNChildren = 0;
  244. if (!mTable)
  245. return CO_E_OBJNOTCONNECTED;
  246. AutoTArray<uint32_t, 30> cellIndices;
  247. mTable->SelectedCellIndices(&cellIndices);
  248. uint32_t maxCells = cellIndices.Length();
  249. if (maxCells == 0)
  250. return S_FALSE;
  251. *aChildren = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCells));
  252. *aNChildren = maxCells;
  253. for (uint32_t i = 0; i < maxCells; i++)
  254. (*aChildren)[i] = cellIndices[i];
  255. return S_OK;
  256. }
  257. STDMETHODIMP
  258. ia2AccessibleTable::get_selectedColumns(long aMaxColumns, long** aColumns,
  259. long* aNColumns)
  260. {
  261. return get_selectedColumns(aColumns, aNColumns);
  262. }
  263. STDMETHODIMP
  264. ia2AccessibleTable::get_selectedRows(long aMaxRows, long** aRows, long* aNRows)
  265. {
  266. return get_selectedRows(aRows, aNRows);
  267. }
  268. STDMETHODIMP
  269. ia2AccessibleTable::get_summary(IUnknown** aAccessible)
  270. {
  271. if (!aAccessible)
  272. return E_INVALIDARG;
  273. // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
  274. // link an accessible object to specify a summary. There is closes method
  275. // in Table::summary to get a summary as a string which is not mapped
  276. // directly to IAccessible2.
  277. *aAccessible = nullptr;
  278. return S_FALSE;
  279. }
  280. STDMETHODIMP
  281. ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
  282. {
  283. if (!aIsSelected)
  284. return E_INVALIDARG;
  285. *aIsSelected = false;
  286. if (!mTable)
  287. return CO_E_OBJNOTCONNECTED;
  288. if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  289. return E_INVALIDARG;
  290. *aIsSelected = mTable->IsColSelected(aColIdx);
  291. return S_OK;
  292. }
  293. STDMETHODIMP
  294. ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
  295. {
  296. if (!aIsSelected)
  297. return E_INVALIDARG;
  298. *aIsSelected = false;
  299. if (!mTable)
  300. return CO_E_OBJNOTCONNECTED;
  301. if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
  302. return E_INVALIDARG;
  303. *aIsSelected = mTable->IsRowSelected(aRowIdx);
  304. return S_OK;
  305. }
  306. STDMETHODIMP
  307. ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
  308. boolean* aIsSelected)
  309. {
  310. if (!aIsSelected)
  311. return E_INVALIDARG;
  312. *aIsSelected = false;
  313. if (!mTable)
  314. return CO_E_OBJNOTCONNECTED;
  315. if (aRowIdx < 0 || aColIdx < 0 ||
  316. static_cast<uint32_t>(aColIdx) >= mTable->ColCount() ||
  317. static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
  318. return E_INVALIDARG;
  319. *aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
  320. return S_OK;
  321. }
  322. STDMETHODIMP
  323. ia2AccessibleTable::selectRow(long aRowIdx)
  324. {
  325. if (!mTable)
  326. return CO_E_OBJNOTCONNECTED;
  327. if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
  328. return E_INVALIDARG;
  329. mTable->SelectRow(aRowIdx);
  330. return S_OK;
  331. }
  332. STDMETHODIMP
  333. ia2AccessibleTable::selectColumn(long aColIdx)
  334. {
  335. if (!mTable)
  336. return CO_E_OBJNOTCONNECTED;
  337. if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  338. return E_INVALIDARG;
  339. mTable->SelectCol(aColIdx);
  340. return S_OK;
  341. }
  342. STDMETHODIMP
  343. ia2AccessibleTable::unselectRow(long aRowIdx)
  344. {
  345. if (!mTable)
  346. return CO_E_OBJNOTCONNECTED;
  347. if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
  348. return E_INVALIDARG;
  349. mTable->UnselectRow(aRowIdx);
  350. return S_OK;
  351. }
  352. STDMETHODIMP
  353. ia2AccessibleTable::unselectColumn(long aColIdx)
  354. {
  355. if (!mTable)
  356. return CO_E_OBJNOTCONNECTED;
  357. if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
  358. return E_INVALIDARG;
  359. mTable->UnselectCol(aColIdx);
  360. return S_OK;
  361. }
  362. STDMETHODIMP
  363. ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
  364. long* aColIdx,
  365. long* aRowExtents,
  366. long* aColExtents,
  367. boolean* aIsSelected)
  368. {
  369. if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
  370. return E_INVALIDARG;
  371. *aRowIdx = 0;
  372. *aColIdx = 0;
  373. *aRowExtents = 0;
  374. *aColExtents = 0;
  375. *aIsSelected = false;
  376. if (!mTable)
  377. return CO_E_OBJNOTCONNECTED;
  378. if (aCellIdx < 0 ||
  379. static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
  380. return E_INVALIDARG;
  381. int32_t colIdx = 0, rowIdx = 0;
  382. mTable->RowAndColIndicesAt(aCellIdx, &rowIdx, &colIdx);
  383. *aRowIdx = rowIdx;
  384. *aColIdx = colIdx;
  385. *aRowExtents = mTable->RowExtentAt(rowIdx, colIdx);
  386. *aColExtents = mTable->ColExtentAt(rowIdx, colIdx);
  387. *aIsSelected = mTable->IsCellSelected(rowIdx, colIdx);
  388. return S_OK;
  389. }
  390. STDMETHODIMP
  391. ia2AccessibleTable::get_modelChange(IA2TableModelChange* aModelChange)
  392. {
  393. return E_NOTIMPL;
  394. }
  395. ////////////////////////////////////////////////////////////////////////////////
  396. // IAccessibleTable2
  397. STDMETHODIMP
  398. ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
  399. {
  400. if (!aCell)
  401. return E_INVALIDARG;
  402. *aCell = nullptr;
  403. if (!mTable)
  404. return CO_E_OBJNOTCONNECTED;
  405. AccessibleWrap* cell =
  406. static_cast<AccessibleWrap*>(mTable->CellAt(aRowIdx, aColIdx));
  407. if (!cell)
  408. return E_INVALIDARG;
  409. (*aCell = static_cast<IAccessible*>(cell))->AddRef();
  410. return S_OK;
  411. }
  412. STDMETHODIMP
  413. ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
  414. {
  415. if (!aCellCount)
  416. return E_INVALIDARG;
  417. *aCellCount = 0;
  418. if (!mTable)
  419. return CO_E_OBJNOTCONNECTED;
  420. *aCellCount = mTable->SelectedCellCount();
  421. return S_OK;
  422. }
  423. STDMETHODIMP
  424. ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
  425. {
  426. if (!aCells || !aNSelectedCells)
  427. return E_INVALIDARG;
  428. *aCells = nullptr;
  429. *aNSelectedCells = 0;
  430. if (!mTable)
  431. return CO_E_OBJNOTCONNECTED;
  432. AutoTArray<Accessible*, 30> cells;
  433. mTable->SelectedCells(&cells);
  434. if (cells.IsEmpty())
  435. return S_FALSE;
  436. *aCells =
  437. static_cast<IUnknown**>(::CoTaskMemAlloc(sizeof(IUnknown*) *
  438. cells.Length()));
  439. if (!*aCells)
  440. return E_OUTOFMEMORY;
  441. for (uint32_t i = 0; i < cells.Length(); i++) {
  442. (*aCells)[i] =
  443. static_cast<IAccessible*>(static_cast<AccessibleWrap*>(cells[i]));
  444. ((*aCells)[i])->AddRef();
  445. }
  446. *aNSelectedCells = cells.Length();
  447. return S_OK;
  448. }
  449. STDMETHODIMP
  450. ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
  451. {
  452. if (!aColumns || !aNColumns)
  453. return E_INVALIDARG;
  454. *aColumns = nullptr;
  455. *aNColumns = 0;
  456. if (!mTable)
  457. return CO_E_OBJNOTCONNECTED;
  458. AutoTArray<uint32_t, 30> colIndices;
  459. mTable->SelectedColIndices(&colIndices);
  460. uint32_t maxCols = colIndices.Length();
  461. if (maxCols == 0)
  462. return S_FALSE;
  463. *aColumns = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCols));
  464. *aNColumns = maxCols;
  465. for (uint32_t i = 0; i < maxCols; i++)
  466. (*aColumns)[i] = colIndices[i];
  467. return S_OK;
  468. }
  469. STDMETHODIMP
  470. ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
  471. {
  472. if (!aRows || !aNRows)
  473. return E_INVALIDARG;
  474. *aRows = nullptr;
  475. *aNRows = 0;
  476. if (!mTable)
  477. return CO_E_OBJNOTCONNECTED;
  478. AutoTArray<uint32_t, 30> rowIndices;
  479. mTable->SelectedRowIndices(&rowIndices);
  480. uint32_t maxRows = rowIndices.Length();
  481. if (maxRows == 0)
  482. return S_FALSE;
  483. *aRows = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxRows));
  484. *aNRows = maxRows;
  485. for (uint32_t i = 0; i < maxRows; i++)
  486. (*aRows)[i] = rowIndices[i];
  487. return S_OK;
  488. }