LCOV - code coverage report
Current view: directory - content/html/content/src - nsHTMLTableElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 530 4 0.8 %
Date: 2012-06-02 Functions: 87 3 3.4 %

       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 Communicator client 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                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "mozilla/Util.h"
      39                 : 
      40                 : #include "nsHTMLTableElement.h"
      41                 : #include "nsIDOMHTMLTableCaptionElem.h"
      42                 : #include "nsIDOMHTMLTableSectionElem.h"
      43                 : #include "nsCOMPtr.h"
      44                 : #include "nsIDOMEventTarget.h"
      45                 : #include "nsDOMError.h"
      46                 : #include "nsContentList.h"
      47                 : #include "nsGenericHTMLElement.h"
      48                 : #include "nsGkAtoms.h"
      49                 : #include "nsStyleConsts.h"
      50                 : #include "nsPresContext.h"
      51                 : #include "nsHTMLParts.h"
      52                 : #include "nsRuleData.h"
      53                 : #include "nsStyleContext.h"
      54                 : #include "nsIDocument.h"
      55                 : #include "nsContentUtils.h"
      56                 : #include "nsIDOMElement.h"
      57                 : #include "nsGenericHTMLElement.h"
      58                 : #include "nsIHTMLCollection.h"
      59                 : #include "nsHTMLStyleSheet.h"
      60                 : #include "dombindings.h"
      61                 : 
      62                 : using namespace mozilla;
      63                 : 
      64                 : /* ------------------------------ TableRowsCollection -------------------------------- */
      65                 : /**
      66                 :  * This class provides a late-bound collection of rows in a table.
      67                 :  * mParent is NOT ref-counted to avoid circular references
      68                 :  */
      69                 : class TableRowsCollection : public nsIHTMLCollection,
      70                 :                             public nsWrapperCache
      71                 : {
      72                 : public:
      73                 :   TableRowsCollection(nsHTMLTableElement *aParent);
      74                 :   virtual ~TableRowsCollection();
      75                 : 
      76               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      77                 :   NS_DECL_NSIDOMHTMLCOLLECTION
      78                 : 
      79               0 :   virtual nsINode* GetParentObject()
      80                 :   {
      81               0 :     return mParent;
      82                 :   }
      83                 : 
      84                 :   NS_IMETHOD    ParentDestroyed();
      85                 : 
      86            1464 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TableRowsCollection)
      87                 : 
      88                 :   // nsWrapperCache
      89               0 :   virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
      90                 :                                bool *triedToWrap)
      91                 :   {
      92                 :     return mozilla::dom::binding::HTMLCollection::create(cx, scope, this,
      93               0 :                                                          triedToWrap);
      94                 :   }
      95                 : 
      96                 : protected:
      97                 :   // Those rows that are not in table sections
      98                 :   nsHTMLTableElement* mParent;
      99                 :   nsRefPtr<nsContentList> mOrphanRows;  
     100                 : };
     101                 : 
     102                 : 
     103               0 : TableRowsCollection::TableRowsCollection(nsHTMLTableElement *aParent)
     104                 :   : mParent(aParent)
     105                 :   , mOrphanRows(new nsContentList(mParent,
     106                 :                                   kNameSpaceID_XHTML,
     107                 :                                   nsGkAtoms::tr,
     108                 :                                   nsGkAtoms::tr,
     109               0 :                                   false))
     110                 : {
     111                 :   // Mark ourselves as a proxy
     112               0 :   SetIsProxy();
     113               0 : }
     114                 : 
     115               0 : TableRowsCollection::~TableRowsCollection()
     116                 : {
     117                 :   // we do NOT have a ref-counted reference to mParent, so do NOT
     118                 :   // release it!  this is to avoid circular references.  The
     119                 :   // instantiator who provided mParent is responsible for managing our
     120                 :   // reference for us.
     121               0 : }
     122                 : 
     123            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
     124               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TableRowsCollection)
     125               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     126               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOrphanRows)
     127               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     128               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TableRowsCollection)
     129               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mOrphanRows,
     130                 :                                                        nsIDOMNodeList)
     131               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     132               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     133               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TableRowsCollection)
     134               0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     135               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     136                 : 
     137               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TableRowsCollection)
     138               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TableRowsCollection)
     139                 : 
     140               0 : NS_INTERFACE_TABLE_HEAD(TableRowsCollection)
     141               0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     142               0 :   NS_INTERFACE_TABLE2(TableRowsCollection, nsIHTMLCollection,
     143                 :                       nsIDOMHTMLCollection)
     144               0 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(TableRowsCollection)
     145               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLCollection)
     146               0 : NS_INTERFACE_MAP_END
     147                 : 
     148                 : // Macro that can be used to avoid copy/pasting code to iterate over the
     149                 : // rowgroups.  _code should be the code to execute for each rowgroup.  The
     150                 : // rowgroup's rows will be in the nsIDOMHTMLCollection* named "rows".  Note
     151                 : // that this may be null at any time.  This macro assumes an nsresult named
     152                 : // |rv| is in scope.
     153                 : #define DO_FOR_EACH_ROWGROUP(_code)                                  \
     154                 :   do {                                                               \
     155                 :     if (mParent) {                                                   \
     156                 :       /* THead */                                                    \
     157                 :       nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;              \
     158                 :       rowGroup = mParent->GetTHead();                                \
     159                 :       nsCOMPtr<nsIDOMHTMLCollection> rows;                           \
     160                 :       if (rowGroup) {                                                \
     161                 :         rowGroup->GetRows(getter_AddRefs(rows));                     \
     162                 :         do { /* gives scoping */                                     \
     163                 :           _code                                                      \
     164                 :         } while (0);                                                 \
     165                 :       }                                                              \
     166                 :       /* TBodies */                                                  \
     167                 :       nsContentList *_tbodies = mParent->TBodies();                  \
     168                 :       nsINode * _node;                                               \
     169                 :       PRUint32 _tbodyIndex = 0;                                      \
     170                 :       _node = _tbodies->GetNodeAt(_tbodyIndex);                      \
     171                 :       while (_node) {                                                \
     172                 :         rowGroup = do_QueryInterface(_node);                         \
     173                 :         if (rowGroup) {                                              \
     174                 :           rowGroup->GetRows(getter_AddRefs(rows));                   \
     175                 :           do { /* gives scoping */                                   \
     176                 :             _code                                                    \
     177                 :           } while (0);                                               \
     178                 :         }                                                            \
     179                 :         _node = _tbodies->GetNodeAt(++_tbodyIndex);                  \
     180                 :       }                                                              \
     181                 :       /* orphan rows */                                              \
     182                 :       rows = mOrphanRows;                                            \
     183                 :       do { /* gives scoping */                                       \
     184                 :         _code                                                        \
     185                 :       } while (0);                                                   \
     186                 :       /* TFoot */                                                    \
     187                 :       rowGroup = mParent->GetTFoot();                                \
     188                 :       rows = nsnull;                                                 \
     189                 :       if (rowGroup) {                                                \
     190                 :         rowGroup->GetRows(getter_AddRefs(rows));                     \
     191                 :         do { /* gives scoping */                                     \
     192                 :           _code                                                      \
     193                 :         } while (0);                                                 \
     194                 :       }                                                              \
     195                 :     }                                                                \
     196                 :   } while (0)
     197                 : 
     198                 : static PRUint32
     199               0 : CountRowsInRowGroup(nsIDOMHTMLCollection* rows)
     200                 : {
     201               0 :   PRUint32 length = 0;
     202                 :   
     203               0 :   if (rows) {
     204               0 :     rows->GetLength(&length);
     205                 :   }
     206                 :   
     207               0 :   return length;
     208                 : }
     209                 : 
     210                 : // we re-count every call.  A better implementation would be to set
     211                 : // ourselves up as an observer of contentAppended, contentInserted,
     212                 : // and contentDeleted
     213                 : NS_IMETHODIMP 
     214               0 : TableRowsCollection::GetLength(PRUint32* aLength)
     215                 : {
     216               0 :   *aLength=0;
     217                 : 
     218               0 :   DO_FOR_EACH_ROWGROUP(
     219                 :     *aLength += CountRowsInRowGroup(rows);
     220                 :   );
     221                 : 
     222               0 :   return NS_OK;
     223                 : }
     224                 : 
     225                 : // Returns the item at index aIndex if available. If null is returned,
     226                 : // then aCount will be set to the number of rows in this row collection.
     227                 : // Otherwise, the value of aCount is undefined.
     228                 : static nsIContent*
     229               0 : GetItemOrCountInRowGroup(nsIDOMHTMLCollection* rows,
     230                 :                          PRUint32 aIndex, PRUint32* aCount)
     231                 : {
     232               0 :   *aCount = 0;
     233                 : 
     234               0 :   if (rows) {
     235               0 :     rows->GetLength(aCount);
     236               0 :     if (aIndex < *aCount) {
     237               0 :       nsCOMPtr<nsINodeList> list = do_QueryInterface(rows);
     238               0 :       return list->GetNodeAt(aIndex);
     239                 :     }
     240                 :   }
     241                 :   
     242               0 :   return nsnull;
     243                 : }
     244                 : 
     245                 : nsIContent*
     246               0 : TableRowsCollection::GetNodeAt(PRUint32 aIndex)
     247                 : {
     248               0 :   DO_FOR_EACH_ROWGROUP(
     249                 :     PRUint32 count;
     250                 :     nsIContent* node = GetItemOrCountInRowGroup(rows, aIndex, &count);
     251                 :     if (node) {
     252                 :       return node; 
     253                 :     }
     254                 : 
     255                 :     NS_ASSERTION(count <= aIndex, "GetItemOrCountInRowGroup screwed up");
     256                 :     aIndex -= count;
     257                 :   );
     258                 : 
     259               0 :   return nsnull;
     260                 : }
     261                 : 
     262                 : NS_IMETHODIMP 
     263               0 : TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
     264                 : {
     265               0 :   nsISupports* node = GetNodeAt(aIndex);
     266               0 :   if (!node) {
     267               0 :     *aReturn = nsnull;
     268                 : 
     269               0 :     return NS_OK;
     270                 :   }
     271                 : 
     272               0 :   return CallQueryInterface(node, aReturn);
     273                 : }
     274                 : 
     275                 : static nsISupports*
     276               0 : GetNamedItemInRowGroup(nsIDOMHTMLCollection* aRows, const nsAString& aName,
     277                 :                        nsWrapperCache** aCache)
     278                 : {
     279               0 :   nsCOMPtr<nsIHTMLCollection> rows = do_QueryInterface(aRows);
     280               0 :   if (rows) {
     281               0 :     return rows->GetNamedItem(aName, aCache);
     282                 :   }
     283                 : 
     284               0 :   return nsnull;
     285                 : }
     286                 : 
     287                 : nsISupports* 
     288               0 : TableRowsCollection::GetNamedItem(const nsAString& aName,
     289                 :                                   nsWrapperCache** aCache)
     290                 : {
     291               0 :   DO_FOR_EACH_ROWGROUP(
     292                 :     nsISupports* item = GetNamedItemInRowGroup(rows, aName, aCache);
     293                 :     if (item) {
     294                 :       return item;
     295                 :     }
     296                 :   );
     297               0 :   *aCache = nsnull;
     298               0 :   return nsnull;
     299                 : }
     300                 : 
     301                 : NS_IMETHODIMP 
     302               0 : TableRowsCollection::NamedItem(const nsAString& aName,
     303                 :                                nsIDOMNode** aReturn)
     304                 : {
     305                 :   nsWrapperCache *cache;
     306               0 :   nsISupports* item = GetNamedItem(aName, &cache);
     307               0 :   if (!item) {
     308               0 :     *aReturn = nsnull;
     309                 : 
     310               0 :     return NS_OK;
     311                 :   }
     312                 : 
     313               0 :   return CallQueryInterface(item, aReturn);
     314                 : }
     315                 : 
     316                 : NS_IMETHODIMP
     317               0 : TableRowsCollection::ParentDestroyed()
     318                 : {
     319                 :   // see comment in destructor, do NOT release mParent!
     320               0 :   mParent = nsnull;
     321                 : 
     322               0 :   return NS_OK;
     323                 : }
     324                 : 
     325                 : /* -------------------------- nsHTMLTableElement --------------------------- */
     326                 : // the class declaration is at the top of this file
     327                 : 
     328                 : 
     329               0 : NS_IMPL_NS_NEW_HTML_ELEMENT(Table)
     330                 : 
     331                 : 
     332               0 : nsHTMLTableElement::nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     333                 :   : nsGenericHTMLElement(aNodeInfo),
     334               0 :     mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
     335                 : {
     336               0 : }
     337                 : 
     338               0 : nsHTMLTableElement::~nsHTMLTableElement()
     339                 : {
     340               0 :   if (mRows) {
     341               0 :     mRows->ParentDestroyed();
     342                 :   }
     343               0 :   ReleaseInheritedAttributes();
     344               0 : }
     345                 : 
     346                 : 
     347            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTableElement)
     348               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLTableElement, nsGenericHTMLElement)
     349               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTBodies)
     350               0 :   if (tmp->mRows) {
     351               0 :     tmp->mRows->ParentDestroyed();
     352                 :   }
     353               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRows)
     354               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     355               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTableElement,
     356                 :                                                   nsGenericHTMLElement)
     357               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTBodies,
     358                 :                                                        nsIDOMNodeList)
     359               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRows)
     360               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     361                 : 
     362               0 : NS_IMPL_ADDREF_INHERITED(nsHTMLTableElement, nsGenericElement) 
     363               0 : NS_IMPL_RELEASE_INHERITED(nsHTMLTableElement, nsGenericElement) 
     364                 : 
     365                 : 
     366               0 : DOMCI_NODE_DATA(HTMLTableElement, nsHTMLTableElement)
     367                 : 
     368                 : // QueryInterface implementation for nsHTMLTableElement
     369               0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLTableElement)
     370               0 :   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLTableElement, nsIDOMHTMLTableElement)
     371               0 :   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLTableElement,
     372                 :                                                nsGenericHTMLElement)
     373               0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTableElement)
     374                 : 
     375                 : 
     376               0 : NS_IMPL_ELEMENT_CLONE(nsHTMLTableElement)
     377                 : 
     378                 : 
     379                 : // the DOM spec says border, cellpadding, cellSpacing are all "wstring"
     380                 : // in fact, they are integers or they are meaningless.  so we store them
     381                 : // here as ints.
     382                 : 
     383               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Align, align)
     384               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, BgColor, bgcolor)
     385               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Border, border)
     386               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellPadding, cellpadding)
     387               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellSpacing, cellspacing)
     388               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Frame, frame)
     389               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Rules, rules)
     390               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Summary, summary)
     391               0 : NS_IMPL_STRING_ATTR(nsHTMLTableElement, Width, width)
     392                 : 
     393                 : 
     394                 : already_AddRefed<nsIDOMHTMLTableCaptionElement>
     395               0 : nsHTMLTableElement::GetCaption()
     396                 : {
     397               0 :   for (nsIContent* cur = nsINode::GetFirstChild(); cur; cur = cur->GetNextSibling()) {
     398               0 :     nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption = do_QueryInterface(cur);
     399               0 :     if (caption) {
     400               0 :       return caption.forget();
     401                 :     }
     402                 :   }
     403               0 :   return nsnull;
     404                 : }
     405                 : 
     406                 : NS_IMETHODIMP
     407               0 : nsHTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
     408                 : {
     409               0 :   nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption = GetCaption();
     410               0 :   caption.forget(aValue);
     411               0 :   return NS_OK;
     412                 : }
     413                 : 
     414                 : NS_IMETHODIMP
     415               0 : nsHTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
     416                 : {
     417               0 :   nsresult rv = DeleteCaption();
     418                 : 
     419               0 :   if (NS_SUCCEEDED(rv)) {
     420               0 :     if (aValue) {
     421               0 :       nsCOMPtr<nsIDOMNode> resultingChild;
     422               0 :       AppendChild(aValue, getter_AddRefs(resultingChild));
     423                 :     }
     424                 :   }
     425                 : 
     426               0 :   return rv;
     427                 : }
     428                 : 
     429                 : already_AddRefed<nsIDOMHTMLTableSectionElement>
     430               0 : nsHTMLTableElement::GetSection(nsIAtom *aTag)
     431                 : {
     432               0 :   for (nsIContent* child = nsINode::GetFirstChild();
     433                 :        child;
     434               0 :        child = child->GetNextSibling()) {
     435               0 :     nsCOMPtr<nsIDOMHTMLTableSectionElement> section = do_QueryInterface(child);
     436               0 :     if (section && child->NodeInfo()->Equals(aTag)) {
     437               0 :       return section.forget();
     438                 :     }
     439                 :   }
     440               0 :   return nsnull;
     441                 : }
     442                 : 
     443                 : NS_IMETHODIMP
     444               0 : nsHTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
     445                 : {
     446               0 :   *aValue = GetTHead().get();
     447                 : 
     448               0 :   return NS_OK;
     449                 : }
     450                 : 
     451                 : NS_IMETHODIMP
     452               0 : nsHTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
     453                 : {
     454               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aValue));
     455               0 :   NS_ENSURE_TRUE(content, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
     456                 : 
     457               0 :   if (!content->NodeInfo()->Equals(nsGkAtoms::thead)) {
     458               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
     459                 :   }
     460                 :   
     461               0 :   nsresult rv = DeleteTHead();
     462               0 :   if (NS_FAILED(rv)) {
     463               0 :     return rv;
     464                 :   }
     465                 : 
     466               0 :   if (aValue) {
     467               0 :     nsCOMPtr<nsIDOMNode> child;
     468               0 :     rv = GetFirstChild(getter_AddRefs(child));
     469               0 :     if (NS_FAILED(rv)) {
     470               0 :       return rv;
     471                 :     }
     472                 :      
     473               0 :     nsCOMPtr<nsIDOMNode> resultChild;
     474               0 :     rv = InsertBefore(aValue, child, getter_AddRefs(resultChild));
     475                 :   }
     476                 : 
     477               0 :   return rv;
     478                 : }
     479                 : 
     480                 : NS_IMETHODIMP
     481               0 : nsHTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
     482                 : {
     483               0 :   *aValue = GetTFoot().get();
     484                 : 
     485               0 :   return NS_OK;
     486                 : }
     487                 : 
     488                 : NS_IMETHODIMP
     489               0 : nsHTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
     490                 : {
     491               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aValue));
     492               0 :   NS_ENSURE_TRUE(content, NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
     493                 : 
     494               0 :   if (!content->NodeInfo()->Equals(nsGkAtoms::tfoot)) {
     495               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
     496                 :   }
     497                 :   
     498               0 :   nsresult rv = DeleteTFoot();
     499               0 :   if (NS_SUCCEEDED(rv)) {
     500               0 :     if (aValue) {
     501               0 :       nsCOMPtr<nsIDOMNode> resultingChild;
     502               0 :       AppendChild(aValue, getter_AddRefs(resultingChild));
     503                 :     }
     504                 :   }
     505                 : 
     506               0 :   return rv;
     507                 : }
     508                 : 
     509                 : NS_IMETHODIMP
     510               0 : nsHTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
     511                 : {
     512               0 :   if (!mRows) {
     513               0 :     mRows = new TableRowsCollection(this);
     514                 :   }
     515                 : 
     516               0 :   *aValue = mRows;
     517               0 :   NS_ADDREF(*aValue);
     518                 : 
     519               0 :   return NS_OK;
     520                 : }
     521                 : 
     522                 : NS_IMETHODIMP
     523               0 : nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
     524                 : {
     525               0 :   NS_ADDREF(*aValue = TBodies());
     526               0 :   return NS_OK;
     527                 : }
     528                 : 
     529                 : nsContentList*
     530               0 : nsHTMLTableElement::TBodies()
     531                 : {
     532               0 :   if (!mTBodies) {
     533                 :     // Not using NS_GetContentList because this should not be cached
     534                 :     mTBodies = new nsContentList(this,
     535                 :                                  kNameSpaceID_XHTML,
     536                 :                                  nsGkAtoms::tbody,
     537                 :                                  nsGkAtoms::tbody,
     538               0 :                                  false);
     539                 :   }
     540                 : 
     541               0 :   return mTBodies;
     542                 : }
     543                 : 
     544                 : NS_IMETHODIMP
     545               0 : nsHTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
     546                 : {
     547               0 :   *aValue = nsnull;
     548                 : 
     549               0 :   nsRefPtr<nsIDOMHTMLTableSectionElement> head = GetTHead();
     550               0 :   if (head) {
     551                 :     // return the existing thead
     552               0 :     head.forget(aValue);
     553               0 :     return NS_OK;
     554                 :   }
     555                 : 
     556               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
     557                 :   nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::thead,
     558               0 :                               getter_AddRefs(nodeInfo));
     559                 : 
     560                 :   nsCOMPtr<nsIContent> newHead =
     561               0 :     NS_NewHTMLTableSectionElement(nodeInfo.forget());
     562                 : 
     563               0 :   if (!newHead) {
     564               0 :     return NS_OK;
     565                 :   }
     566                 : 
     567               0 :   nsCOMPtr<nsIDOMNode> child;
     568               0 :   nsresult rv = GetFirstChild(getter_AddRefs(child));
     569               0 :   NS_ENSURE_SUCCESS(rv, rv);
     570                 : 
     571               0 :   nsCOMPtr<nsIDOMHTMLElement> newHeadAsDOMElement = do_QueryInterface(newHead);
     572                 : 
     573               0 :   nsCOMPtr<nsIDOMNode> resultChild;
     574               0 :   InsertBefore(newHeadAsDOMElement, child, getter_AddRefs(resultChild));
     575               0 :   newHeadAsDOMElement.forget(aValue);
     576               0 :   return NS_OK;
     577                 : }
     578                 : 
     579                 : NS_IMETHODIMP
     580               0 : nsHTMLTableElement::DeleteTHead()
     581                 : {
     582               0 :   nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
     583               0 :   nsresult rv = GetTHead(getter_AddRefs(childToDelete));
     584                 : 
     585               0 :   if ((NS_SUCCEEDED(rv)) && childToDelete) {
     586               0 :     nsCOMPtr<nsIDOMNode> resultingChild;
     587                 :     // mInner does the notification
     588               0 :     RemoveChild(childToDelete, getter_AddRefs(resultingChild));
     589                 :   }
     590                 : 
     591               0 :   return NS_OK;
     592                 : }
     593                 : 
     594                 : NS_IMETHODIMP
     595               0 : nsHTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
     596                 : {
     597               0 :   *aValue = nsnull;
     598                 : 
     599               0 :   nsRefPtr<nsIDOMHTMLTableSectionElement> foot = GetTFoot();
     600               0 :   if (foot) {
     601                 :     // return the existing tfoot
     602               0 :     foot.forget(aValue);
     603               0 :     return NS_OK;
     604                 :   }
     605                 :   // create a new foot rowgroup
     606               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
     607                 :   nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tfoot,
     608               0 :                               getter_AddRefs(nodeInfo));
     609                 : 
     610               0 :   nsCOMPtr<nsIContent> newFoot = NS_NewHTMLTableSectionElement(nodeInfo.forget());
     611                 : 
     612               0 :   if (!newFoot) {
     613               0 :     return NS_OK;
     614                 :   }
     615               0 :   AppendChildTo(newFoot, true);
     616               0 :   nsCOMPtr<nsIDOMHTMLElement> newFootAsDOMElement = do_QueryInterface(newFoot);
     617               0 :   newFootAsDOMElement.forget(aValue);
     618               0 :   return NS_OK;
     619                 : }
     620                 : 
     621                 : NS_IMETHODIMP
     622               0 : nsHTMLTableElement::DeleteTFoot()
     623                 : {
     624               0 :   nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
     625               0 :   nsresult rv = GetTFoot(getter_AddRefs(childToDelete));
     626                 : 
     627               0 :   if ((NS_SUCCEEDED(rv)) && childToDelete) {
     628               0 :     nsCOMPtr<nsIDOMNode> resultingChild;
     629                 :     // mInner does the notification
     630               0 :     RemoveChild(childToDelete, getter_AddRefs(resultingChild));
     631                 :   }
     632                 : 
     633               0 :   return NS_OK;
     634                 : }
     635                 : 
     636                 : NS_IMETHODIMP
     637               0 : nsHTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
     638                 : {
     639               0 :   *aValue = nsnull;
     640                 : 
     641               0 :   if (nsRefPtr<nsIDOMHTMLTableCaptionElement> caption = GetCaption()) {
     642                 :     // return the existing caption
     643               0 :     caption.forget(aValue);
     644               0 :     return NS_OK;
     645                 :   }
     646                 : 
     647                 :   // create a new head rowgroup
     648               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
     649                 :   nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::caption,
     650               0 :                               getter_AddRefs(nodeInfo));
     651                 : 
     652               0 :   nsCOMPtr<nsIContent> newCaption = NS_NewHTMLTableCaptionElement(nodeInfo.forget());
     653                 : 
     654               0 :   if (!newCaption) {
     655               0 :     return NS_OK;
     656                 :   }
     657                 : 
     658               0 :   AppendChildTo(newCaption, true);
     659                 :   nsCOMPtr<nsIDOMHTMLElement> captionAsDOMElement =
     660               0 :     do_QueryInterface(newCaption);
     661               0 :   captionAsDOMElement.forget(aValue);
     662               0 :   return NS_OK;
     663                 : }
     664                 : 
     665                 : NS_IMETHODIMP
     666               0 : nsHTMLTableElement::DeleteCaption()
     667                 : {
     668               0 :   nsCOMPtr<nsIDOMHTMLTableCaptionElement> childToDelete;
     669               0 :   nsresult rv = GetCaption(getter_AddRefs(childToDelete));
     670                 : 
     671               0 :   if ((NS_SUCCEEDED(rv)) && childToDelete) {
     672               0 :     nsCOMPtr<nsIDOMNode> resultingChild;
     673               0 :     RemoveChild(childToDelete, getter_AddRefs(resultingChild));
     674                 :   }
     675                 : 
     676               0 :   return NS_OK;
     677                 : }
     678                 : 
     679                 : NS_IMETHODIMP
     680               0 : nsHTMLTableElement::InsertRow(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
     681                 : {
     682                 :   /* get the ref row at aIndex
     683                 :      if there is one, 
     684                 :        get its parent
     685                 :        insert the new row just before the ref row
     686                 :      else
     687                 :        get the first row group
     688                 :        insert the new row as its first child
     689                 :   */
     690               0 :   *aValue = nsnull;
     691                 : 
     692               0 :   if (aIndex < -1) {
     693               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     694                 :   }
     695                 : 
     696               0 :   nsCOMPtr<nsIDOMHTMLCollection> rows;
     697               0 :   GetRows(getter_AddRefs(rows));
     698                 : 
     699                 :   PRUint32 rowCount;
     700               0 :   rows->GetLength(&rowCount);
     701                 : 
     702               0 :   if ((PRUint32)aIndex > rowCount && aIndex != -1) {
     703               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     704                 :   }
     705                 : 
     706                 :   // use local variable refIndex so we can remember original aIndex
     707               0 :   PRUint32 refIndex = (PRUint32)aIndex;
     708                 : 
     709                 :   nsresult rv;
     710               0 :   if (rowCount > 0) {
     711               0 :     if (refIndex == rowCount || aIndex == -1) {
     712                 :       // we set refIndex to the last row so we can get the last row's
     713                 :       // parent we then do an AppendChild below if (rowCount<aIndex)
     714                 : 
     715               0 :       refIndex = rowCount - 1;
     716                 :     }
     717                 : 
     718               0 :     nsCOMPtr<nsIDOMNode> refRow;
     719               0 :     rows->Item(refIndex, getter_AddRefs(refRow));
     720                 : 
     721               0 :     nsCOMPtr<nsIDOMNode> parent;
     722                 : 
     723               0 :     refRow->GetParentNode(getter_AddRefs(parent));
     724                 :     // create the row
     725               0 :     nsCOMPtr<nsINodeInfo> nodeInfo;
     726                 :     nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tr,
     727               0 :                                 getter_AddRefs(nodeInfo));
     728                 : 
     729               0 :     nsCOMPtr<nsIContent> newRow = NS_NewHTMLTableRowElement(nodeInfo.forget());
     730                 : 
     731               0 :     if (newRow) {
     732               0 :       nsCOMPtr<nsIDOMNode> newRowNode(do_QueryInterface(newRow));
     733               0 :       nsCOMPtr<nsIDOMNode> retChild;
     734                 : 
     735                 :       // If index is -1 or equal to the number of rows, the new row
     736                 :       // is appended.
     737               0 :       if (aIndex == -1 || PRUint32(aIndex) == rowCount) {
     738               0 :         rv = parent->AppendChild(newRowNode, getter_AddRefs(retChild));
     739               0 :         NS_ENSURE_SUCCESS(rv, rv);
     740                 :       }
     741                 :       else
     742                 :       {
     743                 :         // insert the new row before the reference row we found above
     744               0 :         rv = parent->InsertBefore(newRowNode, refRow,
     745               0 :                                   getter_AddRefs(retChild));
     746               0 :         NS_ENSURE_SUCCESS(rv, rv);
     747                 :       }
     748                 : 
     749               0 :       if (retChild) {
     750               0 :         CallQueryInterface(retChild, aValue);
     751                 :       }
     752                 :     }
     753                 :   } else {
     754                 :     // the row count was 0, so 
     755                 :     // find the first row group and insert there as first child
     756               0 :     nsCOMPtr<nsIDOMNode> rowGroup;
     757                 : 
     758               0 :     for (nsIContent* child = nsINode::GetFirstChild();
     759                 :          child;
     760               0 :          child = child->GetNextSibling()) {
     761               0 :       nsINodeInfo *childInfo = child->NodeInfo();
     762               0 :       nsIAtom *localName = childInfo->NameAtom();
     763               0 :       if (childInfo->NamespaceID() == kNameSpaceID_XHTML &&
     764                 :           (localName == nsGkAtoms::thead ||
     765                 :            localName == nsGkAtoms::tbody ||
     766                 :            localName == nsGkAtoms::tfoot)) {
     767               0 :         rowGroup = do_QueryInterface(child);
     768               0 :         NS_ASSERTION(rowGroup, "HTML node did not QI to nsIDOMNode");
     769               0 :         break;
     770                 :       }
     771                 :     }
     772                 : 
     773               0 :     if (!rowGroup) { // need to create a TBODY
     774               0 :       nsCOMPtr<nsINodeInfo> nodeInfo;
     775                 :       nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tbody,
     776               0 :                                   getter_AddRefs(nodeInfo));
     777                 : 
     778                 :       nsCOMPtr<nsIContent> newRowGroup =
     779               0 :         NS_NewHTMLTableSectionElement(nodeInfo.forget());
     780                 : 
     781               0 :       if (newRowGroup) {
     782               0 :         rv = AppendChildTo(newRowGroup, true);
     783               0 :         NS_ENSURE_SUCCESS(rv, rv);
     784                 : 
     785               0 :         rowGroup = do_QueryInterface(newRowGroup);
     786                 :       }
     787                 :     }
     788                 : 
     789               0 :     if (rowGroup) {
     790               0 :       nsCOMPtr<nsINodeInfo> nodeInfo;
     791                 :       nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tr,
     792               0 :                                   getter_AddRefs(nodeInfo));
     793                 : 
     794               0 :       nsCOMPtr<nsIContent> newRow = NS_NewHTMLTableRowElement(nodeInfo.forget());
     795               0 :       if (newRow) {
     796               0 :         nsCOMPtr<nsIDOMNode> firstRow;
     797                 : 
     798                 :         nsCOMPtr<nsIDOMHTMLTableSectionElement> section =
     799               0 :           do_QueryInterface(rowGroup);
     800                 : 
     801               0 :         if (section) {
     802               0 :           nsCOMPtr<nsIDOMHTMLCollection> rows;
     803               0 :           section->GetRows(getter_AddRefs(rows));
     804               0 :           if (rows) {
     805               0 :             rows->Item(0, getter_AddRefs(firstRow));
     806                 :           }
     807                 :         }
     808                 :         
     809               0 :         nsCOMPtr<nsIDOMNode> retNode, newRowNode(do_QueryInterface(newRow));
     810                 : 
     811               0 :         rowGroup->InsertBefore(newRowNode, firstRow, getter_AddRefs(retNode));
     812                 : 
     813               0 :         if (retNode) {
     814               0 :           CallQueryInterface(retNode, aValue);
     815                 :         }
     816                 :       }
     817                 :     }
     818                 :   }
     819                 : 
     820               0 :   return NS_OK;
     821                 : }
     822                 : 
     823                 : NS_IMETHODIMP
     824               0 : nsHTMLTableElement::DeleteRow(PRInt32 aValue)
     825                 : {
     826               0 :   if (aValue < -1) {
     827               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     828                 :   }
     829                 : 
     830               0 :   nsCOMPtr<nsIDOMHTMLCollection> rows;
     831               0 :   GetRows(getter_AddRefs(rows));
     832                 : 
     833                 :   nsresult rv;
     834                 :   PRUint32 refIndex;
     835               0 :   if (aValue == -1) {
     836               0 :     rv = rows->GetLength(&refIndex);
     837               0 :     NS_ENSURE_SUCCESS(rv, rv);
     838                 : 
     839               0 :     if (refIndex == 0) {
     840               0 :       return NS_OK;
     841                 :     }
     842                 : 
     843               0 :     --refIndex;
     844                 :   }
     845                 :   else {
     846               0 :     refIndex = (PRUint32)aValue;
     847                 :   }
     848                 : 
     849               0 :   nsCOMPtr<nsIDOMNode> row;
     850               0 :   rv = rows->Item(refIndex, getter_AddRefs(row));
     851               0 :   NS_ENSURE_SUCCESS(rv, rv);
     852                 : 
     853               0 :   if (!row) {
     854               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     855                 :   }
     856                 : 
     857               0 :   nsCOMPtr<nsIDOMNode> parent;
     858               0 :   row->GetParentNode(getter_AddRefs(parent));
     859               0 :   NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
     860                 : 
     861               0 :   nsCOMPtr<nsIDOMNode> deleted_row;
     862               0 :   return parent->RemoveChild(row, getter_AddRefs(deleted_row));
     863                 : }
     864                 : 
     865                 : static const nsAttrValue::EnumTable kFrameTable[] = {
     866                 :   { "void",   NS_STYLE_TABLE_FRAME_NONE },
     867                 :   { "above",  NS_STYLE_TABLE_FRAME_ABOVE },
     868                 :   { "below",  NS_STYLE_TABLE_FRAME_BELOW },
     869                 :   { "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
     870                 :   { "lhs",    NS_STYLE_TABLE_FRAME_LEFT },
     871                 :   { "rhs",    NS_STYLE_TABLE_FRAME_RIGHT },
     872                 :   { "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
     873                 :   { "box",    NS_STYLE_TABLE_FRAME_BOX },
     874                 :   { "border", NS_STYLE_TABLE_FRAME_BORDER },
     875                 :   { 0 }
     876                 : };
     877                 : 
     878                 : static const nsAttrValue::EnumTable kRulesTable[] = {
     879                 :   { "none",   NS_STYLE_TABLE_RULES_NONE },
     880                 :   { "groups", NS_STYLE_TABLE_RULES_GROUPS },
     881                 :   { "rows",   NS_STYLE_TABLE_RULES_ROWS },
     882                 :   { "cols",   NS_STYLE_TABLE_RULES_COLS },
     883                 :   { "all",    NS_STYLE_TABLE_RULES_ALL },
     884                 :   { 0 }
     885                 : };
     886                 : 
     887                 : static const nsAttrValue::EnumTable kLayoutTable[] = {
     888                 :   { "auto",   NS_STYLE_TABLE_LAYOUT_AUTO },
     889                 :   { "fixed",  NS_STYLE_TABLE_LAYOUT_FIXED },
     890                 :   { 0 }
     891                 : };
     892                 : 
     893                 : 
     894                 : bool
     895               0 : nsHTMLTableElement::ParseAttribute(PRInt32 aNamespaceID,
     896                 :                                    nsIAtom* aAttribute,
     897                 :                                    const nsAString& aValue,
     898                 :                                    nsAttrValue& aResult)
     899                 : {
     900                 :   /* ignore summary, just a string */
     901               0 :   if (aNamespaceID == kNameSpaceID_None) {
     902               0 :     if (aAttribute == nsGkAtoms::cellspacing ||
     903                 :         aAttribute == nsGkAtoms::cellpadding) {
     904               0 :       return aResult.ParseNonNegativeIntValue(aValue);
     905                 :     }
     906               0 :     if (aAttribute == nsGkAtoms::cols ||
     907                 :         aAttribute == nsGkAtoms::border) {
     908               0 :       return aResult.ParseIntWithBounds(aValue, 0);
     909                 :     }
     910               0 :     if (aAttribute == nsGkAtoms::height) {
     911               0 :       return aResult.ParseSpecialIntValue(aValue);
     912                 :     }
     913               0 :     if (aAttribute == nsGkAtoms::width) {
     914               0 :       if (aResult.ParseSpecialIntValue(aValue)) {
     915                 :         // treat 0 width as auto
     916               0 :         nsAttrValue::ValueType type = aResult.Type();
     917                 :         return !((type == nsAttrValue::eInteger &&
     918               0 :                   aResult.GetIntegerValue() == 0) ||
     919                 :                  (type == nsAttrValue::ePercent &&
     920               0 :                   aResult.GetPercentValue() == 0.0f));
     921                 :       }
     922               0 :       return false;
     923                 :     }
     924                 :     
     925               0 :     if (aAttribute == nsGkAtoms::align) {
     926               0 :       return ParseTableHAlignValue(aValue, aResult);
     927                 :     }
     928               0 :     if (aAttribute == nsGkAtoms::bgcolor ||
     929                 :         aAttribute == nsGkAtoms::bordercolor) {
     930               0 :       return aResult.ParseColor(aValue);
     931                 :     }
     932               0 :     if (aAttribute == nsGkAtoms::frame) {
     933               0 :       return aResult.ParseEnumValue(aValue, kFrameTable, false);
     934                 :     }
     935               0 :     if (aAttribute == nsGkAtoms::layout) {
     936               0 :       return aResult.ParseEnumValue(aValue, kLayoutTable, false);
     937                 :     }
     938               0 :     if (aAttribute == nsGkAtoms::rules) {
     939               0 :       return aResult.ParseEnumValue(aValue, kRulesTable, false);
     940                 :     }
     941               0 :     if (aAttribute == nsGkAtoms::hspace ||
     942                 :         aAttribute == nsGkAtoms::vspace) {
     943               0 :       return aResult.ParseIntWithBounds(aValue, 0);
     944                 :     }
     945                 :   }
     946                 : 
     947                 :   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
     948               0 :                                               aResult);
     949                 : }
     950                 : 
     951                 : 
     952                 : 
     953                 : static void
     954               0 : MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
     955                 :                       nsRuleData* aData)
     956                 : {
     957                 :   // XXX Bug 211636:  This function is used by a single style rule
     958                 :   // that's used to match two different type of elements -- tables, and
     959                 :   // table cells.  (nsHTMLTableCellElement overrides
     960                 :   // WalkContentStyleRules so that this happens.)  This violates the
     961                 :   // nsIStyleRule contract, since it's the same style rule object doing
     962                 :   // the mapping in two different ways.  It's also incorrect since it's
     963                 :   // testing the display type of the style context rather than checking
     964                 :   // which *element* it's matching (style rules should not stop matching
     965                 :   // when the display type is changed).
     966                 : 
     967               0 :   nsPresContext* presContext = aData->mPresContext;
     968               0 :   nsCompatibility mode = presContext->CompatibilityMode();
     969                 : 
     970               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
     971                 :     // cellspacing
     972               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
     973               0 :     nsCSSValue* borderSpacing = aData->ValueForBorderSpacing();
     974               0 :     if (value && value->Type() == nsAttrValue::eInteger &&
     975               0 :         borderSpacing->GetUnit() == eCSSUnit_Null) {
     976                 :       borderSpacing->
     977               0 :         SetFloatValue(float(value->GetIntegerValue()), eCSSUnit_Pixel);
     978                 :     }
     979                 :   }
     980               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
     981                 :     const nsAttrValue* value;
     982                 :     // layout
     983               0 :     nsCSSValue* tableLayout = aData->ValueForTableLayout();
     984               0 :     if (tableLayout->GetUnit() == eCSSUnit_Null) {
     985               0 :       value = aAttributes->GetAttr(nsGkAtoms::layout);
     986               0 :       if (value && value->Type() == nsAttrValue::eEnum)
     987               0 :         tableLayout->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     988                 :     }
     989                 :     // cols
     990               0 :     value = aAttributes->GetAttr(nsGkAtoms::cols);
     991               0 :     if (value) {
     992               0 :       nsCSSValue* cols = aData->ValueForCols();
     993               0 :       if (value->Type() == nsAttrValue::eInteger)
     994               0 :         cols->SetIntValue(value->GetIntegerValue(), eCSSUnit_Integer);
     995                 :       else // COLS had no value, so it refers to all columns
     996               0 :         cols->SetIntValue(NS_STYLE_TABLE_COLS_ALL, eCSSUnit_Enumerated);
     997                 :     }
     998                 :   }
     999               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
    1000                 :     // align; Check for enumerated type (it may be another type if
    1001                 :     // illegal)
    1002               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
    1003                 : 
    1004               0 :     if (value && value->Type() == nsAttrValue::eEnum) {
    1005               0 :       if (value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_CENTER ||
    1006               0 :           value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_MOZ_CENTER) {
    1007               0 :         nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
    1008               0 :         if (marginLeft->GetUnit() == eCSSUnit_Null)
    1009               0 :           marginLeft->SetAutoValue();
    1010               0 :         nsCSSValue* marginRight = aData->ValueForMarginRightValue();
    1011               0 :         if (marginRight->GetUnit() == eCSSUnit_Null)
    1012               0 :           marginRight->SetAutoValue();
    1013                 :       }
    1014                 :     }
    1015                 : 
    1016                 :     // hspace is mapped into left and right margin,
    1017                 :     // vspace is mapped into top and bottom margins
    1018                 :     // - *** Quirks Mode only ***
    1019               0 :     if (eCompatibility_NavQuirks == mode) {
    1020               0 :       value = aAttributes->GetAttr(nsGkAtoms::hspace);
    1021                 : 
    1022               0 :       if (value && value->Type() == nsAttrValue::eInteger) {
    1023               0 :         nsCSSValue* marginLeft = aData->ValueForMarginLeftValue();
    1024               0 :         if (marginLeft->GetUnit() == eCSSUnit_Null)
    1025               0 :           marginLeft->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
    1026               0 :         nsCSSValue* marginRight = aData->ValueForMarginRightValue();
    1027               0 :         if (marginRight->GetUnit() == eCSSUnit_Null)
    1028               0 :           marginRight->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    1029                 :       }
    1030                 : 
    1031               0 :       value = aAttributes->GetAttr(nsGkAtoms::vspace);
    1032                 : 
    1033               0 :       if (value && value->Type() == nsAttrValue::eInteger) {
    1034               0 :         nsCSSValue* marginTop = aData->ValueForMarginTop();
    1035               0 :         if (marginTop->GetUnit() == eCSSUnit_Null)
    1036               0 :           marginTop->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
    1037               0 :         nsCSSValue* marginBottom = aData->ValueForMarginBottom();
    1038               0 :         if (marginBottom->GetUnit() == eCSSUnit_Null)
    1039               0 :           marginBottom->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
    1040                 :       }
    1041                 :     }
    1042                 :   }
    1043               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
    1044                 :     // width: value
    1045               0 :     nsCSSValue* width = aData->ValueForWidth();
    1046               0 :     if (width->GetUnit() == eCSSUnit_Null) {
    1047               0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
    1048               0 :       if (value && value->Type() == nsAttrValue::eInteger)
    1049               0 :         width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    1050               0 :       else if (value && value->Type() == nsAttrValue::ePercent)
    1051               0 :         width->SetPercentValue(value->GetPercentValue());
    1052                 :     }
    1053                 : 
    1054                 :     // height: value
    1055               0 :     nsCSSValue* height = aData->ValueForHeight();
    1056               0 :     if (height->GetUnit() == eCSSUnit_Null) {
    1057               0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
    1058               0 :       if (value && value->Type() == nsAttrValue::eInteger)
    1059               0 :         height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
    1060               0 :       else if (value && value->Type() == nsAttrValue::ePercent)
    1061               0 :         height->SetPercentValue(value->GetPercentValue());
    1062                 :     }
    1063                 :   }
    1064               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
    1065                 :     // bordercolor
    1066               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
    1067                 :     nscolor color;
    1068               0 :     if (value && presContext->UseDocumentColors() &&
    1069               0 :         value->GetColorValue(color)) {
    1070               0 :       nsCSSValue* borderLeftColor = aData->ValueForBorderLeftColorValue();
    1071               0 :       if (borderLeftColor->GetUnit() == eCSSUnit_Null)
    1072               0 :         borderLeftColor->SetColorValue(color);
    1073               0 :       nsCSSValue* borderRightColor = aData->ValueForBorderRightColorValue();
    1074               0 :       if (borderRightColor->GetUnit() == eCSSUnit_Null)
    1075               0 :         borderRightColor->SetColorValue(color);
    1076               0 :       nsCSSValue* borderTopColor = aData->ValueForBorderTopColor();
    1077               0 :       if (borderTopColor->GetUnit() == eCSSUnit_Null)
    1078               0 :         borderTopColor->SetColorValue(color);
    1079               0 :       nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
    1080               0 :       if (borderBottomColor->GetUnit() == eCSSUnit_Null)
    1081               0 :         borderBottomColor->SetColorValue(color);
    1082                 :     }
    1083                 : 
    1084                 :     // border
    1085               0 :     const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
    1086               0 :     if (borderValue) {
    1087                 :       // border = 1 pixel default
    1088               0 :       PRInt32 borderThickness = 1;
    1089                 : 
    1090               0 :       if (borderValue->Type() == nsAttrValue::eInteger)
    1091               0 :         borderThickness = borderValue->GetIntegerValue();
    1092                 : 
    1093                 :       // by default, set all border sides to the specified width
    1094               0 :       nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidthValue();
    1095               0 :       if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
    1096               0 :         borderLeftWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
    1097               0 :       nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidthValue();
    1098               0 :       if (borderRightWidth->GetUnit() == eCSSUnit_Null)
    1099               0 :         borderRightWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
    1100               0 :       nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
    1101               0 :       if (borderTopWidth->GetUnit() == eCSSUnit_Null)
    1102               0 :         borderTopWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
    1103               0 :       nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
    1104               0 :       if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
    1105               0 :         borderBottomWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
    1106                 :     }
    1107                 :   }
    1108               0 :   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
    1109               0 :   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
    1110               0 : }
    1111                 : 
    1112                 : NS_IMETHODIMP_(bool)
    1113               0 : nsHTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    1114                 : {
    1115                 :   static const MappedAttributeEntry attributes[] = {
    1116                 :     { &nsGkAtoms::layout },
    1117                 :     { &nsGkAtoms::cellpadding },
    1118                 :     { &nsGkAtoms::cellspacing },
    1119                 :     { &nsGkAtoms::cols },
    1120                 :     { &nsGkAtoms::border },
    1121                 :     { &nsGkAtoms::width },
    1122                 :     { &nsGkAtoms::height },
    1123                 :     { &nsGkAtoms::hspace },
    1124                 :     { &nsGkAtoms::vspace },
    1125                 :     
    1126                 :     { &nsGkAtoms::bordercolor },
    1127                 :     
    1128                 :     { &nsGkAtoms::align },
    1129                 :     { nsnull }
    1130                 :   };
    1131                 : 
    1132                 :   static const MappedAttributeEntry* const map[] = {
    1133                 :     attributes,
    1134                 :     sCommonAttributeMap,
    1135                 :     sBackgroundAttributeMap,
    1136                 :   };
    1137                 : 
    1138               0 :   return FindAttributeDependence(aAttribute, map);
    1139                 : }
    1140                 : 
    1141                 : nsMapRuleToAttributesFunc
    1142               0 : nsHTMLTableElement::GetAttributeMappingFunction() const
    1143                 : {
    1144               0 :   return &MapAttributesIntoRule;
    1145                 : }
    1146                 : 
    1147                 : static void
    1148               0 : MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
    1149                 :                                     nsRuleData* aData)
    1150                 : {
    1151               0 :   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Padding)) {
    1152               0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
    1153               0 :     if (value && value->Type() == nsAttrValue::eInteger) {
    1154                 :       // We have cellpadding.  This will override our padding values if we
    1155                 :       // don't have any set.
    1156               0 :       nsCSSValue padVal(float(value->GetIntegerValue()), eCSSUnit_Pixel);
    1157                 : 
    1158               0 :       nsCSSValue* paddingLeft = aData->ValueForPaddingLeftValue();
    1159               0 :       if (paddingLeft->GetUnit() == eCSSUnit_Null) {
    1160               0 :         *paddingLeft = padVal;
    1161                 :       }
    1162                 : 
    1163               0 :       nsCSSValue* paddingRight = aData->ValueForPaddingRightValue();
    1164               0 :       if (paddingRight->GetUnit() == eCSSUnit_Null) {
    1165               0 :         *paddingRight = padVal;
    1166                 :       }
    1167                 : 
    1168               0 :       nsCSSValue* paddingTop = aData->ValueForPaddingTop();
    1169               0 :       if (paddingTop->GetUnit() == eCSSUnit_Null) {
    1170               0 :         *paddingTop = padVal;
    1171                 :       }
    1172                 : 
    1173               0 :       nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
    1174               0 :       if (paddingBottom->GetUnit() == eCSSUnit_Null) {
    1175               0 :         *paddingBottom = padVal;
    1176                 :       }
    1177                 :     }
    1178                 :   }
    1179               0 : }
    1180                 : 
    1181                 : nsMappedAttributes*
    1182               0 : nsHTMLTableElement::GetAttributesMappedForCell()
    1183                 : {
    1184               0 :   if (mTableInheritedAttributes) {
    1185               0 :     if (mTableInheritedAttributes == TABLE_ATTRS_DIRTY)
    1186               0 :       BuildInheritedAttributes();
    1187               0 :     if (mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
    1188               0 :       return mTableInheritedAttributes;
    1189                 :   }
    1190               0 :   return nsnull;
    1191                 : }
    1192                 : 
    1193                 : void
    1194               0 : nsHTMLTableElement::BuildInheritedAttributes()
    1195                 : {
    1196               0 :   NS_ASSERTION(mTableInheritedAttributes == TABLE_ATTRS_DIRTY,
    1197                 :                "potential leak, plus waste of work");
    1198               0 :   nsIDocument *document = GetCurrentDoc();
    1199                 :   nsHTMLStyleSheet* sheet = document ?
    1200               0 :                               document->GetAttributeStyleSheet() : nsnull;
    1201               0 :   nsRefPtr<nsMappedAttributes> newAttrs;
    1202               0 :   if (sheet) {
    1203               0 :     const nsAttrValue* value = mAttrsAndChildren.GetAttr(nsGkAtoms::cellpadding);
    1204               0 :     if (value) {
    1205                 :       nsRefPtr<nsMappedAttributes> modifiableMapped = new
    1206               0 :       nsMappedAttributes(sheet, MapInheritedTableAttributesIntoRule);
    1207                 : 
    1208               0 :       if (modifiableMapped) {
    1209               0 :         nsAttrValue val(*value);
    1210               0 :         modifiableMapped->SetAndTakeAttr(nsGkAtoms::cellpadding, val);
    1211                 :       }
    1212               0 :       newAttrs = sheet->UniqueMappedAttributes(modifiableMapped);
    1213               0 :       NS_ASSERTION(newAttrs, "out of memory, but handling gracefully");
    1214                 : 
    1215               0 :       if (newAttrs != modifiableMapped) {
    1216                 :         // Reset the stylesheet of modifiableMapped so that it doesn't
    1217                 :         // spend time trying to remove itself from the hash.  There is no
    1218                 :         // risk that modifiableMapped is in the hash since we created
    1219                 :         // it ourselves and it didn't come from the stylesheet (in which
    1220                 :         // case it would not have been modifiable).
    1221               0 :         modifiableMapped->DropStyleSheetReference();
    1222                 :       }
    1223                 :     }
    1224               0 :     mTableInheritedAttributes = newAttrs;
    1225               0 :     NS_IF_ADDREF(mTableInheritedAttributes);
    1226                 :   }
    1227               0 : }
    1228                 : 
    1229                 : nsresult
    1230               0 : nsHTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    1231                 :                               nsIContent* aBindingParent,
    1232                 :                               bool aCompileEventHandlers)
    1233                 : {
    1234               0 :   ReleaseInheritedAttributes();
    1235                 :   return nsGenericHTMLElement::BindToTree(aDocument, aParent,
    1236                 :                                           aBindingParent,
    1237               0 :                                           aCompileEventHandlers);
    1238                 : }
    1239                 : 
    1240                 : void
    1241               0 : nsHTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent)
    1242                 : {
    1243               0 :   ReleaseInheritedAttributes();
    1244               0 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
    1245               0 : }
    1246                 : 
    1247                 : nsresult
    1248               0 : nsHTMLTableElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    1249                 :                                   const nsAttrValueOrString* aValue,
    1250                 :                                   bool aNotify)
    1251                 : {
    1252               0 :   if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
    1253               0 :     ReleaseInheritedAttributes();
    1254                 :   }
    1255                 :   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue,
    1256               0 :                                              aNotify);
    1257                 : }
    1258                 : 
    1259                 : nsresult
    1260               0 : nsHTMLTableElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    1261                 :                                  const nsAttrValue* aValue,
    1262                 :                                  bool aNotify)
    1263                 : {
    1264               0 :   if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
    1265               0 :     BuildInheritedAttributes();
    1266                 :   }
    1267                 :   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
    1268               0 :                                             aNotify);
    1269            4392 : }

Generated by: LCOV version 1.7