Bumping manifests a=b2g-bump
[gecko.git] / editor / libeditor / nsSelectionState.h
blob53b61093d3b19cfa01cf4c91373ac90732178a78
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef __selectionstate_h__
7 #define __selectionstate_h__
9 #include "nsCOMPtr.h"
10 #include "nsIDOMNode.h"
11 #include "nsINode.h"
12 #include "nsTArray.h"
13 #include "nscore.h"
15 class nsCycleCollectionTraversalCallback;
16 class nsIDOMCharacterData;
17 class nsIDOMRange;
18 class nsISelection;
19 class nsRange;
20 namespace mozilla {
21 namespace dom {
22 class Selection;
23 class Text;
27 /***************************************************************************
28 * class for recording selection info. stores selection as collection of
29 * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
30 * ranges since dom gravity will possibly change the ranges.
33 // first a helper struct for saving/setting ranges
34 struct nsRangeStore MOZ_FINAL
36 nsRangeStore();
38 private:
39 // Private destructor, to discourage deletion outside of Release():
40 ~nsRangeStore();
42 public:
43 void StoreRange(nsRange* aRange);
44 already_AddRefed<nsRange> GetRange();
46 NS_INLINE_DECL_REFCOUNTING(nsRangeStore)
48 nsCOMPtr<nsINode> startNode;
49 int32_t startOffset;
50 nsCOMPtr<nsINode> endNode;
51 int32_t endOffset;
54 class nsSelectionState
56 public:
58 nsSelectionState();
59 ~nsSelectionState();
61 void DoTraverse(nsCycleCollectionTraversalCallback &cb);
62 void DoUnlink() { MakeEmpty(); }
64 void SaveSelection(mozilla::dom::Selection *aSel);
65 nsresult RestoreSelection(nsISelection *aSel);
66 bool IsCollapsed();
67 bool IsEqual(nsSelectionState *aSelState);
68 void MakeEmpty();
69 bool IsEmpty();
70 protected:
71 nsTArray<nsRefPtr<nsRangeStore> > mArray;
73 friend class nsRangeUpdater;
76 class nsRangeUpdater
78 public:
80 nsRangeUpdater();
81 ~nsRangeUpdater();
83 void RegisterRangeItem(nsRangeStore *aRangeItem);
84 void DropRangeItem(nsRangeStore *aRangeItem);
85 nsresult RegisterSelectionState(nsSelectionState &aSelState);
86 nsresult DropSelectionState(nsSelectionState &aSelState);
88 // editor selection gravity routines. Note that we can't always depend on
89 // DOM Range gravity to do what we want to the "real" selection. For instance,
90 // if you move a node, that corresponds to deleting it and reinserting it.
91 // DOM Range gravity will promote the selection out of the node on deletion,
92 // which is not what you want if you know you are reinserting it.
93 nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
94 nsresult SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition);
95 nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
96 nsresult SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition);
97 void SelAdjDeleteNode(nsINode* aNode);
98 void SelAdjDeleteNode(nsIDOMNode *aNode);
99 nsresult SelAdjSplitNode(nsINode* aOldRightNode, int32_t aOffset,
100 nsINode* aNewLeftNode);
101 nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode);
102 nsresult SelAdjJoinNodes(nsINode* aLeftNode,
103 nsINode* aRightNode,
104 nsINode* aParent,
105 int32_t aOffset,
106 int32_t aOldLeftNodeLength);
107 nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode,
108 nsIDOMNode *aRightNode,
109 nsIDOMNode *aParent,
110 int32_t aOffset,
111 int32_t aOldLeftNodeLength);
112 void SelAdjInsertText(mozilla::dom::Text& aTextNode, int32_t aOffset,
113 const nsAString &aString);
114 nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
115 int32_t aLength);
116 nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength);
117 // the following gravity routines need will/did sandwiches, because the other gravity
118 // routines will be called inside of these sandwiches, but should be ignored.
119 nsresult WillReplaceContainer();
120 nsresult DidReplaceContainer(mozilla::dom::Element* aOriginalNode,
121 mozilla::dom::Element* aNewNode);
122 nsresult WillRemoveContainer();
123 nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
124 int32_t aOffset, uint32_t aNodeOrigLen);
125 nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen);
126 nsresult WillInsertContainer();
127 nsresult DidInsertContainer();
128 void WillMoveNode();
129 void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
130 nsINode* aNewParent, int32_t aNewOffset);
131 protected:
132 nsTArray<nsRefPtr<nsRangeStore> > mArray;
133 bool mLock;
137 /***************************************************************************
138 * helper class for using nsSelectionState. stack based class for doing
139 * preservation of dom points across editor actions
142 class MOZ_STACK_CLASS nsAutoTrackDOMPoint
144 private:
145 nsRangeUpdater &mRU;
146 // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
147 nsCOMPtr<nsINode>* mNode;
148 nsCOMPtr<nsIDOMNode>* mDOMNode;
149 int32_t* mOffset;
150 nsRefPtr<nsRangeStore> mRangeItem;
151 public:
152 nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater,
153 nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
154 : mRU(aRangeUpdater)
155 , mNode(aNode)
156 , mDOMNode(nullptr)
157 , mOffset(aOffset)
159 mRangeItem = new nsRangeStore();
160 mRangeItem->startNode = *mNode;
161 mRangeItem->endNode = *mNode;
162 mRangeItem->startOffset = *mOffset;
163 mRangeItem->endOffset = *mOffset;
164 mRU.RegisterRangeItem(mRangeItem);
167 nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater,
168 nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
169 : mRU(aRangeUpdater)
170 , mNode(nullptr)
171 , mDOMNode(aNode)
172 , mOffset(aOffset)
174 mRangeItem = new nsRangeStore();
175 mRangeItem->startNode = do_QueryInterface(*mDOMNode);
176 mRangeItem->endNode = do_QueryInterface(*mDOMNode);
177 mRangeItem->startOffset = *mOffset;
178 mRangeItem->endOffset = *mOffset;
179 mRU.RegisterRangeItem(mRangeItem);
182 ~nsAutoTrackDOMPoint()
184 mRU.DropRangeItem(mRangeItem);
185 if (mNode) {
186 *mNode = mRangeItem->startNode;
187 } else {
188 *mDOMNode = GetAsDOMNode(mRangeItem->startNode);
190 *mOffset = mRangeItem->startOffset;
196 /******************************************************************************
197 * another helper class for nsSelectionState. stack based class for doing
198 * Will/DidReplaceContainer()
201 namespace mozilla {
202 namespace dom {
203 class MOZ_STACK_CLASS AutoReplaceContainerSelNotify
205 private:
206 nsRangeUpdater &mRU;
207 Element* mOriginalElement;
208 Element* mNewElement;
210 public:
211 AutoReplaceContainerSelNotify(nsRangeUpdater& aRangeUpdater,
212 Element* aOriginalElement,
213 Element* aNewElement)
214 : mRU(aRangeUpdater)
215 , mOriginalElement(aOriginalElement)
216 , mNewElement(aNewElement)
218 mRU.WillReplaceContainer();
221 ~AutoReplaceContainerSelNotify()
223 mRU.DidReplaceContainer(mOriginalElement, mNewElement);
230 /***************************************************************************
231 * another helper class for nsSelectionState. stack based class for doing
232 * Will/DidRemoveContainer()
235 class MOZ_STACK_CLASS nsAutoRemoveContainerSelNotify
237 private:
238 nsRangeUpdater &mRU;
239 nsIDOMNode *mNode;
240 nsIDOMNode *mParent;
241 int32_t mOffset;
242 uint32_t mNodeOrigLen;
244 public:
245 nsAutoRemoveContainerSelNotify(nsRangeUpdater& aRangeUpdater,
246 nsINode* aNode,
247 nsINode* aParent,
248 int32_t aOffset,
249 uint32_t aNodeOrigLen)
250 : mRU(aRangeUpdater)
251 , mNode(aNode->AsDOMNode())
252 , mParent(aParent->AsDOMNode())
253 , mOffset(aOffset)
254 , mNodeOrigLen(aNodeOrigLen)
256 mRU.WillRemoveContainer();
259 ~nsAutoRemoveContainerSelNotify()
261 mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
265 /***************************************************************************
266 * another helper class for nsSelectionState. stack based class for doing
267 * Will/DidInsertContainer()
270 class MOZ_STACK_CLASS nsAutoInsertContainerSelNotify
272 private:
273 nsRangeUpdater &mRU;
275 public:
276 explicit nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) :
277 mRU(aRangeUpdater)
279 mRU.WillInsertContainer();
282 ~nsAutoInsertContainerSelNotify()
284 mRU.DidInsertContainer();
289 /***************************************************************************
290 * another helper class for nsSelectionState. stack based class for doing
291 * Will/DidMoveNode()
294 class MOZ_STACK_CLASS nsAutoMoveNodeSelNotify
296 private:
297 nsRangeUpdater &mRU;
298 nsINode* mOldParent;
299 nsINode* mNewParent;
300 int32_t mOldOffset;
301 int32_t mNewOffset;
303 public:
304 nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater,
305 nsINode* aOldParent,
306 int32_t aOldOffset,
307 nsINode* aNewParent,
308 int32_t aNewOffset)
309 : mRU(aRangeUpdater)
310 , mOldParent(aOldParent)
311 , mNewParent(aNewParent)
312 , mOldOffset(aOldOffset)
313 , mNewOffset(aNewOffset)
315 MOZ_ASSERT(aOldParent);
316 MOZ_ASSERT(aNewParent);
317 mRU.WillMoveNode();
320 ~nsAutoMoveNodeSelNotify()
322 mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
326 #endif