tng 2003/01/16 12:12:20 Modified: c/src/xercesc/dom/impl DOMCharacterDataImpl.cpp DOMCommentImpl.cpp DOMCommentImpl.hpp DOMProcessingInstructionImpl.cpp DOMProcessingInstructionImpl.hpp DOMRangeImpl.cpp DOMRangeImpl.hpp Log: DOM Fix: Misc Range related fixes Revision Changes Path 1.5 +14 -4 xml-xerces/c/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp Index: DOMCharacterDataImpl.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- DOMCharacterDataImpl.cpp 4 Nov 2002 15:07:34 -0000 1.4 +++ DOMCharacterDataImpl.cpp 16 Jan 2003 20:12:19 -0000 1.5 @@ -251,6 +251,18 @@ if (newLen >= 3999) delete[] newString; + + if (node->getOwnerDocument() != 0) { + Ranges* ranges = ((DOMDocumentImpl *)node->getOwnerDocument())->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; i<sz; i++) { + ranges->elementAt(i)->updateRangeForInsertedText( (DOMNode*)node, offset, datLen); + } + } + } + } } @@ -271,9 +283,7 @@ void DOMCharacterDataImpl::setData(const DOMNode *node, const XMLCh *arg) { - if (castToNodeImpl(node)->isReadOnly()) - throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); - fDataBuf->set(arg); + setNodeValue(node, arg); }; 1.12 +41 -1 xml-xerces/c/src/xercesc/dom/impl/DOMCommentImpl.cpp Index: DOMCommentImpl.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMCommentImpl.cpp,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- DOMCommentImpl.cpp 4 Nov 2002 15:07:34 -0000 1.11 +++ DOMCommentImpl.cpp 16 Jan 2003 20:12:19 -0000 1.12 @@ -60,8 +60,10 @@ #include "DOMCommentImpl.hpp" #include "DOMCharacterDataImpl.hpp" +#include "DOMStringPool.hpp" #include "DOMCasts.hpp" #include "DOMDocumentImpl.hpp" +#include "DOMRangeImpl.hpp" #include <xercesc/dom/DOMNode.hpp> #include <xercesc/dom/DOMException.hpp> #include <xercesc/util/XMLUniDefs.hpp> @@ -125,6 +127,44 @@ throw DOMException(DOMException::INVALID_ACCESS_ERR,0); } } + + +// Non standard extension for the range to work +DOMComment *DOMCommentImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len || offset < 0) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0); + + DOMComment *newText = + getOwnerDocument()->createComment( + this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (this->getOwnerDocument() != 0) { + Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; i<sz; i++) { + ranges->elementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +}; DOMNode* DOMCommentImpl::appendChild(DOMNode *newChild) {return fNode.appendChild (newChild); }; 1.4 +4 -1 xml-xerces/c/src/xercesc/dom/impl/DOMCommentImpl.hpp Index: DOMCommentImpl.hpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMCommentImpl.hpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- DOMCommentImpl.hpp 4 Nov 2002 15:07:34 -0000 1.3 +++ DOMCommentImpl.hpp 16 Jan 2003 20:12:19 -0000 1.4 @@ -107,6 +107,9 @@ virtual void setData(const XMLCh * arg); virtual const XMLCh * substringData(XMLSize_t offset, XMLSize_t count) const; + // Non standard extension for the range to work + DOMComment* splitText(XMLSize_t offset); + }; XERCES_CPP_NAMESPACE_END 1.11 +58 -39 xml-xerces/c/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp Index: DOMProcessingInstructionImpl.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMProcessingInstructionImpl.cpp,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- DOMProcessingInstructionImpl.cpp 4 Nov 2002 15:07:34 -0000 1.10 +++ DOMProcessingInstructionImpl.cpp 16 Jan 2003 20:12:19 -0000 1.11 @@ -61,6 +61,8 @@ #include "DOMProcessingInstructionImpl.hpp" #include "DOMDocumentImpl.hpp" #include "DOMNodeImpl.hpp" +#include "DOMStringPool.hpp" +#include "DOMRangeImpl.hpp" #include <xercesc/dom/DOMException.hpp> #include <xercesc/dom/DOMNode.hpp> @@ -71,22 +73,20 @@ DOMProcessingInstructionImpl::DOMProcessingInstructionImpl(DOMDocument *ownerDoc, const XMLCh *targt, const XMLCh *dat) - : fNode(ownerDoc), fBaseURI(0) + : fNode(ownerDoc), fBaseURI(0), fCharacterData(ownerDoc, dat) { fNode.setIsLeafNode(true); this->fTarget = ((DOMDocumentImpl *)ownerDoc)->cloneString(targt); - this->fData = ((DOMDocumentImpl *)ownerDoc)->cloneString(dat); }; DOMProcessingInstructionImpl::DOMProcessingInstructionImpl( const DOMProcessingInstructionImpl &other, bool deep) - : fNode(other.fNode), fChild(other.fChild) + : fNode(other.fNode), fChild(other.fChild), fCharacterData(other.fCharacterData) { fNode.setIsLeafNode(true); fTarget = other.fTarget; - fData = other.fData; fBaseURI = other.fBaseURI; }; @@ -115,26 +115,6 @@ }; -const XMLCh * DOMProcessingInstructionImpl::getNodeValue() const -{ - return fData; -}; - - -void DOMProcessingInstructionImpl::setNodeValue(const XMLCh *value) -{ - if (fNode.isReadOnly()) - throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); - fData = ((DOMDocumentImpl *)getOwnerDocument())->cloneString(value); -}; - - -const XMLCh * DOMProcessingInstructionImpl::getData() const -{ - return fData; -}; - - /** A PI's "target" states what processor channel the PI's data should be directed to. It is defined differently in HTML and XML. @@ -151,20 +131,6 @@ }; -/** -* Change the data content of this PI. -* Note that setNodeValue is aliased to setData -* @see getData(). -* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is read-only. -*/ -void DOMProcessingInstructionImpl::setData(const XMLCh *arg) -{ - if (fNode.isReadOnly()) - throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, - 0); - fData = ((DOMDocumentImpl *)getOwnerDocument())->cloneString(arg); -}; - void DOMProcessingInstructionImpl::release() { if (fNode.isOwned() && !fNode.isToBeReleased()) @@ -173,6 +139,7 @@ DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument(); if (doc) { fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0); + fCharacterData.releaseBuffer(); doc->release(this, DOMDocumentImpl::PROCESSING_INSTRUCTION_OBJECT); } else { @@ -190,6 +157,43 @@ return fBaseURI? fBaseURI : fNode.fOwnerNode->getBaseURI(); } +// Non standard extension for the range to work +DOMProcessingInstruction *DOMProcessingInstructionImpl::splitText(XMLSize_t offset) +{ + if (fNode.isReadOnly()) + { + throw DOMException( + DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); + } + XMLSize_t len = fCharacterData.fDataBuf->getLen(); + if (offset > len || offset < 0) + throw DOMException(DOMException::INDEX_SIZE_ERR, 0); + + DOMProcessingInstruction *newText = + getOwnerDocument()->createProcessingInstruction(fTarget, + this->substringData(offset, len - offset)); + + DOMNode *parent = getParentNode(); + if (parent != 0) + parent->insertBefore(newText, getNextSibling()); + + fCharacterData.fDataBuf->chop(offset); + + if (this->getOwnerDocument() != 0) { + Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges(); + if (ranges != 0) { + XMLSize_t sz = ranges->size(); + if (sz != 0) { + for (XMLSize_t i =0; i<sz; i++) { + ranges->elementAt(i)->updateSplitInfo( this, newText, offset); + } + } + } + } + + return newText; +}; + // // Delegation stubs for inherited functions // @@ -201,6 +205,7 @@ const XMLCh* DOMProcessingInstructionImpl::getLocalName() const {return fNode.getLocalName (); }; const XMLCh* DOMProcessingInstructionImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); }; DOMNode* DOMProcessingInstructionImpl::getNextSibling() const {return fChild.getNextSibling (); }; + const XMLCh* DOMProcessingInstructionImpl::getNodeValue() const {return fCharacterData.getNodeValue (); }; DOMDocument* DOMProcessingInstructionImpl::getOwnerDocument() const {return fNode.getOwnerDocument (); }; const XMLCh* DOMProcessingInstructionImpl::getPrefix() const {return fNode.getPrefix (); }; DOMNode* DOMProcessingInstructionImpl::getParentNode() const {return fChild.getParentNode (this); }; @@ -228,6 +233,20 @@ bool DOMProcessingInstructionImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }; const XMLCh* DOMProcessingInstructionImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); }; DOMNode* DOMProcessingInstructionImpl::getInterface(const XMLCh* feature) {return fNode.getInterface(feature); }; + +// +// Delegation of CharacerData functions. +// + + + const XMLCh* DOMProcessingInstructionImpl::getData() const {return fCharacterData.getData();}; + void DOMProcessingInstructionImpl::deleteData(XMLSize_t offset, XMLSize_t count) + {fCharacterData.deleteData(this, offset, count);}; + const XMLCh* DOMProcessingInstructionImpl::substringData(XMLSize_t offset, XMLSize_t count) const + {return fCharacterData.substringData(this, offset, count);}; + void DOMProcessingInstructionImpl::setData(const XMLCh *data) {fCharacterData.setData(this, data);}; + void DOMProcessingInstructionImpl::setNodeValue(const XMLCh *nodeValue) {fCharacterData.setNodeValue (this, nodeValue); }; + XERCES_CPP_NAMESPACE_END 1.4 +9 -2 xml-xerces/c/src/xercesc/dom/impl/DOMProcessingInstructionImpl.hpp Index: DOMProcessingInstructionImpl.hpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMProcessingInstructionImpl.hpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- DOMProcessingInstructionImpl.hpp 4 Nov 2002 15:07:34 -0000 1.3 +++ DOMProcessingInstructionImpl.hpp 16 Jan 2003 20:12:19 -0000 1.4 @@ -72,6 +72,7 @@ #include <xercesc/util/XercesDefs.hpp> #include <xercesc/dom/DOMProcessingInstruction.hpp> +#include "DOMCharacterDataImpl.hpp" #include "DOMNodeImpl.hpp" #include "DOMChildNode.hpp" @@ -85,9 +86,10 @@ private: DOMNodeImpl fNode; DOMChildNode fChild; + // use fCharacterData to store its data so that those character utitlites can be used + DOMCharacterDataImpl fCharacterData; XMLCh *fTarget; - XMLCh *fData; const XMLCh *fBaseURI; public: @@ -107,6 +109,11 @@ // NON-DOM: set base uri virtual void setBaseURI(const XMLCh* baseURI); + + // Non standard extension for the range to work + void deleteData(XMLSize_t offset, XMLSize_t count); + const XMLCh* substringData(XMLSize_t offset, XMLSize_t count) const; + DOMProcessingInstruction* splitText(XMLSize_t offset); }; XERCES_CPP_NAMESPACE_END 1.8 +382 -123 xml-xerces/c/src/xercesc/dom/impl/DOMRangeImpl.cpp Index: DOMRangeImpl.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMRangeImpl.cpp,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- DOMRangeImpl.cpp 9 Jan 2003 18:41:12 -0000 1.7 +++ DOMRangeImpl.cpp 16 Jan 2003 20:12:19 -0000 1.8 @@ -61,14 +61,18 @@ #include "DOMRangeImpl.hpp" #include "DOMDocumentImpl.hpp" #include "DOMDocumentFragmentImpl.hpp" +#include "DOMCommentImpl.hpp" +#include "DOMProcessingInstructionImpl.hpp" #include "DOMCasts.hpp" #include <xercesc/dom/DOMException.hpp> #include <xercesc/dom/DOMDocument.hpp> #include <xercesc/dom/DOMRangeException.hpp> #include <xercesc/dom/DOMText.hpp> +#include <xercesc/dom/DOMProcessingInstruction.hpp> #include <xercesc/framework/XMLBuffer.hpp> +#include <xercesc/util/Janitor.hpp> XERCES_CPP_NAMESPACE_BEGIN @@ -114,21 +118,45 @@ DOMNode* DOMRangeImpl::getStartContainer() const { + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0); + } + return fStartContainer; } XMLSize_t DOMRangeImpl::getStartOffset() const { + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0); + } + return fStartOffset; } DOMNode* DOMRangeImpl::getEndContainer() const { + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0); + } + return fEndContainer; } XMLSize_t DOMRangeImpl::getEndOffset() const { + if (fDetached) + { + throw DOMException( + DOMException::INVALID_STATE_ERR, 0); + } + return fEndOffset; } @@ -147,7 +175,7 @@ } //------------------------------- -// Public getter functions +// Public setter functions //------------------------------- void DOMRangeImpl::setStartContainer(const DOMNode* node) @@ -203,13 +231,18 @@ fStartContainer = (DOMNode*) refNode; fStartOffset = offset; - if ((fDocument != refNode->getOwnerDocument() ) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(true); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -226,13 +259,18 @@ fEndContainer = (DOMNode*) refNode; fEndOffset = offset; - if ((fDocument != refNode->getOwnerDocument() ) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(false); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -262,13 +300,18 @@ else fStartOffset = i-1; - if ((fDocument != refNode->getOwnerDocument()) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(true); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -296,13 +339,18 @@ fStartOffset = i; - if ((fDocument != refNode->getOwnerDocument() ) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(true); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fEndContainer)) + collapse(true); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -331,13 +379,18 @@ else fEndOffset = i-1; - if ((fDocument != refNode->getOwnerDocument() ) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(true); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -366,13 +419,18 @@ else fEndOffset = i; - if ((fDocument != refNode->getOwnerDocument() ) - && (refNode->getOwnerDocument() != 0) ) - { - fDocument = refNode->getOwnerDocument(); - collapse(true); + // error if not the same owner document + if (fDocument != refNode->getOwnerDocument()) { + if ( refNode != fDocument ) + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } + // they may be of same document, but not same root container + // collapse if not the same root container + if (!commonAncestorOf(refNode, fStartContainer)) + collapse(false); + //compare the start and end boundary point //collapse if start point is after the end point if(compareBoundaryPoints(DOMRange::END_TO_START, this) == 1) @@ -429,7 +487,11 @@ DOMRangeException::INVALID_NODE_TYPE_ERR, 0); } //First check for the text type node - if (refNode->getNodeType() == DOMNode::TEXT_NODE) + short type = refNode->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { //The node itself is the container. fStartContainer = (DOMNode*) refNode; @@ -437,7 +499,10 @@ //Select all the contents of the node fStartOffset = 0; - fEndOffset = ((DOMText *)refNode)->getLength(); + if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) + fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)refNode)->getData()); + else + fEndOffset = ((DOMText *)refNode)->getLength(); return; } @@ -465,10 +530,19 @@ fEndContainer = (DOMNode*) node; fStartOffset = 0; - if (node->getNodeType() == DOMNode::TEXT_NODE ) { + short type = node->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE)) { + fEndOffset = ((DOMText *)node)->getLength(); return; } + if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) { + fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)node)->getData()); + return; + } DOMNode* first = node->getFirstChild(); if (first == 0) { @@ -510,10 +584,18 @@ DOMNode* realStart = fStartContainer; DOMNode* realEnd = fEndContainer; - if (fStartContainer->getNodeType() == DOMNode::TEXT_NODE) { + type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { realStart = fStartContainer->getParentNode(); } - if (fEndContainer->getNodeType() == DOMNode::TEXT_NODE) { + type = fEndContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { realEnd = fEndContainer->getParentNode(); } @@ -595,16 +677,25 @@ } } - // case 4: preorder traversal of context tree. DOMNode* ancestor = (DOMNode*) commonAncestorOf(pointA, pointB); - DOMNode* current = ancestor; - do { - if (current == pointA) return -1; - if (current == pointB) return 1; - current = nextNode(current, true); + // case 4: preorder traversal of context tree. + if (ancestor) { + DOMNode* current = ancestor; + + do { + if (current == pointA) return -1; + if (current == pointB) return 1; + current = nextNode(current, true); + } + while (current!=0 && current!=ancestor); + } + else { + // case 5: there is no common ancestor of these two points + // it means the two Ranges are not in the same "root container" + throw DOMException( + DOMException::WRONG_DOCUMENT_ERR, 0); } - while (current!=0 && current!=ancestor); return -2; // this should never happen } @@ -670,14 +761,24 @@ DOMNode* parent; DOMNode* next; - if (fStartContainer->getNodeType() == DOMNode::TEXT_NODE) { + type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { //set 'parent' and 'next' here parent = fStartContainer->getParentNode(); //split the text nodes - if (fStartOffset > 0) - ((DOMText*)fStartContainer)->splitText(fStartOffset); + if (fStartOffset > 0) { + if (type == DOMNode::COMMENT_NODE) + ((DOMCommentImpl*)fStartContainer)->splitText(fStartOffset); + else if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) + ((DOMProcessingInstructionImpl*)fStartContainer)->splitText(fStartOffset); + else + ((DOMText*)fStartContainer)->splitText(fStartOffset); + } //update the new start information later. After inserting the first newNode if (fStartOffset == 0) @@ -724,34 +825,33 @@ DOMException::INVALID_STATE_ERR, 0); } + if ((fStartContainer == fEndContainer) && (fEndOffset == fStartOffset)) + return XMLUni::fgZeroLenString; + DOMNode* node = fStartContainer; DOMNode* stopNode = fEndContainer; XMLBuffer retStringBuf; - if ( (fStartContainer->getNodeType() == DOMNode::TEXT_NODE) - || (fStartContainer->getNodeType() == DOMNode::CDATA_SECTION_NODE) ) { + short type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { if (fStartContainer == fEndContainer) { - if (fEndOffset == fStartOffset) { - return XMLUni::fgZeroLenString; - } - else { - - XMLCh* tempString; - XMLCh temp[4000]; - if ((fEndOffset-fStartOffset) >= 3999) - tempString = new XMLCh[fEndOffset-fStartOffset+1]; - else - tempString = temp; + XMLCh* tempString; + XMLCh temp[4000]; + if ((fEndOffset-fStartOffset) >= 3999) + tempString = new XMLCh[fEndOffset-fStartOffset+1]; + else + tempString = temp; - XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, fEndOffset); - const XMLCh* retString = ((DOMDocumentImpl *)fDocument)->getPooledString(tempString); + XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, fEndOffset); + const XMLCh* retString = ((DOMDocumentImpl *)fDocument)->getPooledString(tempString); - if ((fEndOffset-fStartOffset) >= 3999) - delete[] tempString; - - return retString; - } + if ((fEndOffset-fStartOffset) >= 3999) + delete[] tempString; + return retString; } else { XMLSize_t length = XMLString::stringLen(fStartContainer->getNodeValue()); if (length != fStartOffset) { @@ -786,8 +886,11 @@ } } - if ( fEndContainer->getNodeType()!= DOMNode::TEXT_NODE && - fEndContainer->getNodeType()!= DOMNode::CDATA_SECTION_NODE ){ + type = fEndContainer->getNodeType(); + if((type != DOMNode::TEXT_NODE + && type != DOMNode::CDATA_SECTION_NODE + && type != DOMNode::COMMENT_NODE + && type != DOMNode::PROCESSING_INSTRUCTION_NODE)) { int i=fEndOffset; stopNode = fEndContainer->getFirstChild(); while( i>0 && stopNode!=0 ){ @@ -800,15 +903,22 @@ while (node != stopNode) { //look into all kids of the Range if (node == 0) break; - if (node->getNodeType() == DOMNode::TEXT_NODE - || node->getNodeType() == DOMNode::CDATA_SECTION_NODE) { + type = node->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { retStringBuf.append(node->getNodeValue()); } node = nextNode(node, true); } - if (fEndContainer->getNodeType() == DOMNode::TEXT_NODE - || fEndContainer->getNodeType() == DOMNode::CDATA_SECTION_NODE) { + type = fEndContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { if (fEndOffset != 0) { @@ -931,9 +1041,6 @@ if (fDetached) throw DOMException(DOMException::INVALID_STATE_ERR, 0); - if (pointA->getOwnerDocument() != pointB->getOwnerDocument()) - throw DOMException( DOMException::WRONG_DOCUMENT_ERR, 0 ); - //if the containers are same then it itself is its common ancestor. if (pointA == pointB) return pointA; @@ -942,12 +1049,12 @@ VectorNodes startV(1, false); DOMNode* node; - for (node=fStartContainer; node != 0; node=node->getParentNode()) + for (node=(DOMNode*)pointA; node != 0; node=node->getParentNode()) { startV.addElement(node); } VectorNodes endV(1, false); - for (node=fEndContainer; node != 0; node=node->getParentNode()) + for (node=(DOMNode*)pointB; node != 0; node=node->getParentNode()) { endV.addElement(node); } @@ -955,7 +1062,7 @@ int s = startV.size()-1; int e = endV.size()-1; - DOMNode* commonAncestor; + DOMNode* commonAncestor = 0; while (s>=0 && e>=0) { if (startV.elementAt(s) == endV.elementAt(e)) { @@ -1061,22 +1168,55 @@ return traverseSameContainer( how ); // case 2: Child C of start container is ancestor of end container - for (DOMNode* node = fStartContainer->getFirstChild(); node != 0; node=node->getNextSibling()) { - if (isAncestorOf(node, fEndContainer)) - return traverseCommonStartContainer( node, how ); - } + // This can be quickly tested by walking the parent chain of + // end container + int endContainerDepth = 0; + for ( DOMNode* c = fEndContainer, *p = c->getParentNode(); + p != 0; + c = p, p = p->getParentNode()) + { + if (p == fStartContainer) + return traverseCommonStartContainer( c, how ); + ++endContainerDepth; + } // case 3: Child C of end container is ancestor of start container - for (DOMNode* nd = fEndContainer->getFirstChild(); nd != 0; nd=nd->getNextSibling()) { - if (isAncestorOf(nd, fStartContainer)) - return traverseCommonEndContainer( nd, how ); - } + // This can be quickly tested by walking the parent chain of A + int startContainerDepth = 0; + for ( DOMNode* c2 = fStartContainer, *p2 = c2->getParentNode(); + p2 != 0; + c2 = p2, p2 = p2->getParentNode()) + { + if (p2 == fEndContainer) + return traverseCommonEndContainer( c2, how ); + ++startContainerDepth; + } - // case 4: preorder traversal of context tree. - // There is a common ancestor container. Find the + // case 4: There is a common ancestor container. Find the // ancestor siblings that are children of that container. - DOMNode* ancestor = (DOMNode*)commonAncestorOf(fStartContainer, fEndContainer); - return traverseCommonAncestors( ancestor, ancestor, how ); + int depthDiff = startContainerDepth - endContainerDepth; + + DOMNode* startNode = fStartContainer; + while (depthDiff > 0) { + startNode = startNode->getParentNode(); + depthDiff--; + } + + DOMNode* endNode = fEndContainer; + while (depthDiff < 0) { + endNode = endNode->getParentNode(); + depthDiff++; + } + + // ascend the ancestor hierarchy until we have a common parent. + for( DOMNode* sp = startNode->getParentNode(), *ep = endNode->getParentNode(); + sp!=ep; + sp = sp->getParentNode(), ep = ep->getParentNode() ) + { + startNode = sp; + endNode = ep; + } + return traverseCommonAncestors( startNode, endNode, how ); } /** @@ -1098,7 +1238,11 @@ DOMNode* cloneCurrent = 0; // Text node needs special case handling - if ( fStartContainer->getNodeType()== DOMNode::TEXT_NODE ) + short type = fStartContainer->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { cloneCurrent = fStartContainer->cloneNode(false); if (fEndOffset == fStartOffset) { @@ -1120,8 +1264,13 @@ } // set the original text node to its new value - if ( how != CLONE_CONTENTS ) - ((DOMText*)fStartContainer)->deleteData(fStartOffset, fEndOffset-fStartOffset); + if ( how != CLONE_CONTENTS ) { + if(type == DOMNode::PROCESSING_INSTRUCTION_NODE) { + ((DOMProcessingInstructionImpl*)fStartContainer)->deleteData(fStartOffset, fEndOffset-fStartOffset); + } + else + ((DOMCharacterData*)fStartContainer)->deleteData(fStartOffset, fEndOffset-fStartOffset); + } if ( how != DELETE_CONTENTS) frag->appendChild(cloneCurrent); } @@ -1129,7 +1278,7 @@ // Copy nodes between the start/end offsets. DOMNode* n = getSelectedNode( fStartContainer, fStartOffset ); int cnt = fEndOffset - fStartOffset; - while( cnt > 0 ) + while( cnt > 0 && n) { DOMNode* sibling = n->getNextSibling(); DOMNode* xferNode = traverseFullySelected( n, how ); @@ -1137,7 +1286,7 @@ frag->appendChild( xferNode ); --cnt; n = sibling; - } + } } // Nothing is partially selected, so collapse to start point @@ -1443,8 +1592,15 @@ { if ( isFullySelected ) return traverseFullySelected( n, how ); - if ( n->getNodeType()== DOMNode::TEXT_NODE ) + + short type = n->getNodeType(); + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) return traverseTextNode( n, isLeft, how ); + return traversePartiallySelected( n, how ); } @@ -1461,11 +1617,6 @@ case CLONE_CONTENTS: return n->cloneNode( true ); case EXTRACT_CONTENTS: - if ( n->getNodeType()== DOMNode::DOCUMENT_TYPE_NODE ) - { - throw DOMException( - DOMException::HIERARCHY_REQUEST_ERR, 0); - } return n; case DELETE_CONTENTS: // revisit: @@ -1505,7 +1656,8 @@ */ DOMNode* DOMRangeImpl::traverseTextNode( DOMNode*n, bool isLeft, int how ) { - const XMLCh* txtValue = n->getNodeValue(); + XMLCh* txtValue = XMLString::replicate(n->getNodeValue()); + ArrayJanitor<XMLCh> janValue(txtValue); if ( isLeft ) { @@ -1629,7 +1781,11 @@ */ DOMNode* DOMRangeImpl::getSelectedNode( DOMNode*container, int offset ) { - if ( container->getNodeType() == DOMNode::TEXT_NODE ) + short type = container->getNodeType(); + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) return container; // This case is an important convenience for @@ -1652,22 +1808,49 @@ XMLSize_t startOffset, XMLSize_t endOffset) { if ((start == 0) || (end == 0) ) return; - //if both start and end are text check and return - if (start->getNodeType() == DOMNode::TEXT_NODE) { + DOMNode*sNode = 0; + + short type = start->getNodeType(); + if ( type == DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0); + } + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { if (castToNodeImpl(start)->isReadOnly()) { throw DOMException( DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); } + //if both start and end are text check and return if (start == end) return; + + sNode = start; + } else { + //set the start and end nodes to check + sNode = start->getFirstChild(); + for(XMLSize_t i = 0; i<startOffset; i++) + sNode = sNode->getNextSibling(); } - //set the start and end nodes to check - DOMNode*sNode = start->getFirstChild(); - for(XMLSize_t i = 0; i<startOffset; i++) - sNode = sNode->getNextSibling(); DOMNode* eNode; - if (end->getNodeType() == DOMNode::TEXT_NODE) { + type = end->getNodeType(); + if ( type == DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0); + } + + if((type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { eNode = end; //need to check only till this node } else { //need to check all the kids that fall before the end offset value @@ -1685,6 +1868,12 @@ { for(DOMNode* node=start; node != 0 && node !=end; node=node->getNextSibling()) { + if ( node->getNodeType()== DOMNode::DOCUMENT_TYPE_NODE ) + { + throw DOMException( + DOMException::HIERARCHY_REQUEST_ERR, 0); + } + if (castToNodeImpl(node)->isReadOnly()) { throw DOMException( DOMException::NO_MODIFICATION_ALLOWED_ERR, 0); @@ -1713,42 +1902,62 @@ /* This function is called from DOM. -* The text has already beeen replaced. +* The text has already been replaced. * Fix-up any offsets. */ void DOMRangeImpl::receiveReplacedText(DOMNode* node) { if (node == 0) return; + short type = fStartContainer->getNodeType(); if (node == fStartContainer - && fStartContainer->getNodeType() == DOMNode::TEXT_NODE) { + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { fStartOffset = 0; } + type = fEndContainer->getNodeType(); if (node == fEndContainer - && fEndContainer->getNodeType() == DOMNode::TEXT_NODE) { + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { fEndOffset = 0; } } /** This function is called from DOM. -* The text has already beeen inserted. +* The text has already been deleted. * Fix-up any offsets. */ void DOMRangeImpl::updateRangeForDeletedText(DOMNode* node, XMLSize_t offset, int count) { if (node == 0) return; + short type = fStartContainer->getNodeType(); if (node == fStartContainer - && fStartContainer->getNodeType() == DOMNode::TEXT_NODE) { + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { if (fStartOffset > offset+count) { fStartOffset = fStartOffset-count; } else if (fStartOffset > offset) { fStartOffset = offset; } } + type = fEndContainer->getNodeType(); if (node == fEndContainer - && fEndContainer->getNodeType() == DOMNode::TEXT_NODE) { + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { if (fEndOffset > offset+count) { fEndOffset = fEndOffset-count; } else if (fEndOffset > offset) { @@ -1759,6 +1968,40 @@ +/** This function is called from DOM. +* The text has already beeen inserted. +* Fix-up any offsets. +*/ +void DOMRangeImpl::updateRangeForInsertedText(DOMNode* node, XMLSize_t offset, int count) +{ + if (node == 0) return; + + short type = fStartContainer->getNodeType(); + if (node == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fStartOffset > offset) { + fStartOffset = offset; + } + } + type = fEndContainer->getNodeType(); + if (node == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fEndOffset > offset) { + fEndOffset = fEndOffset+count; + } + } +} + + + /** 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. @@ -1818,18 +2061,34 @@ } -void DOMRangeImpl::updateSplitInfo(DOMText* oldNode, DOMText* startNode, XMLSize_t offset) +void DOMRangeImpl::updateSplitInfo(DOMNode* oldNode, DOMNode* startNode, XMLSize_t offset) { if (startNode == 0) return; - if (fStartContainer == oldNode && fStartOffset > offset) { - fStartOffset = fStartOffset - offset; - fStartContainer = startNode; + short type = fStartContainer->getNodeType(); + if (oldNode == fStartContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fStartOffset > offset) { + fStartOffset = fStartOffset - offset; + fStartContainer = startNode; + } } - if (fEndContainer == oldNode && fEndOffset > offset) { + type = fEndContainer->getNodeType(); + if (oldNode == fEndContainer + && (type == DOMNode::TEXT_NODE + || type == DOMNode::CDATA_SECTION_NODE + || type == DOMNode::COMMENT_NODE + || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) + { + if (fEndOffset > offset) { fEndContainer = startNode; - fEndOffset = fEndOffset - offset; + fEndOffset = fEndOffset - offset; + } } } 1.5 +3 -2 xml-xerces/c/src/xercesc/dom/impl/DOMRangeImpl.hpp Index: DOMRangeImpl.hpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMRangeImpl.hpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- DOMRangeImpl.hpp 4 Nov 2002 15:07:34 -0000 1.4 +++ DOMRangeImpl.hpp 16 Jan 2003 20:12:19 -0000 1.5 @@ -156,10 +156,11 @@ DOMDocument* getDocument(); // functions to inform all existing valid ranges about a change - void updateSplitInfo(DOMText* oldNode, DOMText* startNode, XMLSize_t offset); + void updateSplitInfo(DOMNode* oldNode, DOMNode* startNode, XMLSize_t offset); void updateRangeForInsertedNode(DOMNode* node); void receiveReplacedText(DOMNode* node); void updateRangeForDeletedText(DOMNode* node, XMLSize_t offset, int count); + void updateRangeForInsertedText(DOMNode* node, XMLSize_t offset, int count); void updateRangeForDeletedNode(DOMNode* node); private:
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]