cleanup transferable hooks in editor; defer selection manipulation in plain text; ensure hooks are properly positioned (bug 203062) r=kaie, kin; sr=smfr

This commit is contained in:
brade%netscape.com 2003-04-25 21:05:32 +00:00
Родитель a8b6dc06df
Коммит 8795f96966
7 изменённых файлов: 268 добавлений и 260 удалений

Просмотреть файл

@ -45,6 +45,14 @@
#include "nsIEnumerator.h"
#include "nsISupportsArray.h"
// hooks
#include "nsIClipboardDragDropHooks.h"
#include "nsIClipboardDragDropHookList.h"
#include "nsISimpleEnumerator.h"
#include "nsIDocShell.h"
#include "nsIDocument.h"
#include "nsIInterfaceRequestorUtils.h"
/******************************************************************************
* nsAutoSelectionReset
@ -238,3 +246,141 @@ nsEditorUtils::IsLeafNode(nsIDOMNode *aNode)
aNode->HasChildNodes(&hasChildren);
return !hasChildren;
}
/******************************************************************************
* utility methods for drag/drop/copy/paste hooks
*****************************************************************************/
nsresult
nsEditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument *aDoc,
nsISimpleEnumerator **aResult)
{
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
if (!hookObj) return NS_ERROR_FAILURE;
return hookObj->GetHookEnumerator(aResult);
}
PRBool
nsEditorHookUtils::DoAllowDragHook(nsIDOMDocument *aDoc, nsIDOMEvent *aDragEvent)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
if (!enumerator)
return PR_TRUE;
PRBool hasMoreHooks = PR_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)
{
PRBool canDrag = PR_TRUE;
nsresult hookres = override->AllowStartDrag(aDragEvent, &canDrag);
NS_ASSERTION(NS_SUCCEEDED(hookres), "hook failure in AllowStartDrag");
if (!canDrag)
return PR_FALSE;
}
}
return PR_TRUE;
}
PRBool
nsEditorHookUtils::DoDragHook(nsIDOMDocument *aDoc, nsITransferable *aTrans)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
if (!enumerator)
return PR_TRUE;
PRBool hasMoreHooks = PR_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)
{
PRBool canInvokeDrag = PR_TRUE;
nsresult hookResult = override->OnCopyOrDrag(aTrans, &canInvokeDrag);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag");
if (!canInvokeDrag)
return PR_FALSE;
}
}
return PR_TRUE;
}
PRBool
nsEditorHookUtils::DoAllowDropHook(nsIDOMDocument *aDoc, nsIDOMEvent *aEvent,
nsIDragSession *aSession)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
if (!enumerator)
return PR_TRUE;
PRBool hasMoreHooks = PR_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)
{
PRBool allowDrop = PR_TRUE;
nsresult hookResult = override->AllowDrop(aEvent, aSession, &allowDrop);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowDrop");
if (!allowDrop)
return PR_FALSE;
}
}
return PR_TRUE;
}
PRBool
nsEditorHookUtils::DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aDropEvent,
nsITransferable *aTrans)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
if (!enumerator)
return PR_TRUE;
PRBool hasMoreHooks = PR_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)
{
PRBool doInsert = PR_TRUE;
nsresult hookResult = override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
if (!doInsert)
return PR_FALSE;
}
}
return PR_TRUE;
}

Просмотреть файл

@ -266,4 +266,24 @@ class nsEditorUtils
static PRBool IsLeafNode(nsIDOMNode *aNode);
};
class nsIDragSession;
class nsITransferable;
class nsIDOMEvent;
class nsISimpleEnumerator;
class nsEditorHookUtils
{
public:
static PRBool DoAllowDragHook(nsIDOMDocument *aDoc, nsIDOMEvent *aEvent);
static PRBool DoDragHook(nsIDOMDocument *aDoc, nsITransferable *aTrans);
static PRBool DoAllowDropHook(nsIDOMDocument *aDoc, nsIDOMEvent *aEvent,
nsIDragSession *aSession);
static PRBool DoInsertionHook(nsIDOMDocument *aDoc, nsIDOMEvent *aEvent,
nsITransferable *aTrans);
private:
static nsresult GetHookEnumeratorFromDocument(nsIDOMDocument *aDoc,
nsISimpleEnumerator **aEnumerator);
};
#endif // nsEditorUtils_h__

Просмотреть файл

@ -1073,7 +1073,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable
stuffToPaste.Assign(text.get(), len / 2);
nsAutoEditBatch beginBatching(this);
// need to provide a hook from this point
rv = InsertText(stuffToPaste);
rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
}
}
else if (flavor.Equals(NS_LITERAL_STRING(kFileMime)))
@ -1164,8 +1164,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (!dragSession) return NS_OK;
// transferable hooks here
PRBool isAllowed = PR_TRUE;
DoAllowDropHook(aDropEvent, dragSession, &isAllowed);
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
PRBool isAllowed = nsEditorHookUtils::DoAllowDropHook(domdoc, aDropEvent, dragSession);
if (!isAllowed)
return NS_OK;
@ -1181,12 +1182,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (NS_FAILED(rv)) return rv;
if (!trans) return NS_OK; // NS_ERROR_FAILURE; SHOULD WE FAIL?
// handle transferable hooks
PRBool doInsert = PR_TRUE;
DoInsertionHook(aDropEvent, trans, &doInsert);
if (!doInsert)
return NS_OK;
PRUint32 numItems = 0;
rv = dragSession->GetNumDropItems(&numItems);
if (NS_FAILED(rv)) return rv;
@ -1194,6 +1189,11 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
// Combine any deletion and drop insertion into one transaction
nsAutoEditBatch beginBatching(this);
// We never have to delete if selection is already collapsed
PRBool deleteSelection = PR_FALSE;
nsCOMPtr<nsIDOMNode> newSelectionParent;
PRInt32 newSelectionOffset = 0;
PRUint32 i;
PRBool doPlaceCaret = PR_TRUE;
for (i = 0; i < numItems; ++i)
@ -1238,11 +1238,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
infoStr.Assign(text.get(), infoLen / 2);
}
// We never have to delete if selection is already collapsed
PRBool deleteSelection = PR_FALSE;
nsCOMPtr<nsIDOMNode> newSelectionParent;
PRInt32 newSelectionOffset = 0;
if (doPlaceCaret)
{
// check if the user pressed the key to force a copy rather than a move
@ -1372,6 +1367,11 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
doPlaceCaret = PR_FALSE;
}
// handle transferable hooks
PRBool doInsert = nsEditorHookUtils::DoInsertionHook(domdoc, aDropEvent, trans);
if (!doInsert)
return NS_OK;
rv = InsertFromTransferable(trans, contextStr, infoStr, newSelectionParent,
newSelectionOffset, deleteSelection);
}
@ -1541,12 +1541,6 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
rv = PrepareHTMLTransferable(getter_AddRefs(trans), bHavePrivateHTMLFlavor);
if (NS_SUCCEEDED(rv) && trans)
{
// handle transferable hooks
PRBool doInsert = PR_TRUE;
DoInsertionHook(nsnull, trans, &doInsert);
if (!doInsert)
return NS_OK;
// Get the Data from the clipboard
if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
{
@ -1590,6 +1584,14 @@ NS_IMETHODIMP nsHTMLEditor::Paste(PRInt32 aSelectionType)
infoStr.Assign(text.get(), infoLen / 2);
}
}
// handle transferable hooks
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
PRBool doInsert = nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, trans);
if (!doInsert)
return NS_OK;
rv = InsertFromTransferable(trans, contextStr, infoStr,
nsnull, 0, PR_TRUE);
}

Просмотреть файл

@ -45,7 +45,6 @@ REQUIRES = xpcom \
gfx \
widget \
unicharutil \
docshell \
$(NULL)
CPPSRCS = \

Просмотреть файл

@ -86,6 +86,7 @@
#include "nsISupportsPrimitives.h"
#include "nsLayoutCID.h"
#include "nsIDOMNSRange.h"
#include "nsEditorUtils.h"
// Drag & Drop, Clipboard Support
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
@ -661,6 +662,13 @@ nsTextEditorDragListener::DragOver(nsIDOMEvent* aDragEvent)
if (!dragSession) return NS_ERROR_FAILURE;
PRBool canDrop = CanDrop(aDragEvent);
if (canDrop)
{
nsCOMPtr<nsIDOMDocument> domdoc;
mEditor->GetDocument(getter_AddRefs(domdoc));
canDrop = nsEditorHookUtils::DoAllowDropHook(domdoc, aDragEvent, dragSession);
}
dragSession->SetCanDrop(canDrop);
// We need to consume the event to prevent the browser's

Просмотреть файл

@ -35,95 +35,45 @@
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsICaret.h"
#include "nsPlaintextEditor.h"
#include "nsTextEditUtils.h"
#include "nsIDOMText.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMDocument.h"
#include "nsIDOMAttr.h"
#include "nsIDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMNSEvent.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseEvent.h"
#include "nsISelection.h"
#include "nsISelectionPrivate.h"
#include "nsIDOMHTMLAnchorElement.h"
#include "nsIDOMHTMLImageElement.h"
#include "nsISelectionController.h"
#include "nsCRT.h"
#include "nsIServiceManagerUtils.h"
#include "nsIFrameSelection.h" // For TABLESELECTION_ defines
#include "nsICSSLoader.h"
#include "nsICSSStyleSheet.h"
#include "nsIHTMLContentContainer.h"
#include "nsIStyleSet.h"
#include "nsIDocumentObserver.h"
#include "nsIDocumentStateListener.h"
#include "nsIEnumerator.h"
#include "nsIContent.h"
#include "nsIContentIterator.h"
#include "nsEditorCID.h"
#include "nsLayoutCID.h"
#include "nsIDOMRange.h"
#include "nsIDOMNSRange.h"
#include "nsISupportsArray.h"
#include "nsVoidArray.h"
#include "nsIURL.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsIDocumentEncoder.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIImage.h"
#include "nsAOLCiter.h"
#include "nsInternetCiter.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
// netwerk
#include "nsIURI.h"
#include "nsNetUtil.h"
// Drag & Drop, Clipboard
#include "nsWidgetsCID.h"
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsIDragService.h"
#include "nsIDOMNSUIEvent.h"
#include "nsIDocShell.h"
#include "nsIClipboardDragDropHooks.h"
#include "nsIClipboardDragDropHookList.h"
#include "nsISimpleEnumerator.h"
// Misc
#include "nsEditorUtils.h"
#include "nsIPref.h"
const PRUnichar nbsp = 160;
// Drag & Drop, Clipboard Support
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
static NS_DEFINE_CID(kCHTMLFormatConverterCID, NS_HTMLFORMATCONVERTER_CID);
// private clipboard data flavors for html copy/paste
#define kHTMLContext "text/_moz_htmlcontext"
#define kHTMLInfo "text/_moz_htmlinfo"
#if defined(NS_DEBUG) && defined(DEBUG_buster)
static PRBool gNoisy = PR_FALSE;
#else
static const PRBool gNoisy = PR_FALSE;
#endif
NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transferable)
{
@ -139,13 +89,47 @@ NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transfera
return NS_OK;
}
NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *transferable)
nsresult nsPlaintextEditor::InsertTextAt(const nsAString &aStringToInsert,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
PRBool aDoDeleteSelection)
{
if (aDestinationNode)
{
nsresult res;
nsCOMPtr<nsISelection>selection;
res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> targetNode = aDestinationNode;
PRInt32 targetOffset = aDestOffset;
if (aDoDeleteSelection)
{
// Use an auto tracker so that our drop point is correctly
// positioned after the delete.
nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
res = DeleteSelection(eNone);
NS_ENSURE_SUCCESS(res, res);
}
res = selection->Collapse(targetNode, targetOffset);
NS_ENSURE_SUCCESS(res, res);
}
return InsertText(aStringToInsert);
}
NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *aTransferable,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
PRBool aDoDeleteSelection)
{
nsresult rv = NS_OK;
char* bestFlavor = nsnull;
nsCOMPtr<nsISupports> genericDataObj;
PRUint32 len = 0;
if ( NS_SUCCEEDED(transferable->GetAnyTransferData(&bestFlavor, getter_AddRefs(genericDataObj), &len)) )
if ( NS_SUCCEEDED(aTransferable->GetAnyTransferData(&bestFlavor, getter_AddRefs(genericDataObj), &len)) )
{
nsAutoTxnsConserveSelection dontSpazMySelection(this);
nsAutoString flavor, stuffToPaste;
@ -160,7 +144,7 @@ NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *tra
NS_ASSERTION(text.Length() <= (len/2), "Invalid length!");
stuffToPaste.Assign ( text.get(), len / 2 );
nsAutoEditBatch beginBatching(this);
rv = InsertText(stuffToPaste);
rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
}
}
}
@ -187,8 +171,9 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (!dragSession) return NS_OK;
// transferable hooks
PRBool isAllowed = PR_TRUE;
DoAllowDropHook(aDropEvent, dragSession, &isAllowed);
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
PRBool isAllowed = nsEditorHookUtils::DoAllowDropHook(domdoc, aDropEvent, dragSession);
if (!isAllowed)
return NS_OK;
@ -198,11 +183,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (NS_FAILED(rv)) return rv;
if (!trans) return NS_OK; // NS_ERROR_FAILURE; SHOULD WE FAIL?
PRBool doInsert = PR_TRUE;
DoInsertionHook(aDropEvent, trans, &doInsert);
if (!doInsert)
return NS_OK;
PRUint32 numItems = 0;
rv = dragSession->GetNumDropItems(&numItems);
if (NS_FAILED(rv)) return rv;
@ -210,6 +190,10 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
// Combine any deletion and drop insertion into one transaction
nsAutoEditBatch beginBatching(this);
PRBool deleteSelection = PR_FALSE;
nsCOMPtr<nsIDOMNode> newSelectionParent;
PRInt32 newSelectionOffset = 0;
PRUint32 i;
PRBool doPlaceCaret = PR_TRUE;
for (i = 0; i < numItems; ++i)
@ -255,8 +239,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (NS_FAILED(rv)) return rv;
// Parent and offset under the mouse cursor
nsCOMPtr<nsIDOMNode> newSelectionParent;
PRInt32 newSelectionOffset = 0;
rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
if (NS_FAILED(rv)) return rv;
if (!newSelectionParent) return NS_ERROR_FAILURE;
@ -265,7 +247,6 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
if (NS_FAILED(rv)) return rv;
// We never have to delete if selection is already collapsed
PRBool deleteSelection = PR_FALSE;
PRBool cursorIsInSelection = PR_FALSE;
// Check if mouse is in the selection
@ -320,27 +301,15 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
}
}
if (deleteSelection)
{
// Use an auto tracker so that our drop point is correctly
// positioned after the delete.
nsAutoTrackDOMPoint tracker(mRangeUpdater, &newSelectionParent, &newSelectionOffset);
rv = DeleteSelection(eNone);
if (NS_FAILED(rv)) return rv;
}
// If we deleted the selection because we dropped from another doc,
// then we don't have to relocate the caret (insert at the deletion point)
if (!(deleteSelection && srcdomdoc != destdomdoc))
{
// Move the selection to the point under the mouse cursor
selection->Collapse(newSelectionParent, newSelectionOffset);
}
// We have to figure out whether to delete and relocate caret only once
doPlaceCaret = PR_FALSE;
}
rv = InsertTextFromTransferable(trans);
PRBool doInsert = nsEditorHookUtils::DoInsertionHook(domdoc, aDropEvent, trans);
if (!doInsert)
return NS_OK;
rv = InsertTextFromTransferable(trans, newSelectionParent, newSelectionOffset, deleteSelection);
}
return rv;
@ -403,37 +372,7 @@ NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDr
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
if (!hookObj) return NS_ERROR_FAILURE;
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
if (!enumerator) return NS_ERROR_FAILURE;
nsCOMPtr<nsIClipboardDragDropHooks> override;
PRBool hasMoreHooks = PR_FALSE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks)
{
res = enumerator->GetNext(getter_AddRefs(isupp));
if (NS_FAILED(res)) break;
override = do_QueryInterface(isupp);
if (override)
{
res = override->AllowStartDrag(aDragEvent, aCanDrag);
NS_ASSERTION(NS_SUCCEEDED(res), "hook failure in AllowStartDrag");
}
if (!*aCanDrag)
break;
}
*aCanDrag = nsEditorHookUtils::DoAllowDragHook(domdoc, aDragEvent);
return NS_OK;
}
@ -464,38 +403,8 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
// check our transferable hooks (if any)
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
if (!hookObj) return NS_ERROR_FAILURE;
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
if (!enumerator) return NS_ERROR_FAILURE;
nsCOMPtr<nsIClipboardDragDropHooks> override;
PRBool canInvokeDrag = PR_TRUE;
PRBool hasMoreHooks = PR_FALSE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks)
{
rv = enumerator->GetNext(getter_AddRefs(isupp));
if (NS_FAILED(rv)) break;
override = do_QueryInterface(isupp);
if (override)
{
nsresult hookResult = override->OnCopyOrDrag(trans, &canInvokeDrag);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag");
}
// if one of our overrides says we can't invoke drag, return now
if (!canInvokeDrag)
return NS_OK;
}
if (!nsEditorHookUtils::DoDragHook(domdoc, trans))
return NS_OK;
/* invoke drag */
nsCOMPtr<nsIDOMEventTarget> eventTarget;
@ -532,16 +441,17 @@ NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
rv = PrepareTransferable(getter_AddRefs(trans));
if (NS_SUCCEEDED(rv) && trans)
{
// handle transferable hooks
PRBool doInsert = PR_TRUE;
DoInsertionHook(nsnull, trans, &doInsert);
if (!doInsert)
return NS_OK;
// Get the Data from the clipboard
if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
{
rv = InsertTextFromTransferable(trans);
// handle transferable hooks
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
PRBool doInsert = nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, trans);
if (!doInsert)
return NS_OK;
rv = InsertTextFromTransferable(trans, nsnull, nsnull, PR_TRUE);
}
}
@ -707,84 +617,3 @@ nsPlaintextEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
NS_ADDREF(*aTransferable);
return NS_OK;
}
nsresult
nsPlaintextEditor::DoAllowDropHook(nsIDOMEvent* aDropEvent,
nsIDragSession *aSession, PRBool *aAllowDrop)
{
*aAllowDrop = PR_TRUE;
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
if (!hookObj) return NS_ERROR_FAILURE;
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
if (!enumerator) return NS_ERROR_FAILURE;
nsCOMPtr<nsIClipboardDragDropHooks> override;
PRBool hasMoreHooks = PR_FALSE;
nsresult res = NS_OK;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks)
{
res = enumerator->GetNext(getter_AddRefs(isupp));
if (NS_FAILED(res)) break;
override = do_QueryInterface(isupp);
if (override)
{
nsresult hookResult = override->AllowDrop(aDropEvent, aSession, aAllowDrop);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowDrop");
}
if (!*aAllowDrop)
break;
}
return res;
}
nsresult
nsPlaintextEditor::DoInsertionHook(nsIDOMEvent* aDropEvent,
nsITransferable *aTrans, PRBool *aDoInsert)
{
nsCOMPtr<nsIDOMDocument> domdoc;
GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
if (!hookObj) return NS_ERROR_FAILURE;
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
if (!enumerator) return NS_ERROR_FAILURE;
nsCOMPtr<nsIClipboardDragDropHooks> override;
PRBool hasMoreHooks = PR_FALSE;
nsresult res = NS_OK;
while (*aDoInsert &&
NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) && hasMoreHooks)
{
res = enumerator->GetNext(getter_AddRefs(isupp));
if (NS_FAILED(res)) break;
override = do_QueryInterface(isupp);
if (override)
{
nsresult hookResult = override->OnPasteOrDrop(aDropEvent, aTrans, aDoInsert);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
}
}
return res;
}

Просмотреть файл

@ -55,7 +55,6 @@ class nsIDOMKeyEvent;
class nsITransferable;
class nsIDOMEventReceiver;
class nsIDocumentEncoder;
class nsIDragSession;
/**
* The text editor implementation.
@ -186,6 +185,11 @@ public:
PRInt32 &aOutStartOffset,
PRInt32 &aEndOffset);
nsresult InsertTextAt(const nsAString &aStringToInsert,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
PRBool aDoDeleteSelection);
protected:
NS_IMETHOD InitRules();
@ -226,12 +230,12 @@ protected:
// factored methods for handling insertion of data from transferables (drag&drop or clipboard)
NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable);
NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable,
nsIDOMNode *aDestinationNode,
PRInt32 aDestOffset,
PRBool aDoDeleteSelection);
virtual nsresult SetupDocEncoder(nsIDocumentEncoder **aDocEncoder);
virtual nsresult PutDragDataInTransferable(nsITransferable **aTransferable);
virtual nsresult DoAllowDropHook(nsIDOMEvent* aDropEvent, nsIDragSession *aSession, PRBool *aAllowDrop);
virtual nsresult DoInsertionHook(nsIDOMEvent* aDropEvent,
nsITransferable *aTrans, PRBool *aDoInsert);
/** simple utility to handle any error with event listener allocation or registration */
void HandleEventListenerError();