summaryrefslogtreecommitdiffstats
path: root/khtml/xml/dom2_rangeimpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/xml/dom2_rangeimpl.cpp')
-rw-r--r--khtml/xml/dom2_rangeimpl.cpp1640
1 files changed, 0 insertions, 1640 deletions
diff --git a/khtml/xml/dom2_rangeimpl.cpp b/khtml/xml/dom2_rangeimpl.cpp
deleted file mode 100644
index b160ce23f..000000000
--- a/khtml/xml/dom2_rangeimpl.cpp
+++ /dev/null
@@ -1,1640 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 2001-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
- * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
- * (C) 2001 Peter Kelly (pmk@post.com)
- * 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., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "dom/dom_exception.h"
-#include "dom_docimpl.h"
-#include "dom2_rangeimpl.h"
-#include "dom_textimpl.h"
-#include "dom_xmlimpl.h"
-#include "html/html_elementimpl.h"
-#include "misc/htmltags.h"
-
-using namespace DOM;
-
-
-RangeImpl::RangeImpl(DocumentImpl *_ownerDocument)
-{
- m_ownerDocument = _ownerDocument;
- m_ownerDocument->ref();
- m_startContainer = _ownerDocument;
- m_startContainer->ref();
- m_endContainer = _ownerDocument;
- m_endContainer->ref();
- m_startOffset = 0;
- m_endOffset = 0;
- m_detached = false;
-}
-
-RangeImpl::RangeImpl(DocumentImpl *_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 = 0;
- 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) {
- 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) {
- 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->getDocument() != sourceCont->getDocument()) {
- 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 = 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 = 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);
- if (!cmnRoot) return -1; // Whatever...
- 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 ||
- m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
- m_startContainer->nodeType() == Node::COMMENT_NODE) {
-
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
- c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_endOffset,exceptioncode);
- c->deleteData(0,m_startOffset,exceptioncode);
- fragment->appendChild(c,exceptioncode);
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(m_startOffset,m_endOffset-m_startOffset,exceptioncode);
- }
- else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
- // ### operate just on data ?
- }
- else {
- NodeImpl *n = m_startContainer->firstChild();
- unsigned long i;
- for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
- n = n->nextSibling();
- while (n && i < m_endOffset) { // delete until m_endOffset
- NodeImpl *next = n->nextSibling();
- if (action == EXTRACT_CONTENTS)
- fragment->appendChild(n,exceptioncode); // will remove n from its parent
- else if (action == CLONE_CONTENTS)
- fragment->appendChild(n->cloneNode(true),exceptioncode);
- else
- m_startContainer->removeChild(n,exceptioncode);
- n = next;
- i++;
- }
- }
- collapse(true,exceptioncode);
- return fragment;
- }
-
- // Complex case: Start and end containers are different.
- // There are three possiblities here:
- // 1. Start container == cmnRoot (End container must be a descendant)
- // 2. End container == cmnRoot (Start container must be a descendant)
- // 3. Neither is cmnRoot, they are both descendants
- //
- // In case 3, we grab everything after the start (up until a direct child
- // of cmnRoot) into leftContents, and everything before the end (up until
- // a direct child of cmnRoot) into rightContents. Then we process all
- // cmnRoot children between leftContents and rightContents
- //
- // In case 1 or 2, we skip either processing of leftContents or rightContents,
- // in which case the last lot of nodes either goes from the first or last
- // child of cmnRoot.
- //
- // These are deleted, cloned, or extracted (i.e. both) depending on action.
-
- NodeImpl *leftContents = 0;
- if (m_startContainer != cmnRoot) {
- // process the left-hand side of the range, up until the last ancestor of
- // m_startContainer before cmnRoot
- if(m_startContainer->nodeType() == Node::TEXT_NODE ||
- m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
- m_startContainer->nodeType() == Node::COMMENT_NODE) {
-
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
- c->deleteData(0,m_startOffset,exceptioncode);
- leftContents = c;
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(
- m_startOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_startOffset,exceptioncode);
- }
- else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
- // ### operate just on data ?
- // leftContents = ...
- }
- else {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
- leftContents = m_startContainer->cloneNode(false);
- NodeImpl *n = m_startContainer->firstChild();
- unsigned long i;
- for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
- n = n->nextSibling();
- while (n) { // process until end
- NodeImpl *next = n->nextSibling();
- if (action == EXTRACT_CONTENTS)
- leftContents->appendChild(n,exceptioncode); // will remove n from m_startContainer
- else if (action == CLONE_CONTENTS)
- leftContents->appendChild(n->cloneNode(true),exceptioncode);
- else
- m_startContainer->removeChild(n,exceptioncode);
- n = next;
- }
- }
-
- NodeImpl *leftParent = m_startContainer->parentNode();
- NodeImpl *n = m_startContainer->nextSibling();
- for (; leftParent != cmnRoot; leftParent = leftParent->parentNode()) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- NodeImpl *leftContentsParent = leftParent->cloneNode(false);
- leftContentsParent->appendChild(leftContents,exceptioncode);
- leftContents = leftContentsParent;
- }
-
- NodeImpl *next;
- for (; n; n = next ) {
- next = n->nextSibling();
- if (action == EXTRACT_CONTENTS)
- leftContents->appendChild(n,exceptioncode); // will remove n from leftParent
- else if (action == CLONE_CONTENTS)
- leftContents->appendChild(n->cloneNode(true),exceptioncode);
- else
- leftParent->removeChild(n,exceptioncode);
- }
- n = leftParent->nextSibling();
- }
- }
-
- NodeImpl *rightContents = 0;
- if (m_endContainer != cmnRoot) {
- // delete the right-hand side of the range, up until the last ancestor of
- // m_endContainer before cmnRoot
- if(m_endContainer->nodeType() == Node::TEXT_NODE ||
- m_endContainer->nodeType() == Node::CDATA_SECTION_NODE ||
- m_endContainer->nodeType() == Node::COMMENT_NODE) {
-
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_endContainer->cloneNode(true));
- c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_endContainer)->length()-m_endOffset,exceptioncode);
- rightContents = c;
- }
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
- static_cast<CharacterDataImpl*>(m_endContainer)->deleteData(0,m_endOffset,exceptioncode);
- }
- else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
- // ### operate just on data ?
- // rightContents = ...
- }
- else {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
- rightContents = m_endContainer->cloneNode(false);
- NodeImpl *n = m_endContainer->firstChild();
- unsigned long i;
- for(i = 0; i+1 < m_endOffset; i++) // skip to m_endOffset
- n = n->nextSibling();
- NodeImpl *prev;
- for (; n; n = prev ) {
- prev = n->previousSibling();
- if (action == EXTRACT_CONTENTS)
- rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
- else if (action == CLONE_CONTENTS)
- rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
- else
- m_endContainer->removeChild(n,exceptioncode);
- }
- }
-
- NodeImpl *rightParent = m_endContainer->parentNode();
- NodeImpl *n = m_endContainer->previousSibling();
- for (; rightParent != cmnRoot; rightParent = rightParent->parentNode()) {
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
- NodeImpl *rightContentsParent = rightParent->cloneNode(false);
- rightContentsParent->appendChild(rightContents,exceptioncode);
- rightContents = rightContentsParent;
- }
-
- NodeImpl *prev;
- for (; n; n = prev ) {
- prev = n->previousSibling();
- if (action == EXTRACT_CONTENTS)
- rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
- else if (action == CLONE_CONTENTS)
- rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
- else
- rightParent->removeChild(n,exceptioncode);
-
- }
- n = rightParent->previousSibling();
- }
- }
-
- // delete all children of cmnRoot between the start and end container
-
- NodeImpl *processStart; // child of cmnRooot
- if (m_startContainer == cmnRoot) {
- unsigned long i;
- processStart = m_startContainer->firstChild();
- for (i = 0; i < m_startOffset; i++)
- processStart = processStart->nextSibling();
- }
- else {
- processStart = m_startContainer;
- while (processStart->parentNode() != cmnRoot)
- processStart = processStart->parentNode();
- processStart = processStart->nextSibling();
- }
- NodeImpl *processEnd; // child of cmnRooot
- if (m_endContainer == cmnRoot) {
- unsigned long i;
- processEnd = m_endContainer->firstChild();
- for (i = 0; i < m_endOffset; i++)
- processEnd = processEnd->nextSibling();
- }
- else {
- processEnd = m_endContainer;
- while (processEnd->parentNode() != cmnRoot)
- processEnd = processEnd->parentNode();
- }
-
- // Now add leftContents, stuff in between, and rightContents to the fragment
- // (or just delete the stuff in between)
-
- if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
- fragment->appendChild(leftContents,exceptioncode);
-
- NodeImpl *next;
- NodeImpl *n;
- if (processStart) {
- for (n = processStart; n && n != processEnd; n = next) {
- next = n->nextSibling();
-
- if (action == EXTRACT_CONTENTS)
- fragment->appendChild(n,exceptioncode); // will remove from cmnRoot
- else if (action == CLONE_CONTENTS)
- fragment->appendChild(n->cloneNode(true),exceptioncode);
- else
- cmnRoot->removeChild(n,exceptioncode);
- }
- }
-
- if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
- fragment->appendChild(rightContents,exceptioncode);
-
- // collapse to the proper position - see spec section 2.6
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
- if (!partialStart && !partialEnd)
- collapse(true,exceptioncode);
- else if (partialStart) {
- setStartContainer(partialStart->parentNode());
- setEndContainer(partialStart->parentNode());
- m_startOffset = m_endOffset = partialStart->nodeIndex()+1;
- }
- else if (partialEnd) {
- setStartContainer(partialEnd->parentNode());
- setEndContainer(partialEnd->parentNode());
- m_startOffset = m_endOffset = partialEnd->nodeIndex();
- }
- }
- return fragment;
-}
-
-
-DocumentFragmentImpl *RangeImpl::extractContents( int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return 0;
- }
-
- checkDeleteExtract(exceptioncode);
- if (exceptioncode)
- return 0;
-
- return processContents(EXTRACT_CONTENTS,exceptioncode);
-}
-
-DocumentFragmentImpl *RangeImpl::cloneContents( int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return 0;
- }
-
- return processContents(CLONE_CONTENTS,exceptioncode);
-}
-
-void RangeImpl::insertNode( NodeImpl *newNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
- // the Range is read-only.
- NodeImpl *n = m_startContainer;
- while (n && !n->isReadOnly())
- n = n->parentNode();
- if (n) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-
- n = m_endContainer;
- while (n && !n->isReadOnly())
- n = n->parentNode();
- if (n) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-
- // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
- // not created from the same document.
- if (newNode->getDocument() != m_startContainer->getDocument()) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
-
- // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
- // does not allow children of the type of newNode or if newNode is an ancestor of the container.
-
- // an extra one here - if a text node is going to split, it must have a parent to insert into
- if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
-
- // In the case where the container is a text node, we check against the container's parent, because
- // text nodes get split up upon insertion.
- NodeImpl *checkAgainst;
- if (m_startContainer->nodeType() == Node::TEXT_NODE)
- checkAgainst = m_startContainer->parentNode();
- else
- checkAgainst = m_startContainer;
-
- if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
- // check each child node, not the DocumentFragment itself
- NodeImpl *c;
- for (c = newNode->firstChild(); c; c = c->nextSibling()) {
- if (!checkAgainst->childTypeAllowed(c->nodeType())) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
- }
- }
- else {
- if (!checkAgainst->childTypeAllowed(newNode->nodeType())) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
- }
-
- for (n = m_startContainer; n; n = n->parentNode()) {
- if (n == newNode) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
- }
-
- // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
- if( newNode->nodeType() == Node::ATTRIBUTE_NODE ||
- newNode->nodeType() == Node::ENTITY_NODE ||
- newNode->nodeType() == Node::NOTATION_NODE ||
- newNode->nodeType() == Node::DOCUMENT_NODE) {
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
-
- if( m_startContainer->nodeType() == Node::TEXT_NODE ||
- m_startContainer->nodeType() == Node::CDATA_SECTION_NODE )
- {
- TextImpl *newText = static_cast<TextImpl*>(m_startContainer)->splitText(m_startOffset,exceptioncode);
- if (exceptioncode)
- return;
- m_startContainer->parentNode()->insertBefore( newNode, newText, exceptioncode );
- }
- else {
- m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), exceptioncode );
- }
-}
-
-DOMString RangeImpl::toString( int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return DOMString();
- }
-
- DOMString text = "";
- NodeImpl *n = m_startContainer;
-
- /* This function converts a dom range to the plain text string that the user would see in this
- * portion of rendered html.
- *
- * There are several ways ranges can be used.
- *
- * The simplest is the start and endContainer is a text node. The start and end offset is the
- * number of characters into the text to remove/truncate.
- *
- * The next case is the start and endContainer is, well, a container, such a P tag or DIV tag.
- * In this case the start and end offset is the number of children into the container to start
- * from and end at.
- *
- * The other cases are different arrangements of the first two.
- *
- * psuedo code:
- *
- * if start container is not text:
- * count through the children to find where we start (m_startOffset children)
- *
- * loop from the start position:
- * if the current node is text, add the text to our variable 'text', truncating/removing if at the end/start.
- *
- * if the node has children, step to the first child.
- * if the node has no children but does have siblings, step to the next sibling
- * until we find a sibling, go to next the parent but:
- * make sure this sibling isn't past the end of where we are supposed to go. (position > endOffset and the parent is the endContainer)
- *
- */
-
-
- if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)
- return text;
-
-
- if(n->firstChild()) {
- n = n->firstChild();
- int current_offset = m_startOffset;
- while(current_offset-- && n) {
- n = n->nextSibling();
- }
- }
-
- while(n) {
- if(n->nodeType() == DOM::Node::TEXT_NODE ||
- n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
-
- DOMString str;
- str = static_cast<TextImpl *>(n)->string();
- if( n == m_endContainer || n == m_startContainer)
- str = str.copy(); //copy if we are going to modify.
-
- if (n == m_endContainer)
- str.truncate(m_endOffset);
- if (n == m_startContainer)
- str.remove(0,m_startOffset);
- text += str;
- if (n == m_endContainer)
- break;
- }
-
-
- NodeImpl *next = n->firstChild();
- if(!next)
- next = n->nextSibling();
-
- while( !next && n->parentNode() ) {
- if (n == m_endContainer) return text;
- n = n->parentNode();
- if (n == m_endContainer) return text;
- next = n->nextSibling();
- }
-
- if(n->parentNode() == m_endContainer) {
- if(!next) break;
- unsigned long current_offset = 0;
- NodeImpl *it = n;
- while((it = it->previousSibling())) ++current_offset;
- if(current_offset >= m_endOffset) {
- break;
- }
- }
-
- n = next;
- }
- return text;
-}
-
-DOMString RangeImpl::toHTML( int &exceptioncode )
-{
- bool hasHtmlTag = false;
- bool hasBodyTag = false;
- //FIXME: What is this section of code below exactly? Do I want it here?
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return DOMString();
- }
- DOMString text = "";
- NodeImpl *n = m_startContainer;
- int num_tables=0;
- bool in_li = false; //whether we have an li in the text, without an ol/ul
- int depth_difference = 0;
- int lowest_depth_difference = 0;
-
- if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)
- return text;
-
- while(n) {
- /* First, we could have an tag <tagname key=value>otherstuff</tagname> */
- if(n->nodeType() == DOM::Node::ELEMENT_NODE) {
- int elementId = static_cast<ElementImpl *>(n)->id();
- if(elementId == ID_TABLE) num_tables++;
- if(elementId == ID_BODY) hasBodyTag = true;
- if(elementId == ID_HTML) hasHtmlTag = true;
- if(elementId == ID_LI) in_li=true;
- if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables++;
- if(!( !n->hasChildNodes() && (elementId == ID_H1 || elementId == ID_H2 || elementId == ID_H3 || elementId == ID_H4 || elementId ==ID_H5))) { //Don't add <h1/> etc. Just skip these nodes just to make the output html a bit nicer.
- text += static_cast<ElementImpl *>(n)->openTagStartToString(true /*safely expand img urls*/); // adds "<tagname key=value"
- if(n->hasChildNodes()) {
- depth_difference++;
- text += ">";
- } else {
- text += "/>";
- }
- }
- } else
- if(n->nodeType() == DOM::Node::TEXT_NODE ||
- n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
- if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += "<![CDATA[ ";
- long long startOffset = (n == m_startContainer)?(long long)m_startOffset:-1;
- long long endOffset = (n == m_endContainer)?(long long) m_endOffset:-1;
- text += static_cast<TextImpl *>(n)->toString(startOffset, endOffset); //Note this should always work since CDataImpl inherits TextImpl
- if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += " ]]>";
- if(n == m_endContainer) {
- break;
- }
- }
- if(n->parentNode() == m_endContainer && !n->nextSibling()) {
- break;
- }
-
- //if (n == m_endContainer) break;
- NodeImpl *next = n->firstChild();
- if(next) {
- if(n == m_startContainer) {
- //This is the start of our selection, so we have to move to where we have started selecting.
- //For example, if 'n' is "hello <img src='hello.png'> how are you? <img src='goodbye.png'>"
- //then this has four children. If our selection started on the image, then we need to start from there.
- unsigned long current_offset = 0;
- while(current_offset < m_startOffset && next) {
- next = next->nextSibling();
- ++current_offset;
- }
- }
- } else {
- next = n->nextSibling();
-
- if(n->parentNode() == m_endContainer) {
- unsigned long current_offset = 1;
- NodeImpl *it = n;
- while((it = it->previousSibling())) ++current_offset;
-
- if(current_offset >= m_endOffset) {
- break;
- }
- }
- }
-
- while( !next && n->parentNode() ) {
- n = n->parentNode();
- if(n->nodeType() == DOM::Node::ELEMENT_NODE) {
- text += "</";
- text += static_cast<ElementImpl *>(n)->tagName();
- int elementId = static_cast<ElementImpl *>(n)->id();
- if(elementId == ID_TABLE) num_tables--;
- depth_difference--;
- if(lowest_depth_difference > depth_difference) lowest_depth_difference=depth_difference;
- if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables--;
- if(elementId == ID_OL || elementId == ID_UL) in_li=false;
- text += ">";
- }
- next = n->nextSibling();
- }
- n = next;
- }
-
- //We have the html in the selection. But now we need to properly add the opening and closing tags.
- //For example say we have: "Hello <b>Mr. John</b> How are you?" and we select "John" or even
- //"John</b> How" and copy. We want to return "<b>John</b>" and "<b>John</b> How" respectively
-
- //To do this, we need to go up the tree from the start, and prepend those tags.
- //Imagine our selection was this:
- //
- // hello</b></p><p>there
- //
- // The difference in depths between the start and end is -1, and the lowest depth
- // difference from the starting point is -2
- //
- // So from the start of the selection, we want to go down to the lowest_depth_difference
- // and prepend those tags. (<p><b>)
- //
- // From the end of the selection, we want to also go down to the lowest_depth_difference.
- // We know the depth of the end of the selection - i.e. depth_difference.
- //
- //
- n = m_startContainer;
- int startdepth = 0; //by definition - we are counting from zero.
- while((n = n->parentNode()) && startdepth>lowest_depth_difference) {
- if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
- switch (static_cast<ElementImpl *>(n)->id()) {
- case ID_TABLE:
- num_tables--;
- break;
- case ID_BODY:
- hasBodyTag = true;
- break;
- case ID_HTML:
- hasHtmlTag = true;
- break;
- case ID_LI:
- in_li = true;
- break;
- }
- text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text; // prepends "<tagname key=value>"
- }
- startdepth--;
- }
- n = m_endContainer;
- while( depth_difference>lowest_depth_difference && (n = n->parentNode())) {
- if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
- switch (static_cast<ElementImpl *>(n)->id()) {
- case ID_TABLE:
- num_tables++;
- break;
- case ID_OL:
- case ID_UL:
- in_li=false;
- break;
- }
- text += "</";
- text += static_cast<ElementImpl *>(n)->tagName();
- text += ">";
- }
- depth_difference--;
- }
-
- // Now our text string is the same depth on both sides, with nothing lower (in other words all the
- // tags in it match up.) This also means that the end value for n in the first loop is a sibling of the
- // end value for n in the second loop.
- //
- // We now need to go down the tree, and for certain tags, add them in on both ends of the text.
- // For example, if have: "<b>hello</b>" and we select "ll", then we want to go down the tree and
- // add "<b>" and "</b>" to it, to produce "<b>ll</b>".
- //
- // I just guessed at which tags you'd want to keep (bold, italic etc) and which you wouldn't (tables etc).
- // It's just wild guessing. feel free to change.
- //
- // Note we can carry on with the value of n
- if(n) {
- while((n = n->parentNode())) {
- if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
- int elementId = static_cast<ElementImpl *>(n)->id();
- switch (elementId) {
- case ID_TABLE:
- case ID_TD:
- case ID_TR:
- case ID_TH:
- case ID_TBODY:
- case ID_TFOOT:
- case ID_THEAD:
- if(num_tables>0) {
- if(elementId == ID_TABLE) num_tables--;
- text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
- text += "</";
- text += static_cast<ElementImpl *>(n)->tagName();
- text += ">";
-
- }
- break;
-
- case ID_LI:
- if(!in_li) break;
- text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
- text += "</";
- text += static_cast<ElementImpl *>(n)->tagName();
- text += ">";
- break;
-
- case ID_UL:
- case ID_OL:
- if(!in_li) break;
- in_li = false;
- case ID_B:
- case ID_I:
- case ID_U:
- case ID_FONT:
- case ID_S:
- case ID_STRONG:
- case ID_STRIKE:
- case ID_DEL:
- case ID_A:
- case ID_H1:
- case ID_H2:
- case ID_H3:
- case ID_H4:
- case ID_H5:
- //should small, etc be here? so hard to decide. this is such a hack :(
- //There's probably tons of others you'd want here.
- text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
- text += "</";
- text += static_cast<ElementImpl *>(n)->tagName();
- text += ">";
- break;
- }
- }
- }
- }
-
-
- if(!hasBodyTag) text = DOMString("<body>") + text + "</body>";
- else if(!hasHtmlTag) {
- text = DOMString("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
- "<head>\n"
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
- "<meta name=\"Generator\" content=\"KHTML, the KDE Web Page Viewer\" />\n"
- "</head>\n") +
- text +
- "</html>";
- }
- text = DOMString("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n") + text;
-
- return text;
-
-}
-
-DocumentFragment RangeImpl::createContextualFragment ( const DOMString &html, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return DocumentFragment();
- }
-
- if (! m_startContainer->isHTMLElement()) {
- exceptioncode = DOMException::NOT_SUPPORTED_ERR;
- return DocumentFragment();
- }
-
- HTMLElementImpl *e = static_cast<HTMLElementImpl *>(m_startContainer);
- DocumentFragment fragment = e->createContextualFragment(html);
- if (fragment.isNull()) {
- exceptioncode = DOMException::NOT_SUPPORTED_ERR;
- return DocumentFragment();
- }
-
- return fragment;
-}
-
-
-void RangeImpl::detach( int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (m_startContainer)
- m_startContainer->deref();
- m_startContainer = 0;
- if (m_endContainer)
- m_endContainer->deref();
- m_endContainer = 0;
- m_detached = true;
-}
-
-bool RangeImpl::isDetached() const
-{
- return m_detached;
-}
-
-void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const
-{
- if( offset < 0 ) {
- exceptioncode = DOMException::INDEX_SIZE_ERR;
- }
-
- switch (n->nodeType()) {
- case Node::ENTITY_NODE:
- case Node::NOTATION_NODE:
- case Node::DOCUMENT_TYPE_NODE:
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- break;
- case Node::TEXT_NODE:
- case Node::COMMENT_NODE:
- case Node::CDATA_SECTION_NODE:
- if ( (unsigned long)offset > static_cast<CharacterDataImpl*>(n)->length() )
- exceptioncode = DOMException::INDEX_SIZE_ERR;
- break;
- case Node::PROCESSING_INSTRUCTION_NODE:
- // ### are we supposed to check with just data or the whole contents?
- if ( (unsigned long)offset > static_cast<ProcessingInstructionImpl*>(n)->data().length() )
- exceptioncode = DOMException::INDEX_SIZE_ERR;
- break;
- default:
- if ( (unsigned long)offset > n->childNodeCount() )
- exceptioncode = DOMException::INDEX_SIZE_ERR;
- break;
- }
-}
-
-void RangeImpl::checkNodeBA( NodeImpl *n, int &exceptioncode ) const
-{
- // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
- // Attr, Document or DocumentFragment node or if refNode is a Document,
- // DocumentFragment, Attr, Entity, or Notation node.
- NodeImpl *root = n;
- while (root->parentNode())
- root = root->parentNode();
- if (!(root->nodeType() == Node::ATTRIBUTE_NODE ||
- root->nodeType() == Node::DOCUMENT_NODE ||
- root->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)) {
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
-
- if( n->nodeType() == Node::DOCUMENT_NODE ||
- n->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
- n->nodeType() == Node::ATTRIBUTE_NODE ||
- n->nodeType() == Node::ENTITY_NODE ||
- n->nodeType() == Node::NOTATION_NODE )
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
-
-}
-
-RangeImpl *RangeImpl::cloneRange(int &exceptioncode)
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return 0;
- }
-
- return new RangeImpl(m_ownerDocument,m_startContainer,m_startOffset,m_endContainer,m_endOffset);
-}
-
-void RangeImpl::setStartAfter( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- if (refNode->getDocument() != m_ownerDocument) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
- checkNodeBA( refNode, exceptioncode );
- if (exceptioncode)
- return;
-
- setStart( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
-}
-
-void RangeImpl::setEndBefore( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- if (refNode->getDocument() != m_ownerDocument) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
- checkNodeBA( refNode, exceptioncode );
- if (exceptioncode)
- return;
-
- setEnd( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
-}
-
-void RangeImpl::setEndAfter( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- if (refNode->getDocument() != m_ownerDocument) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
- checkNodeBA( refNode, exceptioncode );
- if (exceptioncode)
- return;
-
- setEnd( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
-
-}
-
-void RangeImpl::selectNode( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
- // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
- // node.
- NodeImpl *anc;
- for (anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
- if (anc->nodeType() == Node::ENTITY_NODE ||
- anc->nodeType() == Node::NOTATION_NODE ||
- anc->nodeType() == Node::DOCUMENT_TYPE_NODE) {
-
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
- }
-
- if (refNode->nodeType() == Node::DOCUMENT_NODE ||
- refNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
- refNode->nodeType() == Node::ATTRIBUTE_NODE ||
- refNode->nodeType() == Node::ENTITY_NODE ||
- refNode->nodeType() == Node::NOTATION_NODE) {
-
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
-
- setStartBefore( refNode, exceptioncode );
- if (exceptioncode)
- return;
- setEndAfter( refNode, exceptioncode );
-}
-
-void RangeImpl::selectNodeContents( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
- // or DocumentType node.
- NodeImpl *n;
- for (n = refNode; n; n = n->parentNode()) {
- if (n->nodeType() == Node::ENTITY_NODE ||
- n->nodeType() == Node::NOTATION_NODE ||
- n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
-
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
- }
-
- setStartContainer(refNode);
- m_startOffset = 0;
- setEndContainer(refNode);
- m_endOffset = refNode->childNodeCount();
-}
-
-void RangeImpl::surroundContents( NodeImpl *newParent, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if( !newParent ) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
- // Document, or DocumentFragment node.
- if( newParent->nodeType() == Node::ATTRIBUTE_NODE ||
- newParent->nodeType() == Node::ENTITY_NODE ||
- newParent->nodeType() == Node::NOTATION_NODE ||
- newParent->nodeType() == Node::DOCUMENT_TYPE_NODE ||
- newParent->nodeType() == Node::DOCUMENT_NODE ||
- newParent->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
- exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
-
- // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
- // the Range is read-only.
- if (readOnly()) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-
- NodeImpl *n = m_startContainer;
- while (n && !n->isReadOnly())
- n = n->parentNode();
- if (n) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-
- n = m_endContainer;
- while (n && !n->isReadOnly())
- n = n->parentNode();
- if (n) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-
- // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
- // not created from the same document.
- if (newParent->getDocument() != m_startContainer->getDocument()) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
- // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
- // does not allow children of the type of newParent or if newParent is an ancestor of the container
- // or if node would end up with a child node of a type not allowed by the type of node.
- if (!m_startContainer->childTypeAllowed(newParent->nodeType())) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
-
- for (n = m_startContainer; n; n = n->parentNode()) {
- if (n == newParent) {
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
- }
-
- // ### check if node would end up with a child node of a type not allowed by the type of node
-
- // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text node.
- if (m_startContainer->nodeType() != Node::TEXT_NODE &&
- m_startContainer->nodeType() != Node::COMMENT_NODE &&
- m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
- m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
-
- if (m_startOffset > 0 && m_startOffset < m_startContainer->childNodeCount()) {
- exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
- }
-
- if (m_endContainer->nodeType() != Node::TEXT_NODE &&
- m_endContainer->nodeType() != Node::COMMENT_NODE &&
- m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
- m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
-
- if (m_endOffset > 0 && m_endOffset < m_endContainer->childNodeCount()) {
- exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
- return;
- }
- }
-
- while (newParent->firstChild()) {
- newParent->removeChild(newParent->firstChild(),exceptioncode);
- if (exceptioncode)
- return;
- }
- DocumentFragmentImpl *fragment = extractContents(exceptioncode);
- if (exceptioncode)
- return;
- insertNode( newParent, exceptioncode );
- if (exceptioncode)
- return;
- newParent->appendChild( fragment, exceptioncode );
- if (exceptioncode)
- return;
- selectNode( newParent, exceptioncode );
-}
-
-void RangeImpl::setStartBefore( NodeImpl *refNode, int &exceptioncode )
-{
- if (m_detached) {
- exceptioncode = DOMException::INVALID_STATE_ERR;
- return;
- }
-
- if (!refNode) {
- exceptioncode = DOMException::NOT_FOUND_ERR;
- return;
- }
-
- if (refNode->getDocument() != m_ownerDocument) {
- exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
- return;
- }
-
- checkNodeBA( refNode, exceptioncode );
- if (exceptioncode)
- return;
-
- setStart( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
-}
-
-void RangeImpl::setStartContainer(NodeImpl *_startContainer)
-{
- if (m_startContainer == _startContainer)
- return;
-
- if (m_startContainer)
- m_startContainer->deref();
- m_startContainer = _startContainer;
- if (m_startContainer)
- m_startContainer->ref();
-}
-
-void RangeImpl::setEndContainer(NodeImpl *_endContainer)
-{
- if (m_endContainer == _endContainer)
- return;
-
- if (m_endContainer)
- m_endContainer->deref();
- m_endContainer = _endContainer;
- if (m_endContainer)
- m_endContainer->ref();
-}
-
-void RangeImpl::checkDeleteExtract(int &exceptioncode) {
-
- NodeImpl *start;
- if (m_startContainer->nodeType() != Node::TEXT_NODE &&
- m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
- m_startContainer->nodeType() != Node::COMMENT_NODE &&
- m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
-
- start = m_startContainer->childNode(m_startOffset);
- if (!start) {
- if (m_startContainer->lastChild())
- start = m_startContainer->lastChild()->traverseNextNode();
- else
- start = m_startContainer->traverseNextNode();
- }
- }
- else
- start = m_startContainer;
-
- NodeImpl *end;
- if (m_endContainer->nodeType() != Node::TEXT_NODE &&
- m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
- m_endContainer->nodeType() != Node::COMMENT_NODE &&
- m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
-
- end = m_endContainer->childNode(m_endOffset);
- if (!end) {
- if (m_endContainer->lastChild())
- end = m_endContainer->lastChild()->traverseNextNode();
- else
- end = m_endContainer->traverseNextNode();
- }
- }
- else
- end = m_endContainer;
-
- NodeImpl *n;
- for (n = start; n != end; n = n->traverseNextNode()) {
- if (n->isReadOnly()) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
- if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { // ### is this for only directly under the DF, or anywhere?
- exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
- return;
- }
- }
-
- if (containedByReadOnly()) {
- exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
- return;
- }
-}
-
-
-bool RangeImpl::containedByReadOnly() {
- NodeImpl *n;
- for (n = m_startContainer; n; n = n->parentNode()) {
- if (n->isReadOnly())
- return true;
- }
- for (n = m_endContainer; n; n = n->parentNode()) {
- if (n->isReadOnly())
- return true;
- }
- return false;
-}
-
-
-
-
-
-
-
-