1/* 2 * (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) 5 * (C) 2001 Peter Kelly (pmk@post.com) 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25#ifndef Range_h 26#define Range_h 27 28#include "ExceptionCodePlaceholder.h" 29#include "FloatRect.h" 30#include "FragmentScriptingPermission.h" 31#include "IntRect.h" 32#include "RangeBoundaryPoint.h" 33#include <wtf/Forward.h> 34#include <wtf/RefCounted.h> 35#include <wtf/Vector.h> 36 37namespace WebCore { 38 39class ClientRect; 40class ClientRectList; 41class ContainerNode; 42class Document; 43class DocumentFragment; 44class FloatQuad; 45class Node; 46class NodeWithIndex; 47class Text; 48#if PLATFORM(IOS) 49class SelectionRect; 50class VisiblePosition; 51#endif 52 53class Range : public RefCounted<Range> { 54public: 55 static PassRefPtr<Range> create(Document&); 56 static PassRefPtr<Range> create(Document&, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset); 57 static PassRefPtr<Range> create(Document&, const Position&, const Position&); 58 static PassRefPtr<Range> create(ScriptExecutionContext&); 59#if PLATFORM(IOS) 60 // FIXME: Consider making this a static non-member, non-friend function. 61 static PassRefPtr<Range> create(Document&, const VisiblePosition&, const VisiblePosition&); 62#endif 63 ~Range(); 64 65 Document& ownerDocument() const { return const_cast<Document&>(m_ownerDocument.get()); } 66 67 Node* startContainer() const { return m_start.container(); } 68 int startOffset() const { return m_start.offset(); } 69 Node* endContainer() const { return m_end.container(); } 70 int endOffset() const { return m_end.offset(); } 71 72 Node* startContainer(ExceptionCode&) const; 73 int startOffset(ExceptionCode&) const; 74 Node* endContainer(ExceptionCode&) const; 75 int endOffset(ExceptionCode&) const; 76 bool collapsed(ExceptionCode&) const; 77 78 Node* commonAncestorContainer(ExceptionCode&) const; 79 static Node* commonAncestorContainer(Node* containerA, Node* containerB); 80 void setStart(PassRefPtr<Node> container, int offset, ExceptionCode& = ASSERT_NO_EXCEPTION); 81 void setEnd(PassRefPtr<Node> container, int offset, ExceptionCode& = ASSERT_NO_EXCEPTION); 82 void collapse(bool toStart, ExceptionCode&); 83 bool isPointInRange(Node* refNode, int offset, ExceptionCode&); 84 short comparePoint(Node* refNode, int offset, ExceptionCode&) const; 85 enum CompareResults { NODE_BEFORE, NODE_AFTER, NODE_BEFORE_AND_AFTER, NODE_INSIDE }; 86 CompareResults compareNode(Node* refNode, ExceptionCode&) const; 87 enum CompareHow { START_TO_START, START_TO_END, END_TO_END, END_TO_START }; 88 short compareBoundaryPoints(CompareHow, const Range* sourceRange, ExceptionCode&) const; 89 static short compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionCode&); 90 static short compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionCode&); 91 bool boundaryPointsValid() const; 92 bool intersectsNode(Node* refNode, ExceptionCode&); 93 void deleteContents(ExceptionCode&); 94 PassRefPtr<DocumentFragment> extractContents(ExceptionCode&); 95 PassRefPtr<DocumentFragment> cloneContents(ExceptionCode&); 96 void insertNode(PassRefPtr<Node>, ExceptionCode&); 97 String toString(ExceptionCode&) const; 98 99 String toHTML() const; 100 String text() const; 101 102 PassRefPtr<DocumentFragment> createContextualFragment(const String& html, ExceptionCode&); 103 104 void detach(ExceptionCode&); 105 PassRefPtr<Range> cloneRange(ExceptionCode&) const; 106 107 void setStartAfter(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION); 108 void setEndBefore(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION); 109 void setEndAfter(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION); 110 void selectNode(Node*, ExceptionCode& = ASSERT_NO_EXCEPTION); 111 void selectNodeContents(Node*, ExceptionCode&); 112 void surroundContents(PassRefPtr<Node>, ExceptionCode&); 113 void setStartBefore(Node*, ExceptionCode&); 114 115 const Position startPosition() const { return m_start.toPosition(); } 116 const Position endPosition() const { return m_end.toPosition(); } 117 void setStart(const Position&, ExceptionCode& = ASSERT_NO_EXCEPTION); 118 void setEnd(const Position&, ExceptionCode& = ASSERT_NO_EXCEPTION); 119 120 Node* firstNode() const; 121 Node* pastLastNode() const; 122 123 ShadowRoot* shadowRoot() const; 124 125 enum RangeInFixedPosition { 126 NotFixedPosition, 127 PartiallyFixedPosition, 128 EntirelyFixedPosition 129 }; 130 131 // Not transform-friendly 132 void textRects(Vector<IntRect>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const; 133 IntRect boundingBox() const; 134 135 // Transform-friendly 136 void textQuads(Vector<FloatQuad>&, bool useSelectionHeight = false, RangeInFixedPosition* = 0) const; 137 void getBorderAndTextQuads(Vector<FloatQuad>&) const; 138 FloatRect boundingRect() const; 139#if PLATFORM(IOS) 140 void collectSelectionRects(Vector<SelectionRect>&); 141#endif 142 143 void nodeChildrenChanged(ContainerNode&); 144 void nodeChildrenWillBeRemoved(ContainerNode&); 145 void nodeWillBeRemoved(Node*); 146 147 void textInserted(Node*, unsigned offset, unsigned length); 148 void textRemoved(Node*, unsigned offset, unsigned length); 149 void textNodesMerged(NodeWithIndex& oldNode, unsigned offset); 150 void textNodeSplit(Text* oldNode); 151 152 // Expand range to a unit (word or sentence or block or document) boundary. 153 // Please refer to https://bugs.webkit.org/show_bug.cgi?id=27632 comment #5 154 // for details. 155 void expand(const String&, ExceptionCode&); 156 157 PassRefPtr<ClientRectList> getClientRects() const; 158 PassRefPtr<ClientRect> getBoundingClientRect() const; 159 160#ifndef NDEBUG 161 void formatForDebugger(char* buffer, unsigned length) const; 162#endif 163 164 bool contains(const Range&) const; 165 166private: 167 explicit Range(Document&); 168 Range(Document&, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset); 169 170 void setDocument(Document&); 171 172 Node* checkNodeWOffset(Node*, int offset, ExceptionCode&) const; 173 void checkNodeBA(Node*, ExceptionCode&) const; 174 void checkDeleteExtract(ExceptionCode&); 175 bool containedByReadOnly() const; 176 int maxStartOffset() const; 177 int maxEndOffset() const; 178 179 enum ActionType { Delete, Extract, Clone }; 180 PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&); 181 static PassRefPtr<Node> processContentsBetweenOffsets(ActionType, PassRefPtr<DocumentFragment>, Node*, unsigned startOffset, unsigned endOffset, ExceptionCode&); 182 static void processNodes(ActionType, Vector<RefPtr<Node>>&, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode&); 183 enum ContentsProcessDirection { ProcessContentsForward, ProcessContentsBackward }; 184 static PassRefPtr<Node> processAncestorsAndTheirSiblings(ActionType, Node* container, ContentsProcessDirection, PassRefPtr<Node> clonedContainer, Node* commonRoot, ExceptionCode&); 185 186 Ref<Document> m_ownerDocument; 187 RangeBoundaryPoint m_start; 188 RangeBoundaryPoint m_end; 189}; 190 191PassRefPtr<Range> rangeOfContents(Node&); 192 193bool areRangesEqual(const Range*, const Range*); 194bool rangesOverlap(const Range*, const Range*); 195 196} // namespace 197 198#ifndef NDEBUG 199// Outside the WebCore namespace for ease of invocation from gdb. 200void showTree(const WebCore::Range*); 201#endif 202 203#endif 204