summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/EditorUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor/EditorUtils.cpp')
-rw-r--r--editor/libeditor/EditorUtils.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/editor/libeditor/EditorUtils.cpp b/editor/libeditor/EditorUtils.cpp
new file mode 100644
index 000000000..4ec60c830
--- /dev/null
+++ b/editor/libeditor/EditorUtils.cpp
@@ -0,0 +1,227 @@
+/* -*- 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/. */
+
+#include "mozilla/EditorUtils.h"
+
+#include "mozilla/OwningNonNull.h"
+#include "mozilla/dom/Selection.h"
+#include "nsComponentManagerUtils.h"
+#include "nsError.h"
+#include "nsIClipboardDragDropHookList.h"
+// hooks
+#include "nsIClipboardDragDropHooks.h"
+#include "nsIContent.h"
+#include "nsIContentIterator.h"
+#include "nsIDOMDocument.h"
+#include "nsIDocShell.h"
+#include "nsIDocument.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsINode.h"
+#include "nsISimpleEnumerator.h"
+
+class nsISupports;
+class nsRange;
+
+namespace mozilla {
+
+using namespace dom;
+
+/******************************************************************************
+ * AutoSelectionRestorer
+ *****************************************************************************/
+
+AutoSelectionRestorer::AutoSelectionRestorer(
+ Selection* aSelection,
+ EditorBase* aEditorBase
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+ : mEditorBase(nullptr)
+{
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aEditorBase)) {
+ return;
+ }
+ if (aEditorBase->ArePreservingSelection()) {
+ // We already have initialized mSavedSel, so this must be nested call.
+ return;
+ }
+ mSelection = aSelection;
+ mEditorBase = aEditorBase;
+ mEditorBase->PreserveSelectionAcrossActions(mSelection);
+}
+
+AutoSelectionRestorer::~AutoSelectionRestorer()
+{
+ NS_ASSERTION(!mSelection || mEditorBase,
+ "mEditorBase should be non-null when mSelection is");
+ // mSelection will be null if this was nested call.
+ if (mSelection && mEditorBase->ArePreservingSelection()) {
+ mEditorBase->RestorePreservedSelection(mSelection);
+ }
+}
+
+void
+AutoSelectionRestorer::Abort()
+{
+ NS_ASSERTION(!mSelection || mEditorBase,
+ "mEditorBase should be non-null when mSelection is");
+ if (mSelection) {
+ mEditorBase->StopPreservingSelection();
+ }
+}
+
+/******************************************************************************
+ * some helper classes for iterating the dom tree
+ *****************************************************************************/
+
+DOMIterator::DOMIterator(nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+{
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ mIter = NS_NewContentIterator();
+ DebugOnly<nsresult> rv = mIter->Init(&aNode);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+}
+
+nsresult
+DOMIterator::Init(nsRange& aRange)
+{
+ mIter = NS_NewContentIterator();
+ return mIter->Init(&aRange);
+}
+
+DOMIterator::DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
+{
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+}
+
+DOMIterator::~DOMIterator()
+{
+}
+
+void
+DOMIterator::AppendList(const BoolDomIterFunctor& functor,
+ nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const
+{
+ // Iterate through dom and build list
+ for (; !mIter->IsDone(); mIter->Next()) {
+ nsCOMPtr<nsINode> node = mIter->GetCurrentNode();
+
+ if (functor(node)) {
+ arrayOfNodes.AppendElement(*node);
+ }
+ }
+}
+
+DOMSubtreeIterator::DOMSubtreeIterator(
+ MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
+ : DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)
+{
+}
+
+nsresult
+DOMSubtreeIterator::Init(nsRange& aRange)
+{
+ mIter = NS_NewContentSubtreeIterator();
+ return mIter->Init(&aRange);
+}
+
+DOMSubtreeIterator::~DOMSubtreeIterator()
+{
+}
+
+/******************************************************************************
+ * some general purpose editor utils
+ *****************************************************************************/
+
+bool
+EditorUtils::IsDescendantOf(nsINode* aNode,
+ nsINode* aParent,
+ int32_t* aOffset)
+{
+ MOZ_ASSERT(aNode && aParent);
+ if (aNode == aParent) {
+ return false;
+ }
+
+ for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
+ if (node->GetParentNode() == aParent) {
+ if (aOffset) {
+ *aOffset = aParent->IndexOf(node);
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+EditorUtils::IsDescendantOf(nsIDOMNode* aNode,
+ nsIDOMNode* aParent,
+ int32_t* aOffset)
+{
+ nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+ nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
+ NS_ENSURE_TRUE(node && parent, false);
+ return IsDescendantOf(node, parent, aOffset);
+}
+
+bool
+EditorUtils::IsLeafNode(nsIDOMNode* aNode)
+{
+ bool hasChildren = false;
+ if (aNode)
+ aNode->HasChildNodes(&hasChildren);
+ return !hasChildren;
+}
+
+/******************************************************************************
+ * utility methods for drag/drop/copy/paste hooks
+ *****************************************************************************/
+
+nsresult
+EditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument* aDoc,
+ nsISimpleEnumerator** aResult)
+{
+ nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
+ NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
+ nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
+ NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
+
+ return hookObj->GetHookEnumerator(aResult);
+}
+
+bool
+EditorHookUtils::DoInsertionHook(nsIDOMDocument* aDoc,
+ nsIDOMEvent* aDropEvent,
+ nsITransferable *aTrans)
+{
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
+ NS_ENSURE_TRUE(enumerator, true);
+
+ bool hasMoreHooks = false;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) &&
+ hasMoreHooks) {
+ nsCOMPtr<nsISupports> isupp;
+ if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
+ break;
+ }
+
+ nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
+ if (override) {
+ bool doInsert = true;
+ DebugOnly<nsresult> hookResult =
+ override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
+ NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
+ NS_ENSURE_TRUE(doInsert, false);
+ }
+ }
+
+ return true;
+}
+
+} // namespace mozilla