summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/dom/range.h
blob: 47e208f3b17d932778b5f715b81b414bd1a71d59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * (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, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
 * reserved.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_H_

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/range_boundary_point.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"

namespace blink {

class DOMRect;
class DOMRectList;
class ContainerNode;
class Document;
class DocumentFragment;
class ExceptionState;
class FloatQuad;
class Node;
class NodeWithIndex;
class Text;

class CORE_EXPORT Range final : public ScriptWrappable {
  DEFINE_WRAPPERTYPEINFO();

 public:
  static Range* Create(Document&);

  explicit Range(Document&);
  Range(Document& owner_document, const Position& start, const Position& end);
  Range(Document&,
        Node* start_container,
        unsigned start_offset,
        Node* end_container,
        unsigned end_offset);

  void Dispose();

  Document& OwnerDocument() const {
    DCHECK(owner_document_);
    return *owner_document_.Get();
  }
  Node* startContainer() const { return &start_.Container(); }
  unsigned startOffset() const { return start_.Offset(); }
  Node* endContainer() const { return &end_.Container(); }
  unsigned endOffset() const { return end_.Offset(); }

  bool collapsed() const { return start_ == end_; }
  bool IsConnected() const;

  Node* commonAncestorContainer() const;
  static Node* commonAncestorContainer(const Node* container_a,
                                       const Node* container_b);
  void setStart(Node* container,
                unsigned offset,
                ExceptionState& = ASSERT_NO_EXCEPTION);
  void setEnd(Node* container,
              unsigned offset,
              ExceptionState& = ASSERT_NO_EXCEPTION);
  void collapse(bool to_start);
  bool isPointInRange(Node* ref_node, unsigned offset, ExceptionState&) const;
  int16_t comparePoint(Node* ref_node, unsigned offset, ExceptionState&) const;
  enum CompareResults {
    NODE_BEFORE,
    NODE_AFTER,
    NODE_BEFORE_AND_AFTER,
    NODE_INSIDE
  };
  enum CompareHow { kStartToStart, kStartToEnd, kEndToEnd, kEndToStart };
  int16_t compareBoundaryPoints(unsigned how,
                                const Range* source_range,
                                ExceptionState&) const;
  static int16_t compareBoundaryPoints(Node* container_a,
                                       unsigned offset_a,
                                       Node* container_b,
                                       unsigned offset_b,
                                       ExceptionState&);
  static int16_t compareBoundaryPoints(const RangeBoundaryPoint& boundary_a,
                                       const RangeBoundaryPoint& boundary_b,
                                       ExceptionState&);
  bool BoundaryPointsValid() const;
  bool intersectsNode(Node* ref_node, ExceptionState&);
  void deleteContents(ExceptionState&);
  DocumentFragment* extractContents(ExceptionState&);
  DocumentFragment* cloneContents(ExceptionState&);
  void insertNode(Node*, ExceptionState&);
  String toString() const;

  String GetText() const;

  DocumentFragment* createContextualFragment(const String& html,
                                             ExceptionState&);

  void detach();
  Range* cloneRange() const;

  void setStartAfter(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
  void setEndBefore(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
  void setEndAfter(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
  void selectNode(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
  void selectNodeContents(Node*, ExceptionState&);
  static bool selectNodeContents(Node*, Position&, Position&);
  void surroundContents(Node*, ExceptionState&);
  void setStartBefore(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);

  const Position StartPosition() const { return start_.ToPosition(); }
  const Position EndPosition() const { return end_.ToPosition(); }
  void setStart(const Position&, ExceptionState& = ASSERT_NO_EXCEPTION);
  void setEnd(const Position&, ExceptionState& = ASSERT_NO_EXCEPTION);

  Node* FirstNode() const;
  Node* PastLastNode() const;

  // Not transform-friendly
  IntRect BoundingBox() const;

  // Transform-friendly
  void GetBorderAndTextQuads(Vector<FloatQuad>&) const;
  FloatRect BoundingRect() const;

  void NodeChildrenWillBeRemoved(ContainerNode&);
  void NodeWillBeRemoved(Node&);

  // They are special fixups only for sequential focus navigation
  // starting point.
  void FixupRemovedChildrenAcrossShadowBoundary(ContainerNode& container);
  void FixupRemovedNodeAcrossShadowBoundary(Node& node);

  void DidInsertText(const CharacterData&, unsigned offset, unsigned length);
  void DidRemoveText(const CharacterData&, unsigned offset, unsigned length);
  void DidMergeTextNodes(const NodeWithIndex& old_node, unsigned offset);
  void DidSplitTextNode(const Text& old_node);
  void UpdateOwnerDocumentIfNeeded();

  // Expand range to a unit (word or sentence or block or document) boundary.
  // Please refer to https://bugs.webkit.org/show_bug.cgi?id=27632 comment #5
  // for details.
  void expand(const String&, ExceptionState&);

  DOMRectList* getClientRects() const;
  DOMRect* getBoundingClientRect() const;

  static Node* CheckNodeWOffset(Node*, unsigned offset, ExceptionState&);

  void Trace(Visitor*) const override;

 private:
  void SetDocument(Document&);

  void CheckNodeBA(Node*, ExceptionState&) const;
  void CheckExtractPrecondition(ExceptionState&);
  bool HasSameRoot(const Node&) const;

  enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS };
  DocumentFragment* ProcessContents(ActionType, ExceptionState&);
  static Node* ProcessContentsBetweenOffsets(ActionType,
                                             DocumentFragment*,
                                             Node*,
                                             unsigned start_offset,
                                             unsigned end_offset,
                                             ExceptionState&);
  static void ProcessNodes(ActionType,
                           NodeVector&,
                           Node* old_container,
                           Node* new_container,
                           ExceptionState&);
  enum ContentsProcessDirection {
    kProcessContentsForward,
    kProcessContentsBackward
  };
  static Node* ProcessAncestorsAndTheirSiblings(ActionType,
                                                Node* container,
                                                ContentsProcessDirection,
                                                Node* cloned_container,
                                                Node* common_root,
                                                ExceptionState&);
  void UpdateSelectionIfAddedToSelection();
  void RemoveFromSelectionIfInDifferentRoot(Document& old_document);

  Member<Document> owner_document_;  // Cannot be null.
  RangeBoundaryPoint start_;
  RangeBoundaryPoint end_;

  friend class RangeUpdateScope;
};

CORE_EXPORT bool AreRangesEqual(const Range*, const Range*);

using RangeVector = HeapVector<Member<Range>>;

}  // namespace blink

#if DCHECK_IS_ON()
// Outside the blink namespace for ease of invocation from gdb.
void showTree(const blink::Range*);
#endif

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_H_