rangeimpl.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,660 行 · 第 1/4 页
CPP
1,660 行
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;}/** * Traverses the "left 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 left boundary does * not contain the range's end container. * * A "left 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 "left boundary" is the highest subtree node * that contains the starting container. The root of * this subtree is always partially selected. * * In this example, the nodes that are traversed * as "left boundary" nodes are: F, G, and B. * */DOM_Node RangeImpl::traverseLeftBoundary( DOM_Node root, int how ){ DOM_Node next = getSelectedNode( getStartContainer(), getStartOffset() ); bool isFullySelected = ( next!=getStartContainer() ); if ( next==root ) return traverseNode( next, isFullySelected, true, how ); DOM_Node parent = next.getParentNode(); DOM_Node clonedParent = traverseNode( parent, false, true, how ); while( parent!=null ) { while( next!=null ) { DOM_Node nextSibling = next.getNextSibling(); DOM_Node clonedChild = traverseNode( next, isFullySelected, true, how ); if ( how!=DELETE_CONTENTS ) clonedParent.appendChild(clonedChild); isFullySelected = true; next = nextSibling; } if ( parent==root ) return clonedParent; next = parent.getNextSibling(); parent = parent.getParentNode(); DOM_Node clonedGrandParent = traverseNode( parent, false, true, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null;}/** * Utility method for traversing a single node. * Does not properly handle a text node containing both the * start and end offsets. Such nodes should * have been previously detected and been routed to traverseTextNode. * */DOM_Node RangeImpl::traverseNode( DOM_Node n, bool isFullySelected, bool isLeft, int how ){ if ( isFullySelected ) return traverseFullySelected( n, how ); if ( n.getNodeType()== DOM_Node::TEXT_NODE ) return traverseTextNode( n, isLeft, how ); return traversePartiallySelected( n, how );}/** * Utility method for traversing a single node when * we know a-priori that the node if fully * selected. * */DOM_Node RangeImpl::traverseFullySelected( DOM_Node n, int how ){ switch( how ) { case CLONE_CONTENTS: return n.cloneNode( true ); case EXTRACT_CONTENTS: if ( n.getNodeType()== DOM_Node::DOCUMENT_TYPE_NODE ) { throw DOM_DOMException( DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } return n; case DELETE_CONTENTS: n.getParentNode().removeChild(n); return null; } return null;}/** * Utility method for traversing a single node when * we know a-priori that the node if partially * selected and is not a text node. * */DOM_Node RangeImpl::traversePartiallySelected( DOM_Node n, int how ){ switch( how ) { case DELETE_CONTENTS: return null; case CLONE_CONTENTS: case EXTRACT_CONTENTS: return n.cloneNode( false ); } return null;}/** * Utility method for traversing a text node that we know * a-priori to be on a left or right boundary of the range. * This method does not properly handle text nodes that contain * both the start and end points of the range. * */DOM_Node RangeImpl::traverseTextNode( DOM_Node n, bool isLeft, int how ){ DOMString txtValue = n.getNodeValue(); DOMString newNodeValue; DOMString oldNodeValue; if ( isLeft ) { int offset = getStartOffset(); newNodeValue = txtValue.substringData( offset , fStartContainer.getNodeValue().length()-offset); oldNodeValue = txtValue.substringData( 0, offset ); } else { int offset = getEndOffset(); newNodeValue = txtValue.substringData( 0, offset ); oldNodeValue = txtValue.substringData( offset , fEndContainer.getNodeValue().length()-offset ); } if ( how != CLONE_CONTENTS ) n.setNodeValue( oldNodeValue ); if ( how==DELETE_CONTENTS ) return null; DOM_Node newNode = n.cloneNode( false ); newNode.setNodeValue( newNodeValue ); return newNode;}/** * Utility method to retrieve a child node by index. This method * assumes the caller is trying to find out which node is * selected by the given index. Note that if the index is * greater than the number of children, this implies that the * first node selected is the parent node itself. * */DOM_Node RangeImpl::getSelectedNode( DOM_Node container, int offset ){ if ( container.getNodeType() == DOM_Node::TEXT_NODE ) return container; // This case is an important convenience for // traverseRightBoundary() if ( offset<0 ) return container; DOM_Node child = container.getFirstChild(); while( child!=null && offset > 0 ) { --offset; child = child.getNextSibling(); } if ( child!=null ) return child; return container;}void RangeImpl::checkReadOnly(DOM_Node& start, DOM_Node& end, unsigned int startOffset, unsigned int endOffset){ if ((start == null) || (end == null) ) return; //if both start and end are text check and return if (start.getNodeType() == DOM_Node::TEXT_NODE) { if (start.fImpl->isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (start == end) return; } //set the start and end nodes to check DOM_Node sNode = start.getFirstChild(); for(unsigned int i = 0; i<startOffset; i++) sNode = sNode.getNextSibling(); DOM_Node eNode; if (end.getNodeType() == DOM_Node::TEXT_NODE) { eNode = end; //need to check only till this node } else { //need to check all the kids that fall before the end offset value eNode = end.getFirstChild(); for (unsigned int i = 0; i<endOffset-1; i++) eNode = eNode.getNextSibling(); } //recursivly search if any node is readonly recurseTreeAndCheck(sNode, eNode);}void RangeImpl::recurseTreeAndCheck(DOM_Node& start, DOM_Node& end){ for(DOM_Node node=start; node != null && node !=end; node=node.getNextSibling()) { if (node.fImpl->isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (node.hasChildNodes()) { node = node.getFirstChild(); recurseTreeAndCheck(node, end); } }}DOM_Node RangeImpl::removeChild(DOM_Node& parent, DOM_Node& child){ fRemoveChild = child; //only a precaution measure not to update this range data before removal DOM_Node n = parent.removeChild(child); fRemoveChild = null; return n;}//// Mutation functions///* This function is called from DOM.* The text has already beeen replaced.* Fix-up any offsets.*/void RangeImpl::receiveReplacedText(NodeImpl* node){ if (node == null) return; DOM_Node anode(node); if (anode == fStartContainer && fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) { fStartOffset = 0; } if (anode == fEndContainer && fEndContainer.getNodeType() == DOM_Node::TEXT_NODE) { fEndOffset = 0; }}/** This function is called from DOM.* The text has already beeen inserted.* Fix-up any offsets.*/void RangeImpl::updateRangeForDeletedText(DOM_Node& node, unsigned int offset, int count){ if (node == null) return; if (node == fStartContainer && fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) { if (fStartOffset > offset+count) { fStartOffset = fStartOffset-count; } else if (fStartOffset > offset) { fStartOffset = offset; } } if (node == fEndContainer && fEndContainer.getNodeType() == DOM_Node::TEXT_NODE) { if (fEndOffset > offset+count) { fEndOffset = fEndOffset-count; } else if (fEndOffset > offset) { fEndOffset = offset; } }}/** This function must be called by the DOM _BEFORE_* a node is deleted, because at that time it is* connected in the DOM tree, which we depend on.*/void RangeImpl::updateRangeForDeletedNode(NodeImpl* node){ if (node == null) return; if (fRemoveChild == node) return; DOM_Node tNode(node); if (node->getParentNode() == fStartContainer.fImpl) { unsigned short index = indexOf(tNode, fStartContainer); if ( fStartOffset > index) { fStartOffset--; } } if (node->getParentNode() == fEndContainer.fImpl) { unsigned short index = indexOf(tNode, fEndContainer); if ( fEndOffset > index) { fEndOffset--; } } if (node->getParentNode() != fStartContainer.fImpl || node->getParentNode() != fEndContainer.fImpl) { if (isAncestorOf(node, fStartContainer)) { DOM_Node tpNode(node->getParentNode()); setStartContainer( tpNode ); fStartOffset = indexOf( tNode, tpNode); } if (isAncestorOf(node, fEndContainer)) { DOM_Node tpNode(node->getParentNode()); setEndContainer( tpNode ); fEndOffset = indexOf( tNode, tpNode); } }}void RangeImpl::updateRangeForInsertedNode(NodeImpl* node) { if (node == null) return; if (node->getParentNode() == fStartContainer.fImpl) { unsigned int index = indexOf(DOM_Node(node), fStartContainer); if (index < fStartOffset) { fStartOffset++; } } if (node->getParentNode() == fEndContainer.fImpl) { unsigned int index = indexOf(DOM_Node(node), fEndContainer); if (index < fEndOffset) { fEndOffset++; } }}void RangeImpl::updateSplitInfo(TextImpl* oldNode, TextImpl* startNode, unsigned int offset){ if (startNode == null) return; DOM_Text oldText(oldNode); DOM_Text newText(startNode); if (fStartContainer == oldText && fStartOffset > offset) { fStartOffset = fStartOffset - offset; fStartContainer = newText; } if (fEndContainer == oldText && fEndOffset > offset) { fEndContainer = newText; fEndOffset = fEndOffset - offset; }}XERCES_CPP_NAMESPACE_END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?