editor/libeditor/base/nsEditorUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 #include "mozilla/dom/Selection.h"
     7 #include "nsCOMArray.h"
     8 #include "nsComponentManagerUtils.h"
     9 #include "nsEditorUtils.h"
    10 #include "nsError.h"
    11 #include "nsIClipboardDragDropHookList.h"
    12 // hooks
    13 #include "nsIClipboardDragDropHooks.h"
    14 #include "nsIContent.h"
    15 #include "nsIContentIterator.h"
    16 #include "nsIDOMDocument.h"
    17 #include "nsIDocShell.h"
    18 #include "nsIDocument.h"
    19 #include "nsIInterfaceRequestorUtils.h"
    20 #include "nsINode.h"
    21 #include "nsISimpleEnumerator.h"
    23 class nsIDOMRange;
    24 class nsISupports;
    26 using namespace mozilla;
    27 using namespace mozilla::dom;
    29 /******************************************************************************
    30  * nsAutoSelectionReset
    31  *****************************************************************************/
    33 nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
    34   : mSel(nullptr), mEd(nullptr)
    35 { 
    36   if (!aSel || !aEd) return;    // not much we can do, bail.
    37   if (aEd->ArePreservingSelection()) return;   // we already have initted mSavedSel, so this must be nested call.
    38   mSel = aSel;
    39   mEd = aEd;
    40   if (mSel)
    41   {
    42     mEd->PreserveSelectionAcrossActions(mSel);
    43   }
    44 }
    46 nsAutoSelectionReset::~nsAutoSelectionReset()
    47 {
    48   NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is");
    49   if (mSel && mEd->ArePreservingSelection())   // mSel will be null if this was nested call
    50   {
    51     mEd->RestorePreservedSelection(mSel);
    52   }
    53 }
    55 void
    56 nsAutoSelectionReset::Abort()
    57 {
    58   NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is");
    59   if (mSel)
    60     mEd->StopPreservingSelection();
    61 }
    64 /******************************************************************************
    65  * some helper classes for iterating the dom tree
    66  *****************************************************************************/
    68 nsDOMIterator::nsDOMIterator() :
    69 mIter(nullptr)
    70 {
    71 }
    73 nsDOMIterator::~nsDOMIterator()
    74 {
    75 }
    77 nsresult
    78 nsDOMIterator::Init(nsIDOMRange* aRange)
    79 {
    80   nsresult res;
    81   mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res);
    82   NS_ENSURE_SUCCESS(res, res);
    83   NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
    84   return mIter->Init(aRange);
    85 }
    87 nsresult
    88 nsDOMIterator::Init(nsIDOMNode* aNode)
    89 {
    90   nsresult res;
    91   mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res);
    92   NS_ENSURE_SUCCESS(res, res);
    93   NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
    94   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
    95   return mIter->Init(content);
    96 }
    98 nsresult
    99 nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
   100                           nsCOMArray<nsIDOMNode>& arrayOfNodes) const
   101 {
   102   nsCOMPtr<nsIDOMNode> node;
   104   // iterate through dom and build list
   105   while (!mIter->IsDone())
   106   {
   107     node = do_QueryInterface(mIter->GetCurrentNode());
   108     NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
   110     if (functor(node))
   111     {
   112       arrayOfNodes.AppendObject(node);
   113     }
   114     mIter->Next();
   115   }
   116   return NS_OK;
   117 }
   119 nsDOMSubtreeIterator::nsDOMSubtreeIterator()
   120 {
   121 }
   123 nsDOMSubtreeIterator::~nsDOMSubtreeIterator()
   124 {
   125 }
   127 nsresult
   128 nsDOMSubtreeIterator::Init(nsIDOMRange* aRange)
   129 {
   130   nsresult res;
   131   mIter = do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res);
   132   NS_ENSURE_SUCCESS(res, res);
   133   NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
   134   return mIter->Init(aRange);
   135 }
   137 /******************************************************************************
   138  * some general purpose editor utils
   139  *****************************************************************************/
   141 bool 
   142 nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset) 
   143 {
   144   NS_ENSURE_TRUE(aNode || aParent, false);
   145   if (aNode == aParent) return false;
   147   nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(aNode);
   148   nsresult res;
   150   do
   151   {
   152     res = node->GetParentNode(getter_AddRefs(parent));
   153     NS_ENSURE_SUCCESS(res, false);
   154     if (parent == aParent) 
   155     {
   156       if (aOffset)
   157       {
   158         nsCOMPtr<nsIContent> pCon(do_QueryInterface(parent));
   159         nsCOMPtr<nsIContent> cCon(do_QueryInterface(node));
   160         if (pCon)
   161         {
   162           *aOffset = pCon->IndexOf(cCon);
   163         }
   164       }
   165       return true;
   166     }
   167     node = parent;
   168   } while (parent);
   170   return false;
   171 }
   173 bool
   174 nsEditorUtils::IsLeafNode(nsIDOMNode *aNode)
   175 {
   176   bool hasChildren = false;
   177   if (aNode)
   178     aNode->HasChildNodes(&hasChildren);
   179   return !hasChildren;
   180 }
   182 /******************************************************************************
   183  * utility methods for drag/drop/copy/paste hooks
   184  *****************************************************************************/
   186 nsresult
   187 nsEditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument *aDoc,
   188                                                  nsISimpleEnumerator **aResult)
   189 {
   190   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
   191   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   193   nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
   194   nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
   195   NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
   197   return hookObj->GetHookEnumerator(aResult);
   198 }
   200 bool
   201 nsEditorHookUtils::DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aDropEvent,  
   202                                    nsITransferable *aTrans)
   203 {
   204   nsCOMPtr<nsISimpleEnumerator> enumerator;
   205   GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
   206   NS_ENSURE_TRUE(enumerator, true);
   208   bool hasMoreHooks = false;
   209   while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks)
   210   {
   211     nsCOMPtr<nsISupports> isupp;
   212     if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
   213       break;
   215     nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
   216     if (override)
   217     {
   218       bool doInsert = true;
   219 #ifdef DEBUG
   220       nsresult hookResult =
   221 #endif
   222       override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
   223       NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
   224       NS_ENSURE_TRUE(doInsert, false);
   225     }
   226   }
   228   return true;
   229 }

mercurial