LCOV - code coverage report
Current view: directory - accessible/src/html - nsHTMLTableAccessible.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 733 0 0.0 %
Date: 2012-06-02 Functions: 67 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Aaron Leventhal <aaronl@netscape.com> (original author)
      24                 :  *   Alexander Surkov <surkov.alexander@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsHTMLTableAccessible.h"
      41                 : 
      42                 : #include "nsAccessibilityService.h"
      43                 : #include "nsAccTreeWalker.h"
      44                 : #include "nsAccUtils.h"
      45                 : #include "nsDocAccessible.h"
      46                 : #include "nsTextEquivUtils.h"
      47                 : #include "Relation.h"
      48                 : #include "Role.h"
      49                 : #include "States.h"
      50                 : 
      51                 : #include "nsIAccessibleRelation.h"
      52                 : #include "nsIDOMElement.h"
      53                 : #include "nsIDOMDocument.h"
      54                 : #include "nsIDOMRange.h"
      55                 : #include "nsISelectionPrivate.h"
      56                 : #include "nsINameSpaceManager.h"
      57                 : #include "nsIDOMNodeList.h"
      58                 : #include "nsIDOMHTMLCollection.h"
      59                 : #include "nsIDOMHTMLTableCellElement.h"
      60                 : #include "nsIDOMHTMLTableElement.h"
      61                 : #include "nsIDOMHTMLTableRowElement.h"
      62                 : #include "nsIDOMHTMLTableSectionElem.h"
      63                 : #include "nsIDocument.h"
      64                 : #include "nsIPresShell.h"
      65                 : #include "nsITableLayout.h"
      66                 : #include "nsITableCellLayout.h"
      67                 : #include "nsFrameSelection.h"
      68                 : #include "nsLayoutErrors.h"
      69                 : #include "nsArrayUtils.h"
      70                 : #include "nsComponentManagerUtils.h"
      71                 : 
      72                 : using namespace mozilla::a11y;
      73                 : 
      74                 : ////////////////////////////////////////////////////////////////////////////////
      75                 : // nsHTMLTableCellAccessible
      76                 : ////////////////////////////////////////////////////////////////////////////////
      77                 : 
      78               0 : nsHTMLTableCellAccessible::
      79                 :   nsHTMLTableCellAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
      80               0 :   nsHyperTextAccessibleWrap(aContent, aDoc)
      81                 : {
      82               0 : }
      83                 : 
      84                 : ////////////////////////////////////////////////////////////////////////////////
      85                 : // nsHTMLTableCellAccessible: nsISupports implementation
      86                 : 
      87               0 : NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLTableCellAccessible,
      88                 :                              nsHyperTextAccessible,
      89                 :                              nsIAccessibleTableCell)
      90                 : 
      91                 : ////////////////////////////////////////////////////////////////////////////////
      92                 : // nsHTMLTableCellAccessible: nsAccessible implementation
      93                 : 
      94                 : role
      95               0 : nsHTMLTableCellAccessible::NativeRole()
      96                 : {
      97               0 :   return roles::CELL;
      98                 : }
      99                 : 
     100                 : PRUint64
     101               0 : nsHTMLTableCellAccessible::NativeState()
     102                 : {
     103               0 :   PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
     104                 : 
     105               0 :   nsIFrame *frame = mContent->GetPrimaryFrame();
     106               0 :   NS_ASSERTION(frame, "No frame for valid cell accessible!");
     107                 : 
     108               0 :   if (frame) {
     109               0 :     state |= states::SELECTABLE;
     110               0 :     if (frame->IsSelected())
     111               0 :       state |= states::SELECTED;
     112                 :   }
     113                 : 
     114               0 :   return state;
     115                 : }
     116                 : 
     117                 : nsresult
     118               0 : nsHTMLTableCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
     119                 : {
     120               0 :   if (IsDefunct())
     121               0 :     return NS_ERROR_FAILURE;
     122                 : 
     123               0 :   nsresult rv = nsHyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
     124               0 :   NS_ENSURE_SUCCESS(rv, rv);
     125                 : 
     126                 :   // table-cell-index attribute
     127               0 :   nsCOMPtr<nsIAccessibleTable> tableAcc(GetTableAccessible());
     128               0 :   if (!tableAcc)
     129               0 :     return NS_OK;
     130                 : 
     131               0 :   PRInt32 rowIdx = -1, colIdx = -1;
     132               0 :   rv = GetCellIndexes(rowIdx, colIdx);
     133               0 :   NS_ENSURE_SUCCESS(rv, rv);
     134                 : 
     135               0 :   PRInt32 idx = -1;
     136               0 :   rv = tableAcc->GetCellIndexAt(rowIdx, colIdx, &idx);
     137               0 :   NS_ENSURE_SUCCESS(rv, rv);
     138                 : 
     139               0 :   nsAutoString stringIdx;
     140               0 :   stringIdx.AppendInt(idx);
     141               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx);
     142                 : 
     143                 :   // abbr attribute
     144                 : 
     145                 :   // Pick up object attribute from abbr DOM element (a child of the cell) or
     146                 :   // from abbr DOM attribute.
     147               0 :   nsAutoString abbrText;
     148               0 :   if (GetChildCount() == 1) {
     149               0 :     nsAccessible* abbr = FirstChild();
     150               0 :     if (abbr->IsAbbreviation()) {
     151                 :       nsTextEquivUtils::
     152               0 :         AppendTextEquivFromTextContent(abbr->GetContent()->GetFirstChild(),
     153               0 :                                        &abbrText);
     154                 :     }
     155                 :   }
     156               0 :   if (abbrText.IsEmpty())
     157               0 :     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);
     158                 : 
     159               0 :   if (!abbrText.IsEmpty())
     160               0 :     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::abbr, abbrText);
     161                 : 
     162                 :   // axis attribute
     163               0 :   nsAutoString axisText;
     164               0 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
     165               0 :   if (!axisText.IsEmpty())
     166               0 :     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::axis, axisText);
     167                 : 
     168               0 :   return NS_OK;
     169                 : }
     170                 : 
     171                 : ////////////////////////////////////////////////////////////////////////////////
     172                 : // nsHTMLTableCellAccessible: nsIAccessibleTableCell implementation
     173                 : 
     174                 : NS_IMETHODIMP
     175               0 : nsHTMLTableCellAccessible::GetTable(nsIAccessibleTable **aTable)
     176                 : {
     177               0 :   NS_ENSURE_ARG_POINTER(aTable);
     178               0 :   *aTable = nsnull;
     179                 : 
     180               0 :   if (IsDefunct())
     181               0 :     return NS_OK;
     182                 : 
     183               0 :   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
     184               0 :   table.swap(*aTable);
     185                 : 
     186               0 :   return NS_OK;
     187                 : }
     188                 : 
     189                 : NS_IMETHODIMP
     190               0 : nsHTMLTableCellAccessible::GetColumnIndex(PRInt32 *aColumnIndex)
     191                 : {
     192               0 :   NS_ENSURE_ARG_POINTER(aColumnIndex);
     193               0 :   *aColumnIndex = -1;
     194                 : 
     195               0 :   if (IsDefunct())
     196               0 :     return NS_ERROR_FAILURE;
     197                 : 
     198               0 :   nsITableCellLayout* cellLayout = GetCellLayout();
     199               0 :   NS_ENSURE_STATE(cellLayout);
     200                 : 
     201               0 :   return cellLayout->GetColIndex(*aColumnIndex);
     202                 : }
     203                 : 
     204                 : NS_IMETHODIMP
     205               0 : nsHTMLTableCellAccessible::GetRowIndex(PRInt32 *aRowIndex)
     206                 : {
     207               0 :   NS_ENSURE_ARG_POINTER(aRowIndex);
     208               0 :   *aRowIndex = -1;
     209                 : 
     210               0 :   if (IsDefunct())
     211               0 :     return NS_ERROR_FAILURE;
     212                 : 
     213               0 :   nsITableCellLayout* cellLayout = GetCellLayout();
     214               0 :   NS_ENSURE_STATE(cellLayout);
     215                 : 
     216               0 :   return cellLayout->GetRowIndex(*aRowIndex);
     217                 : }
     218                 : 
     219                 : NS_IMETHODIMP
     220               0 : nsHTMLTableCellAccessible::GetColumnExtent(PRInt32 *aExtentCount)
     221                 : {
     222               0 :   NS_ENSURE_ARG_POINTER(aExtentCount);
     223               0 :   *aExtentCount = 1;
     224                 : 
     225               0 :   PRInt32 rowIdx = -1, colIdx = -1;
     226               0 :   GetCellIndexes(rowIdx, colIdx);
     227                 : 
     228               0 :   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
     229               0 :   NS_ENSURE_STATE(table);
     230                 : 
     231               0 :   return table->GetColumnExtentAt(rowIdx, colIdx, aExtentCount);
     232                 : }
     233                 : 
     234                 : NS_IMETHODIMP
     235               0 : nsHTMLTableCellAccessible::GetRowExtent(PRInt32 *aExtentCount)
     236                 : {
     237               0 :   NS_ENSURE_ARG_POINTER(aExtentCount);
     238               0 :   *aExtentCount = 1;
     239                 : 
     240               0 :   PRInt32 rowIdx = -1, colIdx = -1;
     241               0 :   GetCellIndexes(rowIdx, colIdx);
     242                 : 
     243               0 :   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
     244               0 :   NS_ENSURE_STATE(table);
     245                 : 
     246               0 :   return table->GetRowExtentAt(rowIdx, colIdx, aExtentCount);
     247                 : }
     248                 : 
     249                 : NS_IMETHODIMP
     250               0 : nsHTMLTableCellAccessible::GetColumnHeaderCells(nsIArray **aHeaderCells)
     251                 : {
     252               0 :   NS_ENSURE_ARG_POINTER(aHeaderCells);
     253               0 :   *aHeaderCells = nsnull;
     254                 : 
     255               0 :   if (IsDefunct())
     256               0 :     return NS_ERROR_FAILURE;
     257                 : 
     258               0 :   return GetHeaderCells(nsAccUtils::eColumnHeaderCells, aHeaderCells);
     259                 : }
     260                 : 
     261                 : NS_IMETHODIMP
     262               0 : nsHTMLTableCellAccessible::GetRowHeaderCells(nsIArray **aHeaderCells)
     263                 : {
     264               0 :   NS_ENSURE_ARG_POINTER(aHeaderCells);
     265               0 :   *aHeaderCells = nsnull;
     266                 : 
     267               0 :   if (IsDefunct())
     268               0 :     return NS_ERROR_FAILURE;
     269                 : 
     270               0 :   return GetHeaderCells(nsAccUtils::eRowHeaderCells, aHeaderCells);
     271                 : }
     272                 : 
     273                 : NS_IMETHODIMP
     274               0 : nsHTMLTableCellAccessible::IsSelected(bool *aIsSelected)
     275                 : {
     276               0 :   NS_ENSURE_ARG_POINTER(aIsSelected);
     277               0 :   *aIsSelected = false;
     278                 : 
     279               0 :   if (IsDefunct())
     280               0 :     return NS_ERROR_FAILURE;
     281                 : 
     282               0 :   PRInt32 rowIdx = -1, colIdx = -1;
     283               0 :   GetCellIndexes(rowIdx, colIdx);
     284                 : 
     285               0 :   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
     286               0 :   NS_ENSURE_STATE(table);
     287                 : 
     288               0 :   return table->IsCellSelected(rowIdx, colIdx, aIsSelected);
     289                 : }
     290                 : 
     291                 : ////////////////////////////////////////////////////////////////////////////////
     292                 : // nsHTMLTableCellAccessible: protected implementation
     293                 : 
     294                 : already_AddRefed<nsIAccessibleTable>
     295               0 : nsHTMLTableCellAccessible::GetTableAccessible()
     296                 : {
     297               0 :   nsAccessible* parent = this;
     298               0 :   while ((parent = parent->Parent())) {
     299               0 :     roles::Role role = parent->Role();
     300               0 :     if (role == roles::TABLE || role == roles::TREE_TABLE) {
     301               0 :       nsIAccessibleTable* tableAcc = nsnull;
     302               0 :       CallQueryInterface(parent, &tableAcc);
     303               0 :       return tableAcc;
     304                 :     }
     305                 :   }
     306                 : 
     307               0 :   return nsnull;
     308                 : }
     309                 : 
     310                 : nsITableCellLayout*
     311               0 : nsHTMLTableCellAccessible::GetCellLayout()
     312                 : {
     313               0 :   nsIFrame *frame = mContent->GetPrimaryFrame();
     314               0 :   NS_ASSERTION(frame, "The frame cannot be obtaied for HTML table cell.");
     315               0 :   if (!frame)
     316               0 :     return nsnull;
     317                 : 
     318               0 :   nsITableCellLayout *cellLayout = do_QueryFrame(frame);
     319               0 :   return cellLayout;
     320                 : }
     321                 : 
     322                 : nsresult
     323               0 : nsHTMLTableCellAccessible::GetCellIndexes(PRInt32& aRowIndex,
     324                 :                                           PRInt32& aColIndex)
     325                 : {
     326               0 :   nsITableCellLayout *cellLayout = GetCellLayout();
     327               0 :   NS_ENSURE_STATE(cellLayout);
     328                 : 
     329               0 :   return cellLayout->GetCellIndexes(aRowIndex, aColIndex);
     330                 : }
     331                 : 
     332                 : nsresult
     333               0 : nsHTMLTableCellAccessible::GetHeaderCells(PRInt32 aRowOrColumnHeaderCell,
     334                 :                                           nsIArray **aHeaderCells)
     335                 : {
     336                 :   // Get header cells from @header attribute.
     337               0 :   IDRefsIterator iter(mContent, nsGkAtoms::headers);
     338               0 :   nsIContent* headerCellElm = iter.NextElem();
     339               0 :   if (headerCellElm) {
     340               0 :     nsresult rv = NS_OK;
     341                 :     nsCOMPtr<nsIMutableArray> headerCells =
     342               0 :       do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     343               0 :     NS_ENSURE_SUCCESS(rv, rv);
     344               0 :     roles::Role desiredRole = static_cast<roles::Role>(-1) ;
     345               0 :     if (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells)
     346               0 :       desiredRole = roles::ROWHEADER;
     347               0 :     else if (aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells)
     348               0 :       desiredRole = roles::COLUMNHEADER;
     349                 : 
     350               0 :     do {
     351               0 :       nsAccessible* headerCell = mDoc->GetAccessible(headerCellElm);
     352                 : 
     353               0 :       if (headerCell && headerCell->Role() == desiredRole)
     354               0 :         headerCells->AppendElement(static_cast<nsIAccessible*>(headerCell),
     355               0 :                                    false);
     356                 :     } while ((headerCellElm = iter.NextElem()));
     357                 : 
     358               0 :     NS_ADDREF(*aHeaderCells = headerCells);
     359               0 :     return NS_OK;
     360                 :   }
     361                 : 
     362                 :   // Otherwise calculate header cells from hierarchy (see 11.4.3 "Algorithm to
     363                 :   // find heading information" of w3c HTML 4.01).
     364               0 :   nsCOMPtr<nsIAccessibleTable> table = GetTableAccessible();
     365               0 :   if (table) {
     366                 :     return nsAccUtils::GetHeaderCellsFor(table, this, aRowOrColumnHeaderCell,
     367               0 :                                          aHeaderCells);
     368                 :   }
     369                 : 
     370               0 :   return NS_OK;
     371                 : }
     372                 : 
     373                 : ////////////////////////////////////////////////////////////////////////////////
     374                 : // nsHTMLTableHeaderAccessible
     375                 : ////////////////////////////////////////////////////////////////////////////////
     376                 : 
     377               0 : nsHTMLTableHeaderCellAccessible::
     378                 :   nsHTMLTableHeaderCellAccessible(nsIContent* aContent,
     379                 :                                   nsDocAccessible* aDoc) :
     380               0 :   nsHTMLTableCellAccessible(aContent, aDoc)
     381                 : {
     382               0 : }
     383                 : 
     384                 : ////////////////////////////////////////////////////////////////////////////////
     385                 : // nsHTMLTableHeaderAccessible: nsAccessible implementation
     386                 : 
     387                 : role
     388               0 : nsHTMLTableHeaderCellAccessible::NativeRole()
     389                 : {
     390                 :   // Check value of @scope attribute.
     391                 :   static nsIContent::AttrValuesArray scopeValues[] =
     392                 :     {&nsGkAtoms::col, &nsGkAtoms::row, nsnull};
     393                 :   PRInt32 valueIdx = 
     394               0 :     mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope,
     395               0 :                               scopeValues, eCaseMatters);
     396                 : 
     397               0 :   switch (valueIdx) {
     398                 :     case 0:
     399               0 :       return roles::COLUMNHEADER;
     400                 :     case 1:
     401               0 :       return roles::ROWHEADER;
     402                 :   }
     403                 : 
     404                 :   // Assume it's columnheader if there are headers in siblings, oterwise
     405                 :   // rowheader.
     406               0 :   nsIContent* parentContent = mContent->GetParent();
     407               0 :   if (!parentContent) {
     408               0 :     NS_ERROR("Deattached content on alive accessible?");
     409               0 :     return roles::NOTHING;
     410                 :   }
     411                 : 
     412               0 :   for (nsIContent* siblingContent = mContent->GetPreviousSibling(); siblingContent;
     413               0 :        siblingContent = siblingContent->GetPreviousSibling()) {
     414               0 :     if (siblingContent->IsElement()) {
     415               0 :       return nsCoreUtils::IsHTMLTableHeader(siblingContent) ? 
     416               0 :              roles::COLUMNHEADER : roles::ROWHEADER;
     417                 :     }
     418                 :   }
     419                 : 
     420               0 :   for (nsIContent* siblingContent = mContent->GetNextSibling(); siblingContent;
     421               0 :        siblingContent = siblingContent->GetNextSibling()) {
     422               0 :     if (siblingContent->IsElement()) {
     423               0 :       return nsCoreUtils::IsHTMLTableHeader(siblingContent) ? 
     424               0 :              roles::COLUMNHEADER : roles::ROWHEADER;
     425                 :     }
     426                 :   }
     427                 : 
     428                 :   // No elements in siblings what means the table has one column only. Therefore
     429                 :   // it should be column header.
     430               0 :   return roles::COLUMNHEADER;
     431                 : }
     432                 : 
     433                 : ////////////////////////////////////////////////////////////////////////////////
     434                 : // nsHTMLTableAccessible
     435                 : ////////////////////////////////////////////////////////////////////////////////
     436                 : 
     437               0 : nsHTMLTableAccessible::
     438                 :   nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
     439               0 :   nsAccessibleWrap(aContent, aDoc)
     440                 : {
     441               0 : }
     442                 : 
     443                 : ////////////////////////////////////////////////////////////////////////////////
     444                 : // nsHTMLTableAccessible: nsISupports implementation
     445                 : 
     446               0 : NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
     447                 :                              nsHTMLTableAccessible, nsIAccessibleTable)
     448                 : 
     449                 : 
     450                 : ////////////////////////////////////////////////////////////////////////////////
     451                 : // nsHTMLTableAccessible: nsAccessible implementation
     452                 : 
     453                 : void
     454               0 : nsHTMLTableAccessible::CacheChildren()
     455                 : {
     456                 :   // Move caption accessible so that it's the first child. Check for the first
     457                 :   // caption only, because nsAccessibilityService ensures we don't create
     458                 :   // accessibles for the other captions, since only the first is actually
     459                 :   // visible.
     460               0 :   nsAccTreeWalker walker(mDoc, mContent, CanHaveAnonChildren());
     461                 : 
     462               0 :   nsAccessible* child = nsnull;
     463               0 :   while ((child = walker.NextChild())) {
     464               0 :     if (child->Role() == roles::CAPTION) {
     465               0 :       InsertChildAt(0, child);
     466               0 :       while ((child = walker.NextChild()) && AppendChild(child));
     467               0 :       break;
     468                 :     }
     469               0 :     AppendChild(child);
     470                 :   }
     471               0 : }
     472                 : 
     473                 : role
     474               0 : nsHTMLTableAccessible::NativeRole()
     475                 : {
     476               0 :   return roles::TABLE;
     477                 : }
     478                 : 
     479                 : PRUint64
     480               0 : nsHTMLTableAccessible::NativeState()
     481                 : {
     482               0 :   return nsAccessible::NativeState() | states::READONLY;
     483                 : }
     484                 : 
     485                 : nsresult
     486               0 : nsHTMLTableAccessible::GetNameInternal(nsAString& aName)
     487                 : {
     488               0 :   nsAccessible::GetNameInternal(aName);
     489               0 :   if (!aName.IsEmpty())
     490               0 :     return NS_OK;
     491                 : 
     492                 :   // Use table caption as a name.
     493               0 :   nsAccessible* caption = Caption();
     494               0 :   if (caption) {
     495               0 :     nsIContent* captionContent = caption->GetContent();
     496               0 :     if (captionContent) {
     497               0 :       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
     498               0 :       if (!aName.IsEmpty())
     499               0 :         return NS_OK;
     500                 :     }
     501                 :   }
     502                 : 
     503                 :   // If no caption then use summary as a name.
     504               0 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
     505               0 :   return NS_OK;
     506                 : }
     507                 : 
     508                 : nsresult
     509               0 : nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
     510                 : {
     511               0 :   nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
     512               0 :   NS_ENSURE_SUCCESS(rv, rv);
     513                 : 
     514                 :   bool isProbablyForLayout;
     515               0 :   IsProbablyForLayout(&isProbablyForLayout);
     516               0 :   if (isProbablyForLayout) {
     517               0 :     nsAutoString oldValueUnused;
     518               0 :     aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
     519               0 :                                    NS_LITERAL_STRING("true"), oldValueUnused);
     520                 :   }
     521                 :   
     522               0 :   return NS_OK;
     523                 : }
     524                 : 
     525                 : ////////////////////////////////////////////////////////////////////////////////
     526                 : // nsHTMLTableAccessible: nsIAccessible implementation
     527                 : 
     528                 : Relation
     529               0 : nsHTMLTableAccessible::RelationByType(PRUint32 aType)
     530                 : {
     531               0 :   Relation rel = nsAccessibleWrap::RelationByType(aType);
     532               0 :   if (aType == nsIAccessibleRelation::RELATION_LABELLED_BY)
     533               0 :     rel.AppendTarget(Caption());
     534                 : 
     535                 :   return rel;
     536                 : }
     537                 : 
     538                 : ////////////////////////////////////////////////////////////////////////////////
     539                 : // nsHTMLTableAccessible: nsIAccessibleTable implementation
     540                 : 
     541                 : NS_IMETHODIMP
     542               0 : nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
     543                 : {
     544               0 :   NS_ENSURE_ARG_POINTER(aCaption);
     545                 : 
     546               0 :   NS_IF_ADDREF(*aCaption = Caption());
     547               0 :   return NS_OK;
     548                 : }
     549                 : 
     550                 : NS_IMETHODIMP
     551               0 : nsHTMLTableAccessible::GetSummary(nsAString &aSummary)
     552                 : {
     553               0 :   nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mContent));
     554               0 :   NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
     555                 : 
     556               0 :   return table->GetSummary(aSummary);
     557                 : }
     558                 : 
     559                 : NS_IMETHODIMP
     560               0 : nsHTMLTableAccessible::GetColumnCount(PRInt32 *acolumnCount)
     561                 : {
     562               0 :   NS_ENSURE_ARG_POINTER(acolumnCount);
     563               0 :   *acolumnCount = nsnull;
     564                 : 
     565               0 :   if (IsDefunct())
     566               0 :     return NS_ERROR_FAILURE;
     567                 : 
     568               0 :   nsITableLayout *tableLayout = GetTableLayout();
     569               0 :   NS_ENSURE_STATE(tableLayout);
     570                 : 
     571                 :   PRInt32 rows;
     572               0 :   return tableLayout->GetTableSize(rows, *acolumnCount);
     573                 : }
     574                 : 
     575                 : NS_IMETHODIMP
     576               0 : nsHTMLTableAccessible::GetRowCount(PRInt32 *arowCount)
     577                 : {
     578               0 :   NS_ENSURE_ARG_POINTER(arowCount);
     579               0 :   *arowCount = 0;
     580                 : 
     581               0 :   if (IsDefunct())
     582               0 :     return NS_ERROR_FAILURE;
     583                 : 
     584               0 :   nsITableLayout *tableLayout = GetTableLayout();
     585               0 :   NS_ENSURE_STATE(tableLayout);
     586                 : 
     587                 :   PRInt32 columns;
     588               0 :   return tableLayout->GetTableSize(*arowCount, columns);
     589                 : }
     590                 : 
     591                 : NS_IMETHODIMP
     592               0 : nsHTMLTableAccessible::GetSelectedCellCount(PRUint32* aCount)
     593                 : {
     594               0 :   NS_ENSURE_ARG_POINTER(aCount);
     595               0 :   *aCount = 0;
     596                 : 
     597               0 :   PRInt32 rowCount = 0;
     598               0 :   nsresult rv = GetRowCount(&rowCount);
     599               0 :   NS_ENSURE_SUCCESS(rv, rv);
     600                 : 
     601               0 :   PRInt32 columnCount = 0;
     602               0 :   rv = GetColumnCount(&columnCount);
     603               0 :   NS_ENSURE_SUCCESS(rv, rv);
     604                 : 
     605               0 :   nsITableLayout *tableLayout = GetTableLayout();
     606               0 :   NS_ENSURE_STATE(tableLayout);
     607                 : 
     608               0 :   nsCOMPtr<nsIDOMElement> domElement;
     609               0 :   PRInt32 startRowIndex = 0, startColIndex = 0,
     610                 :     rowSpan, colSpan, actualRowSpan, actualColSpan;
     611               0 :   bool isSelected = false;
     612                 : 
     613                 :   PRInt32 rowIndex;
     614               0 :   for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
     615                 :     PRInt32 columnIndex;
     616               0 :     for (columnIndex = 0; columnIndex < columnCount; columnIndex++) {
     617                 :       rv = tableLayout->GetCellDataAt(rowIndex, columnIndex,
     618               0 :                                       *getter_AddRefs(domElement),
     619                 :                                       startRowIndex, startColIndex,
     620                 :                                       rowSpan, colSpan,
     621                 :                                       actualRowSpan, actualColSpan,
     622               0 :                                       isSelected);
     623                 : 
     624               0 :       if (NS_SUCCEEDED(rv) && startRowIndex == rowIndex &&
     625                 :           startColIndex == columnIndex && isSelected) {
     626               0 :         (*aCount)++;
     627                 :       }
     628                 :     }
     629                 :   }
     630                 : 
     631               0 :   return NS_OK;
     632                 : }
     633                 : 
     634                 : NS_IMETHODIMP
     635               0 : nsHTMLTableAccessible::GetSelectedColumnCount(PRUint32* aCount)
     636                 : {
     637               0 :   NS_ENSURE_ARG_POINTER(aCount);
     638               0 :   *aCount = 0;
     639                 : 
     640               0 :   PRInt32 count = 0;
     641               0 :   nsresult rv = GetColumnCount(&count);
     642               0 :   NS_ENSURE_SUCCESS(rv, rv);
     643                 : 
     644                 :   PRInt32 index;
     645               0 :   for (index = 0; index < count; index++) {
     646               0 :     bool state = false;
     647               0 :     rv = IsColumnSelected(index, &state);
     648               0 :     NS_ENSURE_SUCCESS(rv, rv);
     649                 : 
     650               0 :     if (state)
     651               0 :       (*aCount)++;
     652                 :   }
     653                 : 
     654               0 :   return NS_OK;
     655                 : }
     656                 : 
     657                 : NS_IMETHODIMP
     658               0 : nsHTMLTableAccessible::GetSelectedRowCount(PRUint32* aCount)
     659                 : {
     660               0 :   NS_ENSURE_ARG_POINTER(aCount);
     661               0 :   *aCount = 0;
     662                 : 
     663               0 :   PRInt32 count = 0;
     664               0 :   nsresult rv = GetRowCount(&count);
     665               0 :   NS_ENSURE_SUCCESS(rv, rv);
     666                 : 
     667                 :   PRInt32 index;
     668               0 :   for (index = 0; index < count; index++) {
     669               0 :     bool state = false;
     670               0 :     rv = IsRowSelected(index, &state);
     671               0 :     NS_ENSURE_SUCCESS(rv, rv);
     672                 : 
     673               0 :     if (state)
     674               0 :       (*aCount)++;
     675                 :   }
     676                 : 
     677               0 :   return NS_OK;
     678                 : }
     679                 : 
     680                 : NS_IMETHODIMP
     681               0 : nsHTMLTableAccessible::GetSelectedCells(nsIArray **aCells)
     682                 : {
     683               0 :   NS_ENSURE_ARG_POINTER(aCells);
     684               0 :   *aCells = nsnull;
     685                 : 
     686               0 :   PRInt32 rowCount = 0;
     687               0 :   nsresult rv = GetRowCount(&rowCount);
     688               0 :   NS_ENSURE_SUCCESS(rv, rv);
     689                 : 
     690               0 :   PRInt32 columnCount = 0;
     691               0 :   rv = GetColumnCount(&columnCount);
     692               0 :   NS_ENSURE_SUCCESS(rv, rv);
     693                 : 
     694               0 :   nsITableLayout *tableLayout = GetTableLayout();
     695               0 :   NS_ENSURE_STATE(tableLayout);
     696                 : 
     697                 :   nsCOMPtr<nsIMutableArray> selCells =
     698               0 :     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     699               0 :   NS_ENSURE_SUCCESS(rv, rv);
     700                 : 
     701               0 :   nsCOMPtr<nsIDOMElement> cellElement;
     702               0 :   PRInt32 startRowIndex = 0, startColIndex = 0,
     703                 :     rowSpan, colSpan, actualRowSpan, actualColSpan;
     704               0 :   bool isSelected = false;
     705                 : 
     706                 :   PRInt32 rowIndex, index;
     707               0 :   for (rowIndex = 0, index = 0; rowIndex < rowCount; rowIndex++) {
     708                 :     PRInt32 columnIndex;
     709               0 :     for (columnIndex = 0; columnIndex < columnCount; columnIndex++, index++) {
     710                 :       rv = tableLayout->GetCellDataAt(rowIndex, columnIndex,
     711               0 :                                       *getter_AddRefs(cellElement),
     712                 :                                       startRowIndex, startColIndex,
     713                 :                                       rowSpan, colSpan,
     714                 :                                       actualRowSpan, actualColSpan,
     715               0 :                                       isSelected);
     716                 : 
     717               0 :       if (NS_SUCCEEDED(rv) && startRowIndex == rowIndex &&
     718                 :           startColIndex == columnIndex && isSelected) {
     719               0 :         nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
     720               0 :         nsAccessible *cell = mDoc->GetAccessible(cellContent);
     721               0 :         selCells->AppendElement(static_cast<nsIAccessible*>(cell), false);
     722                 :       }
     723                 :     }
     724                 :   }
     725                 : 
     726               0 :   NS_ADDREF(*aCells = selCells);
     727               0 :   return NS_OK;
     728                 : }
     729                 : 
     730                 : NS_IMETHODIMP
     731               0 : nsHTMLTableAccessible::GetSelectedCellIndices(PRUint32 *aNumCells,
     732                 :                                               PRInt32 **aCells)
     733                 : {
     734               0 :   NS_ENSURE_ARG_POINTER(aNumCells);
     735               0 :   *aNumCells = 0;
     736               0 :   NS_ENSURE_ARG_POINTER(aCells);
     737               0 :   *aCells = nsnull;
     738                 : 
     739               0 :   PRInt32 rowCount = 0;
     740               0 :   nsresult rv = GetRowCount(&rowCount);
     741               0 :   NS_ENSURE_SUCCESS(rv, rv);
     742                 : 
     743               0 :   PRInt32 columnCount = 0;
     744               0 :   rv = GetColumnCount(&columnCount);
     745               0 :   NS_ENSURE_SUCCESS(rv, rv);
     746                 : 
     747               0 :   nsITableLayout *tableLayout = GetTableLayout();
     748               0 :   NS_ENSURE_STATE(tableLayout);
     749                 : 
     750               0 :   nsCOMPtr<nsIDOMElement> domElement;
     751               0 :   PRInt32 startRowIndex = 0, startColIndex = 0,
     752                 :     rowSpan, colSpan, actualRowSpan, actualColSpan;
     753               0 :   bool isSelected = false;
     754                 : 
     755               0 :   PRInt32 cellsCount = columnCount * rowCount;
     756               0 :   nsAutoArrayPtr<bool> states(new bool[cellsCount]);
     757               0 :   NS_ENSURE_TRUE(states, NS_ERROR_OUT_OF_MEMORY);
     758                 : 
     759                 :   PRInt32 rowIndex, index;
     760               0 :   for (rowIndex = 0, index = 0; rowIndex < rowCount; rowIndex++) {
     761                 :     PRInt32 columnIndex;
     762               0 :     for (columnIndex = 0; columnIndex < columnCount; columnIndex++, index++) {
     763                 :       rv = tableLayout->GetCellDataAt(rowIndex, columnIndex,
     764               0 :                                       *getter_AddRefs(domElement),
     765                 :                                       startRowIndex, startColIndex,
     766                 :                                       rowSpan, colSpan,
     767                 :                                       actualRowSpan, actualColSpan,
     768               0 :                                       isSelected);
     769                 : 
     770               0 :       if (NS_SUCCEEDED(rv) && startRowIndex == rowIndex &&
     771                 :           startColIndex == columnIndex && isSelected) {
     772               0 :         states[index] = true;
     773               0 :         (*aNumCells)++;
     774                 :       } else {
     775               0 :         states[index] = false;
     776                 :       }
     777                 :     }
     778                 :   }
     779                 : 
     780                 :   PRInt32 *cellsArray =
     781               0 :     static_cast<PRInt32*>(nsMemory::Alloc((*aNumCells) * sizeof(PRInt32)));
     782               0 :   NS_ENSURE_TRUE(cellsArray, NS_ERROR_OUT_OF_MEMORY);
     783                 : 
     784               0 :   PRInt32 curr = 0;
     785               0 :   for (rowIndex = 0, index = 0; rowIndex < rowCount; rowIndex++) {
     786                 :     PRInt32 columnIndex;
     787               0 :     for (columnIndex = 0; columnIndex < columnCount; columnIndex++, index++) {
     788               0 :       if (states[index]) {
     789               0 :         PRInt32 cellIndex = -1;
     790               0 :         GetCellIndexAt(rowIndex, columnIndex, &cellIndex);
     791               0 :         cellsArray[curr++] = cellIndex;
     792                 :       }
     793                 :     }
     794                 :   }
     795                 : 
     796               0 :   *aCells = cellsArray;
     797               0 :   return NS_OK;
     798                 : }
     799                 : 
     800                 : NS_IMETHODIMP
     801               0 : nsHTMLTableAccessible::GetSelectedColumnIndices(PRUint32 *aNumColumns,
     802                 :                                                 PRInt32 **aColumns)
     803                 : {
     804               0 :   nsresult rv = NS_OK;
     805                 : 
     806                 :   PRInt32 columnCount;
     807               0 :   rv = GetColumnCount(&columnCount);
     808               0 :   NS_ENSURE_SUCCESS(rv, rv);
     809                 : 
     810               0 :   bool *states = new bool[columnCount];
     811               0 :   NS_ENSURE_TRUE(states, NS_ERROR_OUT_OF_MEMORY);
     812                 : 
     813               0 :   *aNumColumns = 0;
     814                 :   PRInt32 index;
     815               0 :   for (index = 0; index < columnCount; index++) {
     816               0 :     rv = IsColumnSelected(index, &states[index]);
     817               0 :     NS_ENSURE_SUCCESS(rv, rv);
     818                 : 
     819               0 :     if (states[index]) {
     820               0 :       (*aNumColumns)++;
     821                 :     }
     822                 :   }
     823                 : 
     824               0 :   PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumColumns) * sizeof(PRInt32));
     825               0 :   if (!outArray) {
     826               0 :     delete []states;
     827               0 :     return NS_ERROR_OUT_OF_MEMORY;
     828                 :   }
     829                 : 
     830               0 :   PRInt32 curr = 0;
     831               0 :   for (index = 0; index < columnCount; index++) {
     832               0 :     if (states[index]) {
     833               0 :       outArray[curr++] = index;
     834                 :     }
     835                 :   }
     836                 : 
     837               0 :   delete []states;
     838               0 :   *aColumns = outArray;
     839               0 :   return rv;
     840                 : }
     841                 : 
     842                 : NS_IMETHODIMP
     843               0 : nsHTMLTableAccessible::GetSelectedRowIndices(PRUint32 *aNumRows,
     844                 :                                              PRInt32 **aRows)
     845                 : {
     846               0 :   nsresult rv = NS_OK;
     847                 : 
     848                 :   PRInt32 rowCount;
     849               0 :   rv = GetRowCount(&rowCount);
     850               0 :   NS_ENSURE_SUCCESS(rv, rv);
     851                 : 
     852               0 :   bool *states = new bool[rowCount];
     853               0 :   NS_ENSURE_TRUE(states, NS_ERROR_OUT_OF_MEMORY);
     854                 : 
     855               0 :   *aNumRows = 0;
     856                 :   PRInt32 index;
     857               0 :   for (index = 0; index < rowCount; index++) {
     858               0 :     rv = IsRowSelected(index, &states[index]);
     859               0 :     NS_ENSURE_SUCCESS(rv, rv);
     860                 : 
     861               0 :     if (states[index]) {
     862               0 :       (*aNumRows)++;
     863                 :     }
     864                 :   }
     865                 : 
     866               0 :   PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumRows) * sizeof(PRInt32));
     867               0 :   if (!outArray) {
     868               0 :     delete []states;
     869               0 :     return NS_ERROR_OUT_OF_MEMORY;
     870                 :   }
     871                 : 
     872               0 :   PRInt32 curr = 0;
     873               0 :   for (index = 0; index < rowCount; index++) {
     874               0 :     if (states[index]) {
     875               0 :       outArray[curr++] = index;
     876                 :     }
     877                 :   }
     878                 : 
     879               0 :   delete []states;
     880               0 :   *aRows = outArray;
     881               0 :   return rv;
     882                 : }
     883                 : 
     884                 : NS_IMETHODIMP
     885               0 : nsHTMLTableAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn,
     886                 :                                  nsIAccessible **aTableCellAccessible)
     887                 : {
     888               0 :   nsCOMPtr<nsIDOMElement> cellElement;
     889               0 :   nsresult rv = GetCellAt(aRow, aColumn, *getter_AddRefs(cellElement));
     890               0 :   NS_ENSURE_SUCCESS(rv, rv);
     891                 : 
     892               0 :   nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
     893               0 :   nsAccessible* cell = mDoc->GetAccessible(cellContent);
     894                 : 
     895               0 :   if (!cell) {
     896               0 :     return NS_ERROR_INVALID_ARG;
     897                 :   }
     898                 : 
     899               0 :   if (cell != this) {
     900                 :     // XXX bug 576838: crazy tables (like table6 in tables/test_table2.html) may
     901                 :     // return itself as a cell what makes Orca hang.
     902               0 :     NS_ADDREF(*aTableCellAccessible = cell);
     903                 :   }
     904                 : 
     905               0 :   return NS_OK;
     906                 : }
     907                 : 
     908                 : NS_IMETHODIMP
     909               0 : nsHTMLTableAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn,
     910                 :                                       PRInt32 *aIndex)
     911                 : {
     912               0 :   NS_ENSURE_ARG_POINTER(aIndex);
     913                 : 
     914               0 :   nsITableLayout *tableLayout = GetTableLayout();
     915               0 :   NS_ENSURE_STATE(tableLayout);
     916                 : 
     917               0 :   nsresult rv = tableLayout->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
     918               0 :   if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
     919               0 :     return NS_ERROR_INVALID_ARG;
     920                 : 
     921               0 :   return NS_OK;
     922                 : }
     923                 : 
     924                 : NS_IMETHODIMP
     925               0 : nsHTMLTableAccessible::GetColumnIndexAt(PRInt32 aIndex, PRInt32 *aColumn)
     926                 : {
     927               0 :   NS_ENSURE_ARG_POINTER(aColumn);
     928                 : 
     929               0 :   if (IsDefunct())
     930               0 :     return NS_ERROR_FAILURE;
     931                 : 
     932               0 :   nsITableLayout *tableLayout = GetTableLayout();
     933               0 :   NS_ENSURE_STATE(tableLayout);
     934                 : 
     935                 :   PRInt32 row;
     936               0 :   nsresult rv = tableLayout->GetRowAndColumnByIndex(aIndex, &row, aColumn);
     937               0 :   NS_ENSURE_SUCCESS(rv, rv);
     938                 : 
     939               0 :   return (row == -1 || *aColumn == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
     940                 : }
     941                 : 
     942                 : NS_IMETHODIMP
     943               0 : nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow)
     944                 : {
     945               0 :   NS_ENSURE_ARG_POINTER(aRow);
     946                 : 
     947               0 :   if (IsDefunct())
     948               0 :     return NS_ERROR_FAILURE;
     949                 : 
     950               0 :   nsITableLayout *tableLayout = GetTableLayout();
     951               0 :   NS_ENSURE_STATE(tableLayout);
     952                 : 
     953                 :   PRInt32 column;
     954               0 :   nsresult rv = tableLayout->GetRowAndColumnByIndex(aIndex, aRow, &column);
     955               0 :   NS_ENSURE_SUCCESS(rv, rv);
     956                 : 
     957               0 :   return (*aRow == -1 || column == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
     958                 : }
     959                 : 
     960                 : NS_IMETHODIMP
     961               0 : nsHTMLTableAccessible::GetRowAndColumnIndicesAt(PRInt32 aIndex,
     962                 :                                                 PRInt32* aRowIdx,
     963                 :                                                 PRInt32* aColumnIdx)
     964                 : {
     965               0 :   NS_ENSURE_ARG_POINTER(aRowIdx);
     966               0 :   *aRowIdx = -1;
     967               0 :   NS_ENSURE_ARG_POINTER(aColumnIdx);
     968               0 :   *aColumnIdx = -1;
     969                 : 
     970               0 :   if (IsDefunct())
     971               0 :     return NS_ERROR_FAILURE;
     972                 : 
     973               0 :   nsITableLayout* tableLayout = GetTableLayout();
     974               0 :   if (tableLayout)
     975               0 :     tableLayout->GetRowAndColumnByIndex(aIndex, aRowIdx, aColumnIdx);
     976                 : 
     977               0 :   return (*aRowIdx == -1 || *aColumnIdx == -1) ? NS_ERROR_INVALID_ARG : NS_OK;
     978                 : }
     979                 : 
     980                 : NS_IMETHODIMP
     981               0 : nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
     982                 :                                          PRInt32 aColumnIndex,
     983                 :                                          PRInt32 *aExtentCount)
     984                 : {
     985               0 :   nsITableLayout *tableLayout = GetTableLayout();
     986               0 :   NS_ENSURE_STATE(tableLayout);
     987                 : 
     988               0 :   nsCOMPtr<nsIDOMElement> domElement;
     989                 :   PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan;
     990                 :   bool isSelected;
     991                 : 
     992                 :   nsresult rv = tableLayout->
     993               0 :     GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
     994                 :                   startRowIndex, startColIndex, rowSpan, colSpan,
     995               0 :                   actualRowSpan, *aExtentCount, isSelected);
     996                 : 
     997               0 :   return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
     998                 : }
     999                 : 
    1000                 : NS_IMETHODIMP
    1001               0 : nsHTMLTableAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
    1002                 :                                       PRInt32 *aExtentCount)
    1003                 : {
    1004               0 :   nsITableLayout *tableLayout = GetTableLayout();
    1005               0 :   NS_ENSURE_STATE(tableLayout);
    1006                 : 
    1007               0 :   nsCOMPtr<nsIDOMElement> domElement;
    1008                 :   PRInt32 startRowIndex, startColIndex, rowSpan, colSpan, actualColSpan;
    1009                 :   bool isSelected;
    1010                 : 
    1011                 :   nsresult rv = tableLayout->
    1012               0 :     GetCellDataAt(aRowIndex, aColumnIndex, *getter_AddRefs(domElement),
    1013                 :                   startRowIndex, startColIndex, rowSpan, colSpan,
    1014               0 :                   *aExtentCount, actualColSpan, isSelected);
    1015                 : 
    1016               0 :   return (rv == NS_TABLELAYOUT_CELL_NOT_FOUND) ? NS_ERROR_INVALID_ARG : NS_OK;
    1017                 : }
    1018                 : 
    1019                 : NS_IMETHODIMP
    1020               0 : nsHTMLTableAccessible::GetColumnDescription(PRInt32 aColumn, nsAString &_retval)
    1021                 : {
    1022               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1023                 : }
    1024                 : 
    1025                 : NS_IMETHODIMP
    1026               0 : nsHTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString &_retval)
    1027                 : {
    1028               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1029                 : }
    1030                 : 
    1031                 : NS_IMETHODIMP
    1032               0 : nsHTMLTableAccessible::IsColumnSelected(PRInt32 aColumn, bool *aIsSelected)
    1033                 : {
    1034               0 :   NS_ENSURE_ARG_POINTER(aIsSelected);
    1035               0 :   *aIsSelected = false;
    1036                 : 
    1037               0 :   PRInt32 colCount = 0;
    1038               0 :   nsresult rv = GetColumnCount(&colCount);
    1039               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1040                 : 
    1041               0 :   if (aColumn < 0 || aColumn >= colCount)
    1042               0 :     return NS_ERROR_INVALID_ARG;
    1043                 : 
    1044               0 :   PRInt32 rowCount = 0;
    1045               0 :   rv = GetRowCount(&rowCount);
    1046               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1047                 : 
    1048               0 :   for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    1049               0 :     bool isSelected = false;
    1050               0 :     rv = IsCellSelected(rowIdx, aColumn, &isSelected);
    1051               0 :     if (NS_SUCCEEDED(rv)) {
    1052               0 :       *aIsSelected = isSelected;
    1053               0 :       if (!isSelected)
    1054               0 :         break;
    1055                 :     }
    1056                 :   }
    1057                 : 
    1058               0 :   return NS_OK;
    1059                 : }
    1060                 : 
    1061                 : NS_IMETHODIMP
    1062               0 : nsHTMLTableAccessible::IsRowSelected(PRInt32 aRow, bool *aIsSelected)
    1063                 : {
    1064               0 :   NS_ENSURE_ARG_POINTER(aIsSelected);
    1065               0 :   *aIsSelected = false;
    1066                 : 
    1067               0 :   PRInt32 rowCount = 0;
    1068               0 :   nsresult rv = GetRowCount(&rowCount);
    1069               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1070                 : 
    1071               0 :   if (aRow < 0 || aRow >= rowCount)
    1072               0 :     return NS_ERROR_INVALID_ARG;
    1073                 : 
    1074               0 :   PRInt32 colCount = 0;
    1075               0 :   rv = GetColumnCount(&colCount);
    1076               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1077                 : 
    1078               0 :   for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++) {
    1079               0 :     bool isSelected = false;
    1080               0 :     rv = IsCellSelected(aRow, colIdx, &isSelected);
    1081               0 :     if (NS_SUCCEEDED(rv)) {
    1082               0 :       *aIsSelected = isSelected;
    1083               0 :       if (!isSelected)
    1084               0 :         break;
    1085                 :     }
    1086                 :   }
    1087                 : 
    1088               0 :   return NS_OK;
    1089                 : }
    1090                 : 
    1091                 : NS_IMETHODIMP
    1092               0 : nsHTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
    1093                 :                                       bool *aIsSelected)
    1094                 : {
    1095               0 :   NS_ENSURE_ARG_POINTER(aIsSelected);
    1096               0 :   *aIsSelected = false;
    1097                 : 
    1098               0 :   nsITableLayout *tableLayout = GetTableLayout();
    1099               0 :   NS_ENSURE_STATE(tableLayout);
    1100                 : 
    1101               0 :   nsCOMPtr<nsIDOMElement> domElement;
    1102               0 :   PRInt32 startRowIndex = 0, startColIndex = 0,
    1103                 :           rowSpan, colSpan, actualRowSpan, actualColSpan;
    1104                 : 
    1105                 :   nsresult rv = tableLayout->
    1106               0 :     GetCellDataAt(aRow, aColumn, *getter_AddRefs(domElement),
    1107                 :                   startRowIndex, startColIndex, rowSpan, colSpan,
    1108               0 :                   actualRowSpan, actualColSpan, *aIsSelected);
    1109                 : 
    1110               0 :   if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
    1111               0 :     return NS_ERROR_INVALID_ARG;
    1112               0 :   return rv;
    1113                 : }
    1114                 : 
    1115                 : NS_IMETHODIMP
    1116               0 : nsHTMLTableAccessible::SelectRow(PRInt32 aRow)
    1117                 : {
    1118               0 :   if (IsDefunct())
    1119               0 :     return NS_ERROR_FAILURE;
    1120                 : 
    1121                 :   nsresult rv =
    1122                 :     RemoveRowsOrColumnsFromSelection(aRow,
    1123                 :                                      nsISelectionPrivate::TABLESELECTION_ROW,
    1124               0 :                                      true);
    1125               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1126                 : 
    1127                 :   return AddRowOrColumnToSelection(aRow,
    1128               0 :                                    nsISelectionPrivate::TABLESELECTION_ROW);
    1129                 : }
    1130                 : 
    1131                 : NS_IMETHODIMP
    1132               0 : nsHTMLTableAccessible::SelectColumn(PRInt32 aColumn)
    1133                 : {
    1134               0 :   if (IsDefunct())
    1135               0 :     return NS_ERROR_FAILURE;
    1136                 : 
    1137                 :   nsresult rv =
    1138                 :     RemoveRowsOrColumnsFromSelection(aColumn,
    1139                 :                                      nsISelectionPrivate::TABLESELECTION_COLUMN,
    1140               0 :                                      true);
    1141               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1142                 : 
    1143                 :   return AddRowOrColumnToSelection(aColumn,
    1144               0 :                                    nsISelectionPrivate::TABLESELECTION_COLUMN);
    1145                 : }
    1146                 : 
    1147                 : NS_IMETHODIMP
    1148               0 : nsHTMLTableAccessible::UnselectRow(PRInt32 aRow)
    1149                 : {
    1150               0 :   if (IsDefunct())
    1151               0 :     return NS_ERROR_FAILURE;
    1152                 : 
    1153                 :   return
    1154                 :     RemoveRowsOrColumnsFromSelection(aRow,
    1155                 :                                      nsISelectionPrivate::TABLESELECTION_ROW,
    1156               0 :                                      false);
    1157                 : }
    1158                 : 
    1159                 : NS_IMETHODIMP
    1160               0 : nsHTMLTableAccessible::UnselectColumn(PRInt32 aColumn)
    1161                 : {
    1162               0 :   if (IsDefunct())
    1163               0 :     return NS_ERROR_FAILURE;
    1164                 : 
    1165                 :   return
    1166                 :     RemoveRowsOrColumnsFromSelection(aColumn,
    1167                 :                                      nsISelectionPrivate::TABLESELECTION_COLUMN,
    1168               0 :                                      false);
    1169                 : }
    1170                 : 
    1171                 : nsresult
    1172               0 : nsHTMLTableAccessible::AddRowOrColumnToSelection(PRInt32 aIndex,
    1173                 :                                                  PRUint32 aTarget)
    1174                 : {
    1175               0 :   bool doSelectRow = (aTarget == nsISelectionPrivate::TABLESELECTION_ROW);
    1176                 : 
    1177               0 :   nsITableLayout *tableLayout = GetTableLayout();
    1178               0 :   NS_ENSURE_STATE(tableLayout);
    1179                 : 
    1180               0 :   nsCOMPtr<nsIDOMElement> cellElm;
    1181                 :   PRInt32 startRowIdx, startColIdx, rowSpan, colSpan,
    1182                 :     actualRowSpan, actualColSpan;
    1183               0 :   bool isSelected = false;
    1184                 : 
    1185               0 :   nsresult rv = NS_OK;
    1186               0 :   PRInt32 count = 0;
    1187               0 :   if (doSelectRow)
    1188               0 :     rv = GetColumnCount(&count);
    1189                 :   else
    1190               0 :     rv = GetRowCount(&count);
    1191                 : 
    1192               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1193                 : 
    1194               0 :   nsIPresShell* presShell(mDoc->PresShell());
    1195                 :   nsRefPtr<nsFrameSelection> tableSelection =
    1196               0 :     const_cast<nsFrameSelection*>(presShell->ConstFrameSelection());
    1197                 : 
    1198               0 :   for (PRInt32 idx = 0; idx < count; idx++) {
    1199               0 :     PRInt32 rowIdx = doSelectRow ? aIndex : idx;
    1200               0 :     PRInt32 colIdx = doSelectRow ? idx : aIndex;
    1201                 :     rv = tableLayout->GetCellDataAt(rowIdx, colIdx,
    1202               0 :                                     *getter_AddRefs(cellElm),
    1203                 :                                     startRowIdx, startColIdx,
    1204                 :                                     rowSpan, colSpan,
    1205                 :                                     actualRowSpan, actualColSpan,
    1206               0 :                                     isSelected);      
    1207                 : 
    1208               0 :     if (NS_SUCCEEDED(rv) && !isSelected) {
    1209               0 :       nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElm));
    1210               0 :       rv = tableSelection->SelectCellElement(cellContent);
    1211               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1212                 :     }
    1213                 :   }
    1214                 : 
    1215               0 :   return NS_OK;
    1216                 : }
    1217                 : 
    1218                 : nsresult
    1219               0 : nsHTMLTableAccessible::RemoveRowsOrColumnsFromSelection(PRInt32 aIndex,
    1220                 :                                                         PRUint32 aTarget,
    1221                 :                                                         bool aIsOuter)
    1222                 : {
    1223               0 :   nsITableLayout *tableLayout = GetTableLayout();
    1224               0 :   NS_ENSURE_STATE(tableLayout);
    1225                 : 
    1226               0 :   nsIPresShell* presShell(mDoc->PresShell());
    1227                 :   nsRefPtr<nsFrameSelection> tableSelection =
    1228               0 :     const_cast<nsFrameSelection*>(presShell->ConstFrameSelection());
    1229                 : 
    1230               0 :   bool doUnselectRow = (aTarget == nsISelectionPrivate::TABLESELECTION_ROW);
    1231               0 :   PRInt32 count = 0;
    1232               0 :   nsresult rv = doUnselectRow ? GetColumnCount(&count) : GetRowCount(&count);
    1233               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1234                 : 
    1235               0 :   PRInt32 startRowIdx = doUnselectRow ? aIndex : 0;
    1236               0 :   PRInt32 endRowIdx = doUnselectRow ? aIndex : count - 1;
    1237               0 :   PRInt32 startColIdx = doUnselectRow ? 0 : aIndex;
    1238               0 :   PRInt32 endColIdx = doUnselectRow ? count - 1 : aIndex;
    1239                 : 
    1240               0 :   if (aIsOuter)
    1241               0 :     return tableSelection->RestrictCellsToSelection(mContent,
    1242                 :                                                     startRowIdx, startColIdx, 
    1243               0 :                                                     endRowIdx, endColIdx);
    1244                 : 
    1245               0 :   return tableSelection->RemoveCellsFromSelection(mContent,
    1246                 :                                                   startRowIdx, startColIdx, 
    1247               0 :                                                   endRowIdx, endColIdx);
    1248                 : }
    1249                 : 
    1250                 : nsITableLayout*
    1251               0 : nsHTMLTableAccessible::GetTableLayout()
    1252                 : {
    1253               0 :   nsIFrame *frame = mContent->GetPrimaryFrame();
    1254               0 :   if (!frame)
    1255               0 :     return nsnull;
    1256                 : 
    1257               0 :   nsITableLayout *tableLayout = do_QueryFrame(frame);
    1258               0 :   return tableLayout;
    1259                 : }
    1260                 : 
    1261                 : nsresult
    1262               0 : nsHTMLTableAccessible::GetCellAt(PRInt32        aRowIndex,
    1263                 :                                  PRInt32        aColIndex,
    1264                 :                                  nsIDOMElement* &aCell)
    1265                 : {
    1266               0 :   PRInt32 startRowIndex = 0, startColIndex = 0,
    1267                 :           rowSpan, colSpan, actualRowSpan, actualColSpan;
    1268                 :   bool isSelected;
    1269                 : 
    1270               0 :   nsITableLayout *tableLayout = GetTableLayout();
    1271               0 :   NS_ENSURE_STATE(tableLayout);
    1272                 : 
    1273                 :   nsresult rv = tableLayout->
    1274                 :     GetCellDataAt(aRowIndex, aColIndex, aCell, startRowIndex, startColIndex,
    1275               0 :                   rowSpan, colSpan, actualRowSpan, actualColSpan, isSelected);
    1276                 : 
    1277               0 :   if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
    1278               0 :     return NS_ERROR_INVALID_ARG;
    1279               0 :   return rv;
    1280                 : }
    1281                 : 
    1282                 : void
    1283               0 : nsHTMLTableAccessible::Description(nsString& aDescription)
    1284                 : {
    1285                 :   // Helpful for debugging layout vs. data tables
    1286               0 :   aDescription.Truncate();
    1287               0 :   nsAccessible::Description(aDescription);
    1288               0 :   if (!aDescription.IsEmpty())
    1289               0 :     return;
    1290                 : 
    1291                 :   // Use summary as description if it weren't used as a name.
    1292                 :   // XXX: get rid code duplication with NameInternal().
    1293               0 :   nsAccessible* caption = Caption();
    1294               0 :   if (caption) {
    1295               0 :     nsIContent* captionContent = caption->GetContent();
    1296               0 :     if (captionContent) {
    1297               0 :       nsAutoString captionText;
    1298                 :       nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent,
    1299               0 :                                                    &captionText);
    1300                 : 
    1301               0 :       if (!captionText.IsEmpty()) { // summary isn't used as a name.
    1302               0 :         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
    1303               0 :                           aDescription);
    1304                 :       }
    1305                 :     }
    1306                 :   }
    1307                 : 
    1308                 : #ifdef SHOW_LAYOUT_HEURISTIC
    1309                 :   if (aDescription.IsEmpty()) {
    1310                 :     bool isProbablyForLayout;
    1311                 :     IsProbablyForLayout(&isProbablyForLayout);
    1312                 :     aDescription = mLayoutHeuristic;
    1313                 :   }
    1314                 : #ifdef DEBUG_A11Y
    1315                 :   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
    1316                 : #endif
    1317                 : #endif
    1318                 : }
    1319                 : 
    1320                 : bool
    1321               0 : nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
    1322                 :                                      bool aAllowEmpty)
    1323                 : {
    1324               0 :   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
    1325               0 :   NS_ENSURE_TRUE(tableElt, false);
    1326                 : 
    1327               0 :   nsCOMPtr<nsIDOMNodeList> nodeList;
    1328               0 :   tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
    1329               0 :   NS_ENSURE_TRUE(nodeList, false);
    1330                 : 
    1331               0 :   nsCOMPtr<nsIDOMNode> foundItem;
    1332               0 :   nodeList->Item(0, getter_AddRefs(foundItem));
    1333               0 :   if (!foundItem)
    1334               0 :     return false;
    1335                 : 
    1336               0 :   if (aAllowEmpty)
    1337               0 :     return true;
    1338                 : 
    1339                 :   // Make sure that the item we found has contents and either has multiple
    1340                 :   // children or the found item is not a whitespace-only text node.
    1341               0 :   nsCOMPtr<nsIContent> foundItemContent = do_QueryInterface(foundItem);
    1342               0 :   if (foundItemContent->GetChildCount() > 1)
    1343               0 :     return true; // Treat multiple child nodes as non-empty
    1344                 : 
    1345               0 :   nsIContent *innerItemContent = foundItemContent->GetFirstChild();
    1346               0 :   if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
    1347               0 :     return true;
    1348                 : 
    1349                 :   // If we found more than one node then return true not depending on
    1350                 :   // aAllowEmpty flag.
    1351                 :   // XXX it might be dummy but bug 501375 where we changed this addresses
    1352                 :   // performance problems only. Note, currently 'aAllowEmpty' flag is used for
    1353                 :   // caption element only. On another hand we create accessible object for
    1354                 :   // the first entry of caption element (see
    1355                 :   // nsHTMLTableAccessible::CacheChildren).
    1356               0 :   nodeList->Item(1, getter_AddRefs(foundItem));
    1357               0 :   return !!foundItem;
    1358                 : }
    1359                 : 
    1360                 : NS_IMETHODIMP
    1361               0 : nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
    1362                 : {
    1363                 :   // Implement a heuristic to determine if table is most likely used for layout
    1364                 :   // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
    1365                 :   // at the beginning or end of a row/col, and especially when they occur at the edge of a table?
    1366                 :   // XXX expose this info via object attributes to AT-SPI
    1367                 : 
    1368                 :   // XXX For now debugging descriptions are always on via SHOW_LAYOUT_HEURISTIC
    1369                 :   // This will allow release trunk builds to be used by testers to refine the algorithm
    1370                 :   // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
    1371                 : #ifdef SHOW_LAYOUT_HEURISTIC
    1372                 : #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
    1373                 :   { *aIsProbablyForLayout = isLayout; \
    1374                 :     mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
    1375                 :     mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
    1376                 : #else
    1377                 : #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
    1378                 : #endif
    1379                 : 
    1380               0 :   *aIsProbablyForLayout = false;
    1381                 : 
    1382               0 :   if (IsDefunct())
    1383               0 :     return NS_ERROR_FAILURE;
    1384                 : 
    1385               0 :   nsDocAccessible* docAccessible = Document();
    1386               0 :   if (docAccessible) {
    1387               0 :     PRUint64 docState = docAccessible->State();
    1388               0 :     if (docState & states::EDITABLE) {  // Need to see all elements while document is being edited
    1389               0 :       RETURN_LAYOUT_ANSWER(false, "In editable document");
    1390                 :     }
    1391                 :   }
    1392                 : 
    1393                 :   // Check to see if an ARIA role overrides the role from native markup,
    1394                 :   // but for which we still expose table semantics (treegrid, for example).
    1395               0 :   if (Role() != roles::TABLE) 
    1396               0 :     RETURN_LAYOUT_ANSWER(false, "Has role attribute");
    1397                 : 
    1398               0 :   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
    1399                 :     // Role attribute is present, but overridden roles have already been dealt with.
    1400                 :     // Only landmarks and other roles that don't override the role from native
    1401                 :     // markup are left to deal with here.
    1402               0 :     RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
    1403                 :   }
    1404                 : 
    1405               0 :   if (mContent->Tag() != nsGkAtoms::table)
    1406               0 :     RETURN_LAYOUT_ANSWER(true, "table built by CSS display:table style");
    1407                 : 
    1408                 :   // Check if datatable attribute has "0" value.
    1409               0 :   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,
    1410               0 :                             NS_LITERAL_STRING("0"), eCaseMatters)) {
    1411               0 :     RETURN_LAYOUT_ANSWER(true, "Has datatable = 0 attribute, it's for layout");
    1412                 :   }
    1413                 : 
    1414                 :   // Check for legitimate data table attributes.
    1415               0 :   nsAutoString summary;
    1416               0 :   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
    1417               0 :       !summary.IsEmpty())
    1418               0 :     RETURN_LAYOUT_ANSWER(false, "Has summary -- legitimate table structures");
    1419                 : 
    1420                 :   // Check for legitimate data table elements.
    1421               0 :   nsAccessible* caption = FirstChild();
    1422               0 :   if (caption && caption->Role() == roles::CAPTION && caption->HasChildren()) 
    1423               0 :     RETURN_LAYOUT_ANSWER(false, "Not empty caption -- legitimate table structures");
    1424                 : 
    1425               0 :   for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
    1426               0 :        childElm = childElm->GetNextSibling()) {
    1427               0 :     if (!childElm->IsHTML())
    1428               0 :       continue;
    1429                 : 
    1430               0 :     if (childElm->Tag() == nsGkAtoms::col ||
    1431               0 :         childElm->Tag() == nsGkAtoms::colgroup ||
    1432               0 :         childElm->Tag() == nsGkAtoms::tfoot ||
    1433               0 :         childElm->Tag() == nsGkAtoms::thead) {
    1434               0 :       RETURN_LAYOUT_ANSWER(false,
    1435                 :                            "Has col, colgroup, tfoot or thead -- legitimate table structures");
    1436                 :     }
    1437                 : 
    1438               0 :     if (childElm->Tag() == nsGkAtoms::tbody) {
    1439               0 :       for (nsIContent* rowElm = childElm->GetFirstChild(); rowElm;
    1440               0 :            rowElm = rowElm->GetNextSibling()) {
    1441               0 :         if (rowElm->IsHTML() && rowElm->Tag() == nsGkAtoms::tr) {
    1442               0 :           for (nsIContent* cellElm = rowElm->GetFirstChild(); cellElm;
    1443               0 :                cellElm = cellElm->GetNextSibling()) {
    1444               0 :             if (cellElm->IsHTML()) {
    1445                 :               
    1446               0 :               if (cellElm->NodeInfo()->Equals(nsGkAtoms::th)) {
    1447               0 :                 RETURN_LAYOUT_ANSWER(false,
    1448                 :                                      "Has th -- legitimate table structures");
    1449                 :               }
    1450                 : 
    1451               0 :               if (cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::headers) ||
    1452               0 :                   cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::scope) ||
    1453               0 :                   cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::abbr)) {
    1454               0 :                 RETURN_LAYOUT_ANSWER(false,
    1455                 :                                      "Has headers, scope, or abbr attribute -- legitimate table structures");
    1456                 :               }
    1457                 : 
    1458               0 :               nsAccessible* cell = mDoc->GetAccessible(cellElm);
    1459               0 :               if (cell && cell->GetChildCount() == 1 &&
    1460               0 :                   cell->FirstChild()->IsAbbreviation()) {
    1461               0 :                 RETURN_LAYOUT_ANSWER(false,
    1462                 :                                      "has abbr -- legitimate table structures");
    1463                 :               }
    1464                 :             }
    1465                 :           }
    1466                 :         }
    1467                 :       }
    1468                 :     }
    1469                 :   }
    1470                 : 
    1471               0 :   if (HasDescendant(NS_LITERAL_STRING("table"))) {
    1472               0 :     RETURN_LAYOUT_ANSWER(true, "Has a nested table within it");
    1473                 :   }
    1474                 : 
    1475                 :   // If only 1 column or only 1 row, it's for layout
    1476                 :   PRInt32 columns, rows;
    1477               0 :   GetColumnCount(&columns);
    1478               0 :   if (columns <=1) {
    1479               0 :     RETURN_LAYOUT_ANSWER(true, "Has only 1 column");
    1480                 :   }
    1481               0 :   GetRowCount(&rows);
    1482               0 :   if (rows <=1) {
    1483               0 :     RETURN_LAYOUT_ANSWER(true, "Has only 1 row");
    1484                 :   }
    1485                 : 
    1486                 :   // Check for many columns
    1487               0 :   if (columns >= 5) {
    1488               0 :     RETURN_LAYOUT_ANSWER(false, ">=5 columns");
    1489                 :   }
    1490                 : 
    1491                 :   // Now we know there are 2-4 columns and 2 or more rows
    1492                 :   // Check to see if there are visible borders on the cells
    1493                 :   // XXX currently, we just check the first cell -- do we really need to do more?
    1494               0 :   nsCOMPtr<nsIDOMElement> cellElement;
    1495               0 :   nsresult rv = GetCellAt(0, 0, *getter_AddRefs(cellElement));
    1496               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1497                 : 
    1498               0 :   nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
    1499               0 :   NS_ENSURE_TRUE(cellContent, NS_ERROR_FAILURE);
    1500               0 :   nsIFrame *cellFrame = cellContent->GetPrimaryFrame();
    1501               0 :   if (!cellFrame) {
    1502               0 :     return NS_OK;
    1503                 :   }
    1504               0 :   nsMargin border;
    1505               0 :   cellFrame->GetBorder(border);
    1506               0 :   if (border.top && border.bottom && border.left && border.right) {
    1507               0 :     RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
    1508                 :   }
    1509                 : 
    1510                 :   /**
    1511                 :    * Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
    1512                 :    */
    1513                 : 
    1514                 :   // Check for styled background color across rows (alternating background
    1515                 :   // color is a common feature for data tables).
    1516               0 :   PRUint32 childCount = GetChildCount();
    1517                 :   nscolor rowColor, prevRowColor;
    1518               0 :   for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
    1519               0 :     nsAccessible* child = GetChildAt(childIdx);
    1520               0 :     if (child->Role() == roles::ROW) {
    1521               0 :       prevRowColor = rowColor;
    1522               0 :       nsIFrame* rowFrame = child->GetFrame();
    1523               0 :       rowColor = rowFrame->GetStyleBackground()->mBackgroundColor;
    1524                 : 
    1525               0 :       if (childIdx > 0 && prevRowColor != rowColor)
    1526               0 :         RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
    1527                 :     }
    1528                 :   }
    1529                 : 
    1530                 :   // Check for many rows
    1531               0 :   const PRInt32 kMaxLayoutRows = 20;
    1532               0 :   if (rows > kMaxLayoutRows) { // A ton of rows, this is probably for data
    1533               0 :     RETURN_LAYOUT_ANSWER(false, ">= kMaxLayoutRows (20) and non-bordered");
    1534                 :   }
    1535                 : 
    1536                 :   // Check for very wide table.
    1537               0 :   nsIFrame* documentFrame = Document()->GetFrame();
    1538               0 :   nsSize documentSize = documentFrame->GetSize();
    1539               0 :   if (documentSize.width > 0) {
    1540               0 :     nsSize tableSize = GetFrame()->GetSize();
    1541               0 :     PRInt32 percentageOfDocWidth = (100 * tableSize.width) / documentSize.width;
    1542               0 :     if (percentageOfDocWidth > 95) {
    1543                 :       // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
    1544                 :       // Probably for layout
    1545               0 :       RETURN_LAYOUT_ANSWER(true,
    1546                 :                            "<= 4 columns, table width is 95% of document width");
    1547                 :     }
    1548                 :   }
    1549                 : 
    1550                 :   // Two column rules
    1551               0 :   if (rows * columns <= 10) {
    1552               0 :     RETURN_LAYOUT_ANSWER(true, "2-4 columns, 10 cells or less, non-bordered");
    1553                 :   }
    1554                 : 
    1555               0 :   if (HasDescendant(NS_LITERAL_STRING("embed")) ||
    1556               0 :       HasDescendant(NS_LITERAL_STRING("object")) ||
    1557               0 :       HasDescendant(NS_LITERAL_STRING("applet")) ||
    1558               0 :       HasDescendant(NS_LITERAL_STRING("iframe"))) {
    1559               0 :     RETURN_LAYOUT_ANSWER(true, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
    1560                 :   }
    1561                 : 
    1562               0 :   RETURN_LAYOUT_ANSWER(false, "no layout factor strong enough, so will guess data");
    1563                 : }
    1564                 : 
    1565                 : 
    1566                 : ////////////////////////////////////////////////////////////////////////////////
    1567                 : // nsHTMLCaptionAccessible
    1568                 : ////////////////////////////////////////////////////////////////////////////////
    1569                 : 
    1570                 : Relation
    1571               0 : nsHTMLCaptionAccessible::RelationByType(PRUint32 aType)
    1572                 : {
    1573               0 :   Relation rel = nsHyperTextAccessible::RelationByType(aType);
    1574               0 :   if (aType == nsIAccessibleRelation::RELATION_LABEL_FOR)
    1575               0 :     rel.AppendTarget(Parent());
    1576                 : 
    1577                 :   return rel;
    1578                 : }
    1579                 : 
    1580                 : role
    1581               0 : nsHTMLCaptionAccessible::NativeRole()
    1582                 : {
    1583               0 :   return roles::CAPTION;
    1584                 : }

Generated by: LCOV version 1.7