diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
index 11b8433b72e..a13968ea82e 100644
--- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -1163,6 +1163,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
dragService->GetCurrentSession(getter_AddRefs(dragSession));
if (!dragSession) return NS_OK;
+ // transferable hooks here
+ PRBool isAllowed = PR_TRUE;
+ DoAllowDropHook(aDropEvent, dragSession, &isAllowed);
+ if (!isAllowed)
+ return NS_OK;
+
// find out if we have our internal html flavor on the clipboard. We don't want to mess
// around with cfhtml if we do.
PRBool bHavePrivateHTMLFlavor = PR_FALSE;
@@ -1302,7 +1308,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
}
// 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
@@ -1370,232 +1375,120 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDrag)
{
- if (!aCanDrag)
- return NS_ERROR_NULL_POINTER;
-
- /* we really should be checking the XY coordinates of the mouseevent and ensure that
- * that particular point is actually within the selection (not just that there is a selection)
- */
- *aCanDrag = PR_FALSE;
-
- // KLUDGE to work around bug 50703
- // After double click and object property editing,
- // we get a spurious drag event
- if (mIgnoreSpuriousDragEvent)
- {
-#ifdef DEBUG_cmanske
- printf(" *** IGNORING SPURIOUS DRAG EVENT!\n");
-#endif
- mIgnoreSpuriousDragEvent = PR_FALSE;
- return NS_OK;
- }
-
- nsCOMPtr selection;
- nsresult res = GetSelection(getter_AddRefs(selection));
- if (NS_FAILED(res)) return res;
-
- PRBool isCollapsed;
- res = selection->GetIsCollapsed(&isCollapsed);
- if (NS_FAILED(res)) return res;
-
- // if we are collapsed, we have no selection so nothing to drag
- if (isCollapsed)
- return NS_OK;
-
- nsCOMPtr eventTarget;
-
- nsCOMPtr nsevent(do_QueryInterface(aDragEvent));
-
- if (nsevent)
- {
- res = nsevent->GetExplicitOriginalTarget(getter_AddRefs(eventTarget));
- if (NS_FAILED(res))
- {
- return res;
- }
- }
-
- if (eventTarget)
- {
- nsCOMPtr eventTargetDomNode = do_QueryInterface(eventTarget);
- if (eventTargetDomNode)
- {
- PRBool isTargetedCorrectly = PR_FALSE;
- res = selection->ContainsNode(eventTargetDomNode, PR_FALSE, &isTargetedCorrectly);
- if (NS_FAILED(res)) return res;
-
- *aCanDrag = isTargetedCorrectly;
- }
- }
-
- return NS_OK;
+ return nsPlaintextEditor::CanDrag(aDragEvent, aCanDrag);
}
-NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent)
+nsresult
+nsHTMLEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
{
- nsresult rv;
-
- nsCOMPtr eventTarget;
- rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget));
+ NS_ENSURE_ARG_POINTER(aTransferable);
+ *aTransferable = nsnull;
+ nsCOMPtr docEncoder;
+ nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
if (NS_FAILED(rv)) return rv;
- nsCOMPtr domnode = do_QueryInterface(eventTarget);
+ NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
- /* get the selection to be dragged */
- nsCOMPtr selection;
- rv = GetSelection(getter_AddRefs(selection));
+ // grab a string
+ nsAutoString buffer, parents, info;
+
+ // find out if we're a plaintext control or not
+ PRUint32 editorFlags = 0;
+ rv = GetFlags(&editorFlags);
if (NS_FAILED(rv)) return rv;
- /* create an array of transferables */
- nsCOMPtr transferableArray;
- NS_NewISupportsArray(getter_AddRefs(transferableArray));
- if (transferableArray == nsnull)
- return NS_ERROR_OUT_OF_MEMORY;
+ PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0);
+ if (!bIsPlainTextControl)
+ {
+ // encode the selection as html with contextual info
+ rv = docEncoder->EncodeToStringWithContext(buffer, parents, info);
+ if (NS_FAILED(rv)) return rv;
+ }
+ else
+ {
+ // encode the selection
+ rv = docEncoder->EncodeToString(buffer);
+ if (NS_FAILED(rv)) return rv;
+ }
- /* get the drag service */
- nsCOMPtr dragService =
- do_GetService("@mozilla.org/widget/dragservice;1", &rv);
+ // if we have an empty string, we're done; otherwise continue
+ if ( buffer.IsEmpty() )
+ return NS_OK;
+
+ nsCOMPtr dataWrapper, contextWrapper, infoWrapper;
+
+ dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = dataWrapper->SetData(buffer);
if (NS_FAILED(rv)) return rv;
/* create html flavor transferable */
nsCOMPtr trans = do_CreateInstance(kCTransferableCID);
NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
- nsCOMPtr domdoc;
- rv = GetDocument(getter_AddRefs(domdoc));
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr doc = do_QueryInterface(domdoc);
- if (doc)
+ if (bIsPlainTextControl)
{
- // find out if we're a plaintext control or not
- PRUint32 editorFlags = 0;
- rv = GetFlags(&editorFlags);
+ // Add the unicode flavor to the transferable
+ rv = trans->AddDataFlavor(kUnicodeMime);
if (NS_FAILED(rv)) return rv;
- PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0);
-
- // get correct mimeType and document encoder flags set
- nsAutoString mimeType;
- PRUint32 docEncoderFlags = 0;
- if (bIsPlainTextControl)
- {
- docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
- mimeType = NS_LITERAL_STRING(kUnicodeMime);
- }
- else
- mimeType = NS_LITERAL_STRING(kHTMLMime);
-
- // set up docEncoder
- nsCOMPtr docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
- NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
-
- rv = docEncoder->Init(doc, mimeType, docEncoderFlags);
+ // QI the data object an |nsISupports| so that when the transferable holds
+ // onto it, it will addref the correct interface.
+ nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper));
+ rv = trans->SetTransferData(kUnicodeMime, genericDataObj,
+ buffer.Length() * sizeof(PRUnichar));
if (NS_FAILED(rv)) return rv;
-
- rv = docEncoder->SetSelection(selection);
+ }
+ else
+ {
+ contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+ NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE);
+ infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+ NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE);
+
+ contextWrapper->SetData(parents);
+ infoWrapper->SetData(info);
+
+ rv = trans->AddDataFlavor(kHTMLMime);
if (NS_FAILED(rv)) return rv;
- // grab a string
- nsAutoString buffer, parents, info;
+ nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID);
+ NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
- if (!bIsPlainTextControl)
+ rv = trans->SetConverter(htmlConverter);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper));
+ rv = trans->SetTransferData(kHTMLMime, genericDataObj,
+ buffer.Length() * sizeof(PRUnichar));
+ if (NS_FAILED(rv)) return rv;
+
+ if (!parents.IsEmpty())
{
- // encode the selection as html with contextual info
- rv = docEncoder->EncodeToStringWithContext(buffer, parents, info);
- if (NS_FAILED(rv)) return rv;
+ // Add the htmlcontext DataFlavor to the transferable
+ trans->AddDataFlavor(kHTMLContext);
+ genericDataObj = do_QueryInterface(contextWrapper);
+ trans->SetTransferData(kHTMLContext, genericDataObj,
+ parents.Length() * sizeof(PRUnichar));
}
- else
+ if (!info.IsEmpty())
{
- // encode the selection
- rv = docEncoder->EncodeToString(buffer);
- if (NS_FAILED(rv)) return rv;
- }
-
- // if we have an empty string, we're done; otherwise continue
- if (!buffer.IsEmpty())
- {
- nsCOMPtr dataWrapper, contextWrapper, infoWrapper;
-
- dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE);
- rv = dataWrapper->SetData(buffer);
- if (NS_FAILED(rv)) return rv;
-
- if (bIsPlainTextControl)
- {
- // Add the unicode flavor to the transferable
- rv = trans->AddDataFlavor(kUnicodeMime);
- if (NS_FAILED(rv)) return rv;
-
- // QI the data object an |nsISupports| so that when the transferable holds
- // onto it, it will addref the correct interface.
- nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper));
- rv = trans->SetTransferData(kUnicodeMime, genericDataObj, buffer.Length() * 2);
- if (NS_FAILED(rv)) return rv;
- }
- else
- {
- contextWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(contextWrapper, NS_ERROR_FAILURE);
- infoWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(infoWrapper, NS_ERROR_FAILURE);
-
- contextWrapper->SetData(parents);
- infoWrapper->SetData(info);
-
- rv = trans->AddDataFlavor(kHTMLMime);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID);
- NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
-
- rv = trans->SetConverter(htmlConverter);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr genericDataObj(do_QueryInterface(dataWrapper));
- rv = trans->SetTransferData(kHTMLMime, genericDataObj, buffer.Length() * 2);
- if (NS_FAILED(rv)) return rv;
-
- if (parents.Length())
- {
- // Add the htmlcontext DataFlavor to the transferable
- trans->AddDataFlavor(kHTMLContext);
- genericDataObj = do_QueryInterface(contextWrapper);
- trans->SetTransferData(kHTMLContext, genericDataObj, parents.Length()*2);
- }
- if (info.Length())
- {
- // Add the htmlinfo DataFlavor to the transferable
- trans->AddDataFlavor(kHTMLInfo);
- genericDataObj = do_QueryInterface(infoWrapper);
- trans->SetTransferData(kHTMLInfo, genericDataObj, info.Length()*2);
- }
- }
-
- /* add the transferable to the array */
- rv = transferableArray->AppendElement(trans);
- if (NS_FAILED(rv)) return rv;
-
- /* invoke drag */
- unsigned int flags;
- // in some cases we'll want to cut rather than copy... hmmmmm...
- flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE;
-
- rv = dragService->InvokeDragSession(domnode, transferableArray, nsnull, flags);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr nsevent(do_QueryInterface(aDragEvent));
-
- if (nsevent)
- {
- nsevent->PreventBubble();
- }
+ // Add the htmlinfo DataFlavor to the transferable
+ trans->AddDataFlavor(kHTMLInfo);
+ genericDataObj = do_QueryInterface(infoWrapper);
+ trans->SetTransferData(kHTMLInfo, genericDataObj,
+ info.Length() * sizeof(PRUnichar));
}
}
- return rv;
+ *aTransferable = trans;
+ NS_ADDREF(*aTransferable);
+ return NS_OK;
}
+NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent)
+{
+ return nsPlaintextEditor::DoDrag(aDragEvent);
+}
PRBool nsHTMLEditor::HavePrivateHTMLFlavor(nsIClipboard *aClipboard)
{
@@ -1642,6 +1535,12 @@ 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())
{
@@ -2267,7 +2166,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
nsCOMPtr contextfrag;
nsCOMPtr contextLeaf, junk;
PRInt32 contextDepth = 0;
- if (aContextStr.Length())
+ if (!aContextStr.IsEmpty())
{
res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode));
NS_ENSURE_SUCCESS(res, res);
@@ -2317,7 +2216,7 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(const nsAString &aInputString,
// get the infoString contents
nsAutoString numstr1, numstr2;
- if (aInfoStr.Length())
+ if (!aInfoStr.IsEmpty())
{
PRInt32 err, sep;
sep = aInfoStr.FindChar((PRUnichar)',');
diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h
index 03d8cf3a11d..07f9c796eb9 100644
--- a/mozilla/editor/libeditor/html/nsHTMLEditor.h
+++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h
@@ -672,6 +672,7 @@ protected:
// factored methods for handling insertion of data from transferables (drag&drop or clipboard)
NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
NS_IMETHOD PrepareHTMLTransferable(nsITransferable **transferable, PRBool havePrivFlavor);
+ nsresult PutDragDataInTransferable(nsITransferable **aTransferable);
NS_IMETHOD InsertFromTransferable(nsITransferable *transferable,
const nsAString & aContextStr,
const nsAString & aInfoStr,
diff --git a/mozilla/editor/libeditor/text/Makefile.in b/mozilla/editor/libeditor/text/Makefile.in
index 4670c77b2ec..fac4c15b94b 100644
--- a/mozilla/editor/libeditor/text/Makefile.in
+++ b/mozilla/editor/libeditor/text/Makefile.in
@@ -45,6 +45,7 @@ REQUIRES = xpcom \
gfx \
widget \
unicharutil \
+ docshell \
$(NULL)
CPPSRCS = \
diff --git a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp
index 46a6cf12ae7..7e0c9e9887c 100644
--- a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -100,6 +100,10 @@
#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"
@@ -182,12 +186,23 @@ NS_IMETHODIMP nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
dragService->GetCurrentSession(getter_AddRefs(dragSession));
if (!dragSession) return NS_OK;
+ // transferable hooks
+ PRBool isAllowed = PR_TRUE;
+ DoAllowDropHook(aDropEvent, dragSession, &isAllowed);
+ if (!isAllowed)
+ return NS_OK;
+
// Get the nsITransferable interface for getting the data from the drop
nsCOMPtr trans;
rv = PrepareTransferable(getter_AddRefs(trans));
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;
@@ -366,13 +381,11 @@ NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDr
nsCOMPtr nsevent(do_QueryInterface(aDragEvent));
if (nsevent) {
- res = nsevent->GetOriginalTarget(getter_AddRefs(eventTarget));
- if (NS_FAILED(res)) {
- return res;
- }
+ res = nsevent->GetExplicitOriginalTarget(getter_AddRefs(eventTarget));
+ if (NS_FAILED(res)) return res;
}
- if ( eventTarget )
+ if (eventTarget)
{
nsCOMPtr eventTargetDomNode = do_QueryInterface(eventTarget);
if ( eventTargetDomNode )
@@ -385,6 +398,42 @@ NS_IMETHODIMP nsPlaintextEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool *aCanDr
}
}
+ if (NS_FAILED(res)) return res;
+ if (!*aCanDrag) return NS_OK;
+
+ nsCOMPtr domdoc;
+ GetDocument(getter_AddRefs(domdoc));
+ nsCOMPtr doc = do_QueryInterface(domdoc);
+ if (!doc) return NS_ERROR_FAILURE;
+
+ nsCOMPtr isupp;
+ doc->GetContainer(getter_AddRefs(isupp));
+ nsCOMPtr docShell = do_QueryInterface(isupp);
+ nsCOMPtr hookObj = do_GetInterface(docShell);
+ if (!hookObj) return NS_ERROR_FAILURE;
+
+ nsCOMPtr enumerator;
+ hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
+ if (!enumerator) return NS_ERROR_FAILURE;
+
+ nsCOMPtr 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;
+ }
+
return NS_OK;
}
@@ -392,14 +441,14 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
{
nsresult rv;
- nsCOMPtr eventTarget;
- rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget));
+ nsCOMPtr trans;
+ rv = PutDragDataInTransferable(getter_AddRefs(trans));
if (NS_FAILED(rv)) return rv;
- nsCOMPtr domnode = do_QueryInterface(eventTarget);
+ if (!trans) return NS_OK; // maybe there was nothing to copy?
- /* get the selection to be dragged */
- nsCOMPtr selection;
- rv = GetSelection(getter_AddRefs(selection));
+ /* get the drag service */
+ nsCOMPtr dragService =
+ do_GetService("@mozilla.org/widget/dragservice;1", &rv);
if (NS_FAILED(rv)) return rv;
/* create an array of transferables */
@@ -408,109 +457,63 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent)
if (transferableArray == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
- /* get the drag service */
- nsCOMPtr dragService =
- do_GetService("@mozilla.org/widget/dragservice;1", &rv);
+ /* add the transferable to the array */
+ rv = transferableArray->AppendElement(trans);
if (NS_FAILED(rv)) return rv;
- /* create html flavor transferable */
- nsCOMPtr trans = do_CreateInstance(kCTransferableCID);
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
-
+ // check our transferable hooks (if any)
nsCOMPtr domdoc;
- rv = GetDocument(getter_AddRefs(domdoc));
- if (NS_FAILED(rv)) return rv;
-
+ GetDocument(getter_AddRefs(domdoc));
nsCOMPtr doc = do_QueryInterface(domdoc);
- if (doc)
+ if (!doc) return NS_ERROR_FAILURE;
+
+ nsCOMPtr isupp;
+ doc->GetContainer(getter_AddRefs(isupp));
+ nsCOMPtr docShell = do_QueryInterface(isupp);
+ nsCOMPtr hookObj = do_GetInterface(docShell);
+ if (!hookObj) return NS_ERROR_FAILURE;
+
+ nsCOMPtr enumerator;
+ hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
+ if (!enumerator) return NS_ERROR_FAILURE;
+
+ nsCOMPtr override;
+ PRBool canInvokeDrag = PR_TRUE;
+ PRBool hasMoreHooks = PR_FALSE;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
+ && hasMoreHooks)
{
- // find out if we're a plaintext control or not
- PRUint32 editorFlags = 0;
- rv = GetFlags(&editorFlags);
- if (NS_FAILED(rv)) return rv;
-
- PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0);
-
- // get correct mimeType and document encoder flags set
- nsAutoString mimeType;
- PRUint32 docEncoderFlags = 0;
- if (bIsPlainTextControl)
+ rv = enumerator->GetNext(getter_AddRefs(isupp));
+ if (NS_FAILED(rv)) break;
+ override = do_QueryInterface(isupp);
+ if (override)
{
- docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
- mimeType = NS_LITERAL_STRING(kUnicodeMime);
+ nsresult hookResult = override->OnCopyOrDrag(trans, &canInvokeDrag);
+ NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag");
}
- else
- mimeType = NS_LITERAL_STRING(kHTMLMime);
-
- // set up docEncoder
- nsCOMPtr docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
- NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
- rv = docEncoder->Init(doc, mimeType, docEncoderFlags);
- if (NS_FAILED(rv)) return rv;
-
- rv = docEncoder->SetSelection(selection);
- if (NS_FAILED(rv)) return rv;
-
- // grab a string
- nsAutoString buffer;
- rv = docEncoder->EncodeToString(buffer);
- if (NS_FAILED(rv)) return rv;
-
- // if we have an empty string, we're done; otherwise continue
- if ( !buffer.IsEmpty() )
- {
- nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
- NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE);
-
- rv = dataWrapper->SetData( buffer );
- if (NS_FAILED(rv)) return rv;
-
- if (bIsPlainTextControl)
- {
- // Add the unicode flavor to the transferable
- rv = trans->AddDataFlavor(kUnicodeMime);
- if (NS_FAILED(rv)) return rv;
- }
- else
- {
- rv = trans->AddDataFlavor(kHTMLMime);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID);
- NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
-
- rv = trans->SetConverter(htmlConverter);
- if (NS_FAILED(rv)) return rv;
- }
-
- // QI the data object an |nsISupports| so that when the transferable holds
- // onto it, it will addref the correct interface.
- nsCOMPtr nsisupportsDataWrapper ( do_QueryInterface(dataWrapper) );
- rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime,
- nsisupportsDataWrapper, buffer.Length() * 2);
- if (NS_FAILED(rv)) return rv;
-
- /* add the transferable to the array */
- rv = transferableArray->AppendElement(trans);
- if (NS_FAILED(rv)) return rv;
-
- /* invoke drag */
- unsigned int flags;
- // in some cases we'll want to cut rather than copy... hmmmmm...
- flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE;
-
- rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags);
- if (NS_FAILED(rv)) return rv;
-
- nsCOMPtr nsevent(do_QueryInterface(aDragEvent));
-
- if (nsevent) {
- nsevent->PreventBubble();
- }
- }
+ // if one of our overrides says we can't invoke drag, return now
+ if (!canInvokeDrag)
+ return NS_OK;
}
+ /* invoke drag */
+ nsCOMPtr eventTarget;
+ rv = aDragEvent->GetTarget(getter_AddRefs(eventTarget));
+ if (NS_FAILED(rv)) return rv;
+ nsCOMPtr domnode = do_QueryInterface(eventTarget);
+
+ unsigned int flags;
+ // in some cases we'll want to cut rather than copy... hmmmmm...
+ flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE;
+
+ rv = dragService->InvokeDragSession(domnode, transferableArray, nsnull, flags);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr nsevent(do_QueryInterface(aDragEvent));
+ if (nsevent)
+ nsevent->PreventBubble();
+
return rv;
}
@@ -529,6 +532,12 @@ 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())
{
@@ -585,3 +594,197 @@ NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, PRBool *aCanPa
*aCanPaste = haveFlavors;
return NS_OK;
}
+
+nsresult
+nsPlaintextEditor::SetupDocEncoder(nsIDocumentEncoder **aDocEncoder)
+{
+ nsCOMPtr domdoc;
+ nsresult rv = GetDocument(getter_AddRefs(domdoc));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr doc = do_QueryInterface(domdoc);
+ if (!doc) return NS_ERROR_FAILURE;
+
+ // find out if we're a plaintext control or not
+ PRUint32 editorFlags = 0;
+ rv = GetFlags(&editorFlags);
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0);
+
+ // get correct mimeType and document encoder flags set
+ nsAutoString mimeType;
+ PRUint32 docEncoderFlags = 0;
+ if (bIsPlainTextControl)
+ {
+ docEncoderFlags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
+ mimeType = NS_LITERAL_STRING(kUnicodeMime);
+ }
+ else
+ mimeType = NS_LITERAL_STRING(kHTMLMime);
+
+ // set up docEncoder
+ nsCOMPtr encoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
+ if (!encoder)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = encoder->Init(doc, mimeType, docEncoderFlags);
+ if (NS_FAILED(rv)) return rv;
+
+ /* get the selection to be dragged */
+ nsCOMPtr selection;
+ rv = GetSelection(getter_AddRefs(selection));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = encoder->SetSelection(selection);
+ if (NS_FAILED(rv)) return rv;
+
+ *aDocEncoder = encoder;
+ NS_ADDREF(*aDocEncoder);
+ return NS_OK;
+}
+
+nsresult
+nsPlaintextEditor::PutDragDataInTransferable(nsITransferable **aTransferable)
+{
+ *aTransferable = nsnull;
+ nsCOMPtr docEncoder;
+ nsresult rv = SetupDocEncoder(getter_AddRefs(docEncoder));
+ if (NS_FAILED(rv)) return rv;
+
+ // grab a string
+ nsAutoString buffer;
+ rv = docEncoder->EncodeToString(buffer);
+ if (NS_FAILED(rv)) return rv;
+
+ // if we have an empty string, we're done; otherwise continue
+ if (buffer.IsEmpty())
+ return NS_OK;
+
+ nsCOMPtr dataWrapper =
+ do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = dataWrapper->SetData(buffer);
+ if (NS_FAILED(rv)) return rv;
+
+ /* create html flavor transferable */
+ nsCOMPtr trans = do_CreateInstance(kCTransferableCID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // find out if we're a plaintext control or not
+ PRUint32 editorFlags = 0;
+ rv = GetFlags(&editorFlags);
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool bIsPlainTextControl = ((editorFlags & eEditorPlaintextMask) != 0);
+ if (bIsPlainTextControl)
+ {
+ // Add the unicode flavor to the transferable
+ rv = trans->AddDataFlavor(kUnicodeMime);
+ if (NS_FAILED(rv)) return rv;
+ }
+ else
+ {
+ rv = trans->AddDataFlavor(kHTMLMime);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr htmlConverter = do_CreateInstance(kCHTMLFormatConverterCID);
+ NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
+
+ rv = trans->SetConverter(htmlConverter);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ // QI the data object an |nsISupports| so that when the transferable holds
+ // onto it, it will addref the correct interface.
+ nsCOMPtr nsisupportsDataWrapper = do_QueryInterface(dataWrapper);
+ rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime,
+ nsisupportsDataWrapper, buffer.Length() * sizeof(PRUnichar));
+ if (NS_FAILED(rv)) return rv;
+
+ *aTransferable = trans;
+ NS_ADDREF(*aTransferable);
+ return NS_OK;
+}
+
+nsresult
+nsPlaintextEditor::DoAllowDropHook(nsIDOMEvent* aDropEvent,
+ nsIDragSession *aSession, PRBool *aAllowDrop)
+{
+ *aAllowDrop = PR_TRUE;
+
+ nsCOMPtr domdoc;
+ GetDocument(getter_AddRefs(domdoc));
+ nsCOMPtr doc = do_QueryInterface(domdoc);
+ if (!doc) return NS_ERROR_FAILURE;
+
+ nsCOMPtr isupp;
+ doc->GetContainer(getter_AddRefs(isupp));
+ nsCOMPtr docShell = do_QueryInterface(isupp);
+ nsCOMPtr hookObj = do_GetInterface(docShell);
+ if (!hookObj) return NS_ERROR_FAILURE;
+
+ nsCOMPtr enumerator;
+ hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
+ if (!enumerator) return NS_ERROR_FAILURE;
+
+ nsCOMPtr 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 domdoc;
+ GetDocument(getter_AddRefs(domdoc));
+ nsCOMPtr doc = do_QueryInterface(domdoc);
+ if (!doc) return NS_ERROR_FAILURE;
+
+ nsCOMPtr isupp;
+ doc->GetContainer(getter_AddRefs(isupp));
+ nsCOMPtr docShell = do_QueryInterface(isupp);
+ nsCOMPtr hookObj = do_GetInterface(docShell);
+ if (!hookObj) return NS_ERROR_FAILURE;
+
+ nsCOMPtr enumerator;
+ hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
+ if (!enumerator) return NS_ERROR_FAILURE;
+
+ nsCOMPtr 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;
+}
diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.h b/mozilla/editor/libeditor/text/nsPlaintextEditor.h
index cdbcdd893a1..aaeb10f84b8 100644
--- a/mozilla/editor/libeditor/text/nsPlaintextEditor.h
+++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.h
@@ -55,6 +55,7 @@ class nsIDOMKeyEvent;
class nsITransferable;
class nsIDOMEventReceiver;
class nsIDocumentEncoder;
+class nsIDragSession;
/**
* The text editor implementation.
@@ -226,6 +227,11 @@ protected:
// factored methods for handling insertion of data from transferables (drag&drop or clipboard)
NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable);
+ 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();