You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by ar...@locus.apache.org on 2000/07/28 03:33:40 UTC

cvs commit: xml-xerces/c/tests/DOM/RangeTest Makefile.in RangeTest.cpp

aruna1      00/07/27 18:33:39

  Modified:    c/Projects/Win32/VC6/xerces-all xerces-all.dsw
               c/Projects/Win32/VC6/xerces-all/XercesLib XercesLib.dsp
               c/src/dom CharacterDataImpl.cpp ChildAndParentNode.cpp
                        CommonParentNode.cpp DOM_Document.cpp
                        DOM_Document.hpp DOM_DocumentFragment.hpp
                        DOM_Node.hpp DOM_Text.hpp DocumentFragmentImpl.hpp
                        DocumentImpl.cpp DocumentImpl.hpp Makefile.in
                        ParentNode.cpp TextImpl.cpp
               c/tests  Makefile.in configure.in
  Added:       c/src/dom DOM_Range.cpp DOM_Range.hpp DOM_RangeException.cpp
                        DOM_RangeException.hpp RangeImpl.cpp RangeImpl.hpp
               c/tests/DOM/RangeTest Makefile.in RangeTest.cpp
  Log:
  DOM Level 2 Range feature introduced
  
  Revision  Changes    Path
  1.19      +12 -0     xml-xerces/c/Projects/Win32/VC6/xerces-all/xerces-all.dsw
  
  Index: xerces-all.dsw
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/Projects/Win32/VC6/xerces-all/xerces-all.dsw,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- xerces-all.dsw	2000/06/01 01:31:06	1.18
  +++ xerces-all.dsw	2000/07/28 01:33:25	1.19
  @@ -165,6 +165,18 @@
   
   ###############################################################################
   
  +Project: "RangeTest"=".\RangeTest\RangeTest.dsp" - Package Owner=<4>
  +
  +Package=<5>
  +{{{
  +}}}
  +
  +Package=<4>
  +{{{
  +}}}
  +
  +###############################################################################
  +
   Project: "Redirect"=".\Redirect\Redirect.dsp" - Package Owner=<4>
   
   Package=<5>
  
  
  
  1.39      +24 -0     xml-xerces/c/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp
  
  Index: XercesLib.dsp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- XercesLib.dsp	2000/07/25 22:41:55	1.38
  +++ XercesLib.dsp	2000/07/28 01:33:26	1.39
  @@ -1064,6 +1064,22 @@
   # End Source File
   # Begin Source File
   
  +SOURCE=..\..\..\..\..\src\dom\DOM_Range.cpp
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=..\..\..\..\..\src\dom\DOM_Range.hpp
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=..\..\..\..\..\src\dom\DOM_RangeException.cpp
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=..\..\..\..\..\src\dom\DOM_RangeException.hpp
  +# End Source File
  +# Begin Source File
  +
   SOURCE=..\..\..\..\..\src\dom\DOM_Text.cpp
   # End Source File
   # Begin Source File
  @@ -1233,6 +1249,14 @@
   # Begin Source File
   
   SOURCE=..\..\..\..\..\src\dom\ProcessingInstructionImpl.hpp
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=..\..\..\..\..\src\dom\RangeImpl.cpp
  +# End Source File
  +# Begin Source File
  +
  +SOURCE=..\..\..\..\..\src\dom\RangeImpl.hpp
   # End Source File
   # Begin Source File
   
  
  
  
  1.14      +29 -1     xml-xerces/c/src/dom/CharacterDataImpl.cpp
  
  Index: CharacterDataImpl.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/CharacterDataImpl.cpp,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- CharacterDataImpl.cpp	2000/05/02 19:22:01	1.13
  +++ CharacterDataImpl.cpp	2000/07/28 01:33:30	1.14
  @@ -55,11 +55,13 @@
    */
   
   /*
  - * $Id: CharacterDataImpl.cpp,v 1.13 2000/05/02 19:22:01 aruna1 Exp $
  + * $Id: CharacterDataImpl.cpp,v 1.14 2000/07/28 01:33:30 aruna1 Exp $
    */
   
   #include "CharacterDataImpl.hpp"
   #include "DOM_DOMException.hpp"
  +#include "RangeImpl.hpp"
  +#include "DocumentImpl.hpp"
   
   
   CharacterDataImpl::CharacterDataImpl(DocumentImpl *ownerDoc,
  @@ -92,6 +94,19 @@
           throw DOM_DOMException(DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
                                  null);
       data = value.clone();
  +
  +    if (this->getOwnerDocument() != null) {
  +        typedef RefVectorOf<RangeImpl> RangeImpls;
  +        RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  +        if (ranges != null) {
  +            unsigned int sz = ranges->size();
  +            if (sz != 0) {
  +                for (unsigned int i =0; i<sz; i++) {
  +                    ranges->elementAt(i)->receiveReplacedText( this);
  +                }
  +            }
  +        }
  +    }
   };
   
   
  @@ -115,6 +130,19 @@
       //       when parameter values are bad.
       //  
       data.deleteData(offset, count);
  +
  +    if (this->getOwnerDocument() != null) {
  +        typedef RefVectorOf<RangeImpl> RangeImpls;
  +        RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  +        if (ranges != null) {
  +            unsigned int sz = ranges->size();
  +            if (sz != 0) {
  +                for (unsigned int i =0; i<sz; i++) {
  +                    ranges->elementAt(i)->updateRangeForDeletedText( (DOM_Node&)*this, offset, count);
  +                }
  +            }
  +        }
  +    }
   };
   
   
  
  
  
  1.3       +2 -1      xml-xerces/c/src/dom/ChildAndParentNode.cpp
  
  Index: ChildAndParentNode.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/ChildAndParentNode.cpp,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ChildAndParentNode.cpp	2000/06/22 22:19:42	1.2
  +++ ChildAndParentNode.cpp	2000/07/28 01:33:30	1.3
  @@ -64,7 +64,7 @@
   //
   
   /*
  - * $Id: ChildAndParentNode.cpp,v 1.2 2000/06/22 22:19:42 aruna1 Exp $
  + * $Id: ChildAndParentNode.cpp,v 1.3 2000/07/28 01:33:30 aruna1 Exp $
    */
   
   /**
  @@ -77,6 +77,7 @@
   #include "DOM_DOMException.hpp"
   #include "TextImpl.hpp"
   #include "DocumentImpl.hpp"
  +#include "RangeImpl.hpp"
   
   #define THIS_CLASS ChildAndParentNode
   #define PARENT_CLASS ChildNode
  
  
  
  1.3       +69 -41    xml-xerces/c/src/dom/CommonParentNode.cpp
  
  Index: CommonParentNode.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/CommonParentNode.cpp,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CommonParentNode.cpp	2000/07/13 00:08:39	1.2
  +++ CommonParentNode.cpp	2000/07/28 01:33:30	1.3
  @@ -55,7 +55,7 @@
    */
   
   /*
  - * $Id: CommonParentNode.cpp,v 1.2 2000/07/13 00:08:39 aruna1 Exp $
  + * $Id: CommonParentNode.cpp,v 1.3 2000/07/28 01:33:30 aruna1 Exp $
    */
   
   
  @@ -270,6 +270,19 @@
           }
       }
       changed();
  +    
  +    if (this->getOwnerDocument() != null) {
  +        typedef RefVectorOf<RangeImpl> RangeImpls;
  +        RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  +        if ( ranges != null) {
  +            unsigned int sz = ranges->size();
  +            if (sz != 0) {
  +                for (unsigned int i =0; i<sz; i++) {
  +                    ranges->elementAt(i)->updateRangeForInsertedNode(newInternal);
  +                }
  +            }
  +        }
  +    }
   
       return newInternal;
   };
  @@ -287,48 +300,63 @@
   {
       if (readOnly())
           throw DOM_DOMException(
  -          DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  -      
  -      if (oldChild != null && oldChild->getParentNode() != this)
  -          throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  -
  -      ChildNode * oldInternal = (ChildNode *) oldChild;
  -
  -      // Patch tree past oldChild
  -      ChildNode *prev = oldInternal->previousSibling;
  -      ChildNode *next = oldInternal->nextSibling;
  -
  -      if (oldInternal != firstChild)
  -          prev->nextSibling = next;
  -      else {
  -          oldInternal->firstChild(false);
  -          firstChild = next;
  -          if (next != null) {
  -              next->firstChild(true);
  -          }
  -      }
  -
  -      if (next != null)         // oldInternal != lastChild
  -          next->previousSibling = prev;
  -      else {
  -          if (firstChild != null) {
  -              // store lastChild as previous sibling of first child
  -              firstChild->previousSibling = prev;
  -          }
  -      }
  -      
  -      // Remove oldChild's references to tree
  -      oldInternal->ownerNode = ownerDocument;
  -      oldInternal->owned(false);
  -      oldInternal->nextSibling = null;
  -      oldInternal->previousSibling = null;
  +        DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  +    
  +    if (oldChild != null && oldChild->getParentNode() != this)
  +        throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  +    
  +    //fix other ranges for change before deleting the node
  +    if (this->getOwnerDocument() !=  null  ) {
  +        typedef RefVectorOf<RangeImpl> RangeImpls;
  +        RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  +        if (ranges != null) {
  +            unsigned int sz = ranges->size();
  +            if (sz != 0) {
  +                for (unsigned int i =0; i<sz; i++) {
  +                    if (ranges->elementAt(i) != null) 
  +                        ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);
  +                }
  +            }
  +        }
  +    }
  +    
  +    ChildNode * oldInternal = (ChildNode *) oldChild;
  +    
  +    // Patch tree past oldChild
  +    ChildNode *prev = oldInternal->previousSibling;
  +    ChildNode *next = oldInternal->nextSibling;
  +    
  +    if (oldInternal != firstChild)
  +        prev->nextSibling = next;
  +    else {
  +        oldInternal->firstChild(false);
  +        firstChild = next;
  +        if (next != null) {
  +            next->firstChild(true);
  +        }
  +    }
  +    
  +    if (next != null)         // oldInternal != lastChild
  +        next->previousSibling = prev;
  +    else {
  +        if (firstChild != null) {
  +            // store lastChild as previous sibling of first child
  +            firstChild->previousSibling = prev;
  +        }
  +    }
  +    
  +    // Remove oldChild's references to tree
  +    oldInternal->ownerNode = ownerDocument;
  +    oldInternal->owned(false);
  +    oldInternal->nextSibling = null;
  +    oldInternal->previousSibling = null;
  +    
  +    changed();
  +    
  +    return oldInternal;
  +};
   
  -      changed();
   
  -      return oldInternal;
  -};
  -  
  -  
   NodeImpl *THIS_CLASS::replaceChild(NodeImpl *newChild, NodeImpl *oldChild)
   {
       insertBefore(newChild, oldChild);
  
  
  
  1.10      +7 -31     xml-xerces/c/src/dom/DOM_Document.cpp
  
  Index: DOM_Document.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_Document.cpp,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- DOM_Document.cpp	2000/05/09 00:22:31	1.9
  +++ DOM_Document.cpp	2000/07/28 01:33:30	1.10
  @@ -55,43 +55,7 @@
    */
   
   /*
  - * $Log: DOM_Document.cpp,v $
  - * Revision 1.9  2000/05/09 00:22:31  andyh
  - * Memory Cleanup.  XMLPlatformUtils::Terminate() deletes all lazily
  - * allocated memory; memory leak checking tools will no longer report
  - * that leaks exist.  (DOM GetElementsByTagID temporarily removed
  - * as part of this.)
  - *
  - * Revision 1.8  2000/04/25 20:29:33  aruna1
  - * DOM_XMLDecl type node introduced to get the information of the
  - * XML Declaration in a document and store it part of the tree
  - *
  - * Revision 1.7  2000/03/24 21:26:32  abagchi
  - * Added getElementById() from patch submitted by Jeff Lewis
  - *
  - * Revision 1.6  2000/03/02 19:53:55  roddey
  - * This checkin includes many changes done while waiting for the
  - * 1.1.0 code to be finished. I can't list them all here, but a list is
  - * available elsewhere.
  - *
  - * Revision 1.5  2000/02/06 07:47:28  rahulj
  - * Year 2K copyright swat.
  - *
  - * Revision 1.4  2000/02/04 01:49:29  aruna1
  - * TreeWalker and NodeIterator changes
  - *
  - * Revision 1.3  2000/01/05 01:16:07  andyh
  - * DOM Level 2 core, namespace support added.
  - *
  - * Revision 1.2  1999/11/23 01:48:14  rahulj
  - * Changed 0L to 0. CC under HPUX is happy now.
  - *
  - * Revision 1.1.1.1  1999/11/09 01:08:50  twl
  - * Initial checkin
  - *
  - * Revision 1.4  1999/11/08 20:44:15  rahul
  - * Swat for adding in Product name and CVS comment log variable.
  - *
  + * $Id: DOM_Document.cpp,v 1.10 2000/07/28 01:33:30 aruna1 Exp $
    */
   
   
  @@ -282,4 +246,10 @@
   {
       return DOM_XMLDecl( ((DocumentImpl *)fImpl)->createXMLDecl(version, encoding, standalone));
   }
  +
  +DOM_Range    DOM_Document::createRange() 
  +{
  +    return DOM_Range( ((DocumentImpl *)fImpl)->createRange() );
  +}
  +
   
  
  
  
  1.13      +15 -45    xml-xerces/c/src/dom/DOM_Document.hpp
  
  Index: DOM_Document.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_Document.hpp,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- DOM_Document.hpp	2000/04/25 20:29:33	1.12
  +++ DOM_Document.hpp	2000/07/28 01:33:30	1.13
  @@ -55,55 +55,7 @@
    */
   
   /*
  - * $Log: DOM_Document.hpp,v $
  - * Revision 1.12  2000/04/25 20:29:33  aruna1
  - * DOM_XMLDecl type node introduced to get the information of the
  - * XML Declaration in a document and store it part of the tree
  - *
  - * Revision 1.11  2000/03/24 21:24:50  abagchi
  - * Added getElementById() from patch submitted by Jeff Lewis
  - *
  - * Revision 1.10  2000/03/02 19:53:55  roddey
  - * This checkin includes many changes done while waiting for the
  - * 1.1.0 code to be finished. I can't list them all here, but a list is
  - * available elsewhere.
  - *
  - * Revision 1.9  2000/02/24 20:11:27  abagchi
  - * Swat for removing Log from API docs
  - *
  - * Revision 1.8  2000/02/17 17:47:24  andyh
  - * Update Doc++ API comments
  - * NameSpace update to track W3C
  - * Changes were made by Chih Hsiang Chou
  - *
  - * Revision 1.7  2000/02/10 19:41:16  abagchi
  - * Added docs for createNodeIterator and createTreeWalker
  - *
  - * Revision 1.6  2000/02/06 07:47:28  rahulj
  - * Year 2K copyright swat.
  - *
  - * Revision 1.5  2000/02/04 01:49:28  aruna1
  - * TreeWalker and NodeIterator changes
  - *
  - * Revision 1.4  2000/01/22 01:38:29  andyh
  - * Remove compiler warnings in DOM impl classes
  - *
  - * Revision 1.3  2000/01/05 01:16:07  andyh
  - * DOM Level 2 core, namespace support added.
  - *
  - * Revision 1.2  1999/12/21 07:47:06  robweir
  - * Patches to support Xalan, where we need to create a
  - * "special" DOM with subclassed Nodes.
  - *
  - * 1. Export the NodeImpl-derived classes
  - * 2. Ensure that their constructors have at least protected access
  - *
  - * Revision 1.1.1.1  1999/11/09 01:08:51  twl
  - * Initial checkin
  - *
  - * Revision 1.4  1999/11/08 20:44:15  rahul
  - * Swat for adding in Product name and CVS comment log variable.
  - *
  + * $Id: DOM_Document.hpp,v 1.13 2000/07/28 01:33:30 aruna1 Exp $
   */
   
   #ifndef DOM_Document_HEADER_GUARD_
  @@ -127,6 +79,7 @@
   #include <dom/DOM_NodeIterator.hpp>
   #include <dom/DOM_TreeWalker.hpp>
   #include <dom/DOM_XMLDecl.hpp>
  +#include <dom/DOM_Range.hpp>
   
   class DocumentImpl;
   class NodeIteratorImpl;
  @@ -460,6 +413,18 @@
                               const DOMString& encoding,
                               const DOMString& standalone);
   
  +    /**
  +	  * To create the range  consisting of boundary-points and offset of the 
  +      * selected contents
  +      *
  +      * @return The initial state of the Range such that both the boundary-points 
  +      * are positioned at the beginning of the corresponding DOM_DOcument, before 
  +      * any content. The range returned can only be used to select content 
  +      * associated with this document, or with documentFragments and Attrs for 
  +      * which this document is the ownerdocument
  +	  */
  +    DOM_Range    createRange(); 
  +
       //@}
       /** @name Getter functions */
       //@{
  @@ -644,6 +609,7 @@
       DOM_Document (DocumentImpl *impl);
   
       friend class DOM_Node;
  +    friend class DocumentImpl;
       friend class NodeIteratorImpl;
       friend class DOM_DOMImplementation;
   
  
  
  
  1.6       +3 -23     xml-xerces/c/src/dom/DOM_DocumentFragment.hpp
  
  Index: DOM_DocumentFragment.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_DocumentFragment.hpp,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DOM_DocumentFragment.hpp	2000/03/02 19:53:55	1.5
  +++ DOM_DocumentFragment.hpp	2000/07/28 01:33:31	1.6
  @@ -55,32 +55,8 @@
    */
   
   /*
  - * $Log: DOM_DocumentFragment.hpp,v $
  - * Revision 1.5  2000/03/02 19:53:55  roddey
  - * This checkin includes many changes done while waiting for the
  - * 1.1.0 code to be finished. I can't list them all here, but a list is
  - * available elsewhere.
  - *
  - * Revision 1.4  2000/02/24 20:11:27  abagchi
  - * Swat for removing Log from API docs
  - *
  - * Revision 1.3  2000/02/06 07:47:29  rahulj
  - * Year 2K copyright swat.
  - *
  - * Revision 1.2  1999/12/21 07:47:06  robweir
  - * Patches to support Xalan, where we need to create a
  - * "special" DOM with subclassed Nodes.
  - *
  - * 1. Export the NodeImpl-derived classes
  - * 2. Ensure that their constructors have at least protected access
  - *
  - * Revision 1.1.1.1  1999/11/09 01:08:51  twl
  - * Initial checkin
  - *
  - * Revision 1.2  1999/11/08 20:44:16  rahul
  - * Swat for adding in Product name and CVS comment log variable.
  - *
  -*/
  + * $Id: DOM_DocumentFragment.hpp,v 1.6 2000/07/28 01:33:31 aruna1 Exp $
  + */
   
   #ifndef DOM_DocumentFragment_HEADER_GUARD_
   #define DOM_DocumentFragment_HEADER_GUARD_
  @@ -194,8 +170,7 @@
       DOM_DocumentFragment(DocumentFragmentImpl *);
   
       friend class DOM_Document;
  -
  -
  +    friend class RangeImpl;
   };
   
   #endif
  
  
  
  1.10      +2 -32     xml-xerces/c/src/dom/DOM_Node.hpp
  
  Index: DOM_Node.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_Node.hpp,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- DOM_Node.hpp	2000/04/25 20:29:33	1.9
  +++ DOM_Node.hpp	2000/07/28 01:33:31	1.10
  @@ -55,42 +55,7 @@
    */
   
   /*
  - * $Log: DOM_Node.hpp,v $
  - * Revision 1.9  2000/04/25 20:29:33  aruna1
  - * DOM_XMLDecl type node introduced to get the information of the
  - * XML Declaration in a document and store it part of the tree
  - *
  - * Revision 1.8  2000/04/19 02:26:16  aruna1
  - * Full support for DOM_EntityReference, DOM_Entity and DOM_DocumentType introduced
  - *
  - * Revision 1.7  2000/03/11 02:17:19  chchou
  - * Fix bug # 29 to have the spefified flag set correctly for AttrImpl.
  - *
  - * Revision 1.6  2000/03/02 19:53:56  roddey
  - * This checkin includes many changes done while waiting for the
  - * 1.1.0 code to be finished. I can't list them all here, but a list is
  - * available elsewhere.
  - *
  - * Revision 1.5  2000/02/24 20:11:28  abagchi
  - * Swat for removing Log from API docs
  - *
  - * Revision 1.4  2000/02/17 17:47:25  andyh
  - * Update Doc++ API comments
  - * NameSpace update to track W3C
  - * Changes were made by Chih Hsiang Chou
  - *
  - * Revision 1.3  2000/02/06 07:47:30  rahulj
  - * Year 2K copyright swat.
  - *
  - * Revision 1.2  2000/01/05 01:16:07  andyh
  - * DOM Level 2 core, namespace support added.
  - *
  - * Revision 1.1.1.1  1999/11/09 01:08:59  twl
  - * Initial checkin
  - *
  - * Revision 1.4  1999/11/08 20:44:19  rahul
  - * Swat for adding in Product name and CVS comment log variable.
  - *
  + * $Id: DOM_Node.hpp,v 1.10 2000/07/28 01:33:31 aruna1 Exp $
    */
   
   #ifndef DOM_Node_HEADER_GUARD_
  @@ -661,6 +626,7 @@
       friend class DOM_NodeList;
       friend class DOMParser;
       friend class DOM_Entity;
  +    friend class RangeImpl;
   
   };
   
  
  
  
  1.8       +4 -0      xml-xerces/c/src/dom/DOM_Text.hpp
  
  Index: DOM_Text.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DOM_Text.hpp,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DOM_Text.hpp	2000/03/24 01:30:50	1.7
  +++ DOM_Text.hpp	2000/07/28 01:33:31	1.8
  @@ -56,6 +56,9 @@
   
   /*
    * $Log: DOM_Text.hpp,v $
  + * Revision 1.8  2000/07/28 01:33:31  aruna1
  + * DOM Level 2 Range feature introduced
  + *
    * Revision 1.7  2000/03/24 01:30:50  chchou
    * Fix bug #8 to support ignorable whitespace text nodes
    *
  @@ -211,6 +214,7 @@
       DOM_Text(TextImpl *);
   
       friend class DOM_Document;
  +    friend class RangeImpl;
   
   
   
  
  
  
  1.10      +2 -1      xml-xerces/c/src/dom/DocumentFragmentImpl.hpp
  
  Index: DocumentFragmentImpl.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DocumentFragmentImpl.hpp,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- DocumentFragmentImpl.hpp	2000/04/27 02:52:43	1.9
  +++ DocumentFragmentImpl.hpp	2000/07/28 01:33:31	1.10
  @@ -57,7 +57,7 @@
    */
   
   /*
  - * $Id: DocumentFragmentImpl.hpp,v 1.9 2000/04/27 02:52:43 lehors Exp $
  + * $Id: DocumentFragmentImpl.hpp,v 1.10 2000/07/28 01:33:31 aruna1 Exp $
    */
   
   //
  @@ -87,6 +87,7 @@
       virtual short getNodeType();
       virtual bool isDocumentFragmentImpl();
       virtual void setNodeValue(const DOMString &);
  +   
   };
   
   #endif
  
  
  
  1.30      +53 -12    xml-xerces/c/src/dom/DocumentImpl.cpp
  
  Index: DocumentImpl.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DocumentImpl.cpp,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- DocumentImpl.cpp	2000/07/19 19:07:50	1.29
  +++ DocumentImpl.cpp	2000/07/28 01:33:31	1.30
  @@ -55,7 +55,7 @@
    */
   
   /*
  - * $Id: DocumentImpl.cpp,v 1.29 2000/07/19 19:07:50 aruna1 Exp $
  + * $Id: DocumentImpl.cpp,v 1.30 2000/07/28 01:33:31 aruna1 Exp $
    */
   
   //
  @@ -89,17 +89,20 @@
   #include "NodeIDMap.hpp"
   #include "DOM_Document.hpp"
   #include <util/HashPtr.hpp>
  +#include "RangeImpl.hpp"
  +#include "DOM_Document.hpp"
   
   DocumentImpl::DocumentImpl()
       : ParentNode(this)
   {
  -    docType=null;
  -    docElement=null;
  -    namePool = new DStringPool(257);
  -    iterators = 0L;
  +    docType     = null;
  +    docElement  = null;
  +    namePool    = new DStringPool(257);
  +    iterators   = 0L;
       treeWalkers = 0L;
  -    fNodeIDMap = 0;
  -	userData = 0;
  +    fNodeIDMap  = 0;
  +	userData    = 0;
  +    ranges      = 0;
   
   };
   
  @@ -116,11 +119,12 @@
   	
       docElement=null;
       appendChild(createElementNS(fNamespaceURI, qualifiedName));  //root element
  -    namePool = new DStringPool(257);
  -    iterators = 0;
  +    namePool    = new DStringPool(257);
  +    iterators   = 0;
       treeWalkers = 0;
  -    fNodeIDMap = 0;
  -	userData = 0;
  +    fNodeIDMap  = 0;
  +	userData    = 0;
  +    ranges      = 0;
   }
   
   void DocumentImpl::setDocumentType(DocumentTypeImpl *doctype)
  @@ -158,6 +162,11 @@
           // The data in the vector is pointers owned by smart pointers, and will be cleaned up when they go away.
           delete treeWalkers;
       }
  +
  +    if (ranges != 0L) {
  +        delete ranges;
  +        ranges = 0;
  +    }
       
   	if (userData)
   		delete userData;
  @@ -696,7 +705,39 @@
       return new XMLDeclImpl(this, version, encoding, standalone);
   }
   
  +RangeImpl* DocumentImpl::createRange()
  +{
  +
  +    RangeImpl* range = new RangeImpl(DOM_Document(this));
  +
  +    if (ranges == 0L) {
  +        ranges = new RangeImpls(1, false);
  +    }
  +    ranges->addElement(range);
  +    return range;
  +}
  +
  +RangeImpls* DocumentImpl::getRanges()
  +{
  +    return ranges;
  +}
   
  +void DocumentImpl::removeRange(RangeImpl* range) 
  +{
  +    if (ranges != null) {
  +        unsigned int sz = ranges->size();
  +        if (sz !=0) {
  +            for (unsigned int i =0; i<sz; i++) {
  +                if (ranges->elementAt(i) == range) {
  +                    ranges->removeElementAt(i);
  +                    delete range;
  +                    break;
  +                }
  +            }
  +        }
  +    }
  +}
  +
   /** Uses the kidOK lookup table to check whether the proposed
       tree structure is legal.
   
  @@ -727,7 +768,7 @@
                 1 << DOM_Node::CDATA_SECTION_NODE |
                 1 << DOM_Node::ENTITY_REFERENCE_NODE |
                 1 << DOM_Node::XML_DECL_NODE;
  -          
  +
             kidOK[DOM_Node::ATTRIBUTE_NODE] = 
                 1 << DOM_Node::TEXT_NODE |
                 1 << DOM_Node::ENTITY_REFERENCE_NODE;
  
  
  
  1.20      +10 -1     xml-xerces/c/src/dom/DocumentImpl.hpp
  
  Index: DocumentImpl.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/DocumentImpl.hpp,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- DocumentImpl.hpp	2000/06/28 17:51:37	1.19
  +++ DocumentImpl.hpp	2000/07/28 01:33:31	1.20
  @@ -58,7 +58,7 @@
    */
   
   /*
  - * $Id: DocumentImpl.hpp,v 1.19 2000/06/28 17:51:37 jpolast Exp $
  + * $Id: DocumentImpl.hpp,v 1.20 2000/07/28 01:33:31 aruna1 Exp $
    */
   
   //
  @@ -99,9 +99,11 @@
   class DOM_DOMImplementation;
   class DOMString;
   class NodeIDMap;
  +class RangeImpl;
   
   typedef RefVectorOf<NodeIteratorImpl> NodeIterators;
   typedef RefVectorOf<TreeWalkerImpl> TreeWalkers;
  +typedef RefVectorOf<RangeImpl> RangeImpls;
   
   
   class CDOM_EXPORT DocumentImpl: public ParentNode {
  @@ -120,8 +122,11 @@
       NodeIterators               *iterators;
       TreeWalkers                 *treeWalkers;
   	RefHashTableOf<void>		*userData;
  +    RangeImpls                  *ranges;
  +
       friend class NodeIteratorImpl;
       friend class TreeWalkerImpl;
  +    friend class RangeImpl;
      	friend class DOMParser;
   
   public:
  @@ -164,6 +169,10 @@
       virtual XMLDeclImpl*        createXMLDecl(const DOMString& version, const DOMString& encoding, const DOMString& standalone);
       virtual void*				getUserData();
       virtual void				setUserData(void* value);
  +    virtual RangeImpl*          createRange();
  +    virtual RangeImpls*         getRanges();  //non-standard api
  +    virtual void                removeRange(RangeImpl* range); //non-standard api
  +
   
   	// helper functions to prevent storing userdata pointers on every node.
       virtual void setUserData(NodeImpl* n, void* data);
  
  
  
  1.16      +7 -1      xml-xerces/c/src/dom/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/Makefile.in,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Makefile.in	2000/07/05 23:16:11	1.15
  +++ Makefile.in	2000/07/28 01:33:32	1.16
  @@ -54,7 +54,7 @@
   # <http://www.apache.org/>.
   #
   #
  -# $Id: Makefile.in,v 1.15 2000/07/05 23:16:11 jpolast Exp $
  +# $Id: Makefile.in,v 1.16 2000/07/28 01:33:32 aruna1 Exp $
   #
   
   PLATFORM = @platform@
  @@ -97,6 +97,8 @@
   	DOM_NodeList.hpp \
   	DOM_Notation.hpp \
   	DOM_ProcessingInstruction.hpp \
  +	DOM_Range.hpp \
  +	DOM_RangeException.hpp \
   	DOM_Text.hpp \
   	DOM_TreeWalker.hpp \
   	DOM_XMLDecl.hpp
  @@ -131,6 +133,7 @@
   	NotationImpl.hpp \
   	ParentNode.hpp \
   	ProcessingInstructionImpl.hpp \
  +	RangeImpl.hpp \
   	RefCountedImpl.hpp \
   	TextImpl.hpp \
   	TreeWalkerImpl.hpp \
  @@ -169,6 +172,8 @@
   	DOM_TreeWalker.$(TO) \
   	DOM_Notation.$(TO) \
   	DOM_ProcessingInstruction.$(TO) \
  +	DOM_Range.$(TO) \
  +	DOM_RangeException.$(TO) \
   	DOM_Text.$(TO) \
   	DOM_XMLDecl.$(TO) \
   	DStringPool.$(TO) \
  @@ -191,6 +196,7 @@
   	NotationImpl.$(TO) \
   	ParentNode.$(TO) \
   	ProcessingInstructionImpl.$(TO) \
  +	RangeImpl.$(TO) \
   	RefCountedImpl.$(TO) \
   	TextImpl.$(TO) \
   	TreeWalkerImpl.$(TO) \
  
  
  
  1.4       +2 -1      xml-xerces/c/src/dom/ParentNode.cpp
  
  Index: ParentNode.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/ParentNode.cpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ParentNode.cpp	2000/06/22 22:19:43	1.3
  +++ ParentNode.cpp	2000/07/28 01:33:32	1.4
  @@ -55,13 +55,14 @@
    */
   
   /*
  - * $Id: ParentNode.cpp,v 1.3 2000/06/22 22:19:43 aruna1 Exp $
  + * $Id: ParentNode.cpp,v 1.4 2000/07/28 01:33:32 aruna1 Exp $
    */
   
   #include "ParentNode.hpp"
   #include "DOM_DOMException.hpp"
   #include "DocumentImpl.hpp"
   #include "TextImpl.hpp"
  +#include "RangeImpl.hpp"
   
   #define THIS_CLASS ParentNode
   #define PARENT_CLASS NodeImpl
  
  
  
  1.13      +18 -2     xml-xerces/c/src/dom/TextImpl.cpp
  
  Index: TextImpl.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/dom/TextImpl.cpp,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- TextImpl.cpp	2000/05/02 19:22:02	1.12
  +++ TextImpl.cpp	2000/07/28 01:33:32	1.13
  @@ -55,7 +55,7 @@
    */
   
   /*
  - * $Id: TextImpl.cpp,v 1.12 2000/05/02 19:22:02 aruna1 Exp $
  + * $Id: TextImpl.cpp,v 1.13 2000/07/28 01:33:32 aruna1 Exp $
    */
   
   #include "DocumentImpl.hpp"
  @@ -64,6 +64,7 @@
   #include "TextImpl.hpp"
   #include "CharacterDataImpl.hpp"
   #include "DStringPool.hpp"
  +#include "RangeImpl.hpp"
   
   static DOMString *gText;   // will be lazily initialized to point to "#text"
   
  @@ -114,15 +115,30 @@
   	unsigned int len = data.length();
       if (offset >= len)
           throw DOM_DOMException(DOM_DOMException::INDEX_SIZE_ERR, null);
  -                
  +               
       TextImpl *newText = 
                   (TextImpl *) getOwnerDocument()->createTextNode(
                           data.substringData(offset, data.length() - offset));
  +
       NodeImpl *parent = getParentNode();
       if (parent != null)
           parent->insertBefore(newText, getNextSibling());
   
       data = data.substringData(0, offset);
  +
  +    if (this->getOwnerDocument() != null) {
  +        typedef RefVectorOf<RangeImpl> RangeImpls;
  +        RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  +        if (ranges != null) {
  +            unsigned int sz = ranges->size();
  +            if (sz != 0) {
  +                for (unsigned int i =0; i<sz; i++) {
  +                    ranges->elementAt(i)->updateSplitInfo( this, newText);
  +                }
  +            }
  +        }
  +    }
  +
       return newText;
   };
   
  
  
  
  1.1                  xml-xerces/c/src/dom/DOM_Range.cpp
  
  Index: DOM_Range.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Id: DOM_Range.cpp,v 1.1 2000/07/28 01:33:31 aruna1 Exp $
   */
  
  
  
  #include <dom/DOM_Range.hpp>
  #include "DocumentImpl.hpp"
  #include "RangeImpl.hpp"
  
  
  
  DOM_Range::DOM_Range()
  :fImpl(0)
  {
  }
  
  DOM_Range::DOM_Range(RangeImpl* impl)
  {
      fImpl = impl;
      RefCountedImpl::addRef(fImpl);
  }
  
  DOM_Range::~DOM_Range()
  {
      RefCountedImpl::removeRef (this->fImpl);
      fImpl = 0;
  };
  
  DOM_Range & DOM_Range::operator = (const DOM_Range &other)
  {
      if (this->fImpl != other.fImpl)
      {
          RefCountedImpl::removeRef(this->fImpl);
          this->fImpl = other.fImpl;
          RefCountedImpl::addRef(this->fImpl);
      }
      return *this;
  };
  
  
  DOM_Range & DOM_Range::operator = (const DOM_NullPtr *other)
  {
      RefCountedImpl::removeRef(this->fImpl);
      this->fImpl = 0;
      return *this;
  };
  
  bool       DOM_Range::operator != (const DOM_Range & other) const
  {
      return this->fImpl != other.fImpl;
  };
  
  
  bool       DOM_Range::operator == (const DOM_Range & other) const
  {
      return this->fImpl == other.fImpl;
  };
  
  bool       DOM_Range::operator != (const DOM_NullPtr * other) const
  {
      return this->fImpl != 0;
  };
  
  
  bool       DOM_Range::operator == (const DOM_NullPtr * other) const
  {
      return this->fImpl == 0;
  }
  
  //getter functions
  
  DOM_Node& DOM_Range::getStartContainer()
  {
      return ((RangeImpl *)fImpl)->getStartContainer();
  }
  unsigned int DOM_Range::getStartOffset()
  {
      return ((RangeImpl *)fImpl)->getStartOffset();
  }
  DOM_Node& DOM_Range::getEndContainer()
  {
          return ((RangeImpl *)fImpl)->getEndContainer();
  }
  unsigned int DOM_Range::getEndOffset()
  {
          return ((RangeImpl *)fImpl)->getEndOffset();
  }
  const DOM_Node& DOM_Range::getCommonAncestorContainer()
  {
          return ((RangeImpl *)fImpl)->getCommonAncestorContainer();
  }
  
  //setter functions    
  
  void DOM_Range::setStart(DOM_Node parent, unsigned int offset)
  {
      this->fImpl->setStart(parent, offset);
  }
  
  void DOM_Range::setEnd(DOM_Node parent, unsigned int offset)
  {
      this->fImpl->setEnd(parent, offset);
  }
  
  void DOM_Range::setStartBefore(DOM_Node refNode)
  {
      this->fImpl->setStartBefore(refNode);
  }
  
  void DOM_Range::setStartAfter(DOM_Node refNode)
  {
      this->fImpl->setStartAfter(refNode);
  }
  
  void DOM_Range::setEndBefore(DOM_Node refNode)
  {
      this->fImpl->setEndBefore(refNode);
  }
  
  void DOM_Range::setEndAfter(DOM_Node refNode)
  {
      this->fImpl->setEndAfter(refNode);
  }
  
  //misc functions
  void DOM_Range::collapse(bool toStart)
  {
      this->fImpl->collapse(toStart);
  }
  
  bool DOM_Range::getCollapsed()
  {
      return ((RangeImpl *)fImpl)->getCollapsed();
  }
  
  void DOM_Range::selectNode(DOM_Node node)
  {
    ((RangeImpl *)fImpl)->selectNode(node); 
  }
  void DOM_Range::selectNodeContents(DOM_Node node)
  {
      ((RangeImpl *)fImpl)->selectNodeContents(node); 
  }
  
  //Functions related to comparing ange Boundrary-Points
  short DOM_Range::compareBoundaryPoints(CompareHow how, const DOM_Range& range)
  {
      return ((RangeImpl *)fImpl)->compareBoundaryPoints(how, range.fImpl);
  }
  
  void DOM_Range::deleteContents()
  {
      ((RangeImpl *)fImpl)->deleteContents();
  }
  
  DOM_DocumentFragment DOM_Range::extractContents()
  {
      return ((RangeImpl *)fImpl)->extractContents();
  }
  
  DOM_DocumentFragment DOM_Range::cloneContents()
  {
      return ((RangeImpl *)fImpl)->cloneContents();
  }
  
  void DOM_Range::insertNode(DOM_Node& node)
  {
      ((RangeImpl *)fImpl)->insertNode(node);
  }
  
  //Misc functions
  void DOM_Range::surroundContents(DOM_Node node)
  {
      ((RangeImpl *)fImpl)->surroundContents(node);
  }
  
  DOM_Range DOM_Range::cloneRange()
  {
      return DOM_Range( ((RangeImpl *)fImpl)->cloneRange() );
  }
  
  DOMString DOM_Range::toString()
  {
      return ((RangeImpl *)fImpl)->toString();
  }
  
  void DOM_Range::detach()
  {
      ((RangeImpl *)fImpl)->detach();
  }
  
  
  
  
  1.1                  xml-xerces/c/src/dom/DOM_Range.hpp
  
  Index: DOM_Range.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Id: DOM_Range.hpp,v 1.1 2000/07/28 01:33:31 aruna1 Exp $
   */
  
  #ifndef DOM_Range_HEADER_GUARD_
  #define DOM_Range_HEADER_GUARD_
  
  #include <util/XercesDefs.hpp>
  #include <dom/DOM_Node.hpp>
  #include <dom/DOMString.hpp>
  #include <dom/DOM_DocumentFragment.hpp>
  
  class RangeImpl;
  
  //class RangeImpl;
  
  class CDOM_EXPORT DOM_Range {
  public:
  
      enum CompareHow {
          START_TO_START  = 0,
          START_TO_END    = 1,
          END_TO_END      = 2,
          END_TO_START    = 3
      };
  
      //c'tor & d'tor
      DOM_Range();
      ~DOM_Range();
  
      
      DOM_Range & operator = (const DOM_Range &other);
      DOM_Range & operator = (const DOM_NullPtr *other);
      bool operator != (const DOM_Range & other) const;
      bool operator == (const DOM_Range & other) const;
      bool operator != (const DOM_NullPtr * other) const;
      bool operator == (const DOM_NullPtr * other) const;
  
      //getter functions
      DOM_Node& getStartContainer();
      unsigned int getStartOffset();
      DOM_Node& getEndContainer();
      unsigned int getEndOffset();
      bool getCollapsed();
      const DOM_Node& getCommonAncestorContainer();
  
      //setter functions
      void setStart(DOM_Node parent, unsigned int offset);
      void setEnd(DOM_Node parent, unsigned int offset);
  
      void setStartBefore(DOM_Node refNode);
      void setStartAfter(DOM_Node refNode);
      void setEndBefore(DOM_Node refNode);
      void setEndAfter(DOM_Node refNode);
     
      //misc functions
      void collapse(bool toStart);
      void selectNode(DOM_Node node);
      void selectNodeContents(DOM_Node node);
  
      //Functions related to comparing range Boundrary-Points
      short compareBoundaryPoints(CompareHow how, const DOM_Range& range);
      void deleteContents();
      DOM_DocumentFragment extractContents();
      DOM_DocumentFragment cloneContents();
      void insertNode(DOM_Node& node);
      //Misc functions
      void surroundContents(DOM_Node node);
      DOM_Range cloneRange();
      DOMString toString();
      void detach();
  
      
       
  
  protected:
  
      DOM_Range(RangeImpl *);
      RangeImpl   *fImpl;
  
      friend class DOM_Document;
  };
  
  
  
  
  #endif
  
  
  
  1.1                  xml-xerces/c/src/dom/DOM_RangeException.cpp
  
  Index: DOM_RangeException.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
   
  /*
   * $Log: DOM_RangeException.cpp,v $
   * Revision 1.1  2000/07/28 01:33:31  aruna1
   * DOM Level 2 Range feature introduced
   *
   */
  
  #include "DOM_RangeException.hpp"
  
  
  DOM_RangeException::DOM_RangeException()
  : DOM_DOMException()
  {
          code = (RangeExceptionCode) 0;
  };
  
  
  DOM_RangeException::DOM_RangeException(RangeExceptionCode exCode, const DOMString &message) 
  : DOM_DOMException(exCode, message) 
  {
     code = exCode;
  };
  
  
  DOM_RangeException::DOM_RangeException(const DOM_RangeException &other) 
  : DOM_DOMException(other)
  {
          code = other.code;
  };
  
  
  DOM_RangeException::~DOM_RangeException() 
  {
  };
  
  
  
  1.1                  xml-xerces/c/src/dom/DOM_RangeException.hpp
  
  Index: DOM_RangeException.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Log: DOM_RangeException.hpp,v $
   * Revision 1.1  2000/07/28 01:33:31  aruna1
   * DOM Level 2 Range feature introduced
   *
   */
  
  #ifndef DOM_RangeException_HEADER_GUARD_
  #define DOM_RangeException_HEADER_GUARD_
  
  #include <dom/DOM_DOMException.hpp>
  
  /**
    * Encapsulate range related DOM error or warning. DOM level 2 implementation. 
    *
    * <p> The DOM will create and throw an instance of DOM_RangeException
    * when an error condition in range is detected.  Exceptions can occur
    * when an application directly manipulates the range elements in DOM document
    * tree that is produced by the parser. 
    *
    * <p>Unlike the other classes in the C++ DOM API, DOM_RangeException
    * is NOT a reference to an underlying implementation class, and
    * does not provide automatic memory management.  Code that catches
    * a DOM Range exception is responsible for deleting it, or otherwise
    * arranging for its disposal.
    *
    */
  class CDOM_EXPORT DOM_RangeException  : public DOM_DOMException {
  public:
      /** @name Enumerators for DOM Range Exceptions */
      //@{
          enum RangeExceptionCode {
                  BAD_BOUNDARYPOINTS_ERR  = 1,
                  INVALID_NODE_TYPE_ERR   = 2
          };
      //@}
  public:
      /** @name Constructors and assignment operator */
      //@{
      /**
        * Default constructor for DOM_RangeException.
        *
        */
      DOM_RangeException();
  
      /**
        * Constructor which takes an error code and a message.
        *
        * @param code The error code which indicates the exception
        * @param message The string containing the error message
        */
      DOM_RangeException(RangeExceptionCode code, const DOMString &message);
  
      /**
        * Copy constructor.
        *
        * @param other The object to be copied.
        */
      DOM_RangeException(const DOM_RangeException &other);
  
      //@}
      /** @name Destructor. */
      //@{
  	 /**
  	  * Destructor for DOM_RangeException.  Applications are responsible
        * for deleting DOM_RangeException objects that they catch after they
        * have completed their exception processing.
  	  *
  	  */
      virtual ~DOM_RangeException();
      //@}
  
      /** @name Public variables. */
       //@{
  	 /**
  	  * A code value, from the set defined by the RangeExceptionCode enum,
        * indicating the type of error that occured.
  	  */
     RangeExceptionCode   code;
  
      //@}
  
  };
  
  #endif
  
  
  
  
  1.1                  xml-xerces/c/src/dom/RangeImpl.cpp
  
  Index: RangeImpl.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Id: RangeImpl.cpp,v 1.1 2000/07/28 01:33:32 aruna1 Exp $
   */
  
  #include "NodeImpl.hpp"
  #include "RangeImpl.hpp"
  #include "DocumentImpl.hpp"
  #include <dom/DOM_DOMException.hpp>
  #include <dom/DOM_Document.hpp>
  #include <dom/DocumentFragmentImpl.hpp>
  #include <dom/DOM_Document.hpp>
  #include <util/RefVectorOf.hpp>
  #include <dom/DOM_RangeException.hpp>
  #include <dom/DOM_DOMException.hpp>
  #include <dom/DOM_Text.hpp>
  
  
  //---------------------
  // C'tor and D'tor 
  //---------------------
  
  RangeImpl::RangeImpl(DOM_Document doc)
    
      :   fDocument(doc),
          fStartContainer(doc),
          fStartOffset(0),
          fEndContainer(doc),
          fEndOffset(0),
          fDetached(false),
          fCollapsed(true),
          fCommonAncestorContainer(0),
          fRemoveChild(0)
  {
  }        
  
  RangeImpl::RangeImpl(const RangeImpl& other)
  {
      fDocument = other.fDocument;
      fStartContainer = other.fStartContainer;
      fStartOffset = other.fStartOffset;
      fEndContainer = other.fEndContainer;
      fEndOffset = other.fEndOffset;
      fDetached = other.fDetached;
      fCollapsed = other.fCollapsed;
      fCommonAncestorContainer = other.fCommonAncestorContainer;
      fRemoveChild = other.fRemoveChild;
  }
  
  RangeImpl::~RangeImpl()
  {
  }
  
  void RangeImpl::unreferenced()
  {
      if (((DocumentImpl*)fDocument.fImpl)->ranges != 0L) {
          int sz = ((DocumentImpl*)fDocument.fImpl)->ranges->size();
          for (int i=0; i< sz; i++) {
              if (((DocumentImpl*)fDocument.fImpl)->ranges->elementAt(i) == this) {
                  ((DocumentImpl*)fDocument.fImpl)->ranges->removeElementAt(i);
                  break;
              }
          }
      }
      delete this;
  };
  
  
  //-------------------------------
  // Public getter functions
  //-------------------------------
  
  
  DOM_Node& RangeImpl::getStartContainer()
  {
      return fStartContainer;
  }
  
  unsigned int RangeImpl::getStartOffset()
  {
      return fStartOffset;
  }
  
  DOM_Node& RangeImpl::getEndContainer()
  {
      return fEndContainer;
  }
  
  unsigned int RangeImpl::getEndOffset()
  {
      return fEndOffset;
  }
  
  
  
  bool RangeImpl::getCollapsed()
  {
      if (fDetached) 
      {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
  
      return ((fStartContainer == fEndContainer) 
               && (fStartOffset == fEndOffset));
  }
  
  //-------------------------------
  // Public getter functions
  //-------------------------------
  
  void RangeImpl::setStartContainer(const DOM_Node& node) 
  {
      fStartContainer = node;
  }
  
  void RangeImpl::setStartOffset(unsigned int offset) 
  {
      fStartOffset = offset;
  }
  
  void RangeImpl::setEndContainer(const DOM_Node& node) 
  {
      fEndContainer = node;
      
  }
  
  void RangeImpl::setEndOffset(unsigned int offset) 
  {
      fEndOffset = offset;
  }
  
  void RangeImpl::setCommonAncestorContainer(const DOM_Node&  node) 
  {
      fCommonAncestorContainer = node;
  }
  
  void RangeImpl::setStart(DOM_Node& refNode, unsigned int offset)
  {
      checkIndex(refNode, offset);
      
      fStartContainer = refNode;
      fStartOffset    = offset;
      
      if ((fDocument != refNode.getOwnerDocument() ) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(true); 
      }
      
      if (fStartOffset >= fEndOffset)
          collapse(true); //collapse the range positions to start
      else
          fCollapsed = false;
  }
  
  void RangeImpl::setEnd(DOM_Node& refNode, unsigned int offset)
  {
      checkIndex(refNode, offset);
              
      fEndContainer   = refNode;
      fEndOffset      = offset;
      
      if ((fDocument != refNode.getOwnerDocument() ) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(false);
      }
      
      if (fEndOffset <= fStartOffset) 
          collapse(false); //collapse the range positions to end
      else
          fCollapsed = false;
  }
  
  void RangeImpl::setStartBefore(DOM_Node& refNode)
  {
      validateNode(refNode);
      
      fStartContainer = refNode.getParentNode();
     unsigned int i = 0;
      for (DOM_Node n = refNode; n!=null; n = n.getPreviousSibling()) {
          i++;
      }
      if (i == 0)
          fStartOffset = 0;
      else
          fStartOffset = i-1;
  
      if ((fDocument != refNode.getOwnerDocument()) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(true); 
      }
      
      if (fStartOffset > fEndOffset)
          collapse(true); //collapse the range positions to start
      else
          fCollapsed = false;
  }
  
  void RangeImpl::setStartAfter(DOM_Node& refNode)
  {
      validateNode(refNode);
  
      fStartContainer = refNode.getParentNode();
      unsigned int i = 0;
      for (DOM_Node n = refNode; n!=null; n = n.getPreviousSibling()) {
          i++;
      }
  
      fStartOffset = i;
      
      if ((fDocument != refNode.getOwnerDocument() ) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(true); 
      }
      
      if (fStartOffset > fEndOffset)
          collapse(true); //collapse the range positions to start
      else
          fCollapsed = false;
  }
  
  void RangeImpl::setEndBefore(DOM_Node& refNode)
  {
      validateNode(refNode);
      
      fEndContainer = refNode.getParentNode();
      unsigned int i = 0;
      for (DOM_Node n = refNode; n!=null; n = n.getPreviousSibling(), i++);
  
      if (i< 1)
          fEndOffset = 0;
      else
          fEndOffset = i-1;
  
      if ((fDocument != refNode.getOwnerDocument() ) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(true); 
      }
      
      if (fEndOffset < fStartOffset) 
          collapse(false); //collapse the range positions to end
      else
          fCollapsed = false;
  }
  
  void RangeImpl::setEndAfter(DOM_Node& refNode)
  {
      validateNode(refNode);
      
      fEndContainer = refNode.getParentNode();
      unsigned int i = 0;
      for (DOM_Node n = refNode; n!=null; n = n.getPreviousSibling(), i++);
  
      if (i ==0)
          fEndOffset = 0;
      else
          fEndOffset = i;
  
      if ((fDocument != refNode.getOwnerDocument() ) 
          && (refNode.getOwnerDocument().fImpl != 0) )
      {
          fDocument = refNode.getOwnerDocument();
          collapse(true); 
      }
      
      if (fEndOffset < fStartOffset) 
          collapse(false); //collapse the range positions to end
      else
          fCollapsed = false;
  }
  //-------------------------------
  // Public Misc. functions
  //-------------------------------
  void RangeImpl::detach()
  {
      fDetached = true;
      
      //nullify nodes
      fStartContainer = 0;
      fStartOffset    = 0;
      fEndContainer   = 0;
      fEndOffset      = 0;
      fCollapsed      = true;
      fCommonAncestorContainer = 0;
  
      fRemoveChild    = 0;
  }
  
  void RangeImpl::collapse(bool toStart)
  {
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
  
      if (toStart) {
          fEndContainer = fStartContainer;
          fEndOffset = fStartOffset;
      } else {
          fStartContainer = fEndContainer;
          fStartOffset = fEndOffset;
      }
      fCollapsed = true;
  }
  
  void RangeImpl::selectNode(DOM_Node& refNode)
  {
      validateNode(refNode);
      short type = refNode.getNodeType();
      if (type ==  DOM_Node::ATTRIBUTE_NODE
          || type == DOM_Node::ENTITY_NODE
          || type == DOM_Node::NOTATION_NODE
          || type == DOM_Node::DOCUMENT_TYPE_NODE
          || type == DOM_Node::DOCUMENT_FRAGMENT_NODE) {
  
          throw DOM_RangeException(
              DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
      }
      //First check for the text type node
      if (type ==  DOM_Node::TEXT_NODE) 
      {
          //The node itself is the container.
          fStartContainer = refNode;
          fEndContainer   = refNode;
          
          //Select all the contents of the node
          fStartOffset = 0;
          fEndOffset = ((DOM_Text &)refNode).getLength();
          return;
      }
  
      DOM_Node parent = refNode.getParentNode();
      if (parent != null ) // REVIST: what to do if it IS null?
      {
          fStartContainer = parent;
          fEndContainer = parent;
        
          unsigned int i = 0;
          for (DOM_Node n = parent.getFirstChild(); n!=null, n!=refNode; n = n.getNextSibling()) {
              i++;
          }
         
          fStartOffset = i;
          fEndOffset = fStartOffset+1;
      }
  }
  
  void RangeImpl::selectNodeContents(DOM_Node& node)
  {
      validateNode(node);
       short type = node.getNodeType();
      if (type == DOM_Node::ENTITY_NODE
          || type == DOM_Node::NOTATION_NODE
          || type == DOM_Node::DOCUMENT_TYPE_NODE) {
  
          throw DOM_RangeException(
              DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
      }
      
      fStartContainer = node;
      fEndContainer = node;
      
      fStartOffset = 0;
      if (node.getNodeType() == DOM_Node::TEXT_NODE ) {
          fEndOffset = ((DOM_Text &)node).getLength();
          return;
      }
  
      DOM_Node first = node.getFirstChild();
      if (first == null) {
          fEndOffset = 0;
          return;
      }
      unsigned int i = 0;
      for (DOM_Node n = first; n!=null; n = n.getNextSibling()) {
          i++;
      }
      fEndOffset = i;
  }
  
  void RangeImpl::surroundContents(DOM_Node& newParent)
  {
      if (newParent==null) return;
   
      //check for elimination criteria
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
  
      if (newParent.getOwnerDocument() !=fDocument) {
          throw DOM_DOMException(
              DOM_DOMException::WRONG_DOCUMENT_ERR, null);
      }
      
      int type = newParent.getNodeType();
      if (type == DOM_Node::ATTRIBUTE_NODE
          || type == DOM_Node::ENTITY_NODE
          || type == DOM_Node::NOTATION_NODE
          || type == DOM_Node::DOCUMENT_TYPE_NODE
          || type == DOM_Node::DOCUMENT_NODE
          || type == DOM_Node::DOCUMENT_FRAGMENT_NODE)
      {
          throw DOM_RangeException(
              DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
      }
      
      DOM_Node root = getCommonAncestorContainer();
      
      DOM_Node realStart = fStartContainer;
      DOM_Node realEnd = fEndContainer;
  
      if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {
          realStart = fStartContainer.getParentNode();
      }
      if (fEndContainer.getNodeType() == DOM_Node::TEXT_NODE) {
          realEnd = fEndContainer.getParentNode();
      }
      
      if (realStart != realEnd) {
          throw DOM_RangeException(
              DOM_RangeException::BAD_BOUNDARYPOINTS_ERR, null);
      }
      
      DOM_DocumentFragment frag = extractContents();
      insertNode(newParent);
      newParent.appendChild(frag);
      selectNode(newParent);
  }
  
  
  short RangeImpl::compareBoundaryPoints(DOM_Range::CompareHow how, RangeImpl* srcRange)
  {
      if (fDocument != srcRange->fDocument) {
          throw DOM_DOMException(
              DOM_DOMException::WRONG_DOCUMENT_ERR, null);
      }
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
  
      DOM_Node pointA, pointB;
      int offsetA, offsetB;
          
      switch (how)
      {
      case (DOM_Range::START_TO_START) :
          pointA = srcRange->getStartContainer();
          pointB = fStartContainer;
          offsetA = srcRange->getStartOffset();
          offsetB = fStartOffset;
          break;
      case (DOM_Range::START_TO_END) :
          pointA = srcRange->getStartContainer();
          pointB = fEndContainer;
          offsetA = srcRange->getStartOffset();
          offsetB = fEndOffset;
          break;
      case (DOM_Range::END_TO_START) :
          pointA = srcRange->getEndContainer();
          pointB = fStartContainer;
          offsetA = srcRange->getEndOffset();
          offsetB = fStartOffset;
          break;
      case (DOM_Range::END_TO_END) :
          pointA = srcRange->getEndContainer();
          pointB = fEndContainer;
          offsetA = srcRange->getEndOffset();
          offsetB = fEndOffset;
          break;
      }
      
      // case 1: same container
      if (pointA == pointB) {
          if (offsetA < offsetB) return -1; //A before B
          if (offsetA == offsetB) return 0; //A equal to B
          return 1; // A after B
      }
      // case 2: Child C of container A is ancestor of B
      for (DOM_Node node = pointA.getFirstChild(); node != null; node=node.getNextSibling()) {
          if (isAncestorOf(node, pointB)) {
              int index = indexOf(node, pointA);
              if (offsetA <=  index) return -1;
              return 1;
          }
      }
      // case 3: Child C of container B is ancestor of A
      for (DOM_Node nd = pointB.getFirstChild(); nd != null; nd=nd.getNextSibling()) {
          if (isAncestorOf(nd, pointA)) {
              int index = indexOf(nd, pointB);
              if (index < offsetB ) return -1; 
              return 1; //B strictly before A
          }
      }
      
      // case 4: preorder traversal of context tree.
      DOM_Node ancestor = commonAncestorOf(pointA, pointB);
      DOM_Node current = ancestor;
      
      do {
          if (current == pointA) return -1;
          if (current == pointB) return 1;
          current = nextNode(current, true); 
      }
      while (current!=null && current!=ancestor);
      
      return -2; // this should never happen
  }
  
  
  void RangeImpl:: deleteContents()
  {
      if ((fStartContainer == null) || (fEndContainer == null) ) return;
      checkReadOnly(fStartContainer, fEndContainer, fStartOffset, fEndOffset);
      
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
      
      DOM_Node current = fStartContainer;
      
      // if same container, simplify case
      if (fStartContainer == fEndContainer) {
          if (fStartOffset == fEndOffset) { // already  collapsed
              return; 
          } 
          if (fStartOffset > fEndOffset)
              throw DOM_RangeException(DOM_RangeException::BAD_BOUNDARYPOINTS_ERR, null);
          
          if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {
              DOMString value = fStartContainer.getNodeValue();
              unsigned int realStart = fStartOffset;
              unsigned int realEnd = fEndOffset;
              
              if (fStartOffset > value.length()) realStart = value.length()-1;
              if (fEndOffset > value.length()) realEnd = value.length()-1;
              
              ((DOM_Text &)fStartContainer).deleteData(realStart, realEnd-realStart);
              
          } else {
              current = fStartContainer.getFirstChild();  
              unsigned int i = 0;
              //move till the start offset 
              for(i = 0; i < fStartOffset && current != null; i++) {
                  current=current.getNextSibling();
              }
                          
              //delete all children after the start offset to end offset
              for(i = 0; i < (fEndOffset-fStartOffset) && (current != null); i++) {
                  DOM_Node newCurrent = current.getNextSibling();
                  removeChild(fStartContainer, current);
                  current = newCurrent;
              }
          }
          collapse(true);
          return;
      }
      
      //The case of partial selections and when start container is not the same as end one
      bool deleteCurrent  = false;
      
       // initialize current for startContainer.
      if (current.getNodeType() == DOM_Node::TEXT_NODE) {
          ((DOM_Text &)current).deleteData(fStartOffset, current.getNodeValue().length()-fStartOffset);
      } else {
          current = current.getFirstChild();
          for (unsigned int i = 0 ; i < fStartOffset && current != null; i++){
              current = current.getNextSibling();
          }
          if (current == null) {
              current = fStartContainer;
          } else if (current != fStartContainer)
              deleteCurrent = true;
      }
      
      DOM_Node parent         = null;
      DOM_Node next;
      DOM_Node partialNode    = null;
      int partialInt          = START;
      DOM_Node startRoot      = null;
      
      DOM_Node root = getCommonAncestorContainer();
      // traverse up from the startContainer...
      // current starts as the node to delete;
      while (current != root && current != null) {
          
          parent = current.getParentNode();
          if (parent == root) {
              if (startRoot == null)
                  startRoot = current;
          } else {
              if (partialNode == null) {
                  partialNode = parent;
                  partialInt = AFTER;
              }
          }
          
          if (parent != root) {
              next = current.getNextSibling();
              DOM_Node nextnext;
              while (next != null)  {
                  nextnext = next.getNextSibling();
                  removeChild(parent, next);
                  next = nextnext;
              }
          }
          
          if (deleteCurrent) {
              removeChild(parent, current);
              deleteCurrent = false;
          }
          current = parent;
      }
      
      DOM_Node endRoot = null;
      // initialize current for endContainer.
      current = fEndContainer;
      if (current.getNodeType() == DOM_Node::TEXT_NODE) {
          ((DOM_Text &)current).deleteData(0, fEndOffset); 
      } else {
          
          if (fEndOffset == 0) { // "before"
              current = fEndContainer;
          }
          else {
              current = current.getFirstChild();
              for(unsigned int i = 1; i < fEndOffset && current != null; i++) {
                  current=current.getNextSibling();
              }
              if (current==null) { // REVIST: index-out-of-range what to do?
                  current = fEndContainer.getLastChild();
              } else 
                  if (current != fStartContainer) {
                      deleteCurrent = true;
                  }
                  
          }
      }
      
      // traverse up from the endContainer...
      while (current != root && current != null) {
          
          parent = current.getParentNode();
          if (parent == root) {
              if (endRoot == null)
                  endRoot = current;
          } else {
              if (partialNode==null) {
                  partialNode = parent;
                  partialInt = BEFORE;
              }
          }
          
          if (parent != root && parent != null) {
              next = current.getPreviousSibling();
              DOM_Node nextnext;
              while (next != null) {
                  nextnext = next.getPreviousSibling();
                  removeChild(parent, next);
                  next = nextnext;
              }
          }
          
          if (deleteCurrent) {
              removeChild(parent, current);
              deleteCurrent = false;
          }
          current = parent;
      }
      
      //if (endRoot == null || startRoot == null) return; //REVIST
      current = endRoot.getPreviousSibling();
      DOM_Node prev = null;
      while (current != null && current != startRoot ) {
          prev = current.getPreviousSibling();
          parent = current.getParentNode();
          if (parent != null) {
              removeChild(parent, current);
          }
          current = prev;
      }
      
      if (partialNode == null) {
          collapse(true);
      } else if (partialInt == AFTER) {
          setStartAfter(partialNode);
          setEndAfter(partialNode);
      } else if (partialInt == BEFORE) {
          setStartBefore(partialNode);
          setEndBefore(partialNode);
      }
  }
  
  DOM_DocumentFragment RangeImpl::extractContents()
  {
      return traverseContents(EXTRACT_CONTENTS);
  }
  
  DOM_DocumentFragment RangeImpl::cloneContents()
  {
      return traverseContents(CLONE_CONTENTS);
  }
  
  
  void RangeImpl::insertNode(DOM_Node& newNode)
  {
      if (newNode == null) return; //don't have to do anything
  
      if (fStartContainer.getParentNode().fImpl->readOnly()) {
          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
          || type == DOM_Node::DOCUMENT_FRAGMENT_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);
      }
  
  }
  
  RangeImpl* RangeImpl::cloneRange()
  {
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
      
      RangeImpl* range = ((DocumentImpl*)fDocument.fImpl)->createRange();
      range->setStart(fStartContainer, fStartOffset);
      range->setEnd(fEndContainer, fEndOffset);
      
      return range;
  }
  
  DOMString RangeImpl::toString()
  {
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
      
      DOM_Node node = fStartContainer;
      
      DOMString tempString;
      if ( (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE)
          || (fStartContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) ) {
          if (fStartContainer == fEndContainer) {
              tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, fEndOffset));
              return tempString;
          } else {
              int length = fStartContainer.getNodeValue().length();
              tempString.appendData(fStartContainer.getNodeValue().substringData(fStartOffset, length - fStartOffset));
          }
      }else if (node == fEndContainer){
          DOM_Node anode = node.getFirstChild();
          unsigned int i = 0;
          for ( ;i<fStartOffset; i++)
              anode = anode.getNextSibling();
          for( ; ( i<fEndOffset || anode!=null); anode = anode.getNextSibling(), i++) {
              if( (anode.getNodeType() == DOM_Node::TEXT_NODE)
                  || (anode.getNodeType() == DOM_Node::CDATA_SECTION_NODE)) {
                  tempString.appendData(anode.getNodeValue());
              }
          }
          return tempString;
      }
      DOM_Node root = getCommonAncestorContainer();
      
      while (node != fEndContainer) {
           node = nextNode(node, true);
          if ((node == null) || (node == fEndContainer)) break;
          
          if (node.getNodeType() == DOM_Node::TEXT_NODE
              ||  node.getNodeType() == DOM_Node::CDATA_SECTION_NODE
              ) {
              tempString.appendData(node.getNodeValue());
          }
      }
      
      if (fEndContainer.getNodeType() == DOM_Node::TEXT_NODE
          || fEndContainer.getNodeType() == DOM_Node::CDATA_SECTION_NODE) {
          tempString.appendData(fEndContainer.getNodeValue().substringData(0,fEndOffset));
      }
      return tempString;
  }
  
  DOM_Document RangeImpl::getDocument()
  {
      return fDocument;
  }
  
  const DOM_Node& RangeImpl::getCommonAncestorContainer()
  {
       return fCommonAncestorContainer = commonAncestorOf(fStartContainer, fEndContainer);    
    
  }
  
  //---------------------
  //private functions
  //---------------------
  
  bool RangeImpl::isValidAncestorType(DOM_Node& node)
  {
      for (DOM_Node aNode = node; aNode!=null; aNode = aNode.getParentNode()) {
          short type = aNode.getNodeType();
          if ( type == DOM_Node::ENTITY_NODE
              || type == DOM_Node::NOTATION_NODE
              || type == DOM_Node::DOCUMENT_TYPE_NODE)
              return false;
      }
      return true;
  }
  
  bool RangeImpl::isAncestorOf(const DOM_Node& a, const DOM_Node& b) {
      for (DOM_Node node=b; node != null; node=node.getParentNode()) {
          if  (node == a) return true;
      }
      return false;
  }
  
  unsigned short RangeImpl::indexOf(const DOM_Node& child, const DOM_Node& parent)
  {
      unsigned short i = 0;
      if (child.getParentNode() != parent) return -1;
      for(DOM_Node node = child; node!= null; node=node.getPreviousSibling()) {
          i++;
      }
      return i;
  }
  
  void RangeImpl::validateNode(DOM_Node& node)
  {
      if( fDetached) {
          throw DOM_DOMException(
              DOM_DOMException::INVALID_STATE_ERR, null);
      }
      
      if ( !isValidAncestorType(node)) {
          throw DOM_RangeException(
              DOM_RangeException::INVALID_NODE_TYPE_ERR, null);
      }
  }
  
  
  DOM_Node RangeImpl::commonAncestorOf(DOM_Node& pointA, DOM_Node& pointB) 
  {
      if (fDetached) 
              throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null);
  
      if (pointA.getOwnerDocument() != pointB.getOwnerDocument())
          throw DOM_DOMException( DOM_DOMException::WRONG_DOCUMENT_ERR, null );
  
      //if the containers are same then it itself is its common ancestor.
      if (pointA == pointB)
          return pointA; 
  
      typedef RefVectorOf<NodeImpl> VectorNodes;
      VectorNodes* startV= new VectorNodes(1, false);
      DOM_Node node;
  
      for (node=fStartContainer; node != null; node=node.getParentNode()) 
      {
          startV->addElement(node.fImpl);
      }
      VectorNodes* endV = new VectorNodes(1, false);
      for (node=fEndContainer; node != null; node=node.getParentNode()) 
      {
          endV->addElement(node.fImpl);
      }
  
      int s = startV->size()-1;
      int e = endV->size()-1;
   
      NodeImpl* commonAncestor;
      
      while (s>=0 && e>=0) {
          if (startV->elementAt(s) == endV->elementAt(e)) {
              commonAncestor = startV->elementAt(s);
          }
          else  break;
          --s;
          --e;
      }
      
      delete startV;
      delete endV;
       
      return DOM_Node(commonAncestor);
  }
  
  void RangeImpl::checkIndex(DOM_Node& node, unsigned int offset)
  {
      validateNode(node);
  
      if (offset < 0) {
          throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null );
      }
      
      short type = node.getNodeType();
      
      if((type == DOM_Node::TEXT_NODE
          || type == DOM_Node::CDATA_SECTION_NODE
          || type == DOM_Node::COMMENT_NODE
          || type == DOM_Node::PROCESSING_INSTRUCTION_NODE)) {
          if (offset > node.getNodeValue().length())
              throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null );
          else  return;
      }
      
      DOM_Node child = node.getFirstChild();
      unsigned int i = 0;
      for (; child != null; i++) {
          child = child.getNextSibling();
      }
      if (i < offset) {
          throw DOM_DOMException( DOM_DOMException::INDEX_SIZE_ERR, null );
      }
      
  }
  
  DOM_Node RangeImpl::nextNode(const DOM_Node& node, bool visitChildren) {
      
      if (node == null) return null;
      
      DOM_Node result;
      if (visitChildren) {
          result = node.getFirstChild();
          if (result != null) {
              return result;
          }
      }
      
      // if hasSibling, return sibling
      result = node.getNextSibling();
      if (result != null) {
          return result;
      }
      
      
      // return parent's 1st sibling.
      DOM_Node parent = node.getParentNode();
      
  
      while ( (parent != null) && (parent != fDocument) )
      {
          result = parent.getNextSibling();
          if (result != null) {
              return result;
          } else {
              parent = parent.getParentNode();
              if (parent == fEndContainer) return parent;
  
          }
          
      }
      // end of list, return null
      return null;            
  }
  
  
  /** This is the master traversal function which is used by
  *  both extractContents and cloneContents().
  */
  DOM_DocumentFragment RangeImpl::traverseContents(TraversalType trvType)
  {
  
      if (fDetached) 
              throw DOM_DOMException(DOM_DOMException::INVALID_STATE_ERR, null);
      
      if (fStartContainer == null || fEndContainer == null) {
          return DOM_DocumentFragment(); // REVIST: Throw exception?
      }
      
      DOM_DocumentFragment frag = fDocument.createDocumentFragment() ;
      
      DOM_Node current = fStartContainer;
      DOM_Node cloneCurrent = null;
      DOM_Node cloneParent = null;
      DOM_Node partialNode = null;
      int partialInt = START;
      
      // if same container, simplify case
      if (fStartContainer == fEndContainer) {
          if (fStartOffset == fEndOffset) { // eg collapsed
              return frag; // REVIST: what is correct re spec?
          }
          if (fStartContainer.getNodeType() == DOM_Node::TEXT_NODE) {
              cloneCurrent = fStartContainer.cloneNode(false);
              cloneCurrent.setNodeValue(
                  cloneCurrent.getNodeValue().substringData(fStartOffset, fEndOffset));
              if (trvType == EXTRACT_CONTENTS) {
                  ((DOM_Text &)current).deleteData(fStartOffset, fEndOffset-fStartOffset);
              }
              frag.appendChild(cloneCurrent);
          } else {
              current = current.getFirstChild();
              unsigned int i = 0;
              for(i = 0; i < fStartOffset && current != null; i++) {
                  current=current.getNextSibling();
              }
              unsigned int n = fEndOffset-fStartOffset;
              for(i = 0; i < n && current != null ;i++) {
                  DOM_Node newCurrent=current.getNextSibling();
                  
                  if (trvType == CLONE_CONTENTS) {
                      cloneCurrent = current.cloneNode(true);
                      frag.appendChild(cloneCurrent);
                  } else
                      if (trvType == EXTRACT_CONTENTS) {
                          frag.appendChild(current);
                      }
                      current = newCurrent;
              }
          }
          if (trvType == EXTRACT_CONTENTS ) {
              collapse(true);
          }
          return frag;
      }
      
      //***** END SIMPLE CASE ****
     
  
      DOM_Node root = getCommonAncestorContainer();
      DOM_Node parent = null;
      // go up the start tree...
      current = fStartContainer;
  
      bool endAtRoot = false;
      
      //REVIST: Always clone TEXT_NODE's?
      if (current.getNodeType() == DOM_Node::TEXT_NODE) {
          cloneCurrent = current.cloneNode(false);
          cloneCurrent.setNodeValue(
              ((DOM_Text&)cloneCurrent).getNodeValue().substringData(fStartOffset, current.getNodeValue().length() - fStartOffset));
          if (trvType == EXTRACT_CONTENTS) {
              ((DOM_Text&)current).deleteData(fStartOffset, current.getNodeValue().length()-fStartOffset);
          }
      } else {
          current = current.getFirstChild();
          for(unsigned int i = 0; i < fStartOffset && current != null; i++) {
              current=current.getNextSibling();
          }
          // current is now at the offset.
          if (current==null) { //"after"
              current = fStartContainer;
          }
          
          if (trvType == CLONE_CONTENTS) {
              cloneCurrent = current.cloneNode(true);
          } else if (trvType == EXTRACT_CONTENTS ) {
                  cloneCurrent = current;
          }
      }
      
      DOM_Node startRoot = null;
      DOM_Node endRoot = null;
      parent = null;
      
  
      if (root == fEndContainer) {
          if (fStartContainer.getParentNode() == fEndContainer) { 
              //a unique situation when start and end are partial under the same pass
              DOM_Node endNode = fEndContainer.getFirstChild();
              for (unsigned int i = 0; 
                  i <= fEndOffset-2; 
                  i++, endNode = endNode.getNextSibling());
              
              if (cloneParent == null)
                  cloneParent = root.cloneNode(false);
              
              cloneParent.appendChild(cloneCurrent); //clone the node from above
              
              for (current= current.getNextSibling(); 
                  current != null, current != endNode.getNextSibling(); 
                  current=current.getNextSibling()) {
                  if (trvType == CLONE_CONTENTS) {
                      cloneCurrent = current.cloneNode(true);
                      cloneParent.appendChild(cloneCurrent);
                  } else if (trvType == EXTRACT_CONTENTS) {
                          cloneParent.appendChild(current);
                  }
              }
              if (trvType == EXTRACT_CONTENTS) {
                  collapse(true);
              }
              frag.appendChild(cloneParent);
              return frag;
          }
      }
  
      // going up in a direct line from boundary point
      // through parents to the common ancestor,
      // all these nodes are partially selected, and must
      // be cloned.
      while (current != root) {
          parent = current.getParentNode();
          
          if (parent == root) {
              cloneParent = frag;
              startRoot = current;
          } else {
              //check if (parent == null) case too
              cloneParent = parent.cloneNode(false);
              if (partialNode==null && parent != root) {
                  partialNode = parent;
                  partialInt = AFTER;
              }
              
          }
          
          // The children to the "right" of the "ancestor hierarchy"
          // are "fully-selected".
          DOM_Node next = null;
          
          //increment to the next sibling BEFORE doing the appendChild
          current = current.getNextSibling();
          //do this appendChild after the increment above.
          cloneParent.appendChild(cloneCurrent);
          
          while (current != null) {
              next = current.getNextSibling();
              
              if (current != null && parent != root) {
                  if (trvType == CLONE_CONTENTS) {
                      cloneCurrent = current.cloneNode(true);
                      cloneParent.appendChild(cloneCurrent);
                  } else
                      if (trvType == EXTRACT_CONTENTS) {
                          cloneParent.appendChild(current);
                      }
              }
              current = next;
          }
          
          current = parent;
          cloneCurrent = cloneParent;
      }
      
      // go up the end tree...
      current = fEndContainer;
      
      if (current.getNodeType() == DOM_Node::TEXT_NODE) {
          cloneCurrent = current.cloneNode(false);
          cloneCurrent.setNodeValue(
              (cloneCurrent.getNodeValue()).substringData(0,fEndOffset));
          if (trvType == EXTRACT_CONTENTS) {
              ((DOM_Text&)current).deleteData(0, fEndOffset);
          }
      } else {
          if (fEndOffset == 0) { // "before"
              current = fEndContainer;
          }
          else {
              current = current.getFirstChild();
              for(unsigned int i = 1; i < fEndOffset && current != null; i++) {
                  current=current.getNextSibling();
              }
              if (current==null) { // REVIST: index-out-of-range what to do?
                  current = fEndContainer.getLastChild();
              }
          }
          if (trvType == CLONE_CONTENTS) {
              cloneCurrent = current.cloneNode(true);
          } else
              if (trvType == EXTRACT_CONTENTS ) {
                  cloneCurrent = current;
              }
      }
      
      while (current != root && current != null) {
          parent = current.getParentNode();
          if (parent == root) {
              cloneParent = frag;
              endRoot = current;
          } else {
              cloneParent = parent.cloneNode(false);
              if (partialNode==null && parent != root) {
                  partialNode = parent;
                  partialInt = BEFORE;
              }
          }
          
          DOM_Node holdCurrent = current;
          
          current = parent.getFirstChild();
          
          cloneParent.appendChild(cloneCurrent);
          
          DOM_Node next = null;
          while (current != holdCurrent && current != null) {
              next = current.getNextSibling();
              // The leftmost children are fully-selected
              // and are removed, and appended, not cloned.
              if (current != null && parent != root) {
                  if (trvType == CLONE_CONTENTS) {
                      cloneCurrent = current.cloneNode(true);
                      cloneParent.appendChild(cloneCurrent);
                  } else
                      if (trvType == EXTRACT_CONTENTS) {
                          //cloneCurrent = current;
                          cloneParent.appendChild(current);
                      }
              }
              current = next;
          }
          
          current = parent;
          cloneCurrent = cloneParent;
          
      }
      
      // traverse the "fully-selected" middle...
      DOM_Node clonedPrevious = frag.getLastChild();
      current = endRoot.getPreviousSibling();
      DOM_Node prev = null;
      while (current != startRoot && current != null) {
          prev = current.getPreviousSibling();
          
          if (trvType == CLONE_CONTENTS) {
              cloneCurrent = current.cloneNode(true);
          } else
              if (trvType == EXTRACT_CONTENTS) {
                  cloneCurrent = current;
              }
              
              frag.insertBefore(cloneCurrent, clonedPrevious);
              
              current = prev;
              clonedPrevious = cloneCurrent;
      }
      
      // collapse the range...
      if (trvType == EXTRACT_CONTENTS ) {
          if (partialNode == null) {
              collapse(true);
          } else
              if (partialInt == AFTER) {
                  setStartAfter(partialNode);
                  setEndAfter(partialNode);
              }
              else if (partialInt == BEFORE) {
                  setStartBefore(partialNode);
                  setEndBefore(partialNode);
              }
      }
  
      
      return frag;
  }
  
  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->readOnly()) {
              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->readOnly()) {
              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)) {
              if (( node->getParentNode()->getNodeType() == DOM_Node::DOCUMENT_FRAGMENT_NODE) )
                  return; //if the node's up in the heirarchy and its parent is doc-frag ignore
              DOM_Node tpNode(node->getParentNode());
              setStartContainer( tpNode );
              fStartOffset = indexOf( tNode, tpNode)-1;
          }
          if (isAncestorOf(node, fEndContainer)) {
              if (( node->getParentNode()->getNodeType() == DOM_Node::DOCUMENT_FRAGMENT_NODE))
                  return;
              DOM_Node tpNode(node->getParentNode());
              setEndContainer( tpNode );
              fEndOffset = indexOf( tNode, tpNode)-1;
          }
      }
      
  }
  
  void RangeImpl::updateRangeForInsertedNode(NodeImpl* node) {
      if (node == null) return;
      
      if (node->getParentNode() == fStartContainer.fImpl) {
          unsigned int index = indexOf(DOM_Node(node), fStartContainer) -1;
          if (index < fStartOffset) {
              fStartOffset++;
          }
      }
      
      if (node->getParentNode() == fEndContainer.fImpl) {
          unsigned int index = indexOf(DOM_Node(node), fEndContainer);
          //if index is equal then the text is inserted before the end of 
          //range so should get included in the range
          
          if (index <= fEndOffset) {
              fEndOffset++;
          }
      }
  }
  
  
  void RangeImpl::updateSplitInfo(TextImpl* oldNode, TextImpl* startNode)
  {
      if (startNode == null) return;
      
      DOM_Text oldText(oldNode);
      DOM_Text newText(startNode);
      unsigned int oldStartOffset;
  
      if (fStartContainer == oldText) {
          oldStartOffset = fStartOffset;
          fStartContainer = newText;
          fStartOffset = 0;
          
          if (fEndContainer == oldText) {
              fEndContainer = newText;
              fEndOffset = fEndOffset - oldStartOffset;
          }
      }
  }
  
  
  
  
  
  
  1.1                  xml-xerces/c/src/dom/RangeImpl.hpp
  
  Index: RangeImpl.hpp
  ===================================================================
  #ifndef RangeImpl_HEADER_GUARD_
  #define RangeImpl_HEADER_GUARD_
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
   /*
   * $Id: RangeImpl.hpp,v 1.1 2000/07/28 01:33:32 aruna1 Exp $
   */
  
  
  
  #include "DOM_Node.hpp"
  #include "RefCountedImpl.hpp"
  #include "DOM_Range.hpp"
  #include "DOM_Text.hpp"
  #include "DOM_Document.hpp"
  #include <util/RefVectorOf.hpp>
  
  
  typedef RefVectorOf<RangeImpl> Ranges;
   
  class CDOM_EXPORT RangeImpl : public RefCountedImpl {
  public:    
      //c'tor
      RangeImpl(DOM_Document doc);
      RangeImpl(const RangeImpl& other);
  
      //d'tor
      ~RangeImpl();
  
      //referencing related functions
      virtual void                unreferenced();
      
  
      //getter functions
      DOM_Node&    getStartContainer();
      unsigned    int getStartOffset();
      DOM_Node&    getEndContainer();
      unsigned int getEndOffset();
      
      
      
      void        collapse(bool toStart);
      bool        getCollapsed();
  
      void        setStartBefore(DOM_Node& node);
      void        setStartAfter(DOM_Node& node);
      void        setEndBefore(DOM_Node& node);
      void        setEndAfter(DOM_Node& node);
  
      void        setStart(DOM_Node& node, unsigned int offset);
      void        setEnd(DOM_Node& node, unsigned int offset);
  
      void        selectNode(DOM_Node& node);
      void        selectNodeContents(DOM_Node& node);
     
      short       compareBoundaryPoints(DOM_Range::CompareHow how, RangeImpl* range);
     
      void        detach();
     
      void        deleteContents();
      
      RangeImpl*  cloneRange();
      DOMString   toString();    
  
      DOM_Document getDocument();
      void        surroundContents(DOM_Node& node);
      DOM_DocumentFragment extractContents();
      DOM_DocumentFragment cloneContents();
      void        insertNode(DOM_Node& newNode);
      const DOM_Node&    getCommonAncestorContainer();
  
      // functions to inform all existing valid ranges about a change
      void updateSplitInfo(TextImpl* oldNode, TextImpl* startNode);
      void updateRangeForInsertedNode(NodeImpl* node);
      void receiveReplacedText(NodeImpl* node);
      void updateRangeForDeletedText(DOM_Node& node, unsigned int offset, int count);
      void updateRangeForDeletedNode(NodeImpl* node);
  
  private:
      enum TraversalType {
          EXTRACT_CONTENTS = 1,
          CLONE_CONTENTS   = 2
      };
  
      enum TraversePoint {
          BEFORE  = -1,    
          START   = 0,
          AFTER   = 1
      };
  
      //setter functions
      void        setStartContainer(const DOM_Node& node); 
      void        setStartOffset(unsigned int offset) ;
      void        setEndContainer(const DOM_Node& node);
      void        setEndOffset(unsigned int offset) ;
      void        setCommonAncestorContainer(const DOM_Node& node) ;
  
      //misc functions
      void        validateNode(DOM_Node& node);
      bool        isValidAncestorType(DOM_Node& node);
      void        checkIndex(DOM_Node& node, unsigned int offset);
      static bool isAncestorOf(const DOM_Node& a, const DOM_Node& b);
      
      unsigned short indexOf(const DOM_Node& child, const DOM_Node& parent);
  
      DOM_Node    commonAncestorOf(DOM_Node& pointA, DOM_Node& pointB);
      DOM_Node    nextNode(const DOM_Node& node, bool visitChildren);
      DOM_DocumentFragment traverseContents(TraversalType type);
      void        checkReadOnly(DOM_Node& start, DOM_Node& end, 
                      unsigned int starOffset, unsigned int endOffset);
      void        recurseTreeAndCheck(DOM_Node& start, DOM_Node& end);
      DOM_Node    removeChild(DOM_Node& parent, DOM_Node& child);
  
     
      //private data 
      DOM_Node        fStartContainer;
      unsigned int    fStartOffset;
      DOM_Node        fEndContainer;
      unsigned int    fEndOffset;
      bool            fCollapsed;
      DOM_Node        fCommonAncestorContainer;
      DOM_Document    fDocument;
      bool            fDetached;
      
      DOM_Node        fRemoveChild;
      
  };
  
  #endif
  
  
  
  1.8       +9 -26     xml-xerces/c/tests/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/tests/Makefile.in,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Makefile.in	2000/05/15 20:46:10	1.7
  +++ Makefile.in	2000/07/28 01:33:39	1.8
  @@ -54,35 +54,8 @@
   # <http://www.apache.org/>.
   # 
   #
  -# $Log: Makefile.in,v $
  -# Revision 1.7  2000/05/15 20:46:10  aruna1
  -# Unix related changes in for NodeIDMap
  +# $Id: Makefile.in,v 1.8 2000/07/28 01:33:39 aruna1 Exp $
   #
  -# Revision 1.6  2000/02/29 02:19:11  rahulj
  -# No more compilation errors under HPUX 11.0. We do not build
  -# DOMMemTest as it crashes the aCC compiler.
  -#
  -# Revision 1.5  2000/02/26 07:20:17  rahulj
  -#  - The threading tests now work on HPUX.
  -#  - Under HPUX 10.20 we do no build DOMMemTest and DOMTest.
  -#    It crashes the compiler.
  -#  - One could not write more worse makefiles than what exists for the
  -#    tests. Hopefully, I will get bugged enough to fix them oneday.
  -#
  -# Revision 1.4  2000/02/18 22:51:39  abagchi
  -# Added Traversal
  -#
  -# Revision 1.3  2000/02/17 20:18:20  abagchi
  -# Added Encoding Test
  -#
  -# Revision 1.2  2000/02/06 07:48:34  rahulj
  -# Year 2K copyright swat.
  -#
  -# Revision 1.1  2000/01/31 22:21:53  aruna1
  -# initial checkin
  -#
  -#
  -#
   
   DOMIDTest_DIR=DOM/DOMIDTest
   DOMMemTest_DIR=DOM/DOMMemTest
  @@ -90,6 +63,7 @@
   Traversal_DIR=DOM/Traversal
   ThreadTest_DIR=ThreadTest
   EncodingTest_DIR=EncodingTest
  +DOMRange_DIR=DOM/RangeTest
   
   LIB_DIR=${XERCESCROOT}/lib
   
  @@ -107,7 +81,7 @@
         all:	domtest threadtest encodingtest traversal
     endif
   else
  -    all:	domidtest dommemtest domtest threadtest encodingtest traversal
  +    all:	domidtest dommemtest domtest threadtest encodingtest traversal rangetest
   endif
   
   domidtest:
  @@ -134,6 +108,10 @@
   	@echo Building "Traversal"
   	cd $(Traversal_DIR) ; $(MAKE) $(MAKE_FLAGS) ; cd ..
   
  +rangetest:
  +	@echo Building "Range"
  +	cd $(DOMRange_DIR) ; $(MAKE) $(MAKE_FLAGS) ; cd ..
  +
   clean:
   	cd $(DOMIDTest_DIR) && $(MAKE) $@ && cd ..
   	cd $(DOMMemTest_DIR) && $(MAKE) $@ && cd ..
  @@ -141,6 +119,7 @@
   	cd $(ThreadTest_DIR) && $(MAKE) $@ && cd ..
   	cd $(EncodingTest_DIR) && $(MAKE) $@ && cd ..
   	cd $(Traversal_DIR) && $(MAKE) $@ && cd ..
  +	cd $(DOMRange_DIR) && $(MAKE) $@ && cd ..
   
   distclean:
   	cd $(DOMIDTest_DIR) && $(MAKE) $@ && cd ..
  @@ -149,6 +128,7 @@
   	cd $(ThreadTest_DIR) && $(MAKE) $@ && cd ..
   	cd $(EncodingTest_DIR) && $(MAKE) $@ && cd ..
   	cd $(Traversal_DIR) && $(MAKE) $@ && cd ..
  +	cd $(DOMRange_DIR) && $(MAKE) $@ && cd ..
   	rm -f Makefile config.cache config.log config.status
   	rm -f *~ core
   
  
  
  
  1.9       +2 -1      xml-xerces/c/tests/configure.in
  
  Index: configure.in
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/tests/configure.in,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- configure.in	2000/06/03 00:01:07	1.8
  +++ configure.in	2000/07/28 01:33:39	1.9
  @@ -1,4 +1,4 @@
  -# $Id: configure.in,v 1.8 2000/06/03 00:01:07 aruna1 Exp $
  +# $Id: configure.in,v 1.9 2000/07/28 01:33:39 aruna1 Exp $
   #
   #
   
  @@ -72,6 +72,7 @@
   DOM/DOMMemTest/Makefile \
   DOM/Traversal/Makefile \
   EncodingTest/Makefile \
  +DOM/RangeTest/Makefile \
   ThreadTest/Makefile])
   
   echo
  
  
  
  1.1                  xml-xerces/c/tests/DOM/RangeTest/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  #
  # The Apache Software License, Version 1.1
  # 
  # Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  # reserved.
  # 
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions
  # are met:
  # 
  # 1. Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer. 
  # 
  # 2. Redistributions in binary form must reproduce the above copyright
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  # 
  # 3. The end-user documentation included with the redistribution,
  #    if any, must include the following acknowledgment:  
  #       "This product includes software developed by the
  #        Apache Software Foundation (http://www.apache.org/)."
  #    Alternately, this acknowledgment may appear in the software itself,
  #    if and wherever such third-party acknowledgments normally appear.
  # 
  # 4. The names "Xerces" and "Apache Software Foundation" must
  #    not be used to endorse or promote products derived from this
  #    software without prior written permission. For written 
  #    permission, please contact apache\@apache.org.
  # 
  # 5. Products derived from this software may not be called "Apache",
  #    nor may "Apache" appear in their name, without prior written
  #    permission of the Apache Software Foundation.
  # 
  # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  # SUCH DAMAGE.
  # ====================================================================
  # 
  # This software consists of voluntary contributions made by many
  # individuals on behalf of the Apache Software Foundation, and was
  # originally based on software copyright (c) 1999, International
  # Business Machines, Inc., http://www.ibm.com .  For more information
  # on the Apache Software Foundation, please see
  # <http://www.apache.org/>.
  # 
  #
  # $Id: Makefile.in,v 1.1 2000/07/28 01:33:39 aruna1 Exp $
  #
  #
  
  ###################################################################
  #                    IMPORTANT NOTE                               #
  ###################################################################
  # If you are going to do the OS390BATCH build, make sure you have #
  # the OS390BATCH environment variable set.                        #
  #                                                                 #
  #   export OS390BATCH=1                                           #
  #                                                                 #
  ###################################################################
  
  PLATFORM = @platform@
  COMPILER = @compiler@
  CXXFLAGS = @cxxflags@
  CFLAGS = @cflags@
  PREFIX = @prefix@
  OSVER = @osver@
  LIBS = @libs@
  CC = @compiler@
  
  include ../../../version.incl
  include ../../Makefile.incl
  
  APP_NAME=RangeTest
  APP_DIR=DOM/RangeTest
  
  OUTDIR= ${XERCESCROOT}/tests/${APP_DIR}
  EXEC=	${XERCESCROOT}/bin
  OBJS=	${OUTDIR}/RangeTest.o
  SRC=	${XERCESCROOT}/tests/${APP_DIR}
  HEADER_FILES=
  INCLUDE = ${INCLUDES}
  
  ## OS390BATCH
  ifeq (${OS390BATCH},1)
  BATCH_TARGET= "//'${LOADMOD}(${APP_NAME})'"
  all: makedir ${BATCH_TARGET}
  else
  all: makedir ${EXEC}/${APP_NAME}
  endif
  
  makedir:
  	-mkdir -p $(OUTDIR)
  
  ${EXEC}/${APP_NAME}: ${OBJS}
  	${LINK} ${PLATFORM_LIB_LINK_OPTIONS} ${OBJS} -o $@ ${LIBRARY_SEARCH_PATHS} ${LIBRARY_NAMES} ${EXTRA_LINK_OPTIONS} 
  
  ${BATCH_TARGET}: ${OBJS}
  	${LINK} ${PLATFORM_LIB_LINK_OPTIONS} ${OBJS} -o $@ ${LIBRARY_SEARCH_PATHS} ${LIBRARY_NAMES} ${EXTRA_LINK_OPTIONS} 
  
  $(OUTDIR)/RangeTest.o: ${SRC}/RangeTest.cpp ${HEADER_FILES}
  	${CC} ${CMP} $(INCLUDE) -o $(OUTDIR)/RangeTest.o ${SRC}/RangeTest.cpp
  
  clean:
  	rm -f ${OBJS} ${EXEC}/${APP_NAME}
  
  distclean:	clean
  	rm -f Makefile
  
  
  
  1.1                  xml-xerces/c/tests/DOM/RangeTest/RangeTest.cpp
  
  Index: RangeTest.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  
  /**
   * $Id: RangeTest.cpp,v 1.1 2000/07/28 01:33:39 aruna1 Exp $
   */
  
  
  /** This RangeTest tests all of the cases delineated as examples
   *  in the DOM Level 2 Range specification, and a few others.
   *  <p>These do not by any means completely test the API and 
   *  corner cases. 
   */
  
  #include <stdio.h>
  #include <string.h>
  #include <dom/DOM.hpp>
  #include <dom/DomMemDebug.hpp>
  #include <parsers/DOMParser.hpp>
  #include <util/PlatformUtils.hpp>
  #include <util/XMLException.hpp>
  #include <util/XMLString.hpp>
  #include <dom/DOM_Range.hpp>
  #include <dom/DOM_XMLDecl.hpp>
  #include <framework/MemBufInputSource.hpp>
  
  
  #define TASSERT(c) tassert((c), __FILE__, __LINE__)
  
  void tassert(bool c, char *file, int line)
  {
      if (!c)
          printf("Failure.  Line %d,   file %s\n", line, file);
  };
  
  
  #define TESTPROLOG entryMemState = DomMemDebug();
  
  #define TESTEPILOG    exitMemState = DomMemDebug(); \
      if (entryMemState != exitMemState) { \
          printf(" Memory leak at line %d, file %s:  ", __LINE__, __FILE__);  \
          exitMemState.printDifference(entryMemState); \
      }
  
  
  #define EXCEPTION_TEST(operation, expected_exception)               \
  {                                                                   \
      try {                                                           \
      operation;                                                      \
      printf(" Error: no exception thrown at line %d\n", __LINE__);   \
  }                                                                   \
      catch (DOM_DOMException &e) {                                       \
      if (e.code != expected_exception)                       \
      printf(" Wrong exception code: %d at line %d\n", e.code, __LINE__); \
  }                                                                 \
      catch (...)   {                                                 \
      printf(" Wrong exception thrown at line %d\n", __LINE__);       \
  }                                                                   \
  }
  
  int  main()
  {
      DomMemDebug     entryMemState, exitMemState;
  
  	try {
  		XMLPlatformUtils::Initialize();
  	}
  	catch (const XMLException& toCatch) {
          char *pMessage = XMLString::transcode(toCatch.getMessage());
          fprintf(stderr, "Error during XMLPlatformUtils::Initialize(). \n"
                          "  Message is: %s\n", pMessage);
          delete [] pMessage;
          return -1;
      }
  
      /*
      Range tests include testing of
      
      createRange
  
      setStart, setStartBefore. setStartAfter, 
      setEnd, setEndBefore. setEndAfter
      getStartContainer, getStartOffset
      getEndContainer, getEndOffset    
      getCommonAncestorContainer
      selectNode
      selectNodeContents
      insertNode
      deleteContents
      collapse
      getCollapsed
      surroundContents
      compareBoundaryPoints
      cloneRange
      cloneContents
      extractContents
      toString
      detach
      */  
      {
          
          {
              DOM_Document    doc = DOM_Document::createDocument();
              //Creating a root element
              DOM_Element     root = doc.createElement("Body");
              doc.appendChild(root);
              
              //Creating the siblings of root
              DOM_Element     E11 = doc.createElement("H1");
              root.appendChild(E11);
              
              DOM_Element     E12 = doc.createElement("P");
              root.appendChild(E12);
              
              //Attaching texts to siblings
              DOM_Text        textNode1 = doc.createTextNode("Title");
              E11.appendChild(textNode1);
              
              DOM_Text        textNode11 = doc.createTextNode("AnotherText");
              E11.appendChild(textNode11);
              
              DOM_Text        textNode2 = doc.createTextNode("Blah xyz");
              E12.appendChild(textNode2);
              
              DOM_Text     E210 = doc.createTextNode("insertedText");
              
              
          }
          
          
          TESTPROLOG;
          {
              //DOM Tree and some usable node creation
              DOM_Document    doc = DOM_Document::createDocument();
              //Creating a root element
              DOM_Element     root = doc.createElement("Body");
              doc.appendChild(root);
              
              //Creating the siblings of root
              DOM_Element     E11 = doc.createElement("H1");
              root.appendChild(E11);
              
              DOM_Element     E12 = doc.createElement("P");
              root.appendChild(E12);
              
              //Attaching texts to siblings
              DOM_Text        textNode1 = doc.createTextNode("Title");
              E11.appendChild(textNode1);
              
              DOM_Text        textNode11 = doc.createTextNode("AnotherText");
              E11.appendChild(textNode11);
              
              DOM_Text        textNode2 = doc.createTextNode("Blah xyz");
              E12.appendChild(textNode2);
              
              //experimental nodes
              DOM_Element     E120 = doc.createElement("Element1");
              DOM_Element     E121 = doc.createElement("Element2");
              DOM_Element     E122 = doc.createElement("Element3");
              DOM_Element     E311 = doc.createElement("SurroundNode1");
              
              DOM_Text     E210 = doc.createTextNode("insertedText");
              
              DOM_Node rt = doc.getDocumentElement();
              DOM_Range range = doc.createRange();
  
       
       
              //Tests start here
              // Initial dom tree looks like :
              // <Body><H1>Title</H1><P>Blah xyz</P>
              //i.e.,            Body
              //     _____________|______________
              //     |                           |
              //     H1                          P
              //     |                           |
              //    "Title"                    "Blah xyz"
  
    
              //test for start and end settings of a range
              range.setStart(rt.getFirstChild(), 0);
              TASSERT(range.getStartContainer() == rt.getFirstChild() );
              TASSERT(range.getStartOffset() == 0);
    
              range.setEnd(rt.getFirstChild(), 1);
              TASSERT(range.getEndContainer() == rt.getFirstChild() );
              TASSERT(range.getEndOffset() == 1);
  
  
              DOM_Node node = range.getCommonAncestorContainer();
              TASSERT(range.getCommonAncestorContainer() == rt.getFirstChild());
             
              //selection related test
              range.selectNode(rt.getLastChild());
              TASSERT(range.getStartContainer() == rt);
              TASSERT(range.getStartOffset() == 1);
              TASSERT(range.getEndContainer() == rt);
              TASSERT(range.getEndOffset() == 2);
  
              //insertion related tests
              range.insertNode(E120);
   
              //only end offset moves and new node gets into range as being inserted at boundary point
              TASSERT(range.getStartContainer() == rt);
              TASSERT(range.getStartOffset() == 1);
              TASSERT(range.getEndContainer() == rt);
              TASSERT(range.getEndOffset() == 3);
  
              range.insertNode(E121);
              //only end offset moves and new node gets into range as being inserted at boundary point
              TASSERT(range.getStartContainer() == rt);
              TASSERT(range.getStartOffset() == 1);
              TASSERT(range.getEndContainer() == rt);
              TASSERT(range.getEndOffset() == 4);
  
              rt.insertBefore(E122, rt.getFirstChild());
              //both offsets move as new node is not part of the range
              TASSERT(range.getStartContainer() == rt);
              TASSERT(range.getStartOffset() == 2);
              TASSERT(range.getEndContainer() == rt);
              TASSERT(range.getEndOffset() == 5);
  
              //changing selection
              range.selectNode(rt.getLastChild().getPreviousSibling());
              TASSERT(range.getStartContainer() == rt);
              TASSERT(range.getStartOffset() == 3);
              TASSERT(range.getEndContainer() == rt);
              TASSERT(range.getEndOffset() == 4);
  
              //deleting related tests
              range.deleteContents();
              TASSERT(rt.getLastChild().getPreviousSibling() == E121);
  
              range.setStart(rt.getFirstChild().getNextSibling().getFirstChild(), 2);
              TASSERT(range.getStartContainer() == rt.getFirstChild().getNextSibling().getFirstChild());
              TASSERT(range.getStartOffset() == 2);
            
              range.setEnd(rt.getFirstChild().getNextSibling().getFirstChild(), 4);
              TASSERT(range.getEndContainer() == rt.getFirstChild().getNextSibling().getFirstChild());
              TASSERT(range.getEndOffset() == 4);
  
              //inserting text between a text node
              range.insertNode(E210);
  
              //only end offset moves and new node gets into range as being inserted at boundary point
              TASSERT(range.getStartContainer() == rt.getFirstChild().getNextSibling().getLastChild().getPreviousSibling());
              TASSERT(range.getStartOffset() == 0);
              TASSERT(range.getEndContainer() == rt.getFirstChild().getNextSibling().getLastChild().getPreviousSibling());
              TASSERT(range.getEndOffset() == 2);
  
              //inserting element node before the selcted text node
              range.insertNode(E120);
              //only end offset moves and new node gets into range as being inserted at boundary point
              TASSERT(range.getStartContainer() == rt.getFirstChild().getNextSibling().getLastChild().getPreviousSibling());
              TASSERT(range.getStartOffset() == 0);
              TASSERT(range.getEndContainer() == rt.getFirstChild().getNextSibling().getLastChild().getPreviousSibling());
              TASSERT(range.getEndOffset() == 2);
  
             //checking the text replacment
              range.getStartContainer().setNodeValue("ReplacedText");
              //collapsed
              TASSERT(range.getCollapsed() == true);
  
              //the offsets are set to 0
              TASSERT(range.getStartOffset() == 0);
              TASSERT(range.getEndOffset() == 0);
         
              //changing the selection. Preparing for 'surround'
              range.setStart(range.getStartContainer().getParentNode(), 2);
              range.setEnd(range.getStartContainer(), 5);
              range.surroundContents(E311);          
                   
              //testing cloning            
              DOM_Range aRange = range.cloneRange();
  
              TASSERT(aRange.getStartContainer() == range.getStartContainer());
              TASSERT(aRange.getEndContainer() == range.getEndContainer());
              TASSERT(aRange.getStartOffset() == 2);
              TASSERT(aRange.getEndOffset() == 3);
              //changing the new ranges start
              aRange.setStart(aRange.getStartContainer().getFirstChild(), 1);
  
              //comparing the ranges
              short compVal = range.compareBoundaryPoints(DOM_Range::END_TO_END, aRange);
              TASSERT(compVal == 0); 
              compVal = range.compareBoundaryPoints(DOM_Range::START_TO_START, aRange);
              TASSERT(compVal == -1);
              compVal = range.compareBoundaryPoints(DOM_Range::START_TO_END, aRange);
              TASSERT(compVal == -1);
              compVal = range.compareBoundaryPoints(DOM_Range::END_TO_START, aRange);
              TASSERT(compVal == 1);
  
              //testing collapse
              //not collapsed
              TASSERT(range.getCollapsed() == false);
              TASSERT(range.getStartOffset() == 2);
              TASSERT(range.getEndOffset() == 3);
  
              
              //selectNodeContents 
              range.selectNodeContents(rt.getLastChild().getFirstChild());
              TASSERT(range.getStartContainer() == rt.getLastChild().getFirstChild());
              TASSERT(range.getEndContainer() == rt.getLastChild().getFirstChild());
              TASSERT(range.getStartOffset() == 0);
              TASSERT(range.getEndOffset() == 8);
              
              //testing collapse
              range.collapse(true); //collapse to start
              TASSERT(range.getCollapsed() == true);
              TASSERT(range.getStartOffset() == 0);
              TASSERT(range.getEndOffset() == 0);
              TASSERT(aRange.getEndOffset() == 3); //other range is unaffected
             
  
              // DOM Tree now looks like this
              //          <Body>
              //  |---------|----------|--------------|
              //  Element3  H1      Element2          P
              //            |                         |
              //  |------|-----------|             "Blah xyz"
              // "Ti" "insertedText" SurroundNode     
              //                     |
              //        |--------|---------------|
              //        Element1 "ReplacedText   "AnotherText"
  
              // range has H1 as start and end container and 2 as start and end offset. in collapsed state
              // aRange has "Ti" as start with 1 as start offset, H1 as end and 3 as end offset
  
  
         
              DOM_DocumentFragment docFrag = aRange.cloneContents();
              TASSERT( docFrag != 0);
              range.selectNode(rt.getFirstChild());
              TASSERT(range.getStartContainer() == rt); 
              
              //Testing toString()
              const char* str = aRange.toString().transcode();
              char* str2 = "iinsertedTextReplacedTextAnotherText";
              TASSERT(*str == *str2);
  
              //start and end before and after tests
              range.setStartBefore(rt.getFirstChild());
              TASSERT(range.getStartOffset() == 0);
              range.setEndBefore(rt.getFirstChild());
              TASSERT(range.getEndOffset() == 0);
              range.setStartAfter(rt.getLastChild());
              TASSERT(range.getStartOffset() == 4);
             
              range.setStartAfter(rt.getFirstChild());
              TASSERT(range.getStartOffset() == 1);
              
              range.setEndBefore(rt.getLastChild());
              TASSERT(range.getEndOffset() == 3);
              
              range.setEndAfter(rt.getLastChild());
              TASSERT(range.getEndOffset() == 4);
              
              //testing extract()
              DOM_DocumentFragment frag2 = range.extractContents();
              TASSERT( frag2 != 0);
              //detaching the other range
              aRange.detach();
              range.detach();
  
  
      }
      TESTEPILOG;
              
      
      } //creating the dom tree and tests
      
      
      //
      //  Print Final allocation stats for full test
      //
      DomMemDebug().print();
      
      // And call the termination method
      XMLPlatformUtils::Terminate();
      
      return 0;
  };