📄 html_tableimpl.cpp
字号:
/**
* This file is part of the DOM implementation for KDE.
*
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* Copyright (C) 2003 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "html/html_documentimpl.h"
#include "html/html_tableimpl.h"
#include "dom/dom_exception.h"
#include "dom/dom_node.h"
#include "misc/htmlhashes.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include "css/cssstyleselector.h"
#include "css/cssproperties.h"
#include "css/cssvalues.h"
#include "css/csshelper.h"
#include "css_valueimpl.h"
#include "css/css_stylesheetimpl.h"
#include "rendering/render_table.h"
#include <kdebug.h>
#include <kglobal.h>
using namespace khtml;
using namespace DOM;
HTMLTableElementImpl::HTMLTableElementImpl(DocumentPtr *doc)
: HTMLElementImpl(doc)
{
tCaption = 0;
head = 0;
foot = 0;
firstBody = 0;
#if 0
rules = None;
frame = Void;
#endif
padding = 1;
m_noBorder = true;
m_solid = false;
}
HTMLTableElementImpl::~HTMLTableElementImpl()
{
}
NodeImpl::Id HTMLTableElementImpl::id() const
{
return ID_TABLE;
}
NodeImpl* HTMLTableElementImpl::setCaption( HTMLTableCaptionElementImpl *c )
{
int exceptioncode = 0;
NodeImpl* r;
if(tCaption) {
replaceChild ( c, tCaption, exceptioncode );
r = c;
}
else
r = insertBefore( c, firstChild(), exceptioncode );
tCaption = c;
return r;
}
NodeImpl* HTMLTableElementImpl::setTHead( HTMLTableSectionElementImpl *s )
{
int exceptioncode = 0;
NodeImpl* r;
if(head) {
replaceChild( s, head, exceptioncode );
r = s;
}
else if( foot )
r = insertBefore( s, foot, exceptioncode );
else if( firstBody )
r = insertBefore( s, firstBody, exceptioncode );
else
r = appendChild( s, exceptioncode );
head = s;
return r;
}
NodeImpl* HTMLTableElementImpl::setTFoot( HTMLTableSectionElementImpl *s )
{
int exceptioncode = 0;
NodeImpl* r;
if(foot) {
replaceChild ( s, foot, exceptioncode );
r = s;
} else if( firstBody )
r = insertBefore( s, firstBody, exceptioncode );
else
r = appendChild( s, exceptioncode );
foot = s;
return r;
}
NodeImpl* HTMLTableElementImpl::setTBody( HTMLTableSectionElementImpl *s )
{
int exceptioncode = 0;
NodeImpl* r;
if(firstBody) {
replaceChild ( s, firstBody, exceptioncode );
r = s;
} else
r = appendChild( s, exceptioncode );
firstBody = s;
return r;
}
HTMLElementImpl *HTMLTableElementImpl::createTHead( )
{
if(!head)
{
int exceptioncode = 0;
head = new HTMLTableSectionElementImpl(docPtr(), ID_THEAD, true /* implicit */);
if(foot)
insertBefore( head, foot, exceptioncode );
else if(firstBody)
insertBefore( head, firstBody, exceptioncode);
else
appendChild(head, exceptioncode);
}
return head;
}
void HTMLTableElementImpl::deleteTHead( )
{
if(head) {
int exceptioncode = 0;
HTMLElementImpl::removeChild(head, exceptioncode);
}
head = 0;
}
HTMLElementImpl *HTMLTableElementImpl::createTFoot( )
{
if(!foot)
{
int exceptioncode = 0;
foot = new HTMLTableSectionElementImpl(docPtr(), ID_TFOOT, true /*implicit */);
if(firstBody)
insertBefore( foot, firstBody, exceptioncode );
else
appendChild(foot, exceptioncode);
}
return foot;
}
void HTMLTableElementImpl::deleteTFoot( )
{
if(foot) {
int exceptioncode = 0;
HTMLElementImpl::removeChild(foot, exceptioncode);
}
foot = 0;
}
HTMLElementImpl *HTMLTableElementImpl::createCaption( )
{
if(!tCaption)
{
int exceptioncode = 0;
tCaption = new HTMLTableCaptionElementImpl(docPtr());
insertBefore( tCaption, firstChild(), exceptioncode );
}
return tCaption;
}
void HTMLTableElementImpl::deleteCaption( )
{
if(tCaption) {
int exceptioncode = 0;
HTMLElementImpl::removeChild(tCaption, exceptioncode);
}
tCaption = 0;
}
HTMLElementImpl *HTMLTableElementImpl::insertRow( long index, int &exceptioncode )
{
// The DOM requires that we create a tbody if the table is empty
// (cf DOM2TS HTMLTableElement31 test)
// (note: this is different from "if the table has no sections", since we can have
// <TABLE><TR>)
if(!firstBody && !head && !foot && !hasChildNodes())
setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY, true /* implicit */) );
//kdDebug(6030) << k_funcinfo << index << endl;
// IE treats index=-1 as default value meaning 'append after last'
// This isn't in the DOM. So, not implemented yet.
HTMLTableSectionElementImpl* section = 0L;
HTMLTableSectionElementImpl* lastSection = 0L;
NodeImpl *node = firstChild();
bool append = (index == -1);
bool found = false;
for ( ; node && (index>=0 || append) ; node = node->nextSibling() )
{
// there could be 2 tfoot elements in the table. Only the first one is the "foot", that's why we have the more
// complicated if statement below.
if ( node != foot && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) )
{
section = static_cast<HTMLTableSectionElementImpl *>(node);
lastSection = section;
//kdDebug(6030) << k_funcinfo << "section id=" << node->id() << " rows:" << section->numRows() << endl;
if ( !append )
{
int rows = section->numRows();
if ( rows > index ) {
found = true;
break;
} else
index -= rows;
//kdDebug(6030) << " index is now " << index << endl;
}
}
}
if ( !found && foot )
section = static_cast<HTMLTableSectionElementImpl *>(foot);
// Index == 0 means "insert before first row in current section"
// or "append after last row" (if there's no current section anymore)
if ( !section && ( index == 0 || append ) )
{
section = lastSection;
index = section ? section->numRows() : 0;
}
if ( section && (index >= 0 || append) ) {
//kdDebug(6030) << "Inserting row into section " << section << " at index " << index << endl;
return section->insertRow( index, exceptioncode );
} else {
// No more sections => index is too big
exceptioncode = DOMException::INDEX_SIZE_ERR;
return 0L;
}
}
void HTMLTableElementImpl::deleteRow( long index, int &exceptioncode )
{
HTMLTableSectionElementImpl* section = 0L;
NodeImpl *node = firstChild();
bool lastRow = index == -1;
HTMLTableSectionElementImpl* lastSection = 0L;
bool found = false;
for ( ; node ; node = node->nextSibling() )
{
if ( node != foot && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) )
{
section = static_cast<HTMLTableSectionElementImpl *>(node);
lastSection = section;
int rows = section->numRows();
if ( !lastRow )
{
if ( rows > index ) {
found = true;
break;
} else
index -= rows;
}
}
section = 0L;
}
if ( !found && foot )
section = static_cast<HTMLTableSectionElementImpl *>(foot);
if ( lastRow )
lastSection->deleteRow( -1, exceptioncode );
else if ( section && index >= 0 && index < section->numRows() )
section->deleteRow( index, exceptioncode );
else
exceptioncode = DOMException::INDEX_SIZE_ERR;
}
NodeImpl *HTMLTableElementImpl::addChild(NodeImpl *child)
{
#ifdef DEBUG_LAYOUT
kdDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child->nodeName().string() << " )" << endl;
#endif
if (child->id() == ID_FORM) {
// First add the child.
HTMLElementImpl::addChild(child);
// Now simply return ourselves as the newnode. This has the effect of
// demoting the form to a leaf and moving it safely out of the way.
return this;
}
// We do not want this check-node-allowed test here, however the code to
// build up tables relies on childAllowed failing to make sure that the
// table is well-formed, the primary work being to add a tbody element.
// As 99.9999% of tables on the weeb do not have tbody elements, it seems
// odd to traverse an "error" case for the most common table markup.
// See <rdar://problem/3719373> Table parsing and construction relies on
// childAllowed failures to build up proper DOM
if (child->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
// child is a DocumentFragment... check all its children instead of child itself
for (NodeImpl *c = child->firstChild(); c; c = c->nextSibling())
if (!childAllowed(c))
return 0;
}
else if (!childAllowed(child)) {
// child is not a DocumentFragment... check if it's allowed directly
return 0;
}
int exceptioncode = 0;
NodeImpl *retval = appendChild( child, exceptioncode );
if ( retval ) {
switch(child->id()) {
case ID_CAPTION:
if ( !tCaption )
tCaption = static_cast<HTMLTableCaptionElementImpl *>(child);
break;
case ID_COL:
case ID_COLGROUP:
break;
case ID_THEAD:
if ( !head )
head = static_cast<HTMLTableSectionElementImpl *>(child);
break;
case ID_TFOOT:
if ( !foot )
foot = static_cast<HTMLTableSectionElementImpl *>(child);
break;
case ID_TBODY:
if ( !firstBody )
firstBody = static_cast<HTMLTableSectionElementImpl *>(child);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -