2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
5 * (C) 1997 Torben Weis (weis@kde.org)
6 * (C) 1998 Waldo Bastian (bastian@kde.org)
7 * (C) 1999 Lars Knoll (knoll@kde.org)
8 * (C) 1999 Antti Koivisto (koivisto@kde.org)
9 * Copyright (C) 2003 Apple Computer, Inc.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
27 #include "html/html_documentimpl.h"
28 #include "html/html_tableimpl.h"
30 #include "dom/dom_exception.h"
31 #include "dom/dom_node.h"
33 #include "misc/htmlhashes.h"
34 #include "khtmlview.h"
35 #include "khtml_part.h"
37 #include "css/cssstyleselector.h"
38 #include "css/cssproperties.h"
39 #include "css/cssvalues.h"
40 #include "css/csshelper.h"
41 #include "css_valueimpl.h"
42 #include "css/css_stylesheetimpl.h"
44 #include "rendering/render_table.h"
49 using namespace khtml;
52 HTMLTableElementImpl::HTMLTableElementImpl(DocumentPtr *doc)
53 : HTMLElementImpl(doc)
71 HTMLTableElementImpl::~HTMLTableElementImpl()
75 NodeImpl::Id HTMLTableElementImpl::id() const
80 NodeImpl* HTMLTableElementImpl::setCaption( HTMLTableCaptionElementImpl *c )
82 int exceptioncode = 0;
85 replaceChild ( c, tCaption, exceptioncode );
89 r = insertBefore( c, firstChild(), exceptioncode );
94 NodeImpl* HTMLTableElementImpl::setTHead( HTMLTableSectionElementImpl *s )
96 int exceptioncode = 0;
99 replaceChild( s, head, exceptioncode );
103 r = insertBefore( s, foot, exceptioncode );
105 r = insertBefore( s, firstBody, exceptioncode );
107 r = appendChild( s, exceptioncode );
113 NodeImpl* HTMLTableElementImpl::setTFoot( HTMLTableSectionElementImpl *s )
115 int exceptioncode = 0;
118 replaceChild ( s, foot, exceptioncode );
120 } else if( firstBody )
121 r = insertBefore( s, firstBody, exceptioncode );
123 r = appendChild( s, exceptioncode );
128 NodeImpl* HTMLTableElementImpl::setTBody( HTMLTableSectionElementImpl *s )
130 int exceptioncode = 0;
134 replaceChild ( s, firstBody, exceptioncode );
137 r = appendChild( s, exceptioncode );
143 HTMLElementImpl *HTMLTableElementImpl::createTHead( )
147 int exceptioncode = 0;
148 head = new HTMLTableSectionElementImpl(docPtr(), ID_THEAD, true /* implicit */);
150 insertBefore( head, foot, exceptioncode );
152 insertBefore( head, firstBody, exceptioncode);
154 appendChild(head, exceptioncode);
159 void HTMLTableElementImpl::deleteTHead( )
162 int exceptioncode = 0;
163 HTMLElementImpl::removeChild(head, exceptioncode);
168 HTMLElementImpl *HTMLTableElementImpl::createTFoot( )
172 int exceptioncode = 0;
173 foot = new HTMLTableSectionElementImpl(docPtr(), ID_TFOOT, true /*implicit */);
175 insertBefore( foot, firstBody, exceptioncode );
177 appendChild(foot, exceptioncode);
182 void HTMLTableElementImpl::deleteTFoot( )
185 int exceptioncode = 0;
186 HTMLElementImpl::removeChild(foot, exceptioncode);
191 HTMLElementImpl *HTMLTableElementImpl::createCaption( )
195 int exceptioncode = 0;
196 tCaption = new HTMLTableCaptionElementImpl(docPtr());
197 insertBefore( tCaption, firstChild(), exceptioncode );
202 void HTMLTableElementImpl::deleteCaption( )
205 int exceptioncode = 0;
206 HTMLElementImpl::removeChild(tCaption, exceptioncode);
211 HTMLElementImpl *HTMLTableElementImpl::insertRow( long index, int &exceptioncode )
213 // The DOM requires that we create a tbody if the table is empty
214 // (cf DOM2TS HTMLTableElement31 test)
215 // (note: this is different from "if the table has no sections", since we can have
217 if(!firstBody && !head && !foot && !hasChildNodes())
218 setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY, true /* implicit */) );
220 //kdDebug(6030) << k_funcinfo << index << endl;
221 // IE treats index=-1 as default value meaning 'append after last'
222 // This isn't in the DOM. So, not implemented yet.
223 HTMLTableSectionElementImpl* section = 0L;
224 HTMLTableSectionElementImpl* lastSection = 0L;
225 NodeImpl *node = firstChild();
226 bool append = (index == -1);
228 for ( ; node && (index>=0 || append) ; node = node->nextSibling() )
230 // there could be 2 tfoot elements in the table. Only the first one is the "foot", that's why we have the more
231 // complicated if statement below.
232 if ( node != foot && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) )
234 section = static_cast<HTMLTableSectionElementImpl *>(node);
235 lastSection = section;
236 //kdDebug(6030) << k_funcinfo << "section id=" << node->id() << " rows:" << section->numRows() << endl;
239 int rows = section->numRows();
240 if ( rows > index ) {
245 //kdDebug(6030) << " index is now " << index << endl;
249 if ( !found && foot )
250 section = static_cast<HTMLTableSectionElementImpl *>(foot);
252 // Index == 0 means "insert before first row in current section"
253 // or "append after last row" (if there's no current section anymore)
254 if ( !section && ( index == 0 || append ) )
256 section = lastSection;
257 index = section ? section->numRows() : 0;
259 if ( section && (index >= 0 || append) ) {
260 //kdDebug(6030) << "Inserting row into section " << section << " at index " << index << endl;
261 return section->insertRow( index, exceptioncode );
263 // No more sections => index is too big
264 exceptioncode = DOMException::INDEX_SIZE_ERR;
269 void HTMLTableElementImpl::deleteRow( long index, int &exceptioncode )
271 HTMLTableSectionElementImpl* section = 0L;
272 NodeImpl *node = firstChild();
273 bool lastRow = index == -1;
274 HTMLTableSectionElementImpl* lastSection = 0L;
276 for ( ; node ; node = node->nextSibling() )
278 if ( node != foot && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) )
280 section = static_cast<HTMLTableSectionElementImpl *>(node);
281 lastSection = section;
282 int rows = section->numRows();
285 if ( rows > index ) {
294 if ( !found && foot )
295 section = static_cast<HTMLTableSectionElementImpl *>(foot);
298 lastSection->deleteRow( -1, exceptioncode );
299 else if ( section && index >= 0 && index < section->numRows() )
300 section->deleteRow( index, exceptioncode );
302 exceptioncode = DOMException::INDEX_SIZE_ERR;
305 NodeImpl *HTMLTableElementImpl::addChild(NodeImpl *child)
308 kdDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child->nodeName().string() << " )" << endl;
311 if (child->id() == ID_FORM) {
312 // First add the child.
313 HTMLElementImpl::addChild(child);
314 // Now simply return ourselves as the newnode. This has the effect of
315 // demoting the form to a leaf and moving it safely out of the way.
319 // We do not want this check-node-allowed test here, however the code to
320 // build up tables relies on childAllowed failing to make sure that the
321 // table is well-formed, the primary work being to add a tbody element.
322 // As 99.9999% of tables on the weeb do not have tbody elements, it seems
323 // odd to traverse an "error" case for the most common table markup.
324 // See <rdar://problem/3719373> Table parsing and construction relies on
325 // childAllowed failures to build up proper DOM
326 if (child->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
327 // child is a DocumentFragment... check all its children instead of child itself
328 for (NodeImpl *c = child->firstChild(); c; c = c->nextSibling())
329 if (!childAllowed(c))
332 else if (!childAllowed(child)) {
333 // child is not a DocumentFragment... check if it's allowed directly
337 int exceptioncode = 0;
338 NodeImpl *retval = appendChild( child, exceptioncode );
340 switch(child->id()) {
343 tCaption = static_cast<HTMLTableCaptionElementImpl *>(child);
350 head = static_cast<HTMLTableSectionElementImpl *>(child);
354 foot = static_cast<HTMLTableSectionElementImpl *>(child);
358 firstBody = static_cast<HTMLTableSectionElementImpl *>(child);
365 bool HTMLTableElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
371 case ATTR_BACKGROUND:
372 case ATTR_CELLSPACING:
378 case ATTR_BORDERCOLOR:
390 return HTMLElementImpl::mapToEntry(attr, result);
393 void HTMLTableElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
398 addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
401 addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
406 if (attr->isNull()) break;
408 CSSValueImpl* val = attr->decl()->getPropertyCSSValue(CSS_PROP_BORDER_LEFT_WIDTH);
411 if (val->isPrimitiveValue()) {
412 CSSPrimitiveValueImpl* primVal = static_cast<CSSPrimitiveValueImpl*>(val);
413 m_noBorder = !primVal->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
419 // ### this needs more work, as the border value is not only
420 // the border of the box, but also between the cells
425 border = attr->value().toInt();
426 #ifdef DEBUG_DRAW_BORDER
429 m_noBorder = !border;
430 DOMString v = QString::number( border );
431 addCSSLength(attr, CSS_PROP_BORDER_WIDTH, v );
434 // wanted by HTML4 specs
436 frame = Void, rules = None;
438 frame = Box, rules = All;
443 addHTMLColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value());
445 case ATTR_BORDERCOLOR:
446 m_solid = attr->decl();
447 if (!attr->decl() && !attr->isEmpty()) {
448 addHTMLColor(attr, CSS_PROP_BORDER_COLOR, attr->value());
449 addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
450 addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
451 addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
452 addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
456 case ATTR_BACKGROUND:
458 QString url = khtml::parseURL( attr->value() ).string();
460 addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, getDocument()->completeURL(url));
465 if ( strcasecmp( attr->value(), "void" ) == 0 )
467 else if ( strcasecmp( attr->value(), "border" ) == 0 )
469 else if ( strcasecmp( attr->value(), "box" ) == 0 )
471 else if ( strcasecmp( attr->value(), "hsides" ) == 0 )
473 else if ( strcasecmp( attr->value(), "vsides" ) == 0 )
475 else if ( strcasecmp( attr->value(), "above" ) == 0 )
477 else if ( strcasecmp( attr->value(), "below" ) == 0 )
479 else if ( strcasecmp( attr->value(), "lhs" ) == 0 )
481 else if ( strcasecmp( attr->value(), "rhs" ) == 0 )
487 if ( strcasecmp( attr->value(), "none" ) == 0 )
489 else if ( strcasecmp( attr->value(), "groups" ) == 0 )
491 else if ( strcasecmp( attr->value(), "rows" ) == 0 )
493 else if ( strcasecmp( attr->value(), "cols" ) == 0 )
495 else if ( strcasecmp( attr->value(), "all" ) == 0 )
499 case ATTR_CELLSPACING:
500 if (!attr->value().isEmpty())
501 addCSSLength(attr, CSS_PROP_BORDER_SPACING, attr->value());
503 case ATTR_CELLPADDING:
504 if (!attr->value().isEmpty())
505 padding = kMax( 0, attr->value().toInt() );
508 if (m_render && m_render->isTable()) {
509 static_cast<RenderTable *>(m_render)->setCellPadding(padding);
510 if (!m_render->needsLayout())
511 m_render->setNeedsLayout(true);
519 c = attr->val()->toInt();
520 addColumns(c-totalCols);
525 addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
526 addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
529 addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
530 addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
533 if (!attr->value().isEmpty())
534 addCSSProperty(attr, CSS_PROP_FLOAT, attr->value());
537 if (!attr->value().isEmpty())
538 addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
543 HTMLElementImpl::parseHTMLAttribute(attr);
547 CSSMutableStyleDeclarationImpl* HTMLTableElementImpl::additionalAttributeStyleDecl()
551 HTMLAttributeImpl attr(ATTR_TABLEBORDER, m_solid ? "solid" : "outset");
552 CSSMappedAttributeDeclarationImpl* decl = getMappedAttributeDecl(ePersistent, &attr);
554 decl = new CSSMappedAttributeDeclarationImpl(0);
555 decl->setParent(getDocument()->elementSheet());
557 decl->setStrictParsing(false); // Mapped attributes are just always quirky.
559 decl->ref(); // This single ref pins us in the table until the document dies.
561 int v = m_solid ? CSS_VAL_SOLID : CSS_VAL_OUTSET;
562 decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, v, false);
563 decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v, false);
564 decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, v, false);
565 decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, v, false);
567 setMappedAttributeDecl(ePersistent, &attr, decl);
570 decl->setMappedState(ePersistent, attr.id(), attr.value());
575 CSSMutableStyleDeclarationImpl* HTMLTableElementImpl::getSharedCellDecl()
577 HTMLAttributeImpl attr(ATTR_CELLBORDER, m_noBorder ? "none" : (m_solid ? "solid" : "inset"));
578 CSSMappedAttributeDeclarationImpl* decl = getMappedAttributeDecl(ePersistent, &attr);
580 decl = new CSSMappedAttributeDeclarationImpl(0);
581 decl->setParent(getDocument()->elementSheet());
583 decl->setStrictParsing(false); // Mapped attributes are just always quirky.
585 decl->ref(); // This single ref pins us in the table until the table dies.
588 decl->setProperty(CSS_PROP_BORDER_WIDTH, "0", false);
590 decl->setProperty(CSS_PROP_BORDER_WIDTH, "1px", false);
591 int v = m_solid ? CSS_VAL_SOLID : CSS_VAL_INSET;
592 decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, v, false);
593 decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v, false);
594 decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, v, false);
595 decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, v, false);
596 decl->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false);
599 setMappedAttributeDecl(ePersistent, &attr, decl);
602 decl->setMappedState(ePersistent, attr.id(), attr.value());
607 void HTMLTableElementImpl::attach()
610 HTMLElementImpl::attach();
611 if ( m_render && m_render->isTable() )
612 static_cast<RenderTable *>(m_render)->setCellPadding( padding );
615 bool HTMLTableElementImpl::isURLAttribute(AttributeImpl *attr) const
617 return attr->id() == ATTR_BACKGROUND;
620 // --------------------------------------------------------------------------
622 bool HTMLTablePartElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
626 case ATTR_BACKGROUND:
627 case ATTR_BORDERCOLOR:
633 result = eCell; // All table parts will just share in the TD space.
638 return HTMLElementImpl::mapToEntry(attr, result);
641 void HTMLTablePartElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
646 addHTMLColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value() );
648 case ATTR_BACKGROUND:
650 QString url = khtml::parseURL( attr->value() ).string();
652 addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, getDocument()->completeURL(url));
655 case ATTR_BORDERCOLOR:
657 if (!attr->value().isEmpty()) {
658 addHTMLColor(attr, CSS_PROP_BORDER_COLOR, attr->value());
659 addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
660 addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
661 addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
662 addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
668 if (!attr->value().isEmpty())
669 addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
674 DOMString v = attr->value();
675 if ( strcasecmp( attr->value(), "middle" ) == 0 || strcasecmp( attr->value(), "center" ) == 0 )
676 addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
677 else if (strcasecmp(attr->value(), "absmiddle") == 0)
678 addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL_CENTER);
679 else if (strcasecmp(attr->value(), "left") == 0)
680 addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
681 else if (strcasecmp(attr->value(), "right") == 0)
682 addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
684 addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, v);
688 if (!attr->value().isEmpty())
689 addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
694 HTMLElementImpl::parseHTMLAttribute(attr);
698 // -------------------------------------------------------------------------
700 HTMLTableSectionElementImpl::HTMLTableSectionElementImpl(DocumentPtr *doc,
701 ushort tagid, bool implicit)
702 : HTMLTablePartElementImpl(doc)
705 m_implicit = implicit;
708 HTMLTableSectionElementImpl::~HTMLTableSectionElementImpl()
712 NodeImpl::Id HTMLTableSectionElementImpl::id() const
717 NodeImpl *HTMLTableSectionElementImpl::addChild(NodeImpl *child)
720 kdDebug( 6030 ) << nodeName().string() << "(Tbody)::addChild( " << child->nodeName().string() << " )" << endl;
723 if (child->id() == ID_FORM) {
724 // First add the child.
725 HTMLElementImpl::addChild(child);
726 // Now simply return ourselves as the newnode. This has the effect of
727 // demoting the form to a leaf and moving it safely out of the way.
730 return HTMLTablePartElementImpl::addChild(child);
733 // these functions are rather slow, since we need to get the row at
734 // the index... but they aren't used during usual HTML parsing anyway
735 HTMLElementImpl *HTMLTableSectionElementImpl::insertRow( long index, int& exceptioncode )
737 HTMLTableRowElementImpl *r = 0L;
738 NodeListImpl *children = childNodes();
739 int numRows = children ? (int)children->length() : 0;
740 //kdDebug(6030) << k_funcinfo << "index=" << index << " numRows=" << numRows << endl;
741 if ( index < -1 || index > numRows ) {
742 exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
746 r = new HTMLTableRowElementImpl(docPtr());
747 if ( numRows == index || index == -1 )
748 appendChild(r, exceptioncode);
754 n = children->item(index);
755 insertBefore(r, n, exceptioncode );
762 void HTMLTableSectionElementImpl::deleteRow( long index, int &exceptioncode )
764 NodeListImpl *children = childNodes();
765 int numRows = children ? (int)children->length() : 0;
766 if ( index == -1 ) index = numRows - 1;
767 if( index >= 0 && index < numRows )
768 HTMLElementImpl::removeChild(children->item(index), exceptioncode);
770 exceptioncode = DOMException::INDEX_SIZE_ERR;
775 int HTMLTableSectionElementImpl::numRows() const
778 const NodeImpl *n = firstChild();
780 if (n->id() == ID_TR)
782 n = n->nextSibling();
788 // -------------------------------------------------------------------------
790 NodeImpl::Id HTMLTableRowElementImpl::id() const
795 NodeImpl *HTMLTableRowElementImpl::addChild(NodeImpl *child)
798 kdDebug( 6030 ) << nodeName().string() << "(Trow)::addChild( " << child->nodeName().string() << " )" << endl;
801 if (child->id() == ID_FORM) {
802 // First add the child.
803 HTMLElementImpl::addChild(child);
804 // Now simply return ourselves as the newnode. This has the effect of
805 // demoting the form to a leaf and moving it safely out of the way.
808 return HTMLTablePartElementImpl::addChild(child);
811 long HTMLTableRowElementImpl::rowIndex() const
815 NodeImpl *table = parentNode();
818 table = table->parentNode();
819 if ( !table || table->id() != ID_TABLE )
822 HTMLTableSectionElementImpl *foot = static_cast<HTMLTableElementImpl *>(table)->tFoot();
823 NodeImpl *node = table->firstChild();
825 if ( node != foot && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) ) {
826 HTMLTableSectionElementImpl* section = static_cast<HTMLTableSectionElementImpl *>(node);
827 const NodeImpl *row = section->firstChild();
832 row = row->nextSibling();
835 node = node->nextSibling();
837 const NodeImpl *row = foot->firstChild();
842 row = row->nextSibling();
844 // should never happen
848 long HTMLTableRowElementImpl::sectionRowIndex() const
851 const NodeImpl *n = this;
853 n = n->previousSibling();
854 if (n && n->isElementNode() && n->id() == ID_TR)
862 HTMLElementImpl *HTMLTableRowElementImpl::insertCell( long index, int &exceptioncode )
864 HTMLTableCellElementImpl *c = 0L;
865 NodeListImpl *children = childNodes();
866 int numCells = children ? children->length() : 0;
867 if ( index < -1 || index > numCells )
868 exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
871 c = new HTMLTableCellElementImpl(docPtr(), ID_TD);
872 if(numCells == index || index == -1)
873 appendChild(c, exceptioncode);
879 n = children->item(index);
880 insertBefore(c, n, exceptioncode);
887 void HTMLTableRowElementImpl::deleteCell( long index, int &exceptioncode )
889 NodeListImpl *children = childNodes();
890 int numCells = children ? children->length() : 0;
891 if ( index == -1 ) index = numCells-1;
892 if( index >= 0 && index < numCells )
893 HTMLElementImpl::removeChild(children->item(index), exceptioncode);
895 exceptioncode = DOMException::INDEX_SIZE_ERR;
899 // -------------------------------------------------------------------------
901 HTMLTableCellElementImpl::HTMLTableCellElementImpl(DocumentPtr *doc, int tag)
902 : HTMLTablePartElementImpl(doc)
912 HTMLTableCellElementImpl::~HTMLTableCellElementImpl()
917 bool HTMLTableCellElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
925 result = eCell; // Because of the quirky behavior of ignoring 0 values, cells are special.
930 return HTMLTablePartElementImpl::mapToEntry(attr, result);
933 void HTMLTableCellElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
939 rSpan = !attr->isNull() ? attr->value().toInt() : 1;
940 // limit this to something not causing an overflow with short int
941 if(rSpan < 1 || rSpan > 1024) rSpan = 1;
945 cSpan = !attr->isNull() ? attr->value().toInt() : 1;
946 // limit this to something not causing an overflow with short int
947 if(cSpan < 1 || cSpan > 1024) cSpan = 1;
951 addCSSProperty(attr, CSS_PROP_WHITE_SPACE, CSS_VAL__KHTML_NOWRAP);
954 if (!attr->value().isEmpty()) {
955 int widthInt = attr->value().toInt();
956 if (widthInt > 0) // width="0" is ignored for compatibility with WinIE.
957 addCSSLength( attr, CSS_PROP_WIDTH, attr->value() );
961 if (!attr->value().isEmpty()) {
962 int heightInt = attr->value().toInt();
963 if (heightInt > 0) // height="0" is ignored for compatibility with WinIE.
964 addCSSLength( attr, CSS_PROP_HEIGHT, attr->value() );
970 HTMLTablePartElementImpl::parseHTMLAttribute(attr);
974 // used by table cells to share style decls created by the enclosing table.
975 CSSMutableStyleDeclarationImpl* HTMLTableCellElementImpl::additionalAttributeStyleDecl()
977 HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parentNode());
978 while(p && p->id() != ID_TABLE)
979 p = static_cast<HTMLElementImpl*>(p->parentNode());
982 HTMLTableElementImpl* table = static_cast<HTMLTableElementImpl*>(p);
983 return table->getSharedCellDecl();
989 void HTMLTableCellElementImpl::attach()
991 HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parentNode());
992 while(p && p->id() != ID_TABLE)
993 p = static_cast<HTMLElementImpl*>(p->parentNode());
995 HTMLTablePartElementImpl::attach();
998 bool HTMLTableCellElementImpl::isURLAttribute(AttributeImpl *attr) const
1000 return attr->id() == ATTR_BACKGROUND;
1003 // -------------------------------------------------------------------------
1005 HTMLTableColElementImpl::HTMLTableColElementImpl(DocumentPtr *doc, ushort i)
1006 : HTMLTablePartElementImpl(doc)
1009 _span = (_id == ID_COLGROUP ? 0 : 1);
1012 NodeImpl::Id HTMLTableColElementImpl::id() const
1017 bool HTMLTableColElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
1021 result = eUniversal;
1026 return HTMLTablePartElementImpl::mapToEntry(attr, result);
1029 void HTMLTableColElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
1034 _span = !attr->isNull() ? attr->value().toInt() : 1;
1037 if (!attr->value().isEmpty())
1038 addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
1041 HTMLTablePartElementImpl::parseHTMLAttribute(attr);
1046 // -------------------------------------------------------------------------
1048 NodeImpl::Id HTMLTableCaptionElementImpl::id() const
1053 bool HTMLTableCaptionElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
1055 if (attr == ATTR_ALIGN) {
1059 return HTMLElementImpl::mapToEntry(attr, result);
1062 void HTMLTableCaptionElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
1067 if (!attr->value().isEmpty())
1068 addCSSProperty(attr, CSS_PROP_CAPTION_SIDE, attr->value());
1071 HTMLElementImpl::parseHTMLAttribute(attr);