1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
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
15
* The Original Code is Mozilla Communicator client code.
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.
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the NPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the NPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
38
#include "nsIDOMHTMLTableElement.h"
39
#include "nsIDOMHTMLTableCaptionElem.h"
40
#include "nsIDOMHTMLTableSectionElem.h"
42
#include "nsIDOMEventReceiver.h"
43
#include "nsDOMError.h"
44
#include "GenericElementCollection.h"
45
#include "nsIHTMLContent.h"
46
#include "nsMappedAttributes.h"
47
#include "nsGenericHTMLElement.h"
48
#include "nsHTMLAtoms.h"
49
#include "nsStyleConsts.h"
50
#include "nsIPresContext.h"
51
#include "nsHTMLParts.h"
52
#include "nsRuleNode.h"
53
#include "nsStyleContext.h"
54
#include "nsIDocument.h"
57
#include "nsIDOMElement.h"
58
#include "nsGenericHTMLElement.h"
59
/* end for collections */
61
class GenericElementCollection;
62
class TableRowsCollection;
64
class nsHTMLTableElement : public nsGenericHTMLElement,
65
public nsIDOMHTMLTableElement
69
virtual ~nsHTMLTableElement();
72
NS_DECL_ISUPPORTS_INHERITED
75
NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
78
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
81
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
83
// nsIDOMHTMLTableElement
84
NS_DECL_NSIDOMHTMLTABLEELEMENT
86
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
87
const nsAString& aValue,
88
nsAttrValue& aResult);
89
NS_IMETHOD AttributeToString(nsIAtom* aAttribute,
90
const nsHTMLValue& aValue,
91
nsAString& aResult) const;
92
NS_IMETHOD GetAttributeMappingFunction(nsMapRuleToAttributesFunc& aMapRuleFunc) const;
93
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
96
already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
98
GenericElementCollection *mTBodies;
99
TableRowsCollection *mRows;
103
/* ------------------------------ TableRowsCollection -------------------------------- */
105
* This class provides a late-bound collection of rows in a table.
106
* mParent is NOT ref-counted to avoid circular references
108
class TableRowsCollection : public nsGenericDOMHTMLCollection
111
TableRowsCollection(nsHTMLTableElement *aParent);
112
virtual ~TableRowsCollection();
114
NS_IMETHOD GetLength(PRUint32* aLength);
115
NS_IMETHOD Item(PRUint32 aIndex, nsIDOMNode** aReturn);
116
NS_IMETHOD NamedItem(const nsAString& aName,
117
nsIDOMNode** aReturn);
119
NS_IMETHOD ParentDestroyed();
122
nsHTMLTableElement * mParent;
126
TableRowsCollection::TableRowsCollection(nsHTMLTableElement *aParent)
127
: nsGenericDOMHTMLCollection()
132
TableRowsCollection::~TableRowsCollection()
134
// we do NOT have a ref-counted reference to mParent, so do NOT
135
// release it! this is to avoid circular references. The
136
// instantiator who provided mParent is responsible for managing our
140
// we re-count every call. A better implementation would be to set
141
// ourselves up as an observer of contentAppended, contentInserted,
142
// and contentDeleted
144
TableRowsCollection::GetLength(PRUint32* aLength)
146
NS_ENSURE_ARG_POINTER(aLength);
152
// count the rows in the thead, tfoot, and all tbodies
153
nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;
155
mParent->GetTHead(getter_AddRefs(rowGroup));
158
nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
160
GenericElementCollection head(content, nsHTMLAtoms::tr);
163
head.GetLength(&rows);
168
mParent->GetTFoot(getter_AddRefs(rowGroup));
171
nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
173
GenericElementCollection foot(content, nsHTMLAtoms::tr);
176
foot.GetLength(&rows);
180
nsCOMPtr<nsIDOMHTMLCollection> tbodies;
182
mParent->GetTBodies(getter_AddRefs(tbodies));
185
nsCOMPtr<nsIDOMNode> node;
191
tbodies->Item(theIndex, getter_AddRefs(node));
194
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
196
GenericElementCollection body(content, nsHTMLAtoms::tr);
199
body.GetLength(&rows);
205
tbodies->Item(theIndex, getter_AddRefs(node));
213
// increments aReturn refcnt by 1
215
TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
222
nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;
225
mParent->GetTHead(getter_AddRefs(rowGroup));
228
nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
230
GenericElementCollection head(content, nsHTMLAtoms::tr);
233
head.GetLength(&rowsInHead);
237
if (count > aIndex) {
238
head.Item(aIndex, aReturn);
244
nsCOMPtr<nsIDOMHTMLCollection> tbodies;
246
mParent->GetTBodies(getter_AddRefs(tbodies));
250
nsCOMPtr<nsIDOMNode> node;
253
tbodies->Item(theIndex, getter_AddRefs(node));
256
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
258
GenericElementCollection body(content, nsHTMLAtoms::tr);
261
body.GetLength(&rows);
263
if ((count+rows) > aIndex) {
264
body.Item(aIndex-count, aReturn);
271
tbodies->Item(theIndex, getter_AddRefs(node));
276
mParent->GetTFoot(getter_AddRefs(rowGroup));
279
nsCOMPtr<nsIContent> content(do_QueryInterface(rowGroup));
281
GenericElementCollection foot(content, nsHTMLAtoms::tr);
282
foot.Item(aIndex-count, aReturn);
290
TableRowsCollection::NamedItem(const nsAString& aName,
291
nsIDOMNode** aReturn)
293
NS_ENSURE_ARG_POINTER(aReturn);
295
// FIXME: Implement this!
303
TableRowsCollection::ParentDestroyed()
305
// see comment in destructor, do NOT release mParent!
311
/* -------------------------- nsHTMLTableElement --------------------------- */
312
// the class declaration is at the top of this file
315
NS_NewHTMLTableElement(nsIHTMLContent** aInstancePtrResult,
316
nsINodeInfo *aNodeInfo, PRBool aFromParser)
318
NS_ENSURE_ARG_POINTER(aInstancePtrResult);
320
nsHTMLTableElement* it = new nsHTMLTableElement();
323
return NS_ERROR_OUT_OF_MEMORY;
326
nsresult rv = it->Init(aNodeInfo);
334
*aInstancePtrResult = NS_STATIC_CAST(nsIHTMLContent *, it);
335
NS_ADDREF(*aInstancePtrResult);
341
nsHTMLTableElement::nsHTMLTableElement()
347
nsHTMLTableElement::~nsHTMLTableElement()
350
mTBodies->ParentDestroyed();
351
NS_RELEASE(mTBodies);
355
mRows->ParentDestroyed();
361
NS_IMPL_ADDREF_INHERITED(nsHTMLTableElement, nsGenericElement)
362
NS_IMPL_RELEASE_INHERITED(nsHTMLTableElement, nsGenericElement)
365
// QueryInterface implementation for nsHTMLTableElement
366
NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLTableElement, nsGenericHTMLElement)
367
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLTableElement)
368
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLTableElement)
369
NS_HTML_CONTENT_INTERFACE_MAP_END
373
nsHTMLTableElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
375
NS_ENSURE_ARG_POINTER(aReturn);
378
nsHTMLTableElement* it = new nsHTMLTableElement();
381
return NS_ERROR_OUT_OF_MEMORY;
384
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
386
nsresult rv = it->Init(mNodeInfo);
391
CopyInnerTo(it, aDeep);
393
*aReturn = NS_STATIC_CAST(nsIDOMNode *, it);
401
// the DOM spec says border, cellpadding, cellSpacing are all "wstring"
402
// in fact, they are integers or they are meaningless. so we store them
405
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Align, align)
406
NS_IMPL_STRING_ATTR(nsHTMLTableElement, BgColor, bgcolor)
407
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Border, border)
408
NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellPadding, cellpadding)
409
NS_IMPL_STRING_ATTR(nsHTMLTableElement, CellSpacing, cellspacing)
410
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Frame, frame)
411
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Rules, rules)
412
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Summary, summary)
413
NS_IMPL_STRING_ATTR(nsHTMLTableElement, Width, width)
417
nsHTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
420
nsCOMPtr<nsIDOMNode> child;
421
GetFirstChild(getter_AddRefs(child));
424
nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption(do_QueryInterface(child));
433
nsIDOMNode *temp = child.get();
434
temp->GetNextSibling(getter_AddRefs(child));
441
nsHTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
443
nsresult rv = DeleteCaption();
445
if (NS_SUCCEEDED(rv)) {
447
nsCOMPtr<nsIDOMNode> resultingChild;
448
AppendChild(aValue, getter_AddRefs(resultingChild));
455
already_AddRefed<nsIDOMHTMLTableSectionElement>
456
nsHTMLTableElement::GetSection(nsIAtom *aTag)
458
PRUint32 childCount = GetChildCount();
460
nsCOMPtr<nsIDOMHTMLTableSectionElement> section;
462
for (PRUint32 i = 0; i < childCount; ++i) {
463
nsIContent *child = GetChildAt(i);
465
section = do_QueryInterface(child);
467
if (section && child->GetNodeInfo()->Equals(aTag)) {
468
nsIDOMHTMLTableSectionElement *result = section;
479
nsHTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
481
*aValue = GetSection(nsHTMLAtoms::thead).get();
487
nsHTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
489
nsresult rv = DeleteTHead();
495
nsCOMPtr<nsIDOMNode> child;
496
rv = GetFirstChild(getter_AddRefs(child));
501
nsCOMPtr<nsIDOMNode> resultChild;
502
rv = InsertBefore(aValue, child, getter_AddRefs(resultChild));
509
nsHTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
511
*aValue = GetSection(nsHTMLAtoms::tfoot).get();
517
nsHTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
519
nsresult rv = DeleteTFoot();
520
if (NS_SUCCEEDED(rv)) {
522
nsCOMPtr<nsIDOMNode> resultingChild;
523
AppendChild(aValue, getter_AddRefs(resultingChild));
531
nsHTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
534
// XXX why was this here NS_ADDREF(nsHTMLAtoms::tr);
535
mRows = new TableRowsCollection(this);
536
NS_ENSURE_TRUE(mRows, NS_ERROR_OUT_OF_MEMORY);
538
NS_ADDREF(mRows); // this table's reference, released in the destructor
548
nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
551
mTBodies = new GenericElementCollection((nsIContent*)this,
554
NS_ENSURE_TRUE(mTBodies, NS_ERROR_OUT_OF_MEMORY);
556
NS_ADDREF(mTBodies); // this table's reference, released in the destructor
559
return CallQueryInterface(mTBodies, aValue);
563
nsHTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
567
nsCOMPtr<nsIDOMHTMLTableSectionElement> head;
569
GetTHead(getter_AddRefs(head));
571
if (head) { // return the existing thead
572
CallQueryInterface(head, aValue);
574
NS_ASSERTION(*aValue, "head must be a DOMHTMLElement");
577
{ // create a new head rowgroup
578
nsCOMPtr<nsIHTMLContent> newHead;
579
nsCOMPtr<nsINodeInfo> nodeInfo;
581
mNodeInfo->NameChanged(nsHTMLAtoms::thead, getter_AddRefs(nodeInfo));
583
rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newHead),nodeInfo);
585
if (NS_SUCCEEDED(rv) && newHead) {
586
nsCOMPtr<nsIDOMNode> child;
588
rv = GetFirstChild(getter_AddRefs(child));
594
CallQueryInterface(newHead, aValue);
596
nsCOMPtr<nsIDOMNode> resultChild;
597
rv = InsertBefore(*aValue, child, getter_AddRefs(resultChild));
605
nsHTMLTableElement::DeleteTHead()
607
nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
608
nsresult rv = GetTHead(getter_AddRefs(childToDelete));
610
if ((NS_SUCCEEDED(rv)) && childToDelete) {
611
nsCOMPtr<nsIDOMNode> resultingChild;
612
// mInner does the notification
613
RemoveChild(childToDelete, getter_AddRefs(resultingChild));
620
nsHTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
624
nsCOMPtr<nsIDOMHTMLTableSectionElement> foot;
626
GetTFoot(getter_AddRefs(foot));
628
if (foot) { // return the existing tfoot
629
CallQueryInterface(foot, aValue);
631
NS_ASSERTION(*aValue, "foot must be a DOMHTMLElement");
634
{ // create a new foot rowgroup
635
nsCOMPtr<nsIHTMLContent> newFoot;
637
nsCOMPtr<nsINodeInfo> nodeInfo;
638
mNodeInfo->NameChanged(nsHTMLAtoms::tfoot, getter_AddRefs(nodeInfo));
640
rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newFoot),nodeInfo);
642
if (NS_SUCCEEDED(rv) && newFoot) {
643
rv = AppendChildTo(newFoot, PR_TRUE, PR_FALSE);
644
CallQueryInterface(newFoot, aValue);
652
nsHTMLTableElement::DeleteTFoot()
654
nsCOMPtr<nsIDOMHTMLTableSectionElement> childToDelete;
655
nsresult rv = GetTFoot(getter_AddRefs(childToDelete));
657
if ((NS_SUCCEEDED(rv)) && childToDelete) {
658
nsCOMPtr<nsIDOMNode> resultingChild;
659
// mInner does the notification
660
RemoveChild(childToDelete, getter_AddRefs(resultingChild));
667
nsHTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
671
nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption;
673
GetCaption(getter_AddRefs(caption));
675
if (caption) { // return the existing thead
676
CallQueryInterface(caption, aValue);
678
NS_ASSERTION(*aValue, "caption must be a DOMHTMLElement");
681
{ // create a new head rowgroup
682
nsCOMPtr<nsIHTMLContent> newCaption;
684
nsCOMPtr<nsINodeInfo> nodeInfo;
685
mNodeInfo->NameChanged(nsHTMLAtoms::caption, getter_AddRefs(nodeInfo));
687
rv = NS_NewHTMLTableCaptionElement(getter_AddRefs(newCaption),nodeInfo);
689
if (NS_SUCCEEDED(rv) && newCaption) {
690
rv = AppendChildTo(newCaption, PR_TRUE, PR_FALSE);
691
CallQueryInterface(newCaption, aValue);
699
nsHTMLTableElement::DeleteCaption()
701
nsCOMPtr<nsIDOMHTMLTableCaptionElement> childToDelete;
702
nsresult rv = GetCaption(getter_AddRefs(childToDelete));
704
if ((NS_SUCCEEDED(rv)) && childToDelete) {
705
nsCOMPtr<nsIDOMNode> resultingChild;
706
RemoveChild(childToDelete, getter_AddRefs(resultingChild));
713
nsHTMLTableElement::InsertRow(PRInt32 aIndex, nsIDOMHTMLElement** aValue)
715
/* get the ref row at aIndex
718
insert the new row just before the ref row
720
get the first row group
721
insert the new row as its first child
726
return NS_ERROR_DOM_INDEX_SIZE_ERR;
731
nsCOMPtr<nsIDOMHTMLCollection> rows;
732
GetRows(getter_AddRefs(rows));
735
rows->GetLength(&rowCount);
737
if ((PRUint32)aIndex > rowCount && aIndex != -1) {
738
return NS_ERROR_DOM_INDEX_SIZE_ERR;
741
// use local variable refIndex so we can remember original aIndex
742
PRUint32 refIndex = (PRUint32)aIndex;
745
if (refIndex == rowCount || aIndex == -1) {
746
// we set refIndex to the last row so we can get the last row's
747
// parent we then do an AppendChild below if (rowCount<aIndex)
749
refIndex = rowCount - 1;
752
nsCOMPtr<nsIDOMNode> refRow;
753
rows->Item(refIndex, getter_AddRefs(refRow));
755
nsCOMPtr<nsIDOMNode> parent;
757
refRow->GetParentNode(getter_AddRefs(parent));
760
nsCOMPtr<nsIHTMLContent> newRow;
762
nsCOMPtr<nsINodeInfo> nodeInfo;
763
mNodeInfo->NameChanged(nsHTMLAtoms::tr, getter_AddRefs(nodeInfo));
765
rv = NS_NewHTMLTableRowElement(getter_AddRefs(newRow), nodeInfo);
767
if (NS_SUCCEEDED(rv) && newRow) {
768
nsCOMPtr<nsIDOMNode> newRowNode(do_QueryInterface(newRow));
769
nsCOMPtr<nsIDOMNode> retChild;
771
// If index is -1 or equal to the number of rows, the new row
773
if (aIndex == -1 || PRUint32(aIndex) == rowCount) {
774
rv = parent->AppendChild(newRowNode, getter_AddRefs(retChild));
778
// insert the new row before the reference row we found above
779
rv = parent->InsertBefore(newRowNode, refRow,
780
getter_AddRefs(retChild));
784
CallQueryInterface(retChild, aValue);
789
{ // the row count was 0, so
790
// find the first row group and insert there as first child
791
nsCOMPtr<nsIDOMNode> rowGroup;
793
GenericElementCollection head(this, nsHTMLAtoms::thead);
797
head.GetLength(&length);
800
head.Item(0, getter_AddRefs(rowGroup));
804
GenericElementCollection body(this, nsHTMLAtoms::tbody);
807
body.GetLength(&length);
810
body.Item(0, getter_AddRefs(rowGroup));
814
GenericElementCollection foot(this, nsHTMLAtoms::tfoot);
818
foot.GetLength(&length);
821
foot.Item(0, getter_AddRefs(rowGroup));
826
if (!rowGroup) { // need to create a TBODY
827
nsCOMPtr<nsIHTMLContent> newRowGroup;
829
nsCOMPtr<nsINodeInfo> nodeInfo;
830
mNodeInfo->NameChanged(nsHTMLAtoms::tbody, getter_AddRefs(nodeInfo));
832
rv = NS_NewHTMLTableSectionElement(getter_AddRefs(newRowGroup),
835
if (NS_SUCCEEDED(rv) && newRowGroup) {
836
rv = AppendChildTo(newRowGroup, PR_TRUE, PR_FALSE);
838
rowGroup = do_QueryInterface(newRowGroup);
843
nsCOMPtr<nsIHTMLContent> newRow;
845
nsCOMPtr<nsINodeInfo> nodeInfo;
846
mNodeInfo->NameChanged(nsHTMLAtoms::tr, getter_AddRefs(nodeInfo));
848
rv = NS_NewHTMLTableRowElement(getter_AddRefs(newRow), nodeInfo);
849
nsCOMPtr<nsIContent> rowGroupContent(do_QueryInterface(rowGroup));
851
GenericElementCollection rowGroupRows(rowGroupContent, nsHTMLAtoms::tr);
853
nsCOMPtr<nsIDOMNode> firstRow;
855
// it's ok if this returns nsnull
856
rowGroupRows.Item(0, getter_AddRefs(firstRow));
859
nsCOMPtr<nsIDOMNode> retNode, newRowNode(do_QueryInterface(newRow));
861
rowGroup->InsertBefore(newRowNode, firstRow, getter_AddRefs(retNode));
864
CallQueryInterface(retNode, aValue);
874
nsHTMLTableElement::DeleteRow(PRInt32 aValue)
877
return NS_ERROR_DOM_INDEX_SIZE_ERR;
880
nsCOMPtr<nsIDOMHTMLCollection> rows;
881
GetRows(getter_AddRefs(rows));
886
rv = rows->GetLength(&refIndex);
887
NS_ENSURE_SUCCESS(rv, rv);
896
refIndex = (PRUint32)aValue;
899
nsCOMPtr<nsIDOMNode> row;
900
rv = rows->Item(refIndex, getter_AddRefs(row));
901
NS_ENSURE_SUCCESS(rv, rv);
904
return NS_ERROR_DOM_INDEX_SIZE_ERR;
907
nsCOMPtr<nsIDOMNode> parent;
908
row->GetParentNode(getter_AddRefs(parent));
909
NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
911
nsCOMPtr<nsIDOMNode> deleted_row;
912
return parent->RemoveChild(row, getter_AddRefs(deleted_row));
915
static const nsHTMLValue::EnumTable kFrameTable[] = {
916
{ "void", NS_STYLE_TABLE_FRAME_NONE },
917
{ "above", NS_STYLE_TABLE_FRAME_ABOVE },
918
{ "below", NS_STYLE_TABLE_FRAME_BELOW },
919
{ "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
920
{ "lhs", NS_STYLE_TABLE_FRAME_LEFT },
921
{ "rhs", NS_STYLE_TABLE_FRAME_RIGHT },
922
{ "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
923
{ "box", NS_STYLE_TABLE_FRAME_BOX },
924
{ "border", NS_STYLE_TABLE_FRAME_BORDER },
928
static const nsHTMLValue::EnumTable kRulesTable[] = {
929
{ "none", NS_STYLE_TABLE_RULES_NONE },
930
{ "groups", NS_STYLE_TABLE_RULES_GROUPS },
931
{ "rows", NS_STYLE_TABLE_RULES_ROWS },
932
{ "cols", NS_STYLE_TABLE_RULES_COLS },
933
{ "all", NS_STYLE_TABLE_RULES_ALL },
937
static const nsHTMLValue::EnumTable kLayoutTable[] = {
938
{ "auto", NS_STYLE_TABLE_LAYOUT_AUTO },
939
{ "fixed", NS_STYLE_TABLE_LAYOUT_FIXED },
945
nsHTMLTableElement::ParseAttribute(nsIAtom* aAttribute,
946
const nsAString& aValue,
947
nsAttrValue& aResult)
949
/* ignore summary, just a string */
950
if (aAttribute == nsHTMLAtoms::cellspacing ||
951
aAttribute == nsHTMLAtoms::cellpadding) {
952
return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
954
if (aAttribute == nsHTMLAtoms::cols) {
955
return aResult.ParseIntWithBounds(aValue, 0);
957
if (aAttribute == nsHTMLAtoms::border) {
958
if (!aResult.ParseIntWithBounds(aValue, 0)) {
959
// XXX this should really be NavQuirks only to allow non numeric value
960
aResult.SetTo(1, nsAttrValue::eInteger);
965
if (aAttribute == nsHTMLAtoms::height) {
966
return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
968
if (aAttribute == nsHTMLAtoms::width) {
969
if (aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE)) {
970
// treat 0 width as auto
971
nsAttrValue::ValueType type = aResult.Type();
972
if ((type == nsAttrValue::eInteger && aResult.GetIntegerValue() == 0) ||
973
(type == nsAttrValue::ePercent && aResult.GetPercentValue() == 0.0f)) {
979
if (aAttribute == nsHTMLAtoms::align) {
980
return ParseTableHAlignValue(aValue, aResult);
982
if (aAttribute == nsHTMLAtoms::bgcolor ||
983
aAttribute == nsHTMLAtoms::bordercolor) {
984
return aResult.ParseColor(aValue, nsGenericHTMLElement::GetOwnerDocument());
986
if (aAttribute == nsHTMLAtoms::frame) {
987
return aResult.ParseEnumValue(aValue, kFrameTable);
989
if (aAttribute == nsHTMLAtoms::layout) {
990
return aResult.ParseEnumValue(aValue, kLayoutTable);
992
if (aAttribute == nsHTMLAtoms::rules) {
993
return aResult.ParseEnumValue(aValue, kRulesTable);
995
if (aAttribute == nsHTMLAtoms::hspace ||
996
aAttribute == nsHTMLAtoms::vspace) {
997
return aResult.ParseIntWithBounds(aValue, 0);
1000
return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
1004
nsHTMLTableElement::AttributeToString(nsIAtom* aAttribute,
1005
const nsHTMLValue& aValue,
1006
nsAString& aResult) const
1008
/* ignore summary, just a string */
1009
/* ignore attributes that are of standard types border, cellpadding,
1010
cellspacing, cols, height, width, background, bgcolor */
1011
if (aAttribute == nsHTMLAtoms::align) {
1012
if (TableHAlignValueToString(aValue, aResult)) {
1013
return NS_CONTENT_ATTR_HAS_VALUE;
1016
else if (aAttribute == nsHTMLAtoms::frame) {
1017
if (aValue.EnumValueToString(kFrameTable, aResult)) {
1018
return NS_CONTENT_ATTR_HAS_VALUE;
1021
else if (aAttribute == nsHTMLAtoms::layout) {
1022
if (aValue.EnumValueToString(kLayoutTable, aResult)) {
1023
return NS_CONTENT_ATTR_HAS_VALUE;
1026
else if (aAttribute == nsHTMLAtoms::rules) {
1027
if (aValue.EnumValueToString(kRulesTable, aResult)) {
1028
return NS_CONTENT_ATTR_HAS_VALUE;
1032
return nsGenericHTMLElement::AttributeToString(aAttribute, aValue, aResult);
1036
MapTableFrameInto(const nsMappedAttributes* aAttributes,
1037
nsRuleData* aData, PRUint8 aBorderStyle)
1039
if (!aData->mMarginData)
1043
if (aData->mMarginData->mBorderStyle.mLeft.GetUnit() == eCSSUnit_Null)
1044
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
1045
if (aData->mMarginData->mBorderStyle.mRight.GetUnit() == eCSSUnit_Null)
1046
aData->mMarginData->mBorderStyle.mRight.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
1047
if (aData->mMarginData->mBorderStyle.mTop.GetUnit() == eCSSUnit_Null)
1048
aData->mMarginData->mBorderStyle.mTop.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
1049
if (aData->mMarginData->mBorderStyle.mBottom.GetUnit() == eCSSUnit_Null)
1050
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(aBorderStyle, eCSSUnit_Enumerated);
1052
nsHTMLValue frameValue;
1053
// 0 out the sides that we want to hide based on the frame attribute
1054
aAttributes->GetAttribute(nsHTMLAtoms::frame, frameValue);
1056
if (frameValue.GetUnit() == eHTMLUnit_Enumerated) {
1057
// adjust the border style based on the value of frame
1058
switch (frameValue.GetIntValue())
1060
case NS_STYLE_TABLE_FRAME_NONE:
1061
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1062
aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1063
aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1064
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1066
case NS_STYLE_TABLE_FRAME_ABOVE:
1067
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1068
aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1069
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1071
case NS_STYLE_TABLE_FRAME_BELOW:
1072
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1073
aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1074
aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1076
case NS_STYLE_TABLE_FRAME_HSIDES:
1077
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1078
aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1080
case NS_STYLE_TABLE_FRAME_LEFT:
1081
aData->mMarginData->mBorderStyle.mRight.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1082
aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1083
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1085
case NS_STYLE_TABLE_FRAME_RIGHT:
1086
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1087
aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1088
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1090
case NS_STYLE_TABLE_FRAME_VSIDES:
1091
aData->mMarginData->mBorderStyle.mTop.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1092
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(NS_STYLE_BORDER_STYLE_NONE, eCSSUnit_Enumerated);
1094
// BOX and BORDER are ignored, the caller has already set all the border sides
1095
// any illegal value is also ignored
1101
MapTableBorderInto(const nsMappedAttributes* aAttributes,
1102
nsRuleData* aData, PRUint8 aBorderStyle)
1104
nsHTMLValue borderValue;
1105
if (aAttributes->GetAttribute(nsHTMLAtoms::border, borderValue) ==
1106
NS_CONTENT_ATTR_NOT_THERE) {
1107
// the absence of "border" with the presence of "frame" implies
1109
if (!aAttributes->GetAttr(nsHTMLAtoms::frame)) {
1112
borderValue.SetIntValue(1, eHTMLUnit_Integer);
1115
if (borderValue.GetUnit() != eHTMLUnit_Integer) {
1116
// empty values of border get rules=all and frame=border
1117
if (aData->mTableData) {
1118
aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_ALL, eCSSUnit_Enumerated);
1119
aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_BORDER, eCSSUnit_Enumerated);
1121
borderValue.SetIntValue(1, eHTMLUnit_Integer);
1124
PRInt32 borderThickness = borderValue.GetIntValue();
1126
if (0 != borderThickness) {
1127
// border != 0 implies rules=all and frame=border
1128
if (aData->mTableData) {
1129
aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_ALL, eCSSUnit_Enumerated);
1130
aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_BORDER, eCSSUnit_Enumerated);
1134
// border = 0 implies rules=none and frame=void
1135
if (aData->mTableData) {
1136
aData->mTableData->mRules.SetIntValue(NS_STYLE_TABLE_RULES_NONE, eCSSUnit_Enumerated);
1137
aData->mTableData->mFrame.SetIntValue(NS_STYLE_TABLE_FRAME_NONE, eCSSUnit_Enumerated);
1142
PRInt32 borderThickness = borderValue.GetIntValue();
1144
if (aData->mMarginData) {
1145
// by default, set all border sides to the specified width
1146
if (aData->mMarginData->mBorderWidth.mLeft.GetUnit() == eCSSUnit_Null)
1147
aData->mMarginData->mBorderWidth.mLeft.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
1148
if (aData->mMarginData->mBorderWidth.mRight.GetUnit() == eCSSUnit_Null)
1149
aData->mMarginData->mBorderWidth.mRight.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
1150
if (aData->mMarginData->mBorderWidth.mTop.GetUnit() == eCSSUnit_Null)
1151
aData->mMarginData->mBorderWidth.mTop .SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
1152
if (aData->mMarginData->mBorderWidth.mBottom.GetUnit() == eCSSUnit_Null)
1153
aData->mMarginData->mBorderWidth.mBottom.SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
1155
// now account for the frame attribute
1156
MapTableFrameInto(aAttributes, aData, aBorderStyle);
1161
MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
1164
// XXX Bug 211636: This function is used by a single style rule
1165
// that's used to match two different type of elements -- tables, and
1166
// table cells. (nsHTMLTableCellElement overrides
1167
// WalkContentStyleRules so that this happens.) This violates the
1168
// nsIStyleRule contract, since it's the same style rule object doing
1169
// the mapping in two different ways. It's also incorrect since it's
1170
// testing the display type of the style context rather than checking
1171
// which *element* it's matching (style rules should not stop matching
1172
// when the display type is changed).
1174
nsCompatibility mode = aData->mPresContext->CompatibilityMode();
1176
if (aData->mSID == eStyleStruct_TableBorder) {
1177
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1178
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
1181
aAttributes->GetAttribute(nsHTMLAtoms::cellspacing, value);
1182
if (value.GetUnit() == eHTMLUnit_Integer) {
1183
if (aData->mTableData->mBorderSpacingX.GetUnit() == eCSSUnit_Null)
1184
aData->mTableData->mBorderSpacingX.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1185
if (aData->mTableData->mBorderSpacingY.GetUnit() == eCSSUnit_Null)
1186
aData->mTableData->mBorderSpacingY.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1188
else if ((value.GetUnit() == eHTMLUnit_Percent) && (eCompatibility_NavQuirks == mode)) {
1189
// in quirks mode, treat a % cellspacing value a pixel value.
1190
if (aData->mTableData->mBorderSpacingX.GetUnit() == eCSSUnit_Null)
1191
aData->mTableData->mBorderSpacingX.SetFloatValue(100.0f * value.GetPercentValue(), eCSSUnit_Pixel);
1192
if (aData->mTableData->mBorderSpacingY.GetUnit() == eCSSUnit_Null)
1193
aData->mTableData->mBorderSpacingY.SetFloatValue(100.0f * value.GetPercentValue(), eCSSUnit_Pixel);
1197
else if (aData->mSID == eStyleStruct_Table) {
1198
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1199
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
1200
MapTableBorderInto(aAttributes, aData, 0);
1204
if (aData->mTableData->mLayout.GetUnit() == eCSSUnit_Null) {
1205
aAttributes->GetAttribute(nsHTMLAtoms::layout, value);
1206
if (value.GetUnit() == eHTMLUnit_Enumerated)
1207
aData->mTableData->mLayout.SetIntValue(value.GetIntValue(), eCSSUnit_Enumerated);
1211
if (aAttributes->GetAttribute(nsHTMLAtoms::cols, value) !=
1212
NS_CONTENT_ATTR_NOT_THERE) {
1213
if (value.GetUnit() == eHTMLUnit_Integer)
1214
aData->mTableData->mCols.SetIntValue(value.GetIntValue(), eCSSUnit_Integer);
1215
else // COLS had no value, so it refers to all columns
1216
aData->mTableData->mCols.SetIntValue(NS_STYLE_TABLE_COLS_ALL, eCSSUnit_Enumerated);
1220
aAttributes->GetAttribute(nsHTMLAtoms::rules, value);
1221
if (value.GetUnit() == eHTMLUnit_Enumerated)
1222
aData->mTableData->mRules.SetIntValue(value.GetIntValue(), eCSSUnit_Enumerated);
1225
else if (aData->mSID == eStyleStruct_Margin) {
1226
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1228
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
1229
// align; Check for enumerated type (it may be another type if
1232
aAttributes->GetAttribute(nsHTMLAtoms::align, value);
1234
if (value.GetUnit() == eHTMLUnit_Enumerated) {
1235
if ((NS_STYLE_TEXT_ALIGN_CENTER == value.GetIntValue()) ||
1236
(NS_STYLE_TEXT_ALIGN_MOZ_CENTER == value.GetIntValue())) {
1237
nsCSSRect& margin = aData->mMarginData->mMargin;
1238
if (margin.mLeft.GetUnit() == eCSSUnit_Null)
1239
margin.mLeft.SetAutoValue();
1240
if (margin.mRight.GetUnit() == eCSSUnit_Null)
1241
margin.mRight.SetAutoValue();
1245
// hspace is mapped into left and right margin,
1246
// vspace is mapped into top and bottom margins
1247
// - *** Quirks Mode only ***
1248
if (eCompatibility_NavQuirks == mode) {
1249
aAttributes->GetAttribute(nsHTMLAtoms::hspace, value);
1251
if (value.GetUnit() == eHTMLUnit_Integer) {
1252
nsCSSRect& margin = aData->mMarginData->mMargin;
1253
if (margin.mLeft.GetUnit() == eCSSUnit_Null)
1254
margin.mLeft.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1255
if (margin.mRight.GetUnit() == eCSSUnit_Null)
1256
margin.mRight.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1259
aAttributes->GetAttribute(nsHTMLAtoms::vspace, value);
1261
if (value.GetUnit() == eHTMLUnit_Integer) {
1262
nsCSSRect& margin = aData->mMarginData->mMargin;
1263
if (margin.mTop.GetUnit() == eCSSUnit_Null)
1264
margin.mTop.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1265
if (margin.mBottom.GetUnit() == eCSSUnit_Null)
1266
margin.mBottom.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1271
else if (aData->mSID == eStyleStruct_Padding) {
1272
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1274
if (readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
1276
aAttributes->GetAttribute(nsHTMLAtoms::cellpadding, value);
1277
if (value.GetUnit() == eHTMLUnit_Integer || value.GetUnit() == eHTMLUnit_Percent) {
1278
// We have cellpadding. This will override our padding values if we don't
1281
if (value.GetUnit() == eHTMLUnit_Integer)
1282
padVal.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1284
// when we support % cellpadding in standard mode, uncomment the following
1285
float pctVal = value.GetPercentValue();
1286
//if (eCompatibility_NavQuirks == mode) {
1287
// in quirks mode treat a pct cellpadding value as a pixel value
1288
padVal.SetFloatValue(100.0f * pctVal, eCSSUnit_Pixel);
1291
// padVal.SetPercentValue(pctVal);
1294
if (aData->mMarginData->mPadding.mLeft.GetUnit() == eCSSUnit_Null)
1295
aData->mMarginData->mPadding.mLeft = padVal;
1296
if (aData->mMarginData->mPadding.mRight.GetUnit() == eCSSUnit_Null)
1297
aData->mMarginData->mPadding.mRight = padVal;
1298
if (aData->mMarginData->mPadding.mTop.GetUnit() == eCSSUnit_Null)
1299
aData->mMarginData->mPadding.mTop = padVal;
1300
if (aData->mMarginData->mPadding.mBottom.GetUnit() == eCSSUnit_Null)
1301
aData->mMarginData->mPadding.mBottom = padVal;
1305
else if (aData->mSID == eStyleStruct_Position) {
1306
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1308
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL) {
1311
if (aData->mPositionData->mWidth.GetUnit() == eCSSUnit_Null) {
1312
aAttributes->GetAttribute(nsHTMLAtoms::width, value);
1313
if (value.GetUnit() == eHTMLUnit_Integer)
1314
aData->mPositionData->mWidth.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1315
else if (value.GetUnit() == eHTMLUnit_Percent)
1316
aData->mPositionData->mWidth.SetPercentValue(value.GetPercentValue());
1320
if (aData->mPositionData->mHeight.GetUnit() == eCSSUnit_Null) {
1321
aAttributes->GetAttribute(nsHTMLAtoms::height, value);
1322
if (value.GetUnit() == eHTMLUnit_Integer)
1323
aData->mPositionData->mHeight.SetFloatValue((float)value.GetIntValue(), eCSSUnit_Pixel);
1324
else if (value.GetUnit() == eHTMLUnit_Percent)
1325
aData->mPositionData->mHeight.SetPercentValue(value.GetPercentValue());
1329
else if (aData->mSID == eStyleStruct_Visibility) {
1330
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1332
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
1333
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
1335
else if (aData->mSID == eStyleStruct_Border) {
1336
if (!aData->mStyleContext) return;
1337
const nsStyleTableBorder* tableStyle = aData->mStyleContext->GetStyleTableBorder();
1338
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1339
if (readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
1340
if (NS_STYLE_BORDER_SEPARATE == tableStyle->mBorderCollapse) {
1341
// Set the cell's border from the table in the separate border model. If there is a border
1342
// on the table, then the mapping to rules=all will take care of borders in the collapsing model.
1344
if (aAttributes->GetAttribute(nsHTMLAtoms::border, value) !=
1345
NS_CONTENT_ATTR_NOT_THERE &&
1346
((value.GetUnit() == eHTMLUnit_Integer &&
1347
value.GetIntValue() > 0) ||
1348
value.IsEmptyString())) {
1349
if (aData->mMarginData->mBorderWidth.mLeft.GetUnit() == eCSSUnit_Null)
1350
aData->mMarginData->mBorderWidth.mLeft.SetFloatValue(1.0f, eCSSUnit_Pixel);
1351
if (aData->mMarginData->mBorderWidth.mRight.GetUnit() == eCSSUnit_Null)
1352
aData->mMarginData->mBorderWidth.mRight.SetFloatValue(1.0f, eCSSUnit_Pixel);
1353
if (aData->mMarginData->mBorderWidth.mTop.GetUnit() == eCSSUnit_Null)
1354
aData->mMarginData->mBorderWidth.mTop.SetFloatValue(1.0f, eCSSUnit_Pixel);
1355
if (aData->mMarginData->mBorderWidth.mBottom.GetUnit() == eCSSUnit_Null)
1356
aData->mMarginData->mBorderWidth.mBottom.SetFloatValue(1.0f, eCSSUnit_Pixel);
1358
PRUint8 borderStyle = (eCompatibility_NavQuirks == mode)
1359
? NS_STYLE_BORDER_STYLE_BG_INSET : NS_STYLE_BORDER_STYLE_INSET;
1360
// BG_INSET results in a border color based on background colors
1361
// used for NavQuirks only...
1363
if (aData->mMarginData->mBorderStyle.mLeft.GetUnit() == eCSSUnit_Null)
1364
aData->mMarginData->mBorderStyle.mLeft.SetIntValue(borderStyle, eCSSUnit_Enumerated);
1365
if (aData->mMarginData->mBorderStyle.mRight.GetUnit() == eCSSUnit_Null)
1366
aData->mMarginData->mBorderStyle.mRight.SetIntValue(borderStyle, eCSSUnit_Enumerated);
1367
if (aData->mMarginData->mBorderStyle.mTop.GetUnit() == eCSSUnit_Null)
1368
aData->mMarginData->mBorderStyle.mTop.SetIntValue(borderStyle, eCSSUnit_Enumerated);
1369
if (aData->mMarginData->mBorderStyle.mBottom.GetUnit() == eCSSUnit_Null)
1370
aData->mMarginData->mBorderStyle.mBottom.SetIntValue(borderStyle, eCSSUnit_Enumerated);
1375
// default border style is the Nav4.6 extension which uses the
1376
// background color as the basis of the outset border. If the
1377
// table has a transparent background then it finds the closest
1378
// ancestor that has a non-transparent
1379
// background. NS_STYLE_BORDER_OUTSET uses the border color of
1380
// the table and if that is not set, then it uses the color.
1382
PRUint8 borderStyle = (eCompatibility_NavQuirks == mode)
1383
? NS_STYLE_BORDER_STYLE_BG_OUTSET :
1384
NS_STYLE_BORDER_STYLE_OUTSET;
1388
if (aAttributes->GetAttribute(nsHTMLAtoms::bordercolor, value) !=
1389
NS_CONTENT_ATTR_NOT_THERE &&
1390
value.GetColorValue(color)) {
1391
if (aData->mMarginData->mBorderColor.mLeft.GetUnit() == eCSSUnit_Null)
1392
aData->mMarginData->mBorderColor.mLeft.SetColorValue(color);
1393
if (aData->mMarginData->mBorderColor.mRight.GetUnit() == eCSSUnit_Null)
1394
aData->mMarginData->mBorderColor.mRight.SetColorValue(color);
1395
if (aData->mMarginData->mBorderColor.mTop.GetUnit() == eCSSUnit_Null)
1396
aData->mMarginData->mBorderColor.mTop.SetColorValue(color);
1397
if (aData->mMarginData->mBorderColor.mBottom.GetUnit() == eCSSUnit_Null)
1398
aData->mMarginData->mBorderColor.mBottom.SetColorValue(color);
1400
borderStyle = NS_STYLE_BORDER_STYLE_OUTSET; // use css outset
1402
else if (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse) {
1403
// make the color grey
1404
nscolor color = NS_RGB(80, 80, 80);
1405
if (aData->mMarginData->mBorderColor.mLeft.GetUnit() == eCSSUnit_Null)
1406
aData->mMarginData->mBorderColor.mLeft.SetColorValue(color);
1407
if (aData->mMarginData->mBorderColor.mRight.GetUnit() == eCSSUnit_Null)
1408
aData->mMarginData->mBorderColor.mRight.SetColorValue(color);
1409
if (aData->mMarginData->mBorderColor.mTop.GetUnit() == eCSSUnit_Null)
1410
aData->mMarginData->mBorderColor.mTop.SetColorValue(color);
1411
if (aData->mMarginData->mBorderColor.mBottom.GetUnit() == eCSSUnit_Null)
1412
aData->mMarginData->mBorderColor.mBottom.SetColorValue(color);
1416
MapTableBorderInto(aAttributes, aData, borderStyle);
1419
else if (aData->mSID == eStyleStruct_Background) {
1420
const nsStyleDisplay* readDisplay = aData->mStyleContext->GetStyleDisplay();
1422
if (readDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_CELL)
1423
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
1427
NS_IMETHODIMP_(PRBool)
1428
nsHTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
1430
static const MappedAttributeEntry attributes[] = {
1431
{ &nsHTMLAtoms::layout },
1432
{ &nsHTMLAtoms::cellpadding },
1433
{ &nsHTMLAtoms::cellspacing },
1434
{ &nsHTMLAtoms::cols },
1435
{ &nsHTMLAtoms::border },
1436
{ &nsHTMLAtoms::frame },
1437
{ &nsHTMLAtoms::width },
1438
{ &nsHTMLAtoms::height },
1439
{ &nsHTMLAtoms::hspace },
1440
{ &nsHTMLAtoms::vspace },
1442
{ &nsHTMLAtoms::bordercolor },
1444
{ &nsHTMLAtoms::align },
1445
{ &nsHTMLAtoms::rules },
1449
static const MappedAttributeEntry* const map[] = {
1451
sCommonAttributeMap,
1452
sBackgroundAttributeMap,
1455
return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
1459
nsHTMLTableElement::GetAttributeMappingFunction(nsMapRuleToAttributesFunc& aMapRuleFunc) const
1461
aMapRuleFunc = &MapAttributesIntoRule;