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__
10 #include "nsIDOMNode.h"
15 class nsCycleCollectionTraversalCallback
;
16 class nsIDOMCharacterData
;
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
39 // Private destructor, to discourage deletion outside of Release():
43 void StoreRange(nsRange
* aRange
);
44 already_AddRefed
<nsRange
> GetRange();
46 NS_INLINE_DECL_REFCOUNTING(nsRangeStore
)
48 nsCOMPtr
<nsINode
> startNode
;
50 nsCOMPtr
<nsINode
> endNode
;
54 class nsSelectionState
61 void DoTraverse(nsCycleCollectionTraversalCallback
&cb
);
62 void DoUnlink() { MakeEmpty(); }
64 void SaveSelection(mozilla::dom::Selection
*aSel
);
65 nsresult
RestoreSelection(nsISelection
*aSel
);
67 bool IsEqual(nsSelectionState
*aSelState
);
71 nsTArray
<nsRefPtr
<nsRangeStore
> > mArray
;
73 friend class 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
,
106 int32_t aOldLeftNodeLength
);
107 nsresult
SelAdjJoinNodes(nsIDOMNode
*aLeftNode
,
108 nsIDOMNode
*aRightNode
,
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
,
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();
129 void DidMoveNode(nsINode
* aOldParent
, int32_t aOldOffset
,
130 nsINode
* aNewParent
, int32_t aNewOffset
);
132 nsTArray
<nsRefPtr
<nsRangeStore
> > mArray
;
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
146 // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
147 nsCOMPtr
<nsINode
>* mNode
;
148 nsCOMPtr
<nsIDOMNode
>* mDOMNode
;
150 nsRefPtr
<nsRangeStore
> mRangeItem
;
152 nsAutoTrackDOMPoint(nsRangeUpdater
&aRangeUpdater
,
153 nsCOMPtr
<nsINode
>* aNode
, int32_t* 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
)
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
);
186 *mNode
= mRangeItem
->startNode
;
188 *mDOMNode
= GetAsDOMNode(mRangeItem
->startNode
);
190 *mOffset
= mRangeItem
->startOffset
;
196 /******************************************************************************
197 * another helper class for nsSelectionState. stack based class for doing
198 * Will/DidReplaceContainer()
203 class MOZ_STACK_CLASS AutoReplaceContainerSelNotify
207 Element
* mOriginalElement
;
208 Element
* mNewElement
;
211 AutoReplaceContainerSelNotify(nsRangeUpdater
& aRangeUpdater
,
212 Element
* aOriginalElement
,
213 Element
* aNewElement
)
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
242 uint32_t mNodeOrigLen
;
245 nsAutoRemoveContainerSelNotify(nsRangeUpdater
& aRangeUpdater
,
249 uint32_t aNodeOrigLen
)
251 , mNode(aNode
->AsDOMNode())
252 , mParent(aParent
->AsDOMNode())
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
276 explicit nsAutoInsertContainerSelNotify(nsRangeUpdater
&aRangeUpdater
) :
279 mRU
.WillInsertContainer();
282 ~nsAutoInsertContainerSelNotify()
284 mRU
.DidInsertContainer();
289 /***************************************************************************
290 * another helper class for nsSelectionState. stack based class for doing
294 class MOZ_STACK_CLASS nsAutoMoveNodeSelNotify
304 nsAutoMoveNodeSelNotify(nsRangeUpdater
&aRangeUpdater
,
310 , mOldParent(aOldParent
)
311 , mNewParent(aNewParent
)
312 , mOldOffset(aOldOffset
)
313 , mNewOffset(aNewOffset
)
315 MOZ_ASSERT(aOldParent
);
316 MOZ_ASSERT(aNewParent
);
320 ~nsAutoMoveNodeSelNotify()
322 mRU
.DidMoveNode(mOldParent
, mOldOffset
, mNewParent
, mNewOffset
);