📄 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-2003 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, 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 "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; rules = None; frame = Void; padding = 1; m_solid = false; // reset font color and sizes here, if we don't have strict parse mode. // this is 90% compatible to ie and mozilla, and the by way easiest solution... // only difference to 100% correct is that in strict mode <font> elements are propagated into tables. if ( getDocument()->parseMode() < DocumentImpl::Transitional ) { addCSSProperty( CSS_PROP_FONT_SIZE, CSS_VAL_MEDIUM ); addCSSProperty( CSS_PROP_COLOR, CSS_VAL__KHTML_TEXT ); }}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; HTMLTableSectionElementImpl* section = 0L; HTMLTableSectionElementImpl* lastSection = 0L; NodeImpl *node = firstChild(); // The DOM requires that index=-1 means 'append after last' 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=" << section->tagName() << " 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; } } } // insertRow(numRows) appends to TFOOT. insertRow(-1) appends to TBODY, hence the !append. if ( !found && !append ) section = static_cast<HTMLTableSectionElementImpl *>(foot); // If index has decreased to 0, it 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 << "(" << section->tagName().string() << ") 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::appendChild(NodeImpl *child, int &exceptioncode){ // #105586, allow javascript to insert a TR inside a TABLE, creation section as needed if(child->id() == ID_TR && (!getDocument()->parsing() || getDocument()->htmlMode() == DocumentImpl::XHtml)) { // See insertRow if (!firstBody && !head && !foot && !hasChildNodes()) { setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY, true /* implicit */) ); } Q_ASSERT( firstBody ); if (firstBody) { return firstBody->appendChild( child, exceptioncode ); } } return HTMLElementImpl::appendChild( child, exceptioncode );}NodeImpl *HTMLTableElementImpl::addChild(NodeImpl *child){#ifdef DEBUG_LAYOUT kdDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child->nodeName().string() << " )" << endl;#endif 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; } } return retval;}void HTMLTableElementImpl::parseAttribute(AttributeImpl *attr){ // ### to CSS!! switch(attr->id()) { case ATTR_WIDTH: if (!attr->value().isEmpty()) addCSSLength( CSS_PROP_WIDTH, attr->value() ); else removeCSSProperty(CSS_PROP_WIDTH); break; case ATTR_HEIGHT: if (!attr->value().isEmpty()) addCSSLength(CSS_PROP_HEIGHT, attr->value()); else removeCSSProperty(CSS_PROP_HEIGHT); break; case ATTR_BORDER: { int border; // ### this needs more work, as the border value is not only // the border of the box, but also between the cells if(!attr->val()) border = 0; else if(attr->val()->l == 0) border = 1; else border = attr->val()->toInt();#ifdef DEBUG_DRAW_BORDER border=1;#endif DOMString v = QString::number( border ); addCSSLength(CSS_PROP_BORDER_WIDTH, v ); // wanted by HTML4 specs if(!border) frame = Void, rules = None; else frame = Box, rules = All; if (attached()) updateFrame(); break; } case ATTR_BGCOLOR: if (!attr->value().isEmpty()) addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value()); else removeCSSProperty(CSS_PROP_BACKGROUND_COLOR); break; case ATTR_BORDERCOLOR: if(!attr->value().isEmpty()) { addHTMLColor(CSS_PROP_BORDER_COLOR, attr->value()); m_solid = true; } if (attached()) updateFrame(); break; case ATTR_BACKGROUND: { if (!attr->value().isEmpty()) { QString url = khtml::parseURL( attr->value() ).string(); url = getDocument()->completeURL( url ); addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" ); } else removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE); break; } case ATTR_FRAME: if ( strcasecmp( attr->value(), "void" ) == 0 ) frame = Void; else if ( strcasecmp( attr->value(), "border" ) == 0 ) frame = Box; else if ( strcasecmp( attr->value(), "box" ) == 0 ) frame = Box; else if ( strcasecmp( attr->value(), "hsides" ) == 0 ) frame = Hsides; else if ( strcasecmp( attr->value(), "vsides" ) == 0 ) frame = Vsides; else if ( strcasecmp( attr->value(), "above" ) == 0 ) frame = Above; else if ( strcasecmp( attr->value(), "below" ) == 0 ) frame = Below; else if ( strcasecmp( attr->value(), "lhs" ) == 0 ) frame = Lhs; else if ( strcasecmp( attr->value(), "rhs" ) == 0 ) frame = Rhs; if (attached()) updateFrame(); break; case ATTR_RULES: if ( strcasecmp( attr->value(), "none" ) == 0 ) rules = None; else if ( strcasecmp( attr->value(), "groups" ) == 0 ) rules = Groups; else if ( strcasecmp( attr->value(), "rows" ) == 0 ) rules = Rows; else if ( strcasecmp( attr->value(), "cols" ) == 0 ) rules = Cols; else if ( strcasecmp( attr->value(), "all" ) == 0 ) rules = All; if (attached()) updateFrame(); break; case ATTR_CELLSPACING: if (!attr->value().isEmpty()) addCSSLength(CSS_PROP_BORDER_SPACING, attr->value(), true); else removeCSSProperty(CSS_PROP_BORDER_SPACING); break; case ATTR_CELLPADDING: if (!attr->value().isEmpty()) padding = kMax( 0, attr->value().toInt() ); else padding = 1; if (m_render && m_render->isTable()) { static_cast<RenderTable *>(m_render)->setCellPadding(padding); if (!m_render->needsLayout()) m_render->setNeedsLayout(true);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -