123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef mozilla_SelectionState_h
- #define mozilla_SelectionState_h
- #include "nsCOMPtr.h"
- #include "nsIDOMNode.h"
- #include "nsINode.h"
- #include "nsTArray.h"
- #include "nscore.h"
- class nsCycleCollectionTraversalCallback;
- class nsIDOMCharacterData;
- class nsRange;
- namespace mozilla {
- class RangeUpdater;
- namespace dom {
- class Selection;
- class Text;
- } // namespace dom
- /**
- * A helper struct for saving/setting ranges.
- */
- struct RangeItem final
- {
- RangeItem();
- private:
- // Private destructor, to discourage deletion outside of Release():
- ~RangeItem();
- public:
- void StoreRange(nsRange* aRange);
- already_AddRefed<nsRange> GetRange();
- NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RangeItem)
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RangeItem)
- nsCOMPtr<nsINode> startNode;
- int32_t startOffset;
- nsCOMPtr<nsINode> endNode;
- int32_t endOffset;
- };
- /**
- * mozilla::SelectionState
- *
- * Class for recording selection info. Stores selection as collection of
- * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
- * ranges since dom gravity will possibly change the ranges.
- */
- class SelectionState final
- {
- public:
- SelectionState();
- ~SelectionState();
- void SaveSelection(dom::Selection *aSel);
- nsresult RestoreSelection(dom::Selection* aSel);
- bool IsCollapsed();
- bool IsEqual(SelectionState *aSelState);
- void MakeEmpty();
- bool IsEmpty();
- private:
- nsTArray<RefPtr<RangeItem>> mArray;
- friend class RangeUpdater;
- friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
- SelectionState&,
- const char*,
- uint32_t);
- friend void ImplCycleCollectionUnlink(SelectionState&);
- };
- inline void
- ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- SelectionState& aField,
- const char* aName,
- uint32_t aFlags = 0)
- {
- ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
- }
- inline void
- ImplCycleCollectionUnlink(SelectionState& aField)
- {
- ImplCycleCollectionUnlink(aField.mArray);
- }
- class RangeUpdater final
- {
- public:
- RangeUpdater();
- ~RangeUpdater();
- void RegisterRangeItem(RangeItem* aRangeItem);
- void DropRangeItem(RangeItem* aRangeItem);
- nsresult RegisterSelectionState(SelectionState& aSelState);
- nsresult DropSelectionState(SelectionState& aSelState);
- // editor selection gravity routines. Note that we can't always depend on
- // DOM Range gravity to do what we want to the "real" selection. For instance,
- // if you move a node, that corresponds to deleting it and reinserting it.
- // DOM Range gravity will promote the selection out of the node on deletion,
- // which is not what you want if you know you are reinserting it.
- nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
- nsresult SelAdjCreateNode(nsIDOMNode* aParent, int32_t aPosition);
- nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
- nsresult SelAdjInsertNode(nsIDOMNode* aParent, int32_t aPosition);
- void SelAdjDeleteNode(nsINode* aNode);
- void SelAdjDeleteNode(nsIDOMNode* aNode);
- nsresult SelAdjSplitNode(nsIContent& aOldRightNode, int32_t aOffset,
- nsIContent* aNewLeftNode);
- nsresult SelAdjJoinNodes(nsINode& aLeftNode,
- nsINode& aRightNode,
- nsINode& aParent,
- int32_t aOffset,
- int32_t aOldLeftNodeLength);
- void SelAdjInsertText(dom::Text& aTextNode, int32_t aOffset,
- const nsAString &aString);
- nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
- int32_t aLength);
- nsresult SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset, int32_t aLength);
- // the following gravity routines need will/did sandwiches, because the other
- // gravity routines will be called inside of these sandwiches, but should be
- // ignored.
- nsresult WillReplaceContainer();
- nsresult DidReplaceContainer(dom::Element* aOriginalNode,
- dom::Element* aNewNode);
- nsresult WillRemoveContainer();
- nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
- int32_t aOffset, uint32_t aNodeOrigLen);
- nsresult DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent,
- int32_t aOffset, uint32_t aNodeOrigLen);
- nsresult WillInsertContainer();
- nsresult DidInsertContainer();
- void WillMoveNode();
- void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
- nsINode* aNewParent, int32_t aNewOffset);
- private:
- friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
- RangeUpdater&,
- const char*,
- uint32_t);
- friend void ImplCycleCollectionUnlink(RangeUpdater& aField);
- nsTArray<RefPtr<RangeItem>> mArray;
- bool mLock;
- };
- inline void
- ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- RangeUpdater& aField,
- const char* aName,
- uint32_t aFlags = 0)
- {
- ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
- }
- inline void
- ImplCycleCollectionUnlink(RangeUpdater& aField)
- {
- ImplCycleCollectionUnlink(aField.mArray);
- }
- /**
- * Helper class for using SelectionState. Stack based class for doing
- * preservation of dom points across editor actions.
- */
- class MOZ_STACK_CLASS AutoTrackDOMPoint final
- {
- private:
- RangeUpdater& mRangeUpdater;
- // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
- nsCOMPtr<nsINode>* mNode;
- nsCOMPtr<nsIDOMNode>* mDOMNode;
- int32_t* mOffset;
- RefPtr<RangeItem> mRangeItem;
- public:
- AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
- nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
- : mRangeUpdater(aRangeUpdater)
- , mNode(aNode)
- , mDOMNode(nullptr)
- , mOffset(aOffset)
- {
- mRangeItem = new RangeItem();
- mRangeItem->startNode = *mNode;
- mRangeItem->endNode = *mNode;
- mRangeItem->startOffset = *mOffset;
- mRangeItem->endOffset = *mOffset;
- mRangeUpdater.RegisterRangeItem(mRangeItem);
- }
- AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
- nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
- : mRangeUpdater(aRangeUpdater)
- , mNode(nullptr)
- , mDOMNode(aNode)
- , mOffset(aOffset)
- {
- mRangeItem = new RangeItem();
- mRangeItem->startNode = do_QueryInterface(*mDOMNode);
- mRangeItem->endNode = do_QueryInterface(*mDOMNode);
- mRangeItem->startOffset = *mOffset;
- mRangeItem->endOffset = *mOffset;
- mRangeUpdater.RegisterRangeItem(mRangeItem);
- }
- ~AutoTrackDOMPoint()
- {
- mRangeUpdater.DropRangeItem(mRangeItem);
- if (mNode) {
- *mNode = mRangeItem->startNode;
- } else {
- *mDOMNode = GetAsDOMNode(mRangeItem->startNode);
- }
- *mOffset = mRangeItem->startOffset;
- }
- };
- /**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidReplaceContainer()
- */
- class MOZ_STACK_CLASS AutoReplaceContainerSelNotify final
- {
- private:
- RangeUpdater& mRangeUpdater;
- dom::Element* mOriginalElement;
- dom::Element* mNewElement;
- public:
- AutoReplaceContainerSelNotify(RangeUpdater& aRangeUpdater,
- dom::Element* aOriginalElement,
- dom::Element* aNewElement)
- : mRangeUpdater(aRangeUpdater)
- , mOriginalElement(aOriginalElement)
- , mNewElement(aNewElement)
- {
- mRangeUpdater.WillReplaceContainer();
- }
- ~AutoReplaceContainerSelNotify()
- {
- mRangeUpdater.DidReplaceContainer(mOriginalElement, mNewElement);
- }
- };
- /**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidRemoveContainer()
- */
- class MOZ_STACK_CLASS AutoRemoveContainerSelNotify final
- {
- private:
- RangeUpdater& mRangeUpdater;
- nsIDOMNode* mNode;
- nsIDOMNode* mParent;
- int32_t mOffset;
- uint32_t mNodeOrigLen;
- public:
- AutoRemoveContainerSelNotify(RangeUpdater& aRangeUpdater,
- nsINode* aNode,
- nsINode* aParent,
- int32_t aOffset,
- uint32_t aNodeOrigLen)
- : mRangeUpdater(aRangeUpdater)
- , mNode(aNode->AsDOMNode())
- , mParent(aParent->AsDOMNode())
- , mOffset(aOffset)
- , mNodeOrigLen(aNodeOrigLen)
- {
- mRangeUpdater.WillRemoveContainer();
- }
- ~AutoRemoveContainerSelNotify()
- {
- mRangeUpdater.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
- }
- };
- /**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidInsertContainer()
- */
- class MOZ_STACK_CLASS AutoInsertContainerSelNotify final
- {
- private:
- RangeUpdater& mRangeUpdater;
- public:
- explicit AutoInsertContainerSelNotify(RangeUpdater& aRangeUpdater)
- : mRangeUpdater(aRangeUpdater)
- {
- mRangeUpdater.WillInsertContainer();
- }
- ~AutoInsertContainerSelNotify()
- {
- mRangeUpdater.DidInsertContainer();
- }
- };
- /**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidMoveNode()
- */
- class MOZ_STACK_CLASS AutoMoveNodeSelNotify final
- {
- private:
- RangeUpdater& mRangeUpdater;
- nsINode* mOldParent;
- nsINode* mNewParent;
- int32_t mOldOffset;
- int32_t mNewOffset;
- public:
- AutoMoveNodeSelNotify(RangeUpdater& aRangeUpdater,
- nsINode* aOldParent,
- int32_t aOldOffset,
- nsINode* aNewParent,
- int32_t aNewOffset)
- : mRangeUpdater(aRangeUpdater)
- , mOldParent(aOldParent)
- , mNewParent(aNewParent)
- , mOldOffset(aOldOffset)
- , mNewOffset(aNewOffset)
- {
- MOZ_ASSERT(aOldParent);
- MOZ_ASSERT(aNewParent);
- mRangeUpdater.WillMoveNode();
- }
- ~AutoMoveNodeSelNotify()
- {
- mRangeUpdater.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
- }
- };
- } // namespace mozilla
- #endif // #ifndef mozilla_SelectionState_h
|