content/base/src/nsRange.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 /*
     7  * Implementation of the DOM nsIDOMRange object.
     8  */
    10 #ifndef nsRange_h___
    11 #define nsRange_h___
    13 #include "nsIDOMRange.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsINode.h"
    16 #include "nsIDocument.h"
    17 #include "nsIDOMNode.h"
    18 #include "prmon.h"
    19 #include "nsStubMutationObserver.h"
    20 #include "nsWrapperCache.h"
    21 #include "mozilla/Attributes.h"
    23 namespace mozilla {
    24 class ErrorResult;
    25 namespace dom {
    26 class DocumentFragment;
    27 class DOMRect;
    28 class DOMRectList;
    29 }
    30 }
    32 class nsRange MOZ_FINAL : public nsIDOMRange,
    33                           public nsStubMutationObserver,
    34                           public nsWrapperCache
    35 {
    36   typedef mozilla::ErrorResult ErrorResult;
    37   typedef mozilla::dom::DOMRect DOMRect;
    38   typedef mozilla::dom::DOMRectList DOMRectList;
    40 public:
    41   nsRange(nsINode* aNode)
    42     : mRoot(nullptr)
    43     , mStartOffset(0)
    44     , mEndOffset(0)
    45     , mIsPositioned(false)
    46     , mIsDetached(false)
    47     , mMaySpanAnonymousSubtrees(false)
    48     , mInSelection(false)
    49     , mStartOffsetWasIncremented(false)
    50     , mEndOffsetWasIncremented(false)
    51     , mEnableGravitationOnElementRemoval(true)
    52 #ifdef DEBUG
    53     , mAssertNextInsertOrAppendIndex(-1)
    54     , mAssertNextInsertOrAppendNode(nullptr)
    55 #endif
    56   {
    57     SetIsDOMBinding();
    58     MOZ_ASSERT(aNode, "range isn't in a document!");
    59     mOwner = aNode->OwnerDoc();
    60   }
    61   virtual ~nsRange();
    63   static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
    64                               nsIDOMNode* aEndParent, int32_t aEndOffset,
    65                               nsRange** aRange);
    66   static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
    67                               nsIDOMNode* aEndParent, int32_t aEndOffset,
    68                               nsIDOMRange** aRange);
    69   static nsresult CreateRange(nsINode* aStartParent, int32_t aStartOffset,
    70                               nsINode* aEndParent, int32_t aEndOffset,
    71                               nsRange** aRange);
    73   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    74   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsRange, nsIDOMRange)
    76   /**
    77    * The DOM Range spec requires that when a node is removed from its parent,
    78    * and the node's subtree contains the start or end point of a range, that
    79    * start or end point is moved up to where the node was removed from its
    80    * parent.
    81    * For some internal uses of Ranges it's useful to disable that behavior,
    82    * so that a range of children within a single parent is preserved even if
    83    * that parent is removed from the document tree.
    84    */
    85   void SetEnableGravitationOnElementRemoval(bool aEnable)
    86   {
    87     mEnableGravitationOnElementRemoval = aEnable;
    88   }
    90   // nsIDOMRange interface
    91   NS_DECL_NSIDOMRANGE
    93   nsINode* GetRoot() const
    94   {
    95     return mRoot;
    96   }
    98   nsINode* GetStartParent() const
    99   {
   100     return mStartParent;
   101   }
   103   nsINode* GetEndParent() const
   104   {
   105     return mEndParent;
   106   }
   108   int32_t StartOffset() const
   109   {
   110     return mStartOffset;
   111   }
   113   int32_t EndOffset() const
   114   {
   115     return mEndOffset;
   116   }
   118   bool IsPositioned() const
   119   {
   120     return mIsPositioned;
   121   }
   123   void SetMaySpanAnonymousSubtrees(bool aMaySpanAnonymousSubtrees)
   124   {
   125     mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
   126   }
   128   /**
   129    * Return true iff this range is part of at least one Selection object
   130    * and isn't detached.
   131    */
   132   bool IsInSelection() const
   133   {
   134     return mInSelection;
   135   }
   137   /**
   138    * Called when the range is added/removed from a Selection.
   139    */
   140   void SetInSelection(bool aInSelection)
   141   {
   142     if (mInSelection == aInSelection) {
   143       return;
   144     }
   145     mInSelection = aInSelection;
   146     nsINode* commonAncestor = GetCommonAncestor();
   147     NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
   148     if (mInSelection) {
   149       RegisterCommonAncestor(commonAncestor);
   150     } else {
   151       UnregisterCommonAncestor(commonAncestor);
   152     }
   153   }
   155   nsINode* GetCommonAncestor() const;
   156   void Reset();
   157   nsresult SetStart(nsINode* aParent, int32_t aOffset);
   158   nsresult SetEnd(nsINode* aParent, int32_t aOffset);
   159   already_AddRefed<nsRange> CloneRange() const;
   161   nsresult Set(nsINode* aStartParent, int32_t aStartOffset,
   162                nsINode* aEndParent, int32_t aEndOffset)
   163   {
   164     // If this starts being hot, we may be able to optimize this a bit,
   165     // but for now just set start and end separately.
   166     nsresult rv = SetStart(aStartParent, aStartOffset);
   167     NS_ENSURE_SUCCESS(rv, rv);
   169     return SetEnd(aEndParent, aEndOffset);
   170   }
   172   NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult);
   174   // nsIMutationObserver methods
   175   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   176   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   177   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   178   NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
   179   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   181   // WebIDL
   182   static already_AddRefed<nsRange>
   183   Constructor(const mozilla::dom::GlobalObject& global,
   184               mozilla::ErrorResult& aRv);
   186   bool Collapsed() const
   187   {
   188     return mIsPositioned && mStartParent == mEndParent &&
   189            mStartOffset == mEndOffset;
   190   }
   191   already_AddRefed<mozilla::dom::DocumentFragment>
   192   CreateContextualFragment(const nsAString& aString, ErrorResult& aError);
   193   already_AddRefed<mozilla::dom::DocumentFragment>
   194   CloneContents(ErrorResult& aErr);
   195   int16_t CompareBoundaryPoints(uint16_t aHow, nsRange& aOther,
   196                                 ErrorResult& aErr);
   197   int16_t ComparePoint(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
   198   void DeleteContents(ErrorResult& aRv);
   199   already_AddRefed<mozilla::dom::DocumentFragment>
   200     ExtractContents(ErrorResult& aErr);
   201   nsINode* GetCommonAncestorContainer(ErrorResult& aRv) const;
   202   nsINode* GetStartContainer(ErrorResult& aRv) const;
   203   uint32_t GetStartOffset(ErrorResult& aRv) const;
   204   nsINode* GetEndContainer(ErrorResult& aRv) const;
   205   uint32_t GetEndOffset(ErrorResult& aRv) const;
   206   void InsertNode(nsINode& aNode, ErrorResult& aErr);
   207   bool IntersectsNode(nsINode& aNode, ErrorResult& aRv);
   208   bool IsPointInRange(nsINode& aParent, uint32_t aOffset, ErrorResult& aErr);
   209   void SelectNode(nsINode& aNode, ErrorResult& aErr);
   210   void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
   211   void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
   212   void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
   213   void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
   214   void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
   215   void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
   216   void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
   217   void SurroundContents(nsINode& aNode, ErrorResult& aErr);
   218   already_AddRefed<DOMRect> GetBoundingClientRect();
   219   already_AddRefed<DOMRectList> GetClientRects();
   221   nsINode* GetParentObject() const { return mOwner; }
   222   virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE MOZ_FINAL;
   224 private:
   225   // no copy's or assigns
   226   nsRange(const nsRange&);
   227   nsRange& operator=(const nsRange&);
   229   /**
   230    * Cut or delete the range's contents.
   231    *
   232    * @param aFragment nsIDOMDocumentFragment containing the nodes.
   233    *                  May be null to indicate the caller doesn't want a fragment.
   234    */
   235   nsresult CutContents(mozilla::dom::DocumentFragment** frag);
   237   static nsresult CloneParentsBetween(nsINode* aAncestor,
   238                                       nsINode* aNode,
   239                                       nsINode** aClosestAncestor,
   240                                       nsINode** aFarthestAncestor);
   242 public:
   243 /******************************************************************************
   244  *  Utility routine to detect if a content node starts before a range and/or
   245  *  ends after a range.  If neither it is contained inside the range.
   246  *
   247  *  XXX - callers responsibility to ensure node in same doc as range!
   248  *
   249  *****************************************************************************/
   250   static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
   251                                      bool *outNodeBefore,
   252                                      bool *outNodeAfter);
   254   static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
   255                              uint32_t aEndOffset);
   257   typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
   258 protected:
   259   void RegisterCommonAncestor(nsINode* aNode);
   260   void UnregisterCommonAncestor(nsINode* aNode);
   261   nsINode* IsValidBoundary(nsINode* aNode);
   263   // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
   264   // and suppress re-registering a range common ancestor node since
   265   // the new text node of a splitText hasn't been inserted yet.
   266   // CharacterDataChanged does the re-registering when needed.
   267   void DoSetRange(nsINode* aStartN, int32_t aStartOffset,
   268                   nsINode* aEndN, int32_t aEndOffset,
   269                   nsINode* aRoot, bool aNotInsertedYet = false);
   271   /**
   272    * For a range for which IsInSelection() is true, return the common
   273    * ancestor for the range.  This method uses the selection bits and
   274    * nsGkAtoms::range property on the nodes to quickly find the ancestor.
   275    * That is, it's a faster version of GetCommonAncestor that only works
   276    * for ranges in a Selection.  The method will assert and the behavior
   277    * is undefined if called on a range where IsInSelection() is false.
   278    */
   279   nsINode* GetRegisteredCommonAncestor();
   281   struct MOZ_STACK_CLASS AutoInvalidateSelection
   282   {
   283     AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
   284     {
   285 #ifdef DEBUG
   286       mWasInSelection = mRange->IsInSelection();
   287 #endif
   288       if (!mRange->IsInSelection() || mIsNested) {
   289         return;
   290       }
   291       mIsNested = true;
   292       mCommonAncestor = mRange->GetRegisteredCommonAncestor();
   293     }
   294     ~AutoInvalidateSelection();
   295     nsRange* mRange;
   296     nsRefPtr<nsINode> mCommonAncestor;
   297 #ifdef DEBUG
   298     bool mWasInSelection;
   299 #endif
   300     static bool mIsNested;
   301   };
   303   nsCOMPtr<nsIDocument> mOwner;
   304   nsCOMPtr<nsINode> mRoot;
   305   nsCOMPtr<nsINode> mStartParent;
   306   nsCOMPtr<nsINode> mEndParent;
   307   int32_t mStartOffset;
   308   int32_t mEndOffset;
   310   bool mIsPositioned;
   311   bool mIsDetached;
   312   bool mMaySpanAnonymousSubtrees;
   313   bool mInSelection;
   314   bool mStartOffsetWasIncremented;
   315   bool mEndOffsetWasIncremented;
   316   bool mEnableGravitationOnElementRemoval;
   317 #ifdef DEBUG
   318   int32_t  mAssertNextInsertOrAppendIndex;
   319   nsINode* mAssertNextInsertOrAppendNode;
   320 #endif
   321 };
   323 inline nsISupports*
   324 ToCanonicalSupports(nsRange* aRange)
   325 {
   326   return static_cast<nsIDOMRange*>(aRange);
   327 }
   329 inline nsISupports*
   330 ToSupports(nsRange* aRange)
   331 {
   332   return static_cast<nsIDOMRange*>(aRange);
   333 }
   335 #endif /* nsRange_h___ */

mercurial