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-2003 Lars Knoll (knoll@kde.org)
8 * (C) 1999 Antti Koivisto (koivisto@kde.org)
9 * (C) 2003 Apple Computer, Inc.
10 * (C) 2006 Maksim Orlovich (maksim@kde.org)
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
28 #include "html_tableimpl.h"
30 #include "html_documentimpl.h"
32 #include <dom/dom_exception.h>
33 #include <dom/dom_node.h>
35 #include <misc/htmlhashes.h>
36 #include <khtmlview.h>
37 #include <khtml_part.h>
39 #include <css/cssstyleselector.h>
40 #include <css/cssproperties.h>
41 #include <css/cssvalues.h>
42 #include <css/csshelper.h>
44 #include <rendering/render_table.h>
49 using namespace khtml
;
52 HTMLTableElementImpl::HTMLTableElementImpl(DocumentImpl
*doc
)
53 : HTMLElementImpl(doc
)
63 HTMLTableElementImpl::~HTMLTableElementImpl()
67 NodeImpl::Id
HTMLTableElementImpl::id() const
72 NodeImpl
* HTMLTableElementImpl::setCaption( HTMLTableCaptionElementImpl
*c
)
74 int exceptioncode
= 0;
76 if(ElementImpl
* cap
= caption()) {
77 replaceChild ( c
, cap
, exceptioncode
);
81 r
= insertBefore( c
, firstChild(), exceptioncode
);
86 NodeImpl
* HTMLTableElementImpl::setTHead( HTMLTableSectionElementImpl
*s
)
88 int exceptioncode
= 0;
90 if( ElementImpl
* head
= tHead() ) {
91 replaceChild( s
, head
, exceptioncode
);
94 else if(ElementImpl
* foot
= tFoot())
95 r
= insertBefore( s
, foot
, exceptioncode
);
96 else if(ElementImpl
* firstBody
= tFirstBody())
97 r
= insertBefore( s
, firstBody
, exceptioncode
);
99 r
= appendChild( s
, exceptioncode
);
105 NodeImpl
* HTMLTableElementImpl::setTFoot( HTMLTableSectionElementImpl
*s
)
107 int exceptioncode
= 0;
109 if(ElementImpl
* foot
= tFoot()) {
110 replaceChild ( s
, foot
, exceptioncode
);
112 } else if(ElementImpl
* firstBody
= tFirstBody())
113 r
= insertBefore( s
, firstBody
, exceptioncode
);
115 r
= appendChild( s
, exceptioncode
);
120 NodeImpl
* HTMLTableElementImpl::setTBody( HTMLTableSectionElementImpl
*s
)
122 int exceptioncode
= 0;
125 if(ElementImpl
* firstBody
= tFirstBody()) {
126 replaceChild ( s
, firstBody
, exceptioncode
);
129 r
= appendChild( s
, exceptioncode
);
135 HTMLElementImpl
*HTMLTableElementImpl::createTHead( )
139 int exceptioncode
= 0;
140 ElementImpl
* head
= new HTMLTableSectionElementImpl(docPtr(), ID_THEAD
, true /* implicit */);
141 if(ElementImpl
* foot
= tFoot())
142 insertBefore( head
, foot
, exceptioncode
);
143 else if(ElementImpl
* firstBody
= tFirstBody())
144 insertBefore( head
, firstBody
, exceptioncode
);
146 appendChild(head
, exceptioncode
);
151 void HTMLTableElementImpl::deleteTHead( )
153 if(ElementImpl
* head
= tHead()) {
154 int exceptioncode
= 0;
155 removeChild(head
, exceptioncode
);
159 HTMLElementImpl
*HTMLTableElementImpl::createTFoot( )
163 int exceptioncode
= 0;
164 ElementImpl
* foot
= new HTMLTableSectionElementImpl(docPtr(), ID_TFOOT
, true /*implicit */);
165 if(ElementImpl
* firstBody
= tFirstBody())
166 insertBefore( foot
, firstBody
, exceptioncode
);
168 appendChild(foot
, exceptioncode
);
173 void HTMLTableElementImpl::deleteTFoot( )
175 if(ElementImpl
* foot
= tFoot()) {
176 int exceptioncode
= 0;
177 removeChild(foot
, exceptioncode
);
181 HTMLElementImpl
*HTMLTableElementImpl::createCaption( )
185 int exceptioncode
= 0;
186 ElementImpl
* tCaption
= new HTMLTableCaptionElementImpl(docPtr());
187 insertBefore( tCaption
, firstChild(), exceptioncode
);
192 void HTMLTableElementImpl::deleteCaption( )
194 if(ElementImpl
* tCaption
= caption()) {
195 int exceptioncode
= 0;
196 removeChild(tCaption
, exceptioncode
);
201 Helper. This checks whether the section contains the desired index, and if so,
202 returns the section. Otherwise, it adjust the index, and returns 0.
203 indices < 0 are considered to be infinite.
205 lastSection is adjusted to reflect the parameter passed in.
207 static inline HTMLTableSectionElementImpl
* processSection(HTMLTableSectionElementImpl
* section
,
208 HTMLTableSectionElementImpl
* &lastSection
, long& index
)
210 lastSection
= section
;
211 if ( index
< 0 ) //append/last mode
214 long rows
= section
->numRows();
215 if ( index
>= rows
) {
223 bool HTMLTableElementImpl::findRowSection(long index
,
224 HTMLTableSectionElementImpl
*& outSection
,
225 long& outIndex
) const
227 HTMLTableSectionElementImpl
* foot
= tFoot();
228 HTMLTableSectionElementImpl
* head
= tHead();
230 HTMLTableSectionElementImpl
* section
= 0L;
231 HTMLTableSectionElementImpl
* lastSection
= 0L;
234 section
= processSection( head
, lastSection
, index
);
237 for ( NodeImpl
*node
= firstChild(); node
; node
= node
->nextSibling() ) {
238 if ( ( node
->id() == ID_THEAD
|| node
->id() == ID_TFOOT
|| node
->id() == ID_TBODY
) &&
239 node
!= foot
&& node
!= head
) {
240 section
= processSection( static_cast<HTMLTableSectionElementImpl
*>(node
),
241 lastSection
, index
);
248 if ( !section
&& foot
)
249 section
= processSection( foot
, lastSection
, index
);
253 outSection
= section
;
256 outSection
= lastSection
;
261 HTMLElementImpl
*HTMLTableElementImpl::insertRow( long index
, int &exceptioncode
)
263 // The DOM requires that we create a tbody if the table is empty
264 // (cf DOM2TS HTMLTableElement31 test). This includes even the cases where
265 // there are <tr>'s immediately under the table, as they're essentially
266 // ignored by these functions.
267 HTMLTableSectionElementImpl
* foot
= tFoot();
268 HTMLTableSectionElementImpl
* head
= tHead();
269 if(!tFirstBody() && !foot
&& !head
)
270 setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY
, true /* implicit */) );
272 //kDebug(6030) << index;
275 HTMLTableSectionElementImpl
* section
;
276 if ( findRowSection( index
, section
, sectionIndex
) )
277 return section
->insertRow( sectionIndex
, exceptioncode
);
278 else if ( index
== -1 || sectionIndex
== 0 )
279 return section
->insertRow( section
->numRows(), exceptioncode
);
281 // The index is too big.
282 exceptioncode
= DOMException::INDEX_SIZE_ERR
;
286 void HTMLTableElementImpl::deleteRow( long index
, int &exceptioncode
)
289 HTMLTableSectionElementImpl
* section
;
290 if ( findRowSection( index
, section
, sectionIndex
) )
291 section
->deleteRow( sectionIndex
, exceptioncode
);
292 else if ( section
&& index
== -1 )
293 section
->deleteRow( -1, exceptioncode
);
295 exceptioncode
= DOMException::INDEX_SIZE_ERR
;
298 NodeImpl
*HTMLTableElementImpl::appendChild(NodeImpl
*child
, int &exceptioncode
)
300 NodeImpl
* retval
= HTMLElementImpl::appendChild( child
, exceptioncode
);
302 handleChildAppend( child
);
306 void HTMLTableElementImpl::handleChildAdd( NodeImpl
*child
)
309 switch(child
->id()) {
311 tCaption
.childAdded(this, child
);
314 head
.childAdded(this, child
);
317 foot
.childAdded(this, child
);
320 firstBody
.childAdded(this, child
);
325 void HTMLTableElementImpl::handleChildAppend( NodeImpl
*child
)
328 switch(child
->id()) {
330 tCaption
.childAppended(child
);
333 head
.childAppended(child
);
336 foot
.childAppended(child
);
339 firstBody
.childAppended(child
);
344 void HTMLTableElementImpl::handleChildRemove( NodeImpl
*child
)
347 switch(child
->id()) {
349 tCaption
.childRemoved(this, child
);
352 head
.childRemoved(this, child
);
355 foot
.childRemoved(this, child
);
358 firstBody
.childRemoved(this, child
);
363 NodeImpl
*HTMLTableElementImpl::addChild(NodeImpl
*child
)
366 kDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child
->nodeName().string() << " )";
369 NodeImpl
*retval
= HTMLElementImpl::addChild( child
);
371 handleChildAppend( child
);
376 NodeImpl
*HTMLTableElementImpl::insertBefore ( NodeImpl
*newChild
, NodeImpl
*refChild
, int &exceptioncode
)
378 NodeImpl
* retval
= HTMLElementImpl::insertBefore( newChild
, refChild
, exceptioncode
);
380 handleChildAdd( newChild
);
385 void HTMLTableElementImpl::replaceChild ( NodeImpl
*newChild
, NodeImpl
*oldChild
, int &exceptioncode
)
387 handleChildRemove( oldChild
); //Always safe.
388 HTMLElementImpl::replaceChild( newChild
, oldChild
, exceptioncode
);
389 if ( !exceptioncode
)
390 handleChildAdd( newChild
);
393 void HTMLTableElementImpl::removeChild ( NodeImpl
*oldChild
, int &exceptioncode
)
395 handleChildRemove( oldChild
);
396 HTMLElementImpl::removeChild( oldChild
, exceptioncode
);
399 static inline bool isTableCellAncestor(NodeImpl
* n
)
401 return n
->id() == ID_THEAD
|| n
->id() == ID_TBODY
||
402 n
->id() == ID_TFOOT
|| n
->id() == ID_TR
;
405 static bool setTableCellsChanged(NodeImpl
* n
)
408 bool cellChanged
= false;
410 if (n
->id() == ID_TD
|| n
->id() == ID_TH
)
412 else if (isTableCellAncestor(n
)) {
413 for (NodeImpl
* child
= n
->firstChild(); child
; child
= child
->nextSibling())
414 cellChanged
|= setTableCellsChanged(child
);
423 void HTMLTableElementImpl::parseAttribute(AttributeImpl
*attr
)
429 if (!attr
->value().isEmpty())
430 addCSSLength( CSS_PROP_WIDTH
, attr
->value() );
432 removeCSSProperty(CSS_PROP_WIDTH
);
435 if (!attr
->value().isEmpty())
436 addCSSLength(CSS_PROP_HEIGHT
, attr
->value());
438 removeCSSProperty(CSS_PROP_HEIGHT
);
444 // ### this needs more work, as the border value is not only
445 // the border of the box, but also between the cells
448 else if(attr
->val()->l
== 0)
451 border
= attr
->val()->toInt(&ok
);
454 #ifdef DEBUG_DRAW_BORDER
457 DOMString v
= QString::number( border
);
458 addCSSLength(CSS_PROP_BORDER_WIDTH
, v
);
460 attr
->rewriteValue( v
);
462 // wanted by HTML4 specs
464 frame
= Void
, rules
= None
;
466 frame
= Box
, rules
= All
;
471 setTableCellsChanged(tFirstBody());
476 if (!attr
->value().isEmpty())
477 addHTMLColor(CSS_PROP_BACKGROUND_COLOR
, attr
->value());
479 removeCSSProperty(CSS_PROP_BACKGROUND_COLOR
);
481 case ATTR_BORDERCOLOR
:
482 if(!attr
->value().isEmpty()) {
483 addHTMLColor(CSS_PROP_BORDER_COLOR
, attr
->value());
487 if (attached()) updateFrame();
489 case ATTR_BACKGROUND
:
491 if (!attr
->value().isEmpty()) {
492 QString url
= khtml::parseURL( attr
->value() ).string();
493 url
= document()->completeURL( url
);
494 addCSSProperty(CSS_PROP_BACKGROUND_IMAGE
, DOMString("url('"+url
+"')") );
497 removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE
);
502 if ( strcasecmp( attr
->value(), "void" ) == 0 )
504 else if ( strcasecmp( attr
->value(), "border" ) == 0 )
506 else if ( strcasecmp( attr
->value(), "box" ) == 0 )
508 else if ( strcasecmp( attr
->value(), "hsides" ) == 0 )
510 else if ( strcasecmp( attr
->value(), "vsides" ) == 0 )
512 else if ( strcasecmp( attr
->value(), "above" ) == 0 )
514 else if ( strcasecmp( attr
->value(), "below" ) == 0 )
516 else if ( strcasecmp( attr
->value(), "lhs" ) == 0 )
518 else if ( strcasecmp( attr
->value(), "rhs" ) == 0 )
521 if (attached()) updateFrame();
524 if ( strcasecmp( attr
->value(), "none" ) == 0 )
526 else if ( strcasecmp( attr
->value(), "groups" ) == 0 )
528 else if ( strcasecmp( attr
->value(), "rows" ) == 0 )
530 else if ( strcasecmp( attr
->value(), "cols" ) == 0 )
532 else if ( strcasecmp( attr
->value(), "all" ) == 0 )
535 if (attached() && tFirstBody())
536 if (setTableCellsChanged(tFirstBody()))
539 case ATTR_CELLSPACING
:
540 if (!attr
->value().isEmpty())
541 addCSSLength(CSS_PROP_BORDER_SPACING
, attr
->value(), true);
543 removeCSSProperty(CSS_PROP_BORDER_SPACING
);
545 case ATTR_CELLPADDING
:
546 if (!attr
->value().isEmpty())
547 padding
= qMax( 0, attr
->value().toInt() );
550 if (m_render
&& m_render
->isTable()) {
551 static_cast<RenderTable
*>(m_render
)->setCellPadding(padding
);
552 if (!m_render
->needsLayout())
553 m_render
->setNeedsLayout(true);
561 c
= attr
->val()->toInt();
562 addColumns(c
-totalCols
);
571 if (!attr
->value().isEmpty())
572 addCSSProperty(CSS_PROP_VERTICAL_ALIGN
, attr
->value().lower());
574 removeCSSProperty(CSS_PROP_VERTICAL_ALIGN
);
579 HTMLElementImpl::parseAttribute(attr
);
583 void HTMLTableElementImpl::attach()
586 HTMLElementImpl::attach();
587 if ( m_render
&& m_render
->isTable() )
588 static_cast<RenderTable
*>(m_render
)->setCellPadding( padding
);
591 void HTMLTableElementImpl::close()
593 ElementImpl
* firstBody
= tFirstBody();
594 if (firstBody
&& !firstBody
->closed())
596 HTMLElementImpl::close();
599 void HTMLTableElementImpl::updateFrame()
601 int v
= m_solid
? CSS_VAL_SOLID
: CSS_VAL_OUTSET
;
603 addCSSProperty(CSS_PROP_BORDER_TOP_STYLE
, v
);
605 addCSSProperty(CSS_PROP_BORDER_TOP_STYLE
, CSS_VAL_NONE
);
607 addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE
, v
);
609 addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE
, CSS_VAL_NONE
);
611 addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE
, v
);
613 addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE
, CSS_VAL_NONE
);
615 addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE
, v
);
617 addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE
, CSS_VAL_NONE
);
620 // --------------------------------------------------------------------------
622 void HTMLTablePartElementImpl::parseAttribute(AttributeImpl
*attr
)
628 addHTMLColor(CSS_PROP_BACKGROUND_COLOR
, attr
->value() );
630 removeCSSProperty(CSS_PROP_BACKGROUND_COLOR
);
632 case ATTR_BACKGROUND
:
635 QString url
= khtml::parseURL( attr
->value() ).string();
636 url
= document()->completeURL( url
);
637 addCSSProperty(CSS_PROP_BACKGROUND_IMAGE
, DOMString("url('"+url
+"')") );
640 removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE
);
643 case ATTR_BORDERCOLOR
:
645 if(!attr
->value().isEmpty()) {
646 addHTMLColor(CSS_PROP_BORDER_COLOR
, attr
->value());
647 addCSSProperty(CSS_PROP_BORDER_TOP_STYLE
, CSS_VAL_SOLID
);
648 addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE
, CSS_VAL_SOLID
);
649 addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE
, CSS_VAL_SOLID
);
650 addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE
, CSS_VAL_SOLID
);
656 DOMString v
= attr
->value();
657 if ( strcasecmp( attr
->value(), "middle" ) == 0 || strcasecmp( attr
->value(), "center" ) == 0 )
658 addCSSProperty(CSS_PROP_TEXT_ALIGN
, CSS_VAL__KHTML_CENTER
);
659 else if (strcasecmp(attr
->value(), "absmiddle") == 0)
660 addCSSProperty(CSS_PROP_TEXT_ALIGN
, CSS_VAL_CENTER
);
661 else if (strcasecmp(attr
->value(), "left") == 0)
662 addCSSProperty(CSS_PROP_TEXT_ALIGN
, CSS_VAL__KHTML_LEFT
);
663 else if (strcasecmp(attr
->value(), "right") == 0)
664 addCSSProperty(CSS_PROP_TEXT_ALIGN
, CSS_VAL__KHTML_RIGHT
);
666 addCSSProperty(CSS_PROP_TEXT_ALIGN
, v
);
671 if (!attr
->value().isEmpty())
672 addCSSProperty(CSS_PROP_VERTICAL_ALIGN
, attr
->value().lower());
674 removeCSSProperty(CSS_PROP_VERTICAL_ALIGN
);
678 if (!attr
->value().isEmpty())
679 addCSSLength(CSS_PROP_HEIGHT
, attr
->value());
681 removeCSSProperty(CSS_PROP_HEIGHT
);
686 HTMLElementImpl::parseAttribute(attr
);
690 // -------------------------------------------------------------------------
692 HTMLTableSectionElementImpl::HTMLTableSectionElementImpl(DocumentImpl
*doc
,
693 ushort tagid
, bool implicit
)
694 : HTMLTablePartElementImpl(doc
)
697 m_implicit
= implicit
;
700 HTMLTableSectionElementImpl::~HTMLTableSectionElementImpl()
704 NodeImpl::Id
HTMLTableSectionElementImpl::id() const
709 // these functions are rather slow, since we need to get the row at
710 // the index... but they aren't used during usual HTML parsing anyway
711 HTMLElementImpl
*HTMLTableSectionElementImpl::insertRow( long index
, int& exceptioncode
)
713 HTMLTableRowElementImpl
*r
= 0L;
714 HTMLCollectionImpl
rows(const_cast<HTMLTableSectionElementImpl
*>(this), HTMLCollectionImpl::TSECTION_ROWS
);
715 int numRows
= rows
.length();
716 //kDebug(6030) << "index=" << index << " numRows=" << numRows;
717 if ( index
< -1 || index
> numRows
) {
718 exceptioncode
= DOMException::INDEX_SIZE_ERR
; // per the DOM
722 r
= new HTMLTableRowElementImpl(docPtr());
723 if ( numRows
== index
|| index
== -1 )
724 appendChild(r
, exceptioncode
);
730 n
= rows
.item(index
);
731 insertBefore(r
, n
, exceptioncode
);
737 void HTMLTableSectionElementImpl::deleteRow( long index
, int &exceptioncode
)
739 HTMLCollectionImpl
rows(const_cast<HTMLTableSectionElementImpl
*>(this), HTMLCollectionImpl::TSECTION_ROWS
);
740 int numRows
= rows
.length();
741 if ( index
== -1 ) index
= numRows
- 1;
742 if( index
>= 0 && index
< numRows
)
743 HTMLElementImpl::removeChild(rows
.item(index
), exceptioncode
);
745 exceptioncode
= DOMException::INDEX_SIZE_ERR
;
749 int HTMLTableSectionElementImpl::numRows() const
751 HTMLCollectionImpl
rows(const_cast<HTMLTableSectionElementImpl
*>(this), HTMLCollectionImpl::TSECTION_ROWS
);
752 return rows
.length();
755 // -------------------------------------------------------------------------
757 NodeImpl::Id
HTMLTableRowElementImpl::id() const
762 long HTMLTableRowElementImpl::rowIndex() const
766 NodeImpl
*table
= parentNode();
769 table
= table
->parentNode();
770 if ( !table
|| table
->id() != ID_TABLE
)
773 HTMLTableSectionElementImpl
*head
= static_cast<HTMLTableElementImpl
*>(table
)->tHead();
774 HTMLTableSectionElementImpl
*foot
= static_cast<HTMLTableElementImpl
*>(table
)->tFoot();
777 const NodeImpl
*row
= head
->firstChild();
781 if (row
->id() == ID_TR
)
783 row
= row
->nextSibling();
787 NodeImpl
*node
= table
->firstChild();
789 if ( node
!= foot
&& node
!= head
&& (node
->id() == ID_THEAD
|| node
->id() == ID_TFOOT
|| node
->id() == ID_TBODY
) ) {
790 HTMLTableSectionElementImpl
* section
= static_cast<HTMLTableSectionElementImpl
*>(node
);
791 const NodeImpl
*row
= section
->firstChild();
795 if (row
->id() == ID_TR
)
797 row
= row
->nextSibling();
800 node
= node
->nextSibling();
802 const NodeImpl
*row
= foot
->firstChild();
806 if (row
->id() == ID_TR
)
808 row
= row
->nextSibling();
810 // should never happen
814 long HTMLTableRowElementImpl::sectionRowIndex() const
817 const NodeImpl
*n
= this;
819 n
= n
->previousSibling();
820 if (n
&& n
->id() == ID_TR
)
828 HTMLElementImpl
*HTMLTableRowElementImpl::insertCell( long index
, int &exceptioncode
)
830 HTMLTableCellElementImpl
*c
= 0L;
831 HTMLCollectionImpl
children(const_cast<HTMLTableRowElementImpl
*>(this), HTMLCollectionImpl::TR_CELLS
);
832 int numCells
= children
.length();
833 if ( index
< -1 || index
> numCells
)
834 exceptioncode
= DOMException::INDEX_SIZE_ERR
; // per the DOM
837 c
= new HTMLTableCellElementImpl(docPtr(), ID_TD
);
838 if(numCells
== index
|| index
== -1)
839 appendChild(c
, exceptioncode
);
845 n
= children
.item(index
);
846 insertBefore(c
, n
, exceptioncode
);
852 void HTMLTableRowElementImpl::deleteCell( long index
, int &exceptioncode
)
854 HTMLCollectionImpl
children(const_cast<HTMLTableRowElementImpl
*>(this), HTMLCollectionImpl::TR_CELLS
);
855 int numCells
= children
.length();
856 if ( index
== -1 ) index
= numCells
-1;
857 if( index
>= 0 && index
< numCells
)
858 HTMLElementImpl::removeChild(children
.item(index
), exceptioncode
);
860 exceptioncode
= DOMException::INDEX_SIZE_ERR
;
863 // -------------------------------------------------------------------------
865 HTMLTableCellElementImpl::HTMLTableCellElementImpl(DocumentImpl
*doc
, int tag
)
866 : HTMLTablePartElementImpl(doc
)
876 HTMLTableCellElementImpl::~HTMLTableCellElementImpl()
880 long HTMLTableCellElementImpl::cellIndex() const
883 for (const NodeImpl
* node
= previousSibling(); node
; node
= node
->previousSibling()) {
884 if (node
->id() == ID_TD
|| node
->id() == ID_TH
)
891 void HTMLTableCellElementImpl::parseAttribute(AttributeImpl
*attr
)
896 // euhm? not supported by other browsers as far as I can see (Dirk)
897 //addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
900 rSpan
= attr
->val() ? attr
->val()->toInt() : 1;
901 // limit this to something not causing an overflow with short int
902 if(rSpan
< 1 || rSpan
> 1024) rSpan
= 1;
904 renderer()->updateFromElement();
907 cSpan
= attr
->val() ? attr
->val()->toInt() : 1;
908 // limit this to something not causing an overflow with short int
909 if(cSpan
< 1 || cSpan
> 1024) cSpan
= 1;
911 renderer()->updateFromElement();
914 if (attr
->val() != 0)
915 addCSSProperty(CSS_PROP_WHITE_SPACE
, CSS_VAL__KHTML_NOWRAP
);
917 removeCSSProperty(CSS_PROP_WHITE_SPACE
);
920 if (!attr
->value().isEmpty())
921 addCSSLength( CSS_PROP_WIDTH
, attr
->value() );
923 removeCSSProperty(CSS_PROP_WIDTH
);
928 HTMLTablePartElementImpl::parseAttribute(attr
);
932 void HTMLTableCellElementImpl::attach()
934 HTMLTablePartElementImpl::attach();
937 // -------------------------------------------------------------------------
939 HTMLTableColElementImpl::HTMLTableColElementImpl(DocumentImpl
*doc
, ushort i
)
940 : HTMLTablePartElementImpl(doc
)
946 NodeImpl::Id
HTMLTableColElementImpl::id() const
952 void HTMLTableColElementImpl::parseAttribute(AttributeImpl
*attr
)
957 _span
= attr
->val() ? attr
->val()->toInt() : 1;
958 if (_span
< 1) _span
= 1;
961 if (!attr
->value().isEmpty())
962 addCSSLength(CSS_PROP_WIDTH
, attr
->value(), false, true );
964 removeCSSProperty(CSS_PROP_WIDTH
);
967 if (!attr
->value().isEmpty())
968 addCSSProperty(CSS_PROP_VERTICAL_ALIGN
, attr
->value().lower());
970 removeCSSProperty(CSS_PROP_VERTICAL_ALIGN
);
973 HTMLTablePartElementImpl::parseAttribute(attr
);
978 // -------------------------------------------------------------------------
980 NodeImpl::Id
HTMLTableCaptionElementImpl::id() const
986 void HTMLTableCaptionElementImpl::parseAttribute(AttributeImpl
*attr
)
991 if (!attr
->value().isEmpty())
992 addCSSProperty(CSS_PROP_CAPTION_SIDE
, attr
->value().lower());
994 removeCSSProperty(CSS_PROP_CAPTION_SIDE
);
997 HTMLElementImpl::parseAttribute(attr
);