LCOV - code coverage report
Current view: top level - editor/libeditor - SelectionState.h (source / functions) Hit Total Coverage
Test: output.info Lines: 2 81 2.5 %
Date: 2017-07-14 16:53:18 Functions: 3 21 14.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #ifndef mozilla_SelectionState_h
       7             : #define mozilla_SelectionState_h
       8             : 
       9             : #include "nsCOMPtr.h"
      10             : #include "nsIDOMNode.h"
      11             : #include "nsINode.h"
      12             : #include "nsTArray.h"
      13             : #include "nscore.h"
      14             : 
      15             : class nsCycleCollectionTraversalCallback;
      16             : class nsIDOMCharacterData;
      17             : class nsRange;
      18             : namespace mozilla {
      19             : class RangeUpdater;
      20             : namespace dom {
      21             : class Selection;
      22             : class Text;
      23             : } // namespace dom
      24             : 
      25             : /**
      26             :  * A helper struct for saving/setting ranges.
      27             :  */
      28             : struct RangeItem final
      29             : {
      30             :   RangeItem();
      31             : 
      32             : private:
      33             :   // Private destructor, to discourage deletion outside of Release():
      34             :   ~RangeItem();
      35             : 
      36             : public:
      37             :   void StoreRange(nsRange* aRange);
      38             :   already_AddRefed<nsRange> GetRange();
      39             : 
      40           2 :   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RangeItem)
      41           2 :   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RangeItem)
      42             : 
      43             :   nsCOMPtr<nsINode> mStartContainer;
      44             :   int32_t mStartOffset;
      45             :   nsCOMPtr<nsINode> mEndContainer;
      46             :   int32_t mEndOffset;
      47             : };
      48             : 
      49             : /**
      50             :  * mozilla::SelectionState
      51             :  *
      52             :  * Class for recording selection info.  Stores selection as collection of
      53             :  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
      54             :  * ranges since dom gravity will possibly change the ranges.
      55             :  */
      56             : 
      57             : class SelectionState final
      58             : {
      59             : public:
      60             :   SelectionState();
      61             :   ~SelectionState();
      62             : 
      63             :   void SaveSelection(dom::Selection *aSel);
      64             :   nsresult RestoreSelection(dom::Selection* aSel);
      65             :   bool IsCollapsed();
      66             :   bool IsEqual(SelectionState *aSelState);
      67             :   void MakeEmpty();
      68             :   bool IsEmpty();
      69             : private:
      70             :   AutoTArray<RefPtr<RangeItem>, 1> mArray;
      71             : 
      72             :   friend class RangeUpdater;
      73             :   friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
      74             :                                           SelectionState&,
      75             :                                           const char*,
      76             :                                           uint32_t);
      77             :   friend void ImplCycleCollectionUnlink(SelectionState&);
      78             : };
      79             : 
      80             : inline void
      81           0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
      82             :                             SelectionState& aField,
      83             :                             const char* aName,
      84             :                             uint32_t aFlags = 0)
      85             : {
      86           0 :   ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
      87           0 : }
      88             : 
      89             : inline void
      90           0 : ImplCycleCollectionUnlink(SelectionState& aField)
      91             : {
      92           0 :   ImplCycleCollectionUnlink(aField.mArray);
      93           0 : }
      94             : 
      95             : class RangeUpdater final
      96             : {
      97             : public:
      98             :   RangeUpdater();
      99             :   ~RangeUpdater();
     100             : 
     101             :   void RegisterRangeItem(RangeItem* aRangeItem);
     102             :   void DropRangeItem(RangeItem* aRangeItem);
     103             :   nsresult RegisterSelectionState(SelectionState& aSelState);
     104             :   nsresult DropSelectionState(SelectionState& aSelState);
     105             : 
     106             :   // editor selection gravity routines.  Note that we can't always depend on
     107             :   // DOM Range gravity to do what we want to the "real" selection.  For instance,
     108             :   // if you move a node, that corresponds to deleting it and reinserting it.
     109             :   // DOM Range gravity will promote the selection out of the node on deletion,
     110             :   // which is not what you want if you know you are reinserting it.
     111             :   nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
     112             :   nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
     113             :   void SelAdjDeleteNode(nsINode* aNode);
     114             :   nsresult SelAdjSplitNode(nsIContent& aOldRightNode, int32_t aOffset,
     115             :                            nsIContent* aNewLeftNode);
     116             :   nsresult SelAdjJoinNodes(nsINode& aLeftNode,
     117             :                            nsINode& aRightNode,
     118             :                            nsINode& aParent,
     119             :                            int32_t aOffset,
     120             :                            int32_t aOldLeftNodeLength);
     121             :   void SelAdjInsertText(dom::Text& aTextNode, int32_t aOffset,
     122             :                         const nsAString &aString);
     123             :   nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
     124             :                             int32_t aLength);
     125             :   nsresult SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
     126             :                             int32_t aOffset, int32_t aLength);
     127             :   // the following gravity routines need will/did sandwiches, because the other
     128             :   // gravity routines will be called inside of these sandwiches, but should be
     129             :   // ignored.
     130             :   nsresult WillReplaceContainer();
     131             :   nsresult DidReplaceContainer(dom::Element* aOriginalNode,
     132             :                                dom::Element* aNewNode);
     133             :   nsresult WillRemoveContainer();
     134             :   nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
     135             :                               int32_t aOffset, uint32_t aNodeOrigLen);
     136             :   nsresult DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent,
     137             :                               int32_t aOffset, uint32_t aNodeOrigLen);
     138             :   nsresult WillInsertContainer();
     139             :   nsresult DidInsertContainer();
     140             :   void WillMoveNode();
     141             :   void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
     142             :                    nsINode* aNewParent, int32_t aNewOffset);
     143             : 
     144             : private:
     145             :   friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
     146             :                                           RangeUpdater&,
     147             :                                           const char*,
     148             :                                           uint32_t);
     149             :   friend void ImplCycleCollectionUnlink(RangeUpdater& aField);
     150             : 
     151             :   nsTArray<RefPtr<RangeItem>> mArray;
     152             :   bool mLock;
     153             : };
     154             : 
     155             : inline void
     156           0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
     157             :                             RangeUpdater& aField,
     158             :                             const char* aName,
     159             :                             uint32_t aFlags = 0)
     160             : {
     161           0 :   ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
     162           0 : }
     163             : 
     164             : inline void
     165           0 : ImplCycleCollectionUnlink(RangeUpdater& aField)
     166             : {
     167           0 :   ImplCycleCollectionUnlink(aField.mArray);
     168           0 : }
     169             : 
     170             : /**
     171             :  * Helper class for using SelectionState.  Stack based class for doing
     172             :  * preservation of dom points across editor actions.
     173             :  */
     174             : 
     175             : class MOZ_STACK_CLASS AutoTrackDOMPoint final
     176             : {
     177             : private:
     178             :   RangeUpdater& mRangeUpdater;
     179             :   // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
     180             :   nsCOMPtr<nsINode>* mNode;
     181             :   nsCOMPtr<nsIDOMNode>* mDOMNode;
     182             :   int32_t* mOffset;
     183             :   RefPtr<RangeItem> mRangeItem;
     184             : 
     185             : public:
     186           0 :   AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
     187             :                     nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
     188           0 :     : mRangeUpdater(aRangeUpdater)
     189             :     , mNode(aNode)
     190             :     , mDOMNode(nullptr)
     191           0 :     , mOffset(aOffset)
     192             :   {
     193           0 :     mRangeItem = new RangeItem();
     194           0 :     mRangeItem->mStartContainer = *mNode;
     195           0 :     mRangeItem->mEndContainer = *mNode;
     196           0 :     mRangeItem->mStartOffset = *mOffset;
     197           0 :     mRangeItem->mEndOffset = *mOffset;
     198           0 :     mRangeUpdater.RegisterRangeItem(mRangeItem);
     199           0 :   }
     200             : 
     201           0 :   AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
     202             :                     nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
     203           0 :     : mRangeUpdater(aRangeUpdater)
     204             :     , mNode(nullptr)
     205             :     , mDOMNode(aNode)
     206           0 :     , mOffset(aOffset)
     207             :   {
     208           0 :     mRangeItem = new RangeItem();
     209           0 :     mRangeItem->mStartContainer = do_QueryInterface(*mDOMNode);
     210           0 :     mRangeItem->mEndContainer = do_QueryInterface(*mDOMNode);
     211           0 :     mRangeItem->mStartOffset = *mOffset;
     212           0 :     mRangeItem->mEndOffset = *mOffset;
     213           0 :     mRangeUpdater.RegisterRangeItem(mRangeItem);
     214           0 :   }
     215             : 
     216           0 :   ~AutoTrackDOMPoint()
     217           0 :   {
     218           0 :     mRangeUpdater.DropRangeItem(mRangeItem);
     219           0 :     if (mNode) {
     220           0 :       *mNode = mRangeItem->mStartContainer;
     221             :     } else {
     222           0 :       *mDOMNode = GetAsDOMNode(mRangeItem->mStartContainer);
     223             :     }
     224           0 :     *mOffset = mRangeItem->mStartOffset;
     225           0 :   }
     226             : };
     227             : 
     228             : /**
     229             :  * Another helper class for SelectionState.  Stack based class for doing
     230             :  * Will/DidReplaceContainer()
     231             :  */
     232             : 
     233             : class MOZ_STACK_CLASS AutoReplaceContainerSelNotify final
     234             : {
     235             : private:
     236             :   RangeUpdater& mRangeUpdater;
     237             :   dom::Element* mOriginalElement;
     238             :   dom::Element* mNewElement;
     239             : 
     240             : public:
     241           0 :   AutoReplaceContainerSelNotify(RangeUpdater& aRangeUpdater,
     242             :                                 dom::Element* aOriginalElement,
     243             :                                 dom::Element* aNewElement)
     244           0 :     : mRangeUpdater(aRangeUpdater)
     245             :     , mOriginalElement(aOriginalElement)
     246           0 :     , mNewElement(aNewElement)
     247             :   {
     248           0 :     mRangeUpdater.WillReplaceContainer();
     249           0 :   }
     250             : 
     251           0 :   ~AutoReplaceContainerSelNotify()
     252           0 :   {
     253           0 :     mRangeUpdater.DidReplaceContainer(mOriginalElement, mNewElement);
     254           0 :   }
     255             : };
     256             : 
     257             : /**
     258             :  * Another helper class for SelectionState.  Stack based class for doing
     259             :  * Will/DidRemoveContainer()
     260             :  */
     261             : 
     262             : class MOZ_STACK_CLASS AutoRemoveContainerSelNotify final
     263             : {
     264             : private:
     265             :   RangeUpdater& mRangeUpdater;
     266             :   nsIDOMNode* mNode;
     267             :   nsIDOMNode* mParent;
     268             :   int32_t mOffset;
     269             :   uint32_t mNodeOrigLen;
     270             : 
     271             : public:
     272           0 :   AutoRemoveContainerSelNotify(RangeUpdater& aRangeUpdater,
     273             :                                nsINode* aNode,
     274             :                                nsINode* aParent,
     275             :                                int32_t aOffset,
     276             :                                uint32_t aNodeOrigLen)
     277           0 :     : mRangeUpdater(aRangeUpdater)
     278           0 :     , mNode(aNode->AsDOMNode())
     279           0 :     , mParent(aParent->AsDOMNode())
     280             :     , mOffset(aOffset)
     281           0 :     , mNodeOrigLen(aNodeOrigLen)
     282             :   {
     283           0 :     mRangeUpdater.WillRemoveContainer();
     284           0 :   }
     285             : 
     286           0 :   ~AutoRemoveContainerSelNotify()
     287           0 :   {
     288           0 :     mRangeUpdater.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
     289           0 :   }
     290             : };
     291             : 
     292             : /**
     293             :  * Another helper class for SelectionState.  Stack based class for doing
     294             :  * Will/DidInsertContainer()
     295             :  */
     296             : 
     297             : class MOZ_STACK_CLASS AutoInsertContainerSelNotify final
     298             : {
     299             : private:
     300             :   RangeUpdater& mRangeUpdater;
     301             : 
     302             : public:
     303           0 :   explicit AutoInsertContainerSelNotify(RangeUpdater& aRangeUpdater)
     304           0 :     : mRangeUpdater(aRangeUpdater)
     305             :   {
     306           0 :     mRangeUpdater.WillInsertContainer();
     307           0 :   }
     308             : 
     309           0 :   ~AutoInsertContainerSelNotify()
     310           0 :   {
     311           0 :     mRangeUpdater.DidInsertContainer();
     312           0 :   }
     313             : };
     314             : 
     315             : /**
     316             :  * Another helper class for SelectionState.  Stack based class for doing
     317             :  * Will/DidMoveNode()
     318             :  */
     319             : 
     320             : class MOZ_STACK_CLASS AutoMoveNodeSelNotify final
     321             : {
     322             : private:
     323             :   RangeUpdater& mRangeUpdater;
     324             :   nsINode* mOldParent;
     325             :   nsINode* mNewParent;
     326             :   int32_t mOldOffset;
     327             :   int32_t mNewOffset;
     328             : 
     329             : public:
     330           0 :   AutoMoveNodeSelNotify(RangeUpdater& aRangeUpdater,
     331             :                         nsINode* aOldParent,
     332             :                         int32_t aOldOffset,
     333             :                         nsINode* aNewParent,
     334             :                         int32_t aNewOffset)
     335           0 :     : mRangeUpdater(aRangeUpdater)
     336             :     , mOldParent(aOldParent)
     337             :     , mNewParent(aNewParent)
     338             :     , mOldOffset(aOldOffset)
     339           0 :     , mNewOffset(aNewOffset)
     340             :   {
     341           0 :     MOZ_ASSERT(aOldParent);
     342           0 :     MOZ_ASSERT(aNewParent);
     343           0 :     mRangeUpdater.WillMoveNode();
     344           0 :   }
     345             : 
     346           0 :   ~AutoMoveNodeSelNotify()
     347           0 :   {
     348           0 :     mRangeUpdater.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
     349           0 :   }
     350             : };
     351             : 
     352             : } // namespace mozilla
     353             : 
     354             : #endif // #ifndef mozilla_SelectionState_h

Generated by: LCOV version 1.13