1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 :
39 : #include "nsEditorUtils.h"
40 : #include "nsIDOMDocument.h"
41 : #include "nsIDOMRange.h"
42 : #include "nsIContent.h"
43 : #include "nsLayoutCID.h"
44 :
45 : // hooks
46 : #include "nsIClipboardDragDropHooks.h"
47 : #include "nsIClipboardDragDropHookList.h"
48 : #include "nsISimpleEnumerator.h"
49 : #include "nsIDocShell.h"
50 : #include "nsIDocument.h"
51 : #include "nsIInterfaceRequestorUtils.h"
52 :
53 :
54 : /******************************************************************************
55 : * nsAutoSelectionReset
56 : *****************************************************************************/
57 :
58 0 : nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) :
59 : mSel(nsnull)
60 0 : ,mEd(nsnull)
61 : {
62 0 : if (!aSel || !aEd) return; // not much we can do, bail.
63 0 : if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
64 0 : mSel = do_QueryInterface(aSel);
65 0 : mEd = aEd;
66 0 : if (mSel)
67 : {
68 0 : mEd->PreserveSelectionAcrossActions(mSel);
69 : }
70 : }
71 :
72 0 : nsAutoSelectionReset::~nsAutoSelectionReset()
73 : {
74 0 : NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is");
75 0 : if (mSel && mEd->ArePreservingSelection()) // mSel will be null if this was nested call
76 : {
77 0 : mEd->RestorePreservedSelection(mSel);
78 : }
79 0 : }
80 :
81 : void
82 0 : nsAutoSelectionReset::Abort()
83 : {
84 0 : NS_ASSERTION(!mSel || mEd, "mEd should be non-null when mSel is");
85 0 : if (mSel)
86 0 : mEd->StopPreservingSelection();
87 0 : }
88 :
89 :
90 : /******************************************************************************
91 : * some helper classes for iterating the dom tree
92 : *****************************************************************************/
93 :
94 0 : nsDOMIterator::nsDOMIterator() :
95 0 : mIter(nsnull)
96 : {
97 0 : }
98 :
99 0 : nsDOMIterator::~nsDOMIterator()
100 : {
101 0 : }
102 :
103 : nsresult
104 0 : nsDOMIterator::Init(nsIDOMRange* aRange)
105 : {
106 : nsresult res;
107 0 : mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res);
108 0 : NS_ENSURE_SUCCESS(res, res);
109 0 : NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
110 0 : return mIter->Init(aRange);
111 : }
112 :
113 : nsresult
114 0 : nsDOMIterator::Init(nsIDOMNode* aNode)
115 : {
116 : nsresult res;
117 0 : mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res);
118 0 : NS_ENSURE_SUCCESS(res, res);
119 0 : NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
120 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
121 0 : return mIter->Init(content);
122 : }
123 :
124 : nsresult
125 0 : nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
126 : nsCOMArray<nsIDOMNode>& arrayOfNodes) const
127 : {
128 0 : nsCOMPtr<nsIDOMNode> node;
129 :
130 : // iterate through dom and build list
131 0 : while (!mIter->IsDone())
132 : {
133 0 : node = do_QueryInterface(mIter->GetCurrentNode());
134 0 : NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
135 :
136 0 : if (functor(node))
137 : {
138 0 : arrayOfNodes.AppendObject(node);
139 : }
140 0 : mIter->Next();
141 : }
142 0 : return NS_OK;
143 : }
144 :
145 0 : nsDOMSubtreeIterator::nsDOMSubtreeIterator()
146 : {
147 0 : }
148 :
149 0 : nsDOMSubtreeIterator::~nsDOMSubtreeIterator()
150 : {
151 0 : }
152 :
153 : nsresult
154 0 : nsDOMSubtreeIterator::Init(nsIDOMRange* aRange)
155 : {
156 : nsresult res;
157 0 : mIter = do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res);
158 0 : NS_ENSURE_SUCCESS(res, res);
159 0 : NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE);
160 0 : return mIter->Init(aRange);
161 : }
162 :
163 : /******************************************************************************
164 : * some general purpose editor utils
165 : *****************************************************************************/
166 :
167 : bool
168 0 : nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset)
169 : {
170 0 : NS_ENSURE_TRUE(aNode || aParent, false);
171 0 : if (aNode == aParent) return false;
172 :
173 0 : nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(aNode);
174 : nsresult res;
175 :
176 0 : do
177 : {
178 0 : res = node->GetParentNode(getter_AddRefs(parent));
179 0 : NS_ENSURE_SUCCESS(res, false);
180 0 : if (parent == aParent)
181 : {
182 0 : if (aOffset)
183 : {
184 0 : nsCOMPtr<nsIContent> pCon(do_QueryInterface(parent));
185 0 : nsCOMPtr<nsIContent> cCon(do_QueryInterface(node));
186 0 : if (pCon)
187 : {
188 0 : *aOffset = pCon->IndexOf(cCon);
189 : }
190 : }
191 0 : return true;
192 : }
193 0 : node = parent;
194 0 : } while (parent);
195 :
196 0 : return false;
197 : }
198 :
199 : bool
200 0 : nsEditorUtils::IsLeafNode(nsIDOMNode *aNode)
201 : {
202 0 : bool hasChildren = false;
203 0 : if (aNode)
204 0 : aNode->HasChildNodes(&hasChildren);
205 0 : return !hasChildren;
206 : }
207 :
208 : /******************************************************************************
209 : * utility methods for drag/drop/copy/paste hooks
210 : *****************************************************************************/
211 :
212 : nsresult
213 0 : nsEditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument *aDoc,
214 : nsISimpleEnumerator **aResult)
215 : {
216 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
217 0 : NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
218 :
219 0 : nsCOMPtr<nsISupports> container = doc->GetContainer();
220 0 : nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
221 0 : nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
222 0 : NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
223 :
224 0 : return hookObj->GetHookEnumerator(aResult);
225 : }
226 :
227 : bool
228 0 : nsEditorHookUtils::DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aDropEvent,
229 : nsITransferable *aTrans)
230 : {
231 0 : nsCOMPtr<nsISimpleEnumerator> enumerator;
232 0 : GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
233 0 : NS_ENSURE_TRUE(enumerator, true);
234 :
235 0 : bool hasMoreHooks = false;
236 0 : while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks)
237 : {
238 0 : nsCOMPtr<nsISupports> isupp;
239 0 : if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
240 : break;
241 :
242 0 : nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
243 0 : if (override)
244 : {
245 0 : bool doInsert = true;
246 : #ifdef DEBUG
247 : nsresult hookResult =
248 : #endif
249 0 : override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
250 0 : NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
251 0 : NS_ENSURE_TRUE(doInsert, false);
252 : }
253 : }
254 :
255 0 : return true;
256 : }
|