diff --git a/mozilla/content/base/public/nsCopySupport.h b/mozilla/content/base/public/nsCopySupport.h index a06a046af22..ecffaa31fc2 100644 --- a/mozilla/content/base/public/nsCopySupport.h +++ b/mozilla/content/base/public/nsCopySupport.h @@ -30,4 +30,5 @@ class nsCopySupport // class of static helper functions for copy support public: static nsresult HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID); + static nsresult IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext); }; diff --git a/mozilla/content/base/src/nsCopySupport.cpp b/mozilla/content/base/src/nsCopySupport.cpp index 5b6ba276ec0..f246fd77eee 100644 --- a/mozilla/content/base/src/nsCopySupport.cpp +++ b/mozilla/content/base/src/nsCopySupport.cpp @@ -36,6 +36,11 @@ #include "nsIUBidiUtils.h" #include "nsIDocument.h" #include "nsIPresShell.h" +#include "nsIDOMRange.h" +#include "nsIDOMNode.h" +#include "nsIDOMElement.h" +#include "nsIHTMLDocument.h" +#include "nsHTMLAtoms.h" static NS_DEFINE_CID(kUBidiUtilCID, NS_UNICHARBIDIUTIL_CID); #endif @@ -58,19 +63,30 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - rv = docEncoder->Init(aDoc, NS_LITERAL_STRING("text/html"), 0); + PRBool bIsPlainTextContext = PR_FALSE; + + rv = IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext); + if (NS_FAILED(rv)) return rv; + + PRBool bIsHTMLCopy = !bIsPlainTextContext; + PRUint32 flags = 0; + nsAutoString mimeType; + + if (bIsHTMLCopy) + mimeType = NS_LITERAL_STRING(kHTMLMime); + else + { + flags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted; + mimeType = NS_LITERAL_STRING(kUnicodeMime); + } + + rv = docEncoder->Init(aDoc, mimeType, flags); if (NS_FAILED(rv)) return rv; rv = docEncoder->SetSelection(aSel); if (NS_FAILED(rv)) return rv; - nsAutoString mimeType; - rv = docEncoder->GetMimeType(mimeType); - if (NS_FAILED(rv)) return rv; - - nsAutoString buffer, parents, info; - PRBool bIsHTMLCopy = PR_FALSE; - if (mimeType.EqualsWithConversion("text/html")) - bIsHTMLCopy = PR_TRUE; + nsAutoString buffer, parents, info; + if (bIsHTMLCopy) { // encode the selection as html with contextual info @@ -222,3 +238,71 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 } return rv; } + +nsresult nsCopySupport::IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext) +{ + nsresult rv; + + if (!aSel || !aIsPlainTextContext) + return NS_ERROR_NULL_POINTER; + + *aIsPlainTextContext = PR_FALSE; + + nsCOMPtr range; + nsCOMPtr commonParent; + PRInt32 count = 0; + + rv = aSel->GetRangeCount(&count); + NS_ENSURE_SUCCESS(rv, rv); + + // if selection is uninitialized return + if (!count) + return NS_ERROR_FAILURE; + + // we'll just use the common parent of the first range. Implicit assumption + // here that multi-range selections are table cell selections, in which case + // the common parent is somewhere in the table and we don't really care where. + rv = aSel->GetRangeAt(0, getter_AddRefs(range)); + NS_ENSURE_SUCCESS(rv, rv); + if (!range) + return NS_ERROR_NULL_POINTER; + range->GetCommonAncestorContainer(getter_AddRefs(commonParent)); + + nsCOMPtr tmp, selContent( do_QueryInterface(commonParent) ); + while (selContent) + { + // checking for selection inside a plaintext form widget + nsCOMPtr atom; + selContent->GetTag(*getter_AddRefs(atom)); + + if (atom.get() == nsHTMLAtoms::input || + atom.get() == nsHTMLAtoms::textarea) + { + *aIsPlainTextContext = PR_TRUE; + break; + } + + if (atom.get() == nsHTMLAtoms::body) + { + // check for moz prewrap style on body. If it's there we are + // in a plaintext editor. This is pretty cheezy but I haven't + // found a good way to tell if we are in a plaintext editor. + nsCOMPtr bodyElem = do_QueryInterface(selContent); + nsAutoString wsVal; + rv = bodyElem->GetAttribute(NS_LITERAL_STRING("style"), wsVal); + if (NS_SUCCEEDED(rv) && (kNotFound != wsVal.Find(NS_LITERAL_STRING("-moz-pre-wrap").get()))) + { + *aIsPlainTextContext = PR_TRUE; + break; + } + } + selContent->GetParent(*getter_AddRefs(tmp)); + selContent = tmp; + } + + // also consider ourselves in a text widget if we can't find an html document + nsCOMPtr htmlDoc = do_QueryInterface(aDoc); + if (!htmlDoc) *aIsPlainTextContext = PR_TRUE; + + return NS_OK; +} diff --git a/mozilla/content/base/src/nsDocumentEncoder.cpp b/mozilla/content/base/src/nsDocumentEncoder.cpp index 7468ad5d404..bc33abf07fb 100644 --- a/mozilla/content/base/src/nsDocumentEncoder.cpp +++ b/mozilla/content/base/src/nsDocumentEncoder.cpp @@ -1087,7 +1087,7 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection) // found a good way to tell if we are in a plaintext editor. nsCOMPtr bodyElem = do_QueryInterface(selContent); nsAutoString wsVal; - rv = bodyElem->GetAttribute(NS_LITERAL_STRING("white-space"), wsVal); + rv = bodyElem->GetAttribute(NS_LITERAL_STRING("style"), wsVal); if (NS_SUCCEEDED(rv) && (kNotFound != wsVal.Find(NS_LITERAL_STRING("-moz-pre-wrap").get()))) { mIsTextWidget = PR_TRUE; diff --git a/mozilla/editor/base/nsHTMLDataTransfer.cpp b/mozilla/editor/base/nsHTMLDataTransfer.cpp index 38df843f0ce..ad5c9bb98d4 100644 --- a/mozilla/editor/base/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/base/nsHTMLDataTransfer.cpp @@ -937,12 +937,8 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) if (NS_FAILED(rv)) return rv; /* create html flavor transferable */ - nsCOMPtr trans; - rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, - NS_GET_IID(nsITransferable), - getter_AddRefs(trans)); - if (NS_FAILED(rv)) return rv; - if ( !trans ) return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr trans = do_CreateInstance(kCTransferableCID); + NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); nsCOMPtr domdoc; rv = GetDocument(getter_AddRefs(domdoc)); @@ -951,47 +947,71 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) nsCOMPtr doc = do_QueryInterface(domdoc); if (doc) { - nsCOMPtr docEncoder; + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; - docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html"); + 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); - docEncoder->Init(doc, NS_LITERAL_STRING("text/html"), 0); - docEncoder->SetSelection(selection); + 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 (NS_FAILED(rv)) return rv; + // if we have an empty string, we're done; otherwise continue if ( !buffer.IsEmpty() ) { - nsCOMPtr htmlConverter; - rv = nsComponentManager::CreateInstance(kCHTMLFormatConverterCID, nsnull, NS_GET_IID(nsIFormatConverter), - getter_AddRefs(htmlConverter)); - if (NS_FAILED(rv)) return rv; - if (!htmlConverter) return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr dataWrapper; - rv = nsComponentManager::CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID, nsnull, - NS_GET_IID(nsISupportsWString), getter_AddRefs(dataWrapper)); - if (NS_FAILED(rv)) return rv; - if ( !dataWrapper ) return NS_ERROR_OUT_OF_MEMORY; - - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID); + NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); rv = dataWrapper->SetData( NS_CONST_CAST(PRUnichar*, buffer.get()) ); 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(kHTMLMime, nsisupportsDataWrapper, buffer.Length() * 2); + rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, + nsisupportsDataWrapper, buffer.Length() * 2); if (NS_FAILED(rv)) return rv; /* add the transferable to the array */ @@ -1001,9 +1021,6 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) /* invoke drag */ unsigned int flags; // in some cases we'll want to cut rather than copy... hmmmmm... - // if ( wantToCut ) - // flags = nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE; - // else flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); diff --git a/mozilla/editor/base/nsPlaintextDataTransfer.cpp b/mozilla/editor/base/nsPlaintextDataTransfer.cpp index 178caa49263..5cb7476005c 100644 --- a/mozilla/editor/base/nsPlaintextDataTransfer.cpp +++ b/mozilla/editor/base/nsPlaintextDataTransfer.cpp @@ -429,12 +429,8 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) if (NS_FAILED(rv)) return rv; /* create html flavor transferable */ - nsCOMPtr trans; - rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, - NS_GET_IID(nsITransferable), - getter_AddRefs(trans)); - if (NS_FAILED(rv)) return rv; - if ( !trans ) return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr trans = do_CreateInstance(kCTransferableCID); + NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); nsCOMPtr domdoc; rv = GetDocument(getter_AddRefs(domdoc)); @@ -443,47 +439,71 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) nsCOMPtr doc = do_QueryInterface(domdoc); if (doc) { - nsCOMPtr docEncoder; + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; - docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html"); + 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); - docEncoder->Init(doc, NS_LITERAL_STRING("text/html"), 0); - docEncoder->SetSelection(selection); + 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 (NS_FAILED(rv)) return rv; + // if we have an empty string, we're done; otherwise continue if ( !buffer.IsEmpty() ) { - nsCOMPtr htmlConverter; - rv = nsComponentManager::CreateInstance(kCHTMLFormatConverterCID, nsnull, NS_GET_IID(nsIFormatConverter), - getter_AddRefs(htmlConverter)); - if (NS_FAILED(rv)) return rv; - if (!htmlConverter) return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr dataWrapper; - rv = nsComponentManager::CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID, nsnull, - NS_GET_IID(nsISupportsWString), getter_AddRefs(dataWrapper)); - if (NS_FAILED(rv)) return rv; - if ( !dataWrapper ) return NS_ERROR_OUT_OF_MEMORY; - - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID); + NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); rv = dataWrapper->SetData( NS_CONST_CAST(PRUnichar*, buffer.get()) ); 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(kHTMLMime, nsisupportsDataWrapper, buffer.Length() * 2); + rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, + nsisupportsDataWrapper, buffer.Length() * 2); if (NS_FAILED(rv)) return rv; /* add the transferable to the array */ @@ -493,9 +513,6 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) /* invoke drag */ unsigned int flags; // in some cases we'll want to cut rather than copy... hmmmmm... - // if ( wantToCut ) - // flags = nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE; - // else flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index 38df843f0ce..ad5c9bb98d4 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -937,12 +937,8 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) if (NS_FAILED(rv)) return rv; /* create html flavor transferable */ - nsCOMPtr trans; - rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, - NS_GET_IID(nsITransferable), - getter_AddRefs(trans)); - if (NS_FAILED(rv)) return rv; - if ( !trans ) return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr trans = do_CreateInstance(kCTransferableCID); + NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); nsCOMPtr domdoc; rv = GetDocument(getter_AddRefs(domdoc)); @@ -951,47 +947,71 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) nsCOMPtr doc = do_QueryInterface(domdoc); if (doc) { - nsCOMPtr docEncoder; + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; - docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html"); + 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); - docEncoder->Init(doc, NS_LITERAL_STRING("text/html"), 0); - docEncoder->SetSelection(selection); + 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 (NS_FAILED(rv)) return rv; + // if we have an empty string, we're done; otherwise continue if ( !buffer.IsEmpty() ) { - nsCOMPtr htmlConverter; - rv = nsComponentManager::CreateInstance(kCHTMLFormatConverterCID, nsnull, NS_GET_IID(nsIFormatConverter), - getter_AddRefs(htmlConverter)); - if (NS_FAILED(rv)) return rv; - if (!htmlConverter) return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr dataWrapper; - rv = nsComponentManager::CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID, nsnull, - NS_GET_IID(nsISupportsWString), getter_AddRefs(dataWrapper)); - if (NS_FAILED(rv)) return rv; - if ( !dataWrapper ) return NS_ERROR_OUT_OF_MEMORY; - - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID); + NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); rv = dataWrapper->SetData( NS_CONST_CAST(PRUnichar*, buffer.get()) ); 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(kHTMLMime, nsisupportsDataWrapper, buffer.Length() * 2); + rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, + nsisupportsDataWrapper, buffer.Length() * 2); if (NS_FAILED(rv)) return rv; /* add the transferable to the array */ @@ -1001,9 +1021,6 @@ NS_IMETHODIMP nsHTMLEditor::DoDrag(nsIDOMEvent *aDragEvent) /* invoke drag */ unsigned int flags; // in some cases we'll want to cut rather than copy... hmmmmm... - // if ( wantToCut ) - // flags = nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE; - // else flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); diff --git a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp index 178caa49263..5cb7476005c 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp @@ -429,12 +429,8 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) if (NS_FAILED(rv)) return rv; /* create html flavor transferable */ - nsCOMPtr trans; - rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, - NS_GET_IID(nsITransferable), - getter_AddRefs(trans)); - if (NS_FAILED(rv)) return rv; - if ( !trans ) return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr trans = do_CreateInstance(kCTransferableCID); + NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE); nsCOMPtr domdoc; rv = GetDocument(getter_AddRefs(domdoc)); @@ -443,47 +439,71 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) nsCOMPtr doc = do_QueryInterface(domdoc); if (doc) { - nsCOMPtr docEncoder; + // find out if we're a plaintext control or not + PRUint32 editorFlags = 0; + rv = GetFlags(&editorFlags); + if (NS_FAILED(rv)) return rv; - docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html"); + 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); - docEncoder->Init(doc, NS_LITERAL_STRING("text/html"), 0); - docEncoder->SetSelection(selection); + 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 (NS_FAILED(rv)) return rv; + // if we have an empty string, we're done; otherwise continue if ( !buffer.IsEmpty() ) { - nsCOMPtr htmlConverter; - rv = nsComponentManager::CreateInstance(kCHTMLFormatConverterCID, nsnull, NS_GET_IID(nsIFormatConverter), - getter_AddRefs(htmlConverter)); - if (NS_FAILED(rv)) return rv; - if (!htmlConverter) return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr dataWrapper; - rv = nsComponentManager::CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID, nsnull, - NS_GET_IID(nsISupportsWString), getter_AddRefs(dataWrapper)); - if (NS_FAILED(rv)) return rv; - if ( !dataWrapper ) return NS_ERROR_OUT_OF_MEMORY; - - rv = trans->AddDataFlavor(kHTMLMime); - if (NS_FAILED(rv)) return rv; - rv = trans->SetConverter(htmlConverter); - if (NS_FAILED(rv)) return rv; + nsCOMPtr dataWrapper = do_CreateInstance(NS_SUPPORTS_WSTRING_CONTRACTID); + NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE); rv = dataWrapper->SetData( NS_CONST_CAST(PRUnichar*, buffer.get()) ); 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(kHTMLMime, nsisupportsDataWrapper, buffer.Length() * 2); + rv = trans->SetTransferData(bIsPlainTextControl ? kUnicodeMime : kHTMLMime, + nsisupportsDataWrapper, buffer.Length() * 2); if (NS_FAILED(rv)) return rv; /* add the transferable to the array */ @@ -493,9 +513,6 @@ NS_IMETHODIMP nsPlaintextEditor::DoDrag(nsIDOMEvent *aDragEvent) /* invoke drag */ unsigned int flags; // in some cases we'll want to cut rather than copy... hmmmmm... - // if ( wantToCut ) - // flags = nsIDragService.DRAGDROP_ACTION_COPY + nsIDragService.DRAGDROP_ACTION_MOVE; - // else flags = nsIDragService::DRAGDROP_ACTION_COPY + nsIDragService::DRAGDROP_ACTION_MOVE; rv = dragService->InvokeDragSession( domnode, transferableArray, nsnull, flags); diff --git a/mozilla/layout/base/src/nsCopySupport.cpp b/mozilla/layout/base/src/nsCopySupport.cpp index 5b6ba276ec0..f246fd77eee 100644 --- a/mozilla/layout/base/src/nsCopySupport.cpp +++ b/mozilla/layout/base/src/nsCopySupport.cpp @@ -36,6 +36,11 @@ #include "nsIUBidiUtils.h" #include "nsIDocument.h" #include "nsIPresShell.h" +#include "nsIDOMRange.h" +#include "nsIDOMNode.h" +#include "nsIDOMElement.h" +#include "nsIHTMLDocument.h" +#include "nsHTMLAtoms.h" static NS_DEFINE_CID(kUBidiUtilCID, NS_UNICHARBIDIUTIL_CID); #endif @@ -58,19 +63,30 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID); NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - rv = docEncoder->Init(aDoc, NS_LITERAL_STRING("text/html"), 0); + PRBool bIsPlainTextContext = PR_FALSE; + + rv = IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext); + if (NS_FAILED(rv)) return rv; + + PRBool bIsHTMLCopy = !bIsPlainTextContext; + PRUint32 flags = 0; + nsAutoString mimeType; + + if (bIsHTMLCopy) + mimeType = NS_LITERAL_STRING(kHTMLMime); + else + { + flags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted; + mimeType = NS_LITERAL_STRING(kUnicodeMime); + } + + rv = docEncoder->Init(aDoc, mimeType, flags); if (NS_FAILED(rv)) return rv; rv = docEncoder->SetSelection(aSel); if (NS_FAILED(rv)) return rv; - nsAutoString mimeType; - rv = docEncoder->GetMimeType(mimeType); - if (NS_FAILED(rv)) return rv; - - nsAutoString buffer, parents, info; - PRBool bIsHTMLCopy = PR_FALSE; - if (mimeType.EqualsWithConversion("text/html")) - bIsHTMLCopy = PR_TRUE; + nsAutoString buffer, parents, info; + if (bIsHTMLCopy) { // encode the selection as html with contextual info @@ -222,3 +238,71 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 } return rv; } + +nsresult nsCopySupport::IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext) +{ + nsresult rv; + + if (!aSel || !aIsPlainTextContext) + return NS_ERROR_NULL_POINTER; + + *aIsPlainTextContext = PR_FALSE; + + nsCOMPtr range; + nsCOMPtr commonParent; + PRInt32 count = 0; + + rv = aSel->GetRangeCount(&count); + NS_ENSURE_SUCCESS(rv, rv); + + // if selection is uninitialized return + if (!count) + return NS_ERROR_FAILURE; + + // we'll just use the common parent of the first range. Implicit assumption + // here that multi-range selections are table cell selections, in which case + // the common parent is somewhere in the table and we don't really care where. + rv = aSel->GetRangeAt(0, getter_AddRefs(range)); + NS_ENSURE_SUCCESS(rv, rv); + if (!range) + return NS_ERROR_NULL_POINTER; + range->GetCommonAncestorContainer(getter_AddRefs(commonParent)); + + nsCOMPtr tmp, selContent( do_QueryInterface(commonParent) ); + while (selContent) + { + // checking for selection inside a plaintext form widget + nsCOMPtr atom; + selContent->GetTag(*getter_AddRefs(atom)); + + if (atom.get() == nsHTMLAtoms::input || + atom.get() == nsHTMLAtoms::textarea) + { + *aIsPlainTextContext = PR_TRUE; + break; + } + + if (atom.get() == nsHTMLAtoms::body) + { + // check for moz prewrap style on body. If it's there we are + // in a plaintext editor. This is pretty cheezy but I haven't + // found a good way to tell if we are in a plaintext editor. + nsCOMPtr bodyElem = do_QueryInterface(selContent); + nsAutoString wsVal; + rv = bodyElem->GetAttribute(NS_LITERAL_STRING("style"), wsVal); + if (NS_SUCCEEDED(rv) && (kNotFound != wsVal.Find(NS_LITERAL_STRING("-moz-pre-wrap").get()))) + { + *aIsPlainTextContext = PR_TRUE; + break; + } + } + selContent->GetParent(*getter_AddRefs(tmp)); + selContent = tmp; + } + + // also consider ourselves in a text widget if we can't find an html document + nsCOMPtr htmlDoc = do_QueryInterface(aDoc); + if (!htmlDoc) *aIsPlainTextContext = PR_TRUE; + + return NS_OK; +} diff --git a/mozilla/layout/base/src/nsCopySupport.h b/mozilla/layout/base/src/nsCopySupport.h index a06a046af22..ecffaa31fc2 100644 --- a/mozilla/layout/base/src/nsCopySupport.h +++ b/mozilla/layout/base/src/nsCopySupport.h @@ -30,4 +30,5 @@ class nsCopySupport // class of static helper functions for copy support public: static nsresult HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16 aClipboardID); + static nsresult IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext); };