⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dom2_rangeimpl.cpp

📁 将konqueror浏览器移植到ARM9 2410中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/** * This file is part of the DOM implementation for KDE. * * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * (C) 2001 Peter Kelly (pmk@post.com) * * 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. * * $Id: dom2_rangeimpl.cpp,v 1.23 2001/07/15 19:55:01 mueller Exp $ */#include "dom/dom2_traversal.h"#include "dom/dom_node.h"#include "dom/dom_doc.h"#include "dom/dom_string.h"#include "dom/dom_text.h"#include "dom/dom_exception.h"#include "dom_docimpl.h"#include "dom2_rangeimpl.h"#include "dom2_traversalimpl.h"#include "dom_textimpl.h"#include "dom_xmlimpl.h"using namespace DOM;RangeImpl::RangeImpl(DocumentPtr *_ownerDocument){    m_ownerDocument = _ownerDocument;    m_ownerDocument->ref();    m_startContainer = _ownerDocument->document();    m_startContainer->ref();    m_endContainer = _ownerDocument->document();    m_endContainer->ref();    m_startOffset = 0;    m_endOffset = 0;    m_detached = false;}RangeImpl::RangeImpl(DocumentPtr *_ownerDocument,              NodeImpl *_startContainer, long _startOffset,              NodeImpl *_endContainer, long _endOffset){    m_ownerDocument = _ownerDocument;    m_ownerDocument->ref();    m_startContainer = _startContainer;    m_startContainer->ref();    m_startOffset = _startOffset;    m_endContainer = _endContainer;    m_endContainer->ref();    m_endOffset = _endOffset;    m_detached = false;}RangeImpl::~RangeImpl(){    m_ownerDocument->deref();    int exceptioncode;    if (!m_detached)        detach(exceptioncode);}NodeImpl *RangeImpl::startContainer(int &exceptioncode) const{    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    return m_startContainer;}long RangeImpl::startOffset(int &exceptioncode) const{    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    return m_startOffset;}NodeImpl *RangeImpl::endContainer(int &exceptioncode) const{    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    return m_endContainer;}long RangeImpl::endOffset(int &exceptioncode) const{    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    return m_endOffset;}NodeImpl *RangeImpl::commonAncestorContainer(int &exceptioncode){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    NodeImpl *com = commonAncestorContainer(m_startContainer,m_endContainer);    if (!com) //  should never happen        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;    return com;}NodeImpl *RangeImpl::commonAncestorContainer(NodeImpl *containerA, NodeImpl *containerB){    NodeImpl *parentStart;    for (parentStart = containerA; parentStart; parentStart = parentStart->parentNode()) {        NodeImpl *parentEnd = containerB;        while( parentEnd && (parentStart != parentEnd) )            parentEnd = parentEnd->parentNode();        if(parentStart == parentEnd)  break;    }    return parentStart;}bool RangeImpl::collapsed(int &exceptioncode) const{    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    return (m_startContainer == m_endContainer && m_startOffset == m_endOffset);}void RangeImpl::setStart( NodeImpl *refNode, long offset, int &exceptioncode ){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return;    }    if (!refNode) {        exceptioncode = DOMException::NOT_FOUND_ERR;        return;    }    if (refNode->getDocument() != m_ownerDocument->document()) {        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;        return;    }    checkNodeWOffset( refNode, offset, exceptioncode );    if (exceptioncode)        return;    setStartContainer(refNode);    m_startOffset = offset;    // check if different root container    NodeImpl *endRootContainer = m_endContainer;    while (endRootContainer->parentNode())        endRootContainer = endRootContainer->parentNode();    NodeImpl *startRootContainer = m_startContainer;    while (startRootContainer->parentNode())        startRootContainer = startRootContainer->parentNode();    if (startRootContainer != endRootContainer)        collapse(true,exceptioncode);    // check if new start after end    else if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)        collapse(true,exceptioncode);}void RangeImpl::setEnd( NodeImpl *refNode, long offset, int &exceptioncode ){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return;    }    if (!refNode) {        exceptioncode = DOMException::NOT_FOUND_ERR;        return;    }    if (refNode->getDocument() != m_ownerDocument->document()) {        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;        return;    }    checkNodeWOffset( refNode, offset, exceptioncode );    if (exceptioncode)        return;    setEndContainer(refNode);    m_endOffset = offset;    // check if different root container    NodeImpl *endRootContainer = m_endContainer;    while (endRootContainer->parentNode())        endRootContainer = endRootContainer->parentNode();    NodeImpl *startRootContainer = m_startContainer;    while (startRootContainer->parentNode())        startRootContainer = startRootContainer->parentNode();    if (startRootContainer != endRootContainer)        collapse(false,exceptioncode);    // check if new end before start    if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)        collapse(false,exceptioncode);}void RangeImpl::collapse( bool toStart, int &exceptioncode ){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return;    }    if( toStart )   // collapse to start    {        setEndContainer(m_startContainer);        m_endOffset = m_startOffset;    }    else            // collapse to end    {        setStartContainer(m_endContainer);        m_startOffset = m_endOffset;    }}short RangeImpl::compareBoundaryPoints( Range::CompareHow how, RangeImpl *sourceRange, int &exceptioncode ){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return 0;    }    if (!sourceRange) {        exceptioncode = DOMException::NOT_FOUND_ERR;        return 0;    }    NodeImpl *thisCont = commonAncestorContainer(exceptioncode);    NodeImpl *sourceCont = sourceRange->commonAncestorContainer(exceptioncode);    if (exceptioncode)        return 0;    if (thisCont->ownerDocument() != sourceCont->ownerDocument()) {        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;        return 0;    }    NodeImpl *thisTop = thisCont;    NodeImpl *sourceTop = sourceCont;    while (thisTop->parentNode())	thisTop = thisTop->parentNode();    while (sourceTop->parentNode())	sourceTop = sourceTop->parentNode();    if (thisTop != sourceTop) { // in different DocumentFragments        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;        return 0;    }    switch(how)    {    case Range::START_TO_START:        return compareBoundaryPoints( m_startContainer, m_startOffset,                                      sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );        break;    case Range::START_TO_END:        return compareBoundaryPoints( m_startContainer, m_startOffset,                                      sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );        break;    case Range::END_TO_END:        return compareBoundaryPoints( m_endContainer, m_endOffset,                                      sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );        break;    case Range::END_TO_START:        return compareBoundaryPoints( m_endContainer, m_endOffset,                                      sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );        break;    default:        exceptioncode = DOMException::SYNTAX_ERR;        return 0;    }}short RangeImpl::compareBoundaryPoints( NodeImpl *containerA, long offsetA, NodeImpl *containerB, long offsetB ){    // see DOM2 traversal & range section 2.5    // case 1: both points have the same container    if( containerA == containerB )    {        if( offsetA == offsetB )  return 0;    // A is equal to B        if( offsetA < offsetB )  return -1;    // A is before B        else  return 1;                        // A is after B    }    // case 2: node C (container B or an ancestor) is a child node of A    NodeImpl *c = containerB;    while (c && c->parentNode() != containerA)        c = c->parentNode();    if (c) {        int offsetC = 0;        NodeImpl *n = n = containerA->firstChild();        while (n != c) {            offsetC++;            n = n->nextSibling();        }        if( offsetA <= offsetC )  return -1;    // A is before B        else  return 1;                        // A is after B    }    // case 3: node C (container A or an ancestor) is a child node of B    c = containerA;    while (c && c->parentNode() != containerB)        c = c->parentNode();    if (c) {        int offsetC = 0;        NodeImpl *n = n = containerB->firstChild();        while (n != c) {            offsetC++;            n = n->nextSibling();        }        if( offsetC < offsetB )  return -1;    // A is before B        else  return 1;                        // A is after B    }    // case 4: containers A & B are siblings, or children of siblings    // ### we need to do a traversal here instead    NodeImpl *cmnRoot = commonAncestorContainer(containerA,containerB);    NodeImpl *childA = containerA;    while (childA->parentNode() != cmnRoot)        childA = childA->parentNode();    NodeImpl *childB = containerB;    while (childB->parentNode() != cmnRoot)        childB = childB->parentNode();    NodeImpl *n = cmnRoot->firstChild();    int i = 0;    int childAOffset = -1;    int childBOffset = -1;    while (childAOffset < 0 || childBOffset < 0) {        if (n == childA)            childAOffset = i;        if (n == childB)            childBOffset = i;        n = n->nextSibling();        i++;    }    if( childAOffset == childBOffset )  return 0;    // A is equal to B    if( childAOffset < childBOffset )   return -1;    // A is before B    else  return 1;                        // A is after B}bool RangeImpl::boundaryPointsValid(  ){    short valid =  compareBoundaryPoints( m_startContainer, m_startOffset,                                          m_endContainer, m_endOffset );    if( valid == 1 )  return false;    else  return true;}void RangeImpl::deleteContents( int &exceptioncode ) {    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return;    }    checkDeleteExtract(exceptioncode);    if (exceptioncode)	return;    processContents(DELETE_CONTENTS,exceptioncode);}DocumentFragmentImpl *RangeImpl::processContents ( ActionType action, int &exceptioncode ){    // ### when mutation events are implemented, we will have to take into account    // situations where the tree is being transformed while we delete - ugh!    // ### perhaps disable node deletion notification for this range while we do this?    if (collapsed(exceptioncode))        return 0;    if (exceptioncode)        return 0;    NodeImpl *cmnRoot = commonAncestorContainer(exceptioncode);    if (exceptioncode)        return 0;    // what is the highest node that partially selects the start of the range?    NodeImpl *partialStart = 0;    if (m_startContainer != cmnRoot) {	partialStart = m_startContainer;	while (partialStart->parentNode() != cmnRoot)	    partialStart = partialStart->parentNode();    }    // what is the highest node that partially selects the end of the range?    NodeImpl *partialEnd = 0;    if (m_endContainer != cmnRoot) {	partialEnd = m_endContainer;	while (partialEnd->parentNode() != cmnRoot)	    partialEnd = partialEnd->parentNode();    }    DocumentFragmentImpl *fragment = 0;    if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)        fragment = new DocumentFragmentImpl(m_ownerDocument);    // Simple case: the start and end containers are the same. We just grab    // everything >= start offset and < end offset    if (m_startContainer == m_endContainer) {        if(m_startContainer->nodeType() == Node::TEXT_NODE ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -