📄 dom_nodeimpl.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * * 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 <qrect.h>#include "htmlattrs.h"#include "dom_nodeimpl.h"#include "dom_node.h"#include "dom_exception.h"#include "dom_elementimpl.h"#include "dom_docimpl.h"#include "render_object.h"#include "kdebug.h"#define QT_ALLOC_QCHAR_VEC( N ) (QChar*) new char[ 2*( N ) ]#define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P ))using namespace DOM;using namespace khtml;const QChar NodeImpl::LESSTHAN = '<';const QChar NodeImpl::MORETHAN = '>';const QChar NodeImpl::SLASH = '/';const QChar NodeImpl::SPACE = ' ';const QChar NodeImpl::EQUALS = '=';const QChar NodeImpl::QUOTE = '"';NodeImpl::NodeImpl(DocumentImpl *doc) : document(doc), m_render(0), m_complexText( false ), m_hasEvents( false ), m_hasId( false ), m_hasClass( false ), m_hasStyle( false ), m_hasTooltip( false ), m_pressed( false ), m_mouseInside( false ), m_attached( false ), m_changed( false ), m_specified( false ){}NodeImpl::~NodeImpl(){ setOwnerDocument(0);}DOMString NodeImpl::nodeValue() const{ return 0;}void NodeImpl::setNodeValue( const DOMString & ){ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);}const DOMString NodeImpl::nodeName() const{ return 0;}unsigned short NodeImpl::nodeType() const{ return 0;}NodeImpl *NodeImpl::parentNode() const{ return 0;}NodeListImpl *NodeImpl::childNodes(){ return new ChildNodeListImpl(this);}NodeImpl *NodeImpl::firstChild() const{ return 0;}NodeImpl *NodeImpl::lastChild() const{ return 0;}NodeImpl *NodeImpl::previousSibling() const{ return 0;}NodeImpl *NodeImpl::nextSibling() const{ return 0;}NamedNodeMapImpl *NodeImpl::attributes() const{ return 0;}void NodeImpl::setPreviousSibling(NodeImpl *){}void NodeImpl::setNextSibling(NodeImpl *){}void NodeImpl::setOwnerDocument(DocumentImpl *_document){ if (document) document->changedNodes.remove(this); document = _document;}NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl * ){ throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);}NodeImpl *NodeImpl::replaceChild( NodeImpl *, NodeImpl * ){ throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);}NodeImpl *NodeImpl::removeChild( NodeImpl * ){ throw DOMException(DOMException::NOT_FOUND_ERR);}NodeImpl *NodeImpl::appendChild( NodeImpl * ){ throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);}bool NodeImpl::hasChildNodes( ){ return false;}NodeImpl *NodeImpl::cloneNode( bool ){ // we have no childs, so we just clone this Node return new NodeImpl(document);}// helper functions not being part of the DOMvoid NodeImpl::setParent(NodeImpl *){}void NodeImpl::setFirstChild(NodeImpl *){}void NodeImpl::setLastChild(NodeImpl *){}NodeImpl *NodeImpl::addChild(NodeImpl *){ throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); return 0;}QString NodeImpl::toHTML(){ long offset = 0; const int stdInc = 10000; long currentLength = stdInc; QChar *htmlText = QT_ALLOC_QCHAR_VEC(stdInc); recursive( htmlText, currentLength, offset, stdInc ); QString finishedHtmlText( htmlText, offset ); return finishedHtmlText;}void NodeImpl::recursive( QChar *&htmlText, long ¤tLength, long &offset, int stdInc ){ DOMString me; // Copy who I am into the htmlText string if ( nodeType() == Node::TEXT_NODE ) { me = nodeValue(); int i = me.length(); while( (currentLength - offset) <= i*2+4) increaseStringLength( htmlText, currentLength, offset, stdInc); memcpy(htmlText+offset, me.stringPtr(), i*2); offset += i; } else { // If I am an element, not a text me = nodeName(); int i = me.length(); while( (currentLength - offset) <= i*2+4) increaseStringLength( htmlText, currentLength, offset, stdInc); memcpy(htmlText+offset, &LESSTHAN, 2); // prints < memcpy(htmlText+offset+1, me.stringPtr(), i*2); // prints tagname // print attributes if( nodeType() == Node::ELEMENT_NODE ) { int lattrs = 0; ElementImpl *el = static_cast<ElementImpl *>(this); AttrImpl *attr; NamedNodeMapImpl *attrs = static_cast<NamedNodeMapImpl*>(el->attributes()); unsigned long lmap = attrs->length(); for( uint j=0; j<lmap; j++ ) { attr = static_cast<AttrImpl*>(attrs->item(i)); unsigned long lname = attr->name().length(); unsigned long lvalue = attr->value().length(); while( (currentLength - offset) <= (signed)(i*2+lattrs+lname+lvalue+4) ) increaseStringLength( htmlText, currentLength, offset, stdInc); memcpy(htmlText+offset+i+lattrs+1, &SPACE, 2); // prints a space memcpy(htmlText+offset+i+lattrs+2, attr->name().stringPtr(), lname*2); memcpy(htmlText+offset+i+lattrs+lname+2, &EQUALS, 2); // prints = memcpy(htmlText+offset+i+lattrs+lname+3, "E, 2); // prints " memcpy(htmlText+offset+i+lattrs+lname+4, attr->value().stringPtr(), lvalue*2); memcpy(htmlText+offset+i+lattrs+lname+lvalue+4, "E, 2); // prints " lattrs += lname + lvalue + 4; } offset += lattrs; } // print ending bracket of start tag if( firstChild() == 0 ) // if element has no endtag { memcpy(htmlText+offset+i+1, &SPACE, 2); // prints a space memcpy(htmlText+offset+i+2, &SLASH, 2); // prints / memcpy(htmlText+offset+i+3, &MORETHAN, 2); // prints > offset += i+4; } else // if element has endtag { memcpy(htmlText+offset+i+1, &MORETHAN, 2); // prints > offset += i+2; } } if( firstChild() != 0 ) { // print firstChild firstChild()->recursive( htmlText, currentLength, offset, stdInc); // Print my ending tag if ( nodeType() != Node::TEXT_NODE ) { me = nodeName(); int i = me.length(); while( (currentLength - offset) <= i*2+3) increaseStringLength( htmlText, currentLength, offset, stdInc); memcpy(htmlText+offset, &LESSTHAN, 2); // prints < memcpy(htmlText+offset+1, &SLASH, 2); // prints / memcpy(htmlText+offset+2, me.stringPtr(), i*2); // prints tagname memcpy(htmlText+offset+i+2, &MORETHAN, 2); // prints > offset += i+3; } } // print next sibling if( nextSibling() ) nextSibling()->recursive( htmlText, currentLength, offset, stdInc);}bool NodeImpl::increaseStringLength( QChar *&htmlText, long ¤tLength, long offset, int stdInc){ currentLength += stdInc; QChar *htmlTextTmp = QT_ALLOC_QCHAR_VEC( currentLength ); memcpy( htmlTextTmp, htmlText, offset*sizeof(QChar) ); QT_DELETE_QCHAR_VEC( htmlText ); htmlText = htmlTextTmp; return true; // should return false if not enough memory}void NodeImpl::applyChanges(bool, bool){ setChanged(false);}void NodeImpl::getCursor(int offset, int &_x, int &_y, int &height){ if(m_render) m_render->cursorPos(offset, _x, _y, height); else _x = _y = height = -1;}QRect NodeImpl::getRect(){ int _x, _y; if(m_render) { m_render->absolutePosition(_x, _y); return QRect( _x, _y, m_render->width(), m_render->height() ); } return QRect();}void NodeImpl::setKeyboardFocus(ActivationState b){ if (m_render) { m_render->setKeyboardFocus(b); RenderObject *cb = m_render->containingBlock(); // repaint one pixel outside the element`s dimensions to make // sure that a Selection (that can be larger than the object) // is completely redrawn. cb->repaintRectangle(-3, -1, cb->width()+5, cb->height()+3); }}void NodeImpl::setChanged(bool b){ if (b && !changed() && document) document->changedNodes.append(this); m_changed = b;}//--------------------------------------------------------------------NodeWParentImpl::NodeWParentImpl(DocumentImpl *doc) : NodeImpl(doc){ _parent = 0; _previous = 0; _next = 0;}NodeWParentImpl::~NodeWParentImpl(){ // previous and next node may still reference this!!! // hope this fix is fine... if(_previous) _previous->setNextSibling(0); if(_next) _next->setPreviousSibling(0);}NodeImpl *NodeWParentImpl::parentNode() const{ return _parent;}NodeImpl *NodeWParentImpl::previousSibling() const{ return _previous;}NodeImpl *NodeWParentImpl::nextSibling() const{ return _next;}NodeImpl *NodeWParentImpl::cloneNode( bool ){ // we have no childs, so we just clone this Node // the parent is set to 0 anyway... return new NodeWParentImpl(document);}// not part of the DOMvoid NodeWParentImpl::setParent(NodeImpl *n){ _parent = n;}bool NodeWParentImpl::deleteMe(){ if(!_parent && _ref <= 0) return true; return false;}void NodeWParentImpl::setPreviousSibling(NodeImpl *n){ if(!_parent) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); _previous = n;}void NodeWParentImpl::setNextSibling(NodeImpl *n){ if(!_parent) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); _next = n;}void NodeWParentImpl::checkReadOnly(){}//-------------------------------------------------------------------------NodeBaseImpl::NodeBaseImpl(DocumentImpl *doc) : NodeWParentImpl(doc){ _first = _last = 0;}NodeBaseImpl::~NodeBaseImpl(){ //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl; // we have to tell all children, that the parent has died... NodeImpl *n; NodeImpl *next; for( n = _first; n != 0; n = next ) { next = n->nextSibling(); n->setPreviousSibling(0); n->setNextSibling(0); n->setParent(0); if(n->deleteMe()) delete n; else n->setOwnerDocument(0); }}NodeImpl *NodeBaseImpl::firstChild() const{ return _first;}NodeImpl *NodeBaseImpl::lastChild() const{ return _last;}NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild ){ checkReadOnly(); if (!newChild || (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE && !newChild->firstChild())) throw DOMException(DOMException::NOT_FOUND_ERR); if(!refChild) return appendChild(newChild); checkSameDocument(newChild); checkNoOwner(newChild); checkIsChild(refChild); if(newChild->parentNode() == this) removeChild(newChild); bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE; NodeImpl *nextChild; NodeImpl *child = isFragment ? newChild->firstChild() : newChild; NodeImpl *prev = refChild->previousSibling(); while (child) { nextChild = isFragment ? child->nextSibling() : 0; checkNoOwner(child); if(!childAllowed(child)) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); // if already in the tree, remove it first! NodeImpl *newParent = child->parentNode();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -