/* * This file is part of the DOM implementation for KDE. * * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) * (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2004 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * This file includes excerpts from the Document Object Model (DOM) * Level 2 Specification (Candidate Recommendation) * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved. * */ #ifndef _dom2_range_h_ #define _dom2_range_h_ #include <dom/dom_doc.h> #include <dom/dom_misc.h> namespace DOM { class DocumentFragment; class Node; class DOMString; class DocumentImpl; class RangeImpl; class DOMException; // Introduced in DOM Level 2: class RangeException { public: RangeException(unsigned short _code) { code = _code; } RangeException(const RangeException &other) { code = other.code; } RangeException & operator = (const RangeException &other) { code = other.code; return *this; } virtual ~RangeException() {} /** * An integer indicating the type of error generated. * */ enum RangeExceptionCode { BAD_BOUNDARYPOINTS_ERR = 1, INVALID_NODE_TYPE_ERR = 2, _EXCEPTION_OFFSET = 2000, _EXCEPTION_MAX = 2999 }; unsigned short code; }; class Range { friend class DocumentImpl; friend class Document; friend class RangeImpl; public: Range(); Range(const Document rootContainer); Range(const Range &other); Range(const Node startContainer, const long startOffset, const Node endContainer, const long endOffset); Range & operator = (const Range &other); ~Range(); /** * Node within which the range begins * */ Node startContainer() const; /** * Offset within the starting node of the range. * */ long startOffset() const; /** * Node within which the range ends * */ Node endContainer() const; /** * Offset within the ending node of the range. * */ long endOffset() const; /** * TRUE if the range is collapsed * */ bool collapsed() const; /** * Gets the common ancestor container of the range's two end-points. * Also sets it. * */ // ### BIC make const in the next release Node commonAncestorContainer(); /** * Sets the attributes describing the start of the range. * * @param refNode The <code> refNode </code> value. This parameter * must be different from <code> null </code> . * * @param offset The <code> startOffset </code> value. * * @return * * @exception RangeException * NULL_NODE_ERR: Raised if <code> refNode </code> is <code> null * </code> . * * INVALID_NODE_TYPE_ERR: Raised if <code> refNode </code> or an * ancestor of <code> refNode </code> is an Attr, Entity, * Notation, or DocumentType node. * * If an offset is out-of-bounds, should it just be fixed up or * should an exception be raised. * */ void setStart ( const Node &refNode, long offset ); /** * Sets the attributes describing the end of a range. * * @param refNode The <code> refNode </code> value. This parameter * must be different from <code> null </code> . * * @param offset The <code> endOffset </code> value. * * @return * * @exception RangeException * NULL_NODE_ERR: Raised if <code> refNode </code> is <code> null * </code> . * * INVALID_NODE_TYPE_ERR: Raised if <code> refNode </code> or an * ancestor of <code> refNode </code> is an Attr, Entity, * Notation, or DocumentType node. * */ void setEnd ( const Node &refNode, long offset ); /** * Sets the start position to be before a node * * @param refNode Range starts before <code> refNode </code> * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code> refNode * </code> is an Attr, Entity, Notation, or DocumentType node or * if <code> refNode </code> is a Document, DocumentFragment, * Attr, Entity, or Notation node. * */ void setStartBefore ( const Node &refNode ); /** * Sets the start position to be after a node * * @param refNode Range starts after <code> refNode </code> * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code> refNode * </code> is an Attr, Entity, Notation, or DocumentType node or * if <code> refNode </code> is a Document, DocumentFragment, * Attr, Entity, or Notation node. * */ void setStartAfter ( const Node &refNode ); /** * Sets the end position to be before a node. * * @param refNode Range ends before <code> refNode </code> * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code> refNode * </code> is an Attr, Entity, Notation, or DocumentType node or * if <code> refNode </code> is a Document, DocumentFragment, * Attr, Entity, or Notation node. * */ void setEndBefore ( const Node &refNode ); /** * Sets the end of a range to be after a node * * @param refNode Range ends after <code> refNode </code> . * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code> refNode * </code> is an Attr, Entity, Notation or DocumentType node or if * <code> refNode </code> is a Document, DocumentFragment, Attr, * Entity, or Notation node. * */ void setEndAfter ( const Node &refNode ); /** * Collapse a range onto one of its end-points * * @param toStart If TRUE, collapses the Range onto its start; if * FALSE, collapses it onto its end. * * @return * */ void collapse ( bool toStart ); /** * Select a node and its contents * * @param refNode The node to select. * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code> refNode * </code> is an Attr, Entity, Notation or DocumentType node or if * <code> refNode </code> is a Document, DocumentFragment, Attr, * Entity, or Notation node. * */ void selectNode ( const Node &refNode ); /** * Select the contents within a node * * @param refNode Node to select from * * @return * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if <code> refNode </code> or an * ancestor of <code> refNode </code> is an Attr, Entity, Notation * or DocumentType node. * */ void selectNodeContents ( const Node &refNode ); enum CompareHow { START_TO_START = 0, START_TO_END = 1, END_TO_END = 2, END_TO_START = 3 }; /** * Compare the end-points of two ranges in a document. * * @param how * * @param sourceRange * * @return -1, 0 or 1 depending on whether the corresponding * end-point of the Range is before, equal to, or after the * corresponding end-point of <code> sourceRange </code> . * * @exception DOMException * WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the * same document or document fragment. * */ short compareBoundaryPoints ( CompareHow how, const Range &sourceRange ); /** * @internal * not part of the DOM * * Compare the boundary-points of a range. * * Return true if the startContainer is before the endContainer, * or if they are equal. * Return false if the startContainer is after the endContainer. * */ bool boundaryPointsValid ( ); /** * Removes the contents of a range from the containing document or * document fragment without returning a reference to the removed * content. * * @return * * @exception DOMException * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the * content of the range is read-only or any of the nodes that * contain any of the content of the range are read-only. * */ void deleteContents ( ); /** * Moves the contents of a range from the containing document or * document fragment to a new DocumentFragment. * * @return A DocumentFragment containing the extracted contents. * * @exception DOMException * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the * content of the range is read-only or any of the nodes which * contain any of the content of the range are read-only. * * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be * extracted into the new DocumentFragment. * */ DocumentFragment extractContents ( ); /** * Duplicates the contents of a range * * @return A DocumentFragment containing contents equivalent to * those of this range. * * @exception DOMException * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be * extracted into the new DocumentFragment. * */ DocumentFragment cloneContents ( ); /** * Inserts a node into the document or document fragment at the * start of the range. * * @param newNode The node to insert at the start of the range * * @return * * @exception DOMException * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of * the start of the range is read-only. * * WRONG_DOCUMENT_ERR: Raised if <code> newNode </code> and the * container of the start of the Range were not created from the * same document. * * HIERARCHY_REQUEST_ERR: Raised if the container of the start of * the Range is of a type that does not allow children of the type * of <code> newNode </code> or if <code> newNode </code> is an * ancestor of the container . * * @exception RangeException * INVALID_NODE_TYPE_ERR: Raised if <code> node </code> is an * Attr, Entity, Notation, DocumentFragment, or Document node. * */ void insertNode ( const Node &newNode ); /** * Reparents the contents of the range to the given node and * inserts the node at the position of the start of the range. * * @param newParent The node to surround the contents with. * * @return * * @exception DOMException * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of * either end-point of the range is read-only. * * WRONG_DOCUMENT_ERR: Raised if <code> newParent </code> and the * container of the start of the Range were not created from the * same document. * * HIERARCHY_REQUEST_ERR: Raised if the container of the start of * the Range is of a type that does not allow children of the type * of <code> newParent </code> or if <code> newParent </code> is * an ancestor of the container or if <code> node </code> would * end up with a child node of a type not allowed by the type of * <code> node </code> . * * @exception RangeException * BAD_ENDPOINTS_ERR: Raised if the range partially selects a * non-text node. * * INVALID_NODE_TYPE_ERR: Raised if <code> node </code> is an * Attr, Entity, DocumentType, Notation, Document, or * DocumentFragment node. * */ void surroundContents ( const Node &newParent ); /** * Produces a new range whose end-points are equal to the * end-points of the range. * * @return The duplicated range. * */ Range cloneRange ( ); /** * Returns the contents of a range as a string. * * @return The contents of the range. * */ DOMString toString ( ); /** * @internal Not part of DOM */ DOMString toHTML ( ); /* Mozilla extension - only works for HTML documents. */ DocumentFragment createContextualFragment (DOMString &html); /** * Called to indicate that the range is no longer in use and that * the implementation may relinquish any resources associated with * this range. Subsequent calls to any methods or attribute getters * on this range will result in a DOMException being thrown with an * error code of INVALID_STATE_ERR. * */ void detach ( ); /** * not part of the DOM * TRUE if the range is detached * */ bool isDetached() const; /** * @internal * not part of the DOM */ Range(RangeImpl *i); RangeImpl *handle() const; bool isNull() const; protected: RangeImpl *impl; private: void throwException(int exceptioncode) const; }; bool operator==(const Range &, const Range &); inline bool operator!=(const Range &a, const Range &b) { return !(a == b); } // Used determine how to interpret the offsets used in DOM Ranges. inline bool offsetInCharacters(unsigned short type) { switch (type) { case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: return false; case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: return true; case Node::DOCUMENT_TYPE_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: assert(false); // should never be reached return false; } assert(false); // should never be reached return false; } } // namespace #endif