/** * Traverses the "right boundary" of this range and * operates on each "boundary node" according to the * how parameter. It is a-priori assumed * by this method that the right boundary does * not contain the range's start container. * * A "right boundary" is best visualized by thinking * of a sample tree: * A * /|\ * / | \ * / | \ * B C D * /|\ /|\ * E F G H I J * * Imagine first a range that begins between the * "E" and "F" nodes and ends between the * "I" and "J" nodes. The start container is * "B" and the end container is "D". Given this setup, * the following applies: * * Partially Selected Nodes: B, D<br> * Fully Selected Nodes: F, G, C, H, I * * The "right boundary" is the highest subtree node * that contains the ending container. The root of * this subtree is always partially selected. * * In this example, the nodes that are traversed * as "right boundary" nodes are: H, I, and D. * */ DOM_Node RangeImpl::traverseRightBoundary( DOM_Node root, int how ) { DOM_Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); bool isFullySelected = ( next!=fEndContainer ); if ( next==root ) return traverseNode( next, isFullySelected, false, how ); DOM_Node parent = next.getParentNode(); DOM_Node clonedParent = traverseNode( parent, false, false, how ); while( parent!=null ) { while( next!=null ) { DOM_Node prevSibling = next.getPreviousSibling(); DOM_Node clonedChild = traverseNode( next, isFullySelected, false, how ); if ( how!=DELETE_CONTENTS ) { clonedParent.insertBefore( clonedChild, clonedParent.getFirstChild() ); } isFullySelected = true; next = prevSibling; } if ( parent==root ) return clonedParent; next = parent.getPreviousSibling(); parent = parent.getParentNode(); DOM_Node clonedGrandParent = traverseNode( parent, false, false, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null; }
void RangeImpl::insertNode(DOM_Node& newNode) { if (newNode == null) return; //don't have to do anything for (DOM_Node aNode = fStartContainer; aNode!=null; aNode = aNode.getParentNode()) { if (aNode.fImpl->isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } } if (fDocument != newNode.getOwnerDocument()) { throw DOM_DOMException( DOM_DOMException::WRONG_DOCUMENT_ERR, null); } // Prevent cycles in the tree. //isKidOK() is not checked here as its taken care by insertBefore() function if (isAncestorOf( newNode, fStartContainer)) { throw DOM_DOMException( DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } if( fDetached) { throw DOM_DOMException( DOM_DOMException::INVALID_STATE_ERR, null); } int type = newNode.getNodeType(); if (type == DOM_Node::ATTRIBUTE_NODE || type == DOM_Node::ENTITY_NODE || type == DOM_Node::NOTATION_NODE || type == DOM_Node::DOCUMENT_NODE) { throw DOM_RangeException( DOM_RangeException::INVALID_NODE_TYPE_ERR, null); } DOM_Node parent; DOM_Node next; if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) { //set 'parent' and 'next' here parent = fStartContainer.getParentNode(); //split the text nodes if (fStartOffset > 0) ((DOM_Text &)fStartContainer).splitText(fStartOffset); //update the new start information later. After inserting the first newNode if (fStartOffset == 0) next = fStartContainer; else next = fStartContainer.getNextSibling(); } // end of text handling else { parent = fStartContainer; next = fStartContainer.getFirstChild(); for(unsigned int i = 0; (i < fStartOffset) && (next != null); i++) { next=next.getNextSibling(); } } if (parent != null) { if (next != null) parent.insertBefore(newNode, next); else parent.appendChild(newNode); } }