1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/nsEditorUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,229 @@ 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 +#include "mozilla/dom/Selection.h" 1.10 +#include "nsCOMArray.h" 1.11 +#include "nsComponentManagerUtils.h" 1.12 +#include "nsEditorUtils.h" 1.13 +#include "nsError.h" 1.14 +#include "nsIClipboardDragDropHookList.h" 1.15 +// hooks 1.16 +#include "nsIClipboardDragDropHooks.h" 1.17 +#include "nsIContent.h" 1.18 +#include "nsIContentIterator.h" 1.19 +#include "nsIDOMDocument.h" 1.20 +#include "nsIDocShell.h" 1.21 +#include "nsIDocument.h" 1.22 +#include "nsIInterfaceRequestorUtils.h" 1.23 +#include "nsINode.h" 1.24 +#include "nsISimpleEnumerator.h" 1.25 + 1.26 +class nsIDOMRange; 1.27 +class nsISupports; 1.28 + 1.29 +using namespace mozilla; 1.30 +using namespace mozilla::dom; 1.31 + 1.32 +/****************************************************************************** 1.33 + * nsAutoSelectionReset 1.34 + *****************************************************************************/ 1.35 + 1.36 +nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd) 1.37 + : mSel(nullptr), mEd(nullptr) 1.38 +{ 1.39 + if (!aSel || !aEd) return; // not much we can do, bail. 1.40 + if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call. 1.41 + mSel = aSel; 1.42 + mEd = aEd; 1.43 + if (mSel) 1.44 + { 1.45 + mEd->PreserveSelectionAcrossActions(mSel); 1.46 + } 1.47 +} 1.48 + 1.49 +nsAutoSelectionReset::~nsAutoSelectionReset() 1.50 +{ 1.51 + NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is"); 1.52 + if (mSel && mEd->ArePreservingSelection()) // mSel will be null if this was nested call 1.53 + { 1.54 + mEd->RestorePreservedSelection(mSel); 1.55 + } 1.56 +} 1.57 + 1.58 +void 1.59 +nsAutoSelectionReset::Abort() 1.60 +{ 1.61 + NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is"); 1.62 + if (mSel) 1.63 + mEd->StopPreservingSelection(); 1.64 +} 1.65 + 1.66 + 1.67 +/****************************************************************************** 1.68 + * some helper classes for iterating the dom tree 1.69 + *****************************************************************************/ 1.70 + 1.71 +nsDOMIterator::nsDOMIterator() : 1.72 +mIter(nullptr) 1.73 +{ 1.74 +} 1.75 + 1.76 +nsDOMIterator::~nsDOMIterator() 1.77 +{ 1.78 +} 1.79 + 1.80 +nsresult 1.81 +nsDOMIterator::Init(nsIDOMRange* aRange) 1.82 +{ 1.83 + nsresult res; 1.84 + mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res); 1.85 + NS_ENSURE_SUCCESS(res, res); 1.86 + NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); 1.87 + return mIter->Init(aRange); 1.88 +} 1.89 + 1.90 +nsresult 1.91 +nsDOMIterator::Init(nsIDOMNode* aNode) 1.92 +{ 1.93 + nsresult res; 1.94 + mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res); 1.95 + NS_ENSURE_SUCCESS(res, res); 1.96 + NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); 1.97 + nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); 1.98 + return mIter->Init(content); 1.99 +} 1.100 + 1.101 +nsresult 1.102 +nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor, 1.103 + nsCOMArray<nsIDOMNode>& arrayOfNodes) const 1.104 +{ 1.105 + nsCOMPtr<nsIDOMNode> node; 1.106 + 1.107 + // iterate through dom and build list 1.108 + while (!mIter->IsDone()) 1.109 + { 1.110 + node = do_QueryInterface(mIter->GetCurrentNode()); 1.111 + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); 1.112 + 1.113 + if (functor(node)) 1.114 + { 1.115 + arrayOfNodes.AppendObject(node); 1.116 + } 1.117 + mIter->Next(); 1.118 + } 1.119 + return NS_OK; 1.120 +} 1.121 + 1.122 +nsDOMSubtreeIterator::nsDOMSubtreeIterator() 1.123 +{ 1.124 +} 1.125 + 1.126 +nsDOMSubtreeIterator::~nsDOMSubtreeIterator() 1.127 +{ 1.128 +} 1.129 + 1.130 +nsresult 1.131 +nsDOMSubtreeIterator::Init(nsIDOMRange* aRange) 1.132 +{ 1.133 + nsresult res; 1.134 + mIter = do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); 1.135 + NS_ENSURE_SUCCESS(res, res); 1.136 + NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); 1.137 + return mIter->Init(aRange); 1.138 +} 1.139 + 1.140 +/****************************************************************************** 1.141 + * some general purpose editor utils 1.142 + *****************************************************************************/ 1.143 + 1.144 +bool 1.145 +nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t *aOffset) 1.146 +{ 1.147 + NS_ENSURE_TRUE(aNode || aParent, false); 1.148 + if (aNode == aParent) return false; 1.149 + 1.150 + nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(aNode); 1.151 + nsresult res; 1.152 + 1.153 + do 1.154 + { 1.155 + res = node->GetParentNode(getter_AddRefs(parent)); 1.156 + NS_ENSURE_SUCCESS(res, false); 1.157 + if (parent == aParent) 1.158 + { 1.159 + if (aOffset) 1.160 + { 1.161 + nsCOMPtr<nsIContent> pCon(do_QueryInterface(parent)); 1.162 + nsCOMPtr<nsIContent> cCon(do_QueryInterface(node)); 1.163 + if (pCon) 1.164 + { 1.165 + *aOffset = pCon->IndexOf(cCon); 1.166 + } 1.167 + } 1.168 + return true; 1.169 + } 1.170 + node = parent; 1.171 + } while (parent); 1.172 + 1.173 + return false; 1.174 +} 1.175 + 1.176 +bool 1.177 +nsEditorUtils::IsLeafNode(nsIDOMNode *aNode) 1.178 +{ 1.179 + bool hasChildren = false; 1.180 + if (aNode) 1.181 + aNode->HasChildNodes(&hasChildren); 1.182 + return !hasChildren; 1.183 +} 1.184 + 1.185 +/****************************************************************************** 1.186 + * utility methods for drag/drop/copy/paste hooks 1.187 + *****************************************************************************/ 1.188 + 1.189 +nsresult 1.190 +nsEditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument *aDoc, 1.191 + nsISimpleEnumerator **aResult) 1.192 +{ 1.193 + nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc); 1.194 + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); 1.195 + 1.196 + nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell(); 1.197 + nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell); 1.198 + NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE); 1.199 + 1.200 + return hookObj->GetHookEnumerator(aResult); 1.201 +} 1.202 + 1.203 +bool 1.204 +nsEditorHookUtils::DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aDropEvent, 1.205 + nsITransferable *aTrans) 1.206 +{ 1.207 + nsCOMPtr<nsISimpleEnumerator> enumerator; 1.208 + GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator)); 1.209 + NS_ENSURE_TRUE(enumerator, true); 1.210 + 1.211 + bool hasMoreHooks = false; 1.212 + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks) 1.213 + { 1.214 + nsCOMPtr<nsISupports> isupp; 1.215 + if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) 1.216 + break; 1.217 + 1.218 + nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp); 1.219 + if (override) 1.220 + { 1.221 + bool doInsert = true; 1.222 +#ifdef DEBUG 1.223 + nsresult hookResult = 1.224 +#endif 1.225 + override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert); 1.226 + NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop"); 1.227 + NS_ENSURE_TRUE(doInsert, false); 1.228 + } 1.229 + } 1.230 + 1.231 + return true; 1.232 +}