1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/nsSelectionState.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,283 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef __selectionstate_h__ 1.10 +#define __selectionstate_h__ 1.11 + 1.12 +#include "nsCOMPtr.h" 1.13 +#include "nsIDOMNode.h" 1.14 +#include "nsINode.h" 1.15 +#include "nsTArray.h" 1.16 +#include "nscore.h" 1.17 + 1.18 +class nsCycleCollectionTraversalCallback; 1.19 +class nsIDOMCharacterData; 1.20 +class nsIDOMRange; 1.21 +class nsISelection; 1.22 +class nsRange; 1.23 +namespace mozilla { 1.24 +namespace dom { 1.25 +class Selection; 1.26 +} 1.27 +} 1.28 + 1.29 +/*************************************************************************** 1.30 + * class for recording selection info. stores selection as collection of 1.31 + * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store 1.32 + * ranges since dom gravity will possibly change the ranges. 1.33 + */ 1.34 + 1.35 +// first a helper struct for saving/setting ranges 1.36 +struct nsRangeStore MOZ_FINAL 1.37 +{ 1.38 + nsRangeStore(); 1.39 + 1.40 +private: 1.41 + // Private destructor, to discourage deletion outside of Release(): 1.42 + ~nsRangeStore(); 1.43 + 1.44 +public: 1.45 + nsresult StoreRange(nsIDOMRange *aRange); 1.46 + nsresult GetRange(nsRange** outRange); 1.47 + 1.48 + NS_INLINE_DECL_REFCOUNTING(nsRangeStore) 1.49 + 1.50 + nsCOMPtr<nsIDOMNode> startNode; 1.51 + int32_t startOffset; 1.52 + nsCOMPtr<nsIDOMNode> endNode; 1.53 + int32_t endOffset; 1.54 + // DEBUG: static int32_t n; 1.55 +}; 1.56 + 1.57 +class nsSelectionState 1.58 +{ 1.59 + public: 1.60 + 1.61 + nsSelectionState(); 1.62 + ~nsSelectionState(); 1.63 + 1.64 + void DoTraverse(nsCycleCollectionTraversalCallback &cb); 1.65 + void DoUnlink() { MakeEmpty(); } 1.66 + 1.67 + void SaveSelection(mozilla::dom::Selection *aSel); 1.68 + nsresult RestoreSelection(nsISelection *aSel); 1.69 + bool IsCollapsed(); 1.70 + bool IsEqual(nsSelectionState *aSelState); 1.71 + void MakeEmpty(); 1.72 + bool IsEmpty(); 1.73 + protected: 1.74 + nsTArray<nsRefPtr<nsRangeStore> > mArray; 1.75 + 1.76 + friend class nsRangeUpdater; 1.77 +}; 1.78 + 1.79 +class nsRangeUpdater 1.80 +{ 1.81 + public: 1.82 + 1.83 + nsRangeUpdater(); 1.84 + ~nsRangeUpdater(); 1.85 + 1.86 + void RegisterRangeItem(nsRangeStore *aRangeItem); 1.87 + void DropRangeItem(nsRangeStore *aRangeItem); 1.88 + nsresult RegisterSelectionState(nsSelectionState &aSelState); 1.89 + nsresult DropSelectionState(nsSelectionState &aSelState); 1.90 + 1.91 + // editor selection gravity routines. Note that we can't always depend on 1.92 + // DOM Range gravity to do what we want to the "real" selection. For instance, 1.93 + // if you move a node, that corresponds to deleting it and reinserting it. 1.94 + // DOM Range gravity will promote the selection out of the node on deletion, 1.95 + // which is not what you want if you know you are reinserting it. 1.96 + nsresult SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition); 1.97 + nsresult SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition); 1.98 + void SelAdjDeleteNode(nsIDOMNode *aNode); 1.99 + nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode); 1.100 + nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode, 1.101 + nsIDOMNode *aRightNode, 1.102 + nsIDOMNode *aParent, 1.103 + int32_t aOffset, 1.104 + int32_t aOldLeftNodeLength); 1.105 + nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString); 1.106 + nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength); 1.107 + // the following gravity routines need will/did sandwiches, because the other gravity 1.108 + // routines will be called inside of these sandwiches, but should be ignored. 1.109 + nsresult WillReplaceContainer(); 1.110 + nsresult DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode); 1.111 + nsresult WillRemoveContainer(); 1.112 + nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen); 1.113 + nsresult WillInsertContainer(); 1.114 + nsresult DidInsertContainer(); 1.115 + void WillMoveNode(); 1.116 + void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset, 1.117 + nsINode* aNewParent, int32_t aNewOffset); 1.118 + protected: 1.119 + nsTArray<nsRefPtr<nsRangeStore> > mArray; 1.120 + bool mLock; 1.121 +}; 1.122 + 1.123 + 1.124 +/*************************************************************************** 1.125 + * helper class for using nsSelectionState. stack based class for doing 1.126 + * preservation of dom points across editor actions 1.127 + */ 1.128 + 1.129 +class MOZ_STACK_CLASS nsAutoTrackDOMPoint 1.130 +{ 1.131 + private: 1.132 + nsRangeUpdater &mRU; 1.133 + nsCOMPtr<nsIDOMNode> *mNode; 1.134 + int32_t *mOffset; 1.135 + nsRefPtr<nsRangeStore> mRangeItem; 1.136 + public: 1.137 + nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, int32_t *aOffset) : 1.138 + mRU(aRangeUpdater) 1.139 + ,mNode(aNode) 1.140 + ,mOffset(aOffset) 1.141 + { 1.142 + mRangeItem = new nsRangeStore(); 1.143 + mRangeItem->startNode = *mNode; 1.144 + mRangeItem->endNode = *mNode; 1.145 + mRangeItem->startOffset = *mOffset; 1.146 + mRangeItem->endOffset = *mOffset; 1.147 + mRU.RegisterRangeItem(mRangeItem); 1.148 + } 1.149 + 1.150 + ~nsAutoTrackDOMPoint() 1.151 + { 1.152 + mRU.DropRangeItem(mRangeItem); 1.153 + *mNode = mRangeItem->startNode; 1.154 + *mOffset = mRangeItem->startOffset; 1.155 + } 1.156 +}; 1.157 + 1.158 + 1.159 + 1.160 +/*************************************************************************** 1.161 + * another helper class for nsSelectionState. stack based class for doing 1.162 + * Will/DidReplaceContainer() 1.163 + */ 1.164 + 1.165 +class MOZ_STACK_CLASS nsAutoReplaceContainerSelNotify 1.166 +{ 1.167 + private: 1.168 + nsRangeUpdater &mRU; 1.169 + nsIDOMNode *mOriginalNode; 1.170 + nsIDOMNode *mNewNode; 1.171 + 1.172 + public: 1.173 + nsAutoReplaceContainerSelNotify(nsRangeUpdater &aRangeUpdater, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) : 1.174 + mRU(aRangeUpdater) 1.175 + ,mOriginalNode(aOriginalNode) 1.176 + ,mNewNode(aNewNode) 1.177 + { 1.178 + mRU.WillReplaceContainer(); 1.179 + } 1.180 + 1.181 + ~nsAutoReplaceContainerSelNotify() 1.182 + { 1.183 + mRU.DidReplaceContainer(mOriginalNode, mNewNode); 1.184 + } 1.185 +}; 1.186 + 1.187 + 1.188 +/*************************************************************************** 1.189 + * another helper class for nsSelectionState. stack based class for doing 1.190 + * Will/DidRemoveContainer() 1.191 + */ 1.192 + 1.193 +class MOZ_STACK_CLASS nsAutoRemoveContainerSelNotify 1.194 +{ 1.195 + private: 1.196 + nsRangeUpdater &mRU; 1.197 + nsIDOMNode *mNode; 1.198 + nsIDOMNode *mParent; 1.199 + int32_t mOffset; 1.200 + uint32_t mNodeOrigLen; 1.201 + 1.202 + public: 1.203 + nsAutoRemoveContainerSelNotify(nsRangeUpdater& aRangeUpdater, 1.204 + nsINode* aNode, 1.205 + nsINode* aParent, 1.206 + int32_t aOffset, 1.207 + uint32_t aNodeOrigLen) 1.208 + : mRU(aRangeUpdater) 1.209 + , mNode(aNode->AsDOMNode()) 1.210 + , mParent(aParent->AsDOMNode()) 1.211 + , mOffset(aOffset) 1.212 + , mNodeOrigLen(aNodeOrigLen) 1.213 + { 1.214 + mRU.WillRemoveContainer(); 1.215 + } 1.216 + 1.217 + ~nsAutoRemoveContainerSelNotify() 1.218 + { 1.219 + mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen); 1.220 + } 1.221 +}; 1.222 + 1.223 +/*************************************************************************** 1.224 + * another helper class for nsSelectionState. stack based class for doing 1.225 + * Will/DidInsertContainer() 1.226 + */ 1.227 + 1.228 +class MOZ_STACK_CLASS nsAutoInsertContainerSelNotify 1.229 +{ 1.230 + private: 1.231 + nsRangeUpdater &mRU; 1.232 + 1.233 + public: 1.234 + nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) : 1.235 + mRU(aRangeUpdater) 1.236 + { 1.237 + mRU.WillInsertContainer(); 1.238 + } 1.239 + 1.240 + ~nsAutoInsertContainerSelNotify() 1.241 + { 1.242 + mRU.DidInsertContainer(); 1.243 + } 1.244 +}; 1.245 + 1.246 + 1.247 +/*************************************************************************** 1.248 + * another helper class for nsSelectionState. stack based class for doing 1.249 + * Will/DidMoveNode() 1.250 + */ 1.251 + 1.252 +class MOZ_STACK_CLASS nsAutoMoveNodeSelNotify 1.253 +{ 1.254 + private: 1.255 + nsRangeUpdater &mRU; 1.256 + nsINode* mOldParent; 1.257 + nsINode* mNewParent; 1.258 + int32_t mOldOffset; 1.259 + int32_t mNewOffset; 1.260 + 1.261 + public: 1.262 + nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater, 1.263 + nsINode* aOldParent, 1.264 + int32_t aOldOffset, 1.265 + nsINode* aNewParent, 1.266 + int32_t aNewOffset) 1.267 + : mRU(aRangeUpdater) 1.268 + , mOldParent(aOldParent) 1.269 + , mNewParent(aNewParent) 1.270 + , mOldOffset(aOldOffset) 1.271 + , mNewOffset(aNewOffset) 1.272 + { 1.273 + MOZ_ASSERT(aOldParent); 1.274 + MOZ_ASSERT(aNewParent); 1.275 + mRU.WillMoveNode(); 1.276 + } 1.277 + 1.278 + ~nsAutoMoveNodeSelNotify() 1.279 + { 1.280 + mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset); 1.281 + } 1.282 +}; 1.283 + 1.284 +#endif 1.285 + 1.286 +