editor/libeditor/base/nsEditorUtils.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:ad99a2fdd20b
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 #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"
22
23 class nsIDOMRange;
24 class nsISupports;
25
26 using namespace mozilla;
27 using namespace mozilla::dom;
28
29 /******************************************************************************
30 * nsAutoSelectionReset
31 *****************************************************************************/
32
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 }
45
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 }
54
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 }
62
63
64 /******************************************************************************
65 * some helper classes for iterating the dom tree
66 *****************************************************************************/
67
68 nsDOMIterator::nsDOMIterator() :
69 mIter(nullptr)
70 {
71 }
72
73 nsDOMIterator::~nsDOMIterator()
74 {
75 }
76
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 }
86
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 }
97
98 nsresult
99 nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
100 nsCOMArray<nsIDOMNode>& arrayOfNodes) const
101 {
102 nsCOMPtr<nsIDOMNode> node;
103
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);
109
110 if (functor(node))
111 {
112 arrayOfNodes.AppendObject(node);
113 }
114 mIter->Next();
115 }
116 return NS_OK;
117 }
118
119 nsDOMSubtreeIterator::nsDOMSubtreeIterator()
120 {
121 }
122
123 nsDOMSubtreeIterator::~nsDOMSubtreeIterator()
124 {
125 }
126
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 }
136
137 /******************************************************************************
138 * some general purpose editor utils
139 *****************************************************************************/
140
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;
146
147 nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(aNode);
148 nsresult res;
149
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);
169
170 return false;
171 }
172
173 bool
174 nsEditorUtils::IsLeafNode(nsIDOMNode *aNode)
175 {
176 bool hasChildren = false;
177 if (aNode)
178 aNode->HasChildNodes(&hasChildren);
179 return !hasChildren;
180 }
181
182 /******************************************************************************
183 * utility methods for drag/drop/copy/paste hooks
184 *****************************************************************************/
185
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);
192
193 nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
194 nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
195 NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
196
197 return hookObj->GetHookEnumerator(aResult);
198 }
199
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);
207
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;
214
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 }
227
228 return true;
229 }

mercurial