mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 23:15:38 +00:00
Bug 244685 Implement SourceURL for CF_HTML clipboard copy/drag'n'drop p=david.gardiner@unisa.edu.au r=dean_tessman sr=me
This commit is contained in:
parent
0343a92091
commit
c4c3378210
@ -21,6 +21,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kathleen Brade <brade@netscape.com>
|
||||
* David Gardiner <david.gardiner@unisa.edu.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -78,48 +79,70 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRBool bIsPlainTextContext = PR_FALSE;
|
||||
|
||||
rv = IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool bIsHTMLCopy = !bIsPlainTextContext;
|
||||
nsAutoString mimeType;
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder;
|
||||
|
||||
docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
|
||||
|
||||
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.AssignLiteral(kHTMLMime);
|
||||
else
|
||||
{
|
||||
flags |= nsIDocumentEncoder::OutputBodyOnly | nsIDocumentEncoder::OutputPreformatted;
|
||||
mimeType.AssignLiteral(kUnicodeMime);
|
||||
}
|
||||
// We always require a plaintext version
|
||||
mimeType.AssignLiteral(kUnicodeMime);
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted;
|
||||
|
||||
rv = docEncoder->Init(aDoc, mimeType, flags);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = docEncoder->SetSelection(aSel);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString buffer, parents, info;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoString buffer, parents, info, shortcut, textBuffer, plaintextBuffer;
|
||||
|
||||
rv = docEncoder->EncodeToString(textBuffer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// this string may still contain HTML formatting, so we need to remove that too.
|
||||
nsCOMPtr<nsIFormatConverter> htmlConverter = do_CreateInstance(kHTMLConverterCID);
|
||||
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISupportsString> plainHTML;
|
||||
plainHTML = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(plainHTML, NS_ERROR_FAILURE);
|
||||
nsresult plainhtml_rv = plainHTML->SetData(textBuffer);
|
||||
|
||||
nsCOMPtr<nsISupportsString> ConvertedData;
|
||||
PRUint32 ConvertedLen;
|
||||
htmlConverter->Convert(kHTMLMime, plainHTML, textBuffer.Length() * 2, kUnicodeMime, getter_AddRefs(ConvertedData), &ConvertedLen);
|
||||
|
||||
nsresult converted_rv = ConvertedData->GetData(plaintextBuffer);
|
||||
|
||||
// sometimes we also need the HTML version
|
||||
if (bIsHTMLCopy) {
|
||||
mimeType.AssignLiteral(kHTMLMime);
|
||||
|
||||
flags = 0;
|
||||
|
||||
rv = docEncoder->Init(aDoc, mimeType, flags);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = docEncoder->SetSelection(aSel);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (bIsHTMLCopy)
|
||||
{
|
||||
// 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 Clipboard
|
||||
@ -133,47 +156,58 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
|
||||
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
|
||||
if ( trans )
|
||||
{
|
||||
nsCOMPtr<nsISupportsString> textWrapper;
|
||||
|
||||
textWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(textWrapper, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult text_rv = textWrapper->SetData(plaintextBuffer);
|
||||
|
||||
if (bIsHTMLCopy)
|
||||
{
|
||||
// set up the data converter
|
||||
nsCOMPtr<nsIFormatConverter> htmlConverter = do_CreateInstance(kHTMLConverterCID);
|
||||
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
|
||||
trans->SetConverter(htmlConverter);
|
||||
}
|
||||
|
||||
// get wStrings to hold clip data
|
||||
nsCOMPtr<nsISupportsString> dataWrapper, contextWrapper, infoWrapper;
|
||||
dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE);
|
||||
if (bIsHTMLCopy)
|
||||
{
|
||||
|
||||
// get wStrings to hold clip data
|
||||
nsCOMPtr<nsISupportsString> dataWrapper, contextWrapper, infoWrapper, urlWrapper;
|
||||
|
||||
dataWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(dataWrapper, NS_ERROR_FAILURE);
|
||||
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);
|
||||
}
|
||||
|
||||
// populate the strings
|
||||
nsresult data_rv = NS_OK, context_rv = NS_OK, info_rv = NS_OK;
|
||||
data_rv =
|
||||
dataWrapper->SetData(buffer);
|
||||
if (bIsHTMLCopy)
|
||||
{
|
||||
context_rv =
|
||||
contextWrapper->SetData(parents);
|
||||
info_rv =
|
||||
infoWrapper->SetData(info);
|
||||
}
|
||||
|
||||
// QI the data object an |nsISupports| so that when the transferable holds
|
||||
// onto it, it will addref the correct interface.
|
||||
nsCOMPtr<nsISupports> genericDataObj ( do_QueryInterface(dataWrapper) );
|
||||
if (bIsHTMLCopy)
|
||||
{
|
||||
urlWrapper = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(urlWrapper, NS_ERROR_FAILURE);
|
||||
|
||||
// populate the strings
|
||||
nsresult data_rv = dataWrapper->SetData(buffer);
|
||||
nsresult context_rv = contextWrapper->SetData(parents);
|
||||
nsresult info_rv = infoWrapper->SetData(info);
|
||||
|
||||
// Try and get source URI of the items that are being dragged
|
||||
nsIURI *uri = aDoc->GetDocumentURI();
|
||||
|
||||
nsCAutoString spec;
|
||||
uri->GetSpec(spec);
|
||||
|
||||
AppendUTF8toUTF16(spec, shortcut);
|
||||
shortcut.Append(PRUnichar('\n'));
|
||||
|
||||
// and get document title
|
||||
shortcut.Append(aDoc->GetDocumentTitle());
|
||||
|
||||
nsresult url_rv = urlWrapper->SetData(shortcut);
|
||||
|
||||
// QI the data object an |nsISupports| so that when the transferable holds
|
||||
// onto it, it will addref the correct interface.
|
||||
nsCOMPtr<nsISupports> genericDataObj;
|
||||
|
||||
if (!buffer.IsEmpty() && NS_SUCCEEDED(data_rv))
|
||||
{
|
||||
// Add the html DataFlavor to the transferable
|
||||
trans->AddDataFlavor(kHTMLMime);
|
||||
genericDataObj = do_QueryInterface(dataWrapper);
|
||||
trans->SetTransferData(kHTMLMime, genericDataObj, buffer.Length()*2);
|
||||
}
|
||||
if (!parents.IsEmpty() && NS_SUCCEEDED(context_rv))
|
||||
@ -190,14 +224,37 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
|
||||
genericDataObj = do_QueryInterface(infoWrapper);
|
||||
trans->SetTransferData(kHTMLInfo, genericDataObj, info.Length()*2);
|
||||
}
|
||||
if (!plaintextBuffer.IsEmpty() && NS_SUCCEEDED(text_rv))
|
||||
{
|
||||
// unicode text
|
||||
// Add the unicode DataFlavor to the transferable
|
||||
// If we didn't have this, then nsDataObj::GetData matches text/unicode against
|
||||
// the kURLMime flavour which is not desirable (eg. when pasting into Notepad)
|
||||
trans->AddDataFlavor(kUnicodeMime);
|
||||
genericDataObj = do_QueryInterface(textWrapper);
|
||||
trans->SetTransferData(kUnicodeMime, genericDataObj, plaintextBuffer.Length()*2);
|
||||
}
|
||||
// url
|
||||
if (!shortcut.IsEmpty() && NS_SUCCEEDED(url_rv))
|
||||
{
|
||||
// Add the URL DataFlavor to the transferable
|
||||
trans->AddDataFlavor(kURLMime);
|
||||
genericDataObj = do_QueryInterface(urlWrapper);
|
||||
trans->SetTransferData(kURLMime, genericDataObj, shortcut.Length()*2);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!buffer.IsEmpty() && NS_SUCCEEDED(data_rv))
|
||||
// QI the data object an |nsISupports| so that when the transferable holds
|
||||
// onto it, it will addref the correct interface.
|
||||
nsCOMPtr<nsISupports> genericDataObj ( do_QueryInterface(textWrapper) );
|
||||
|
||||
if (!plaintextBuffer.IsEmpty() && NS_SUCCEEDED(text_rv))
|
||||
{
|
||||
// Add the unicode DataFlavor to the transferable
|
||||
trans->AddDataFlavor(kUnicodeMime);
|
||||
trans->SetTransferData(kUnicodeMime, genericDataObj, buffer.Length()*2);
|
||||
trans->SetTransferData(kUnicodeMime, genericDataObj, plaintextBuffer.Length()*2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Sean Echevarria <sean@beatnik.com>
|
||||
* David Gardiner <david.gardiner@unisa.edu.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -130,7 +131,7 @@ UINT nsClipboard::GetFormat(const char* aMimeStr)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsresult nsClipboard::CreateNativeDataObject(nsITransferable * aTransferable, IDataObject ** aDataObj)
|
||||
nsresult nsClipboard::CreateNativeDataObject(nsITransferable * aTransferable, IDataObject ** aDataObj, nsIURI * uri)
|
||||
{
|
||||
if (nsnull == aTransferable) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -138,8 +139,11 @@ nsresult nsClipboard::CreateNativeDataObject(nsITransferable * aTransferable, ID
|
||||
|
||||
// Create our native DataObject that implements
|
||||
// the OLE IDataObject interface
|
||||
nsDataObj * dataObj;
|
||||
dataObj = new nsDataObj();
|
||||
nsDataObj * dataObj = new nsDataObj(uri);
|
||||
|
||||
if (!dataObj)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
dataObj->AddRef();
|
||||
|
||||
// No set it up with all the right data flavors & enums
|
||||
@ -270,7 +274,7 @@ NS_IMETHODIMP nsClipboard::SetNativeClipboardData ( PRInt32 aWhichClipboard )
|
||||
::OleSetClipboard(NULL);
|
||||
|
||||
IDataObject * dataObj;
|
||||
if ( NS_SUCCEEDED(CreateNativeDataObject(mTransferable, &dataObj)) ) { // this add refs
|
||||
if ( NS_SUCCEEDED(CreateNativeDataObject(mTransferable, &dataObj, NULL)) ) { // this add refs dataObj
|
||||
::OleSetClipboard(dataObj);
|
||||
dataObj->Release();
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include "nsBaseClipboard.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIURI.h"
|
||||
#include <windows.h>
|
||||
|
||||
class nsITransferable;
|
||||
@ -70,7 +71,8 @@ public:
|
||||
|
||||
// Internal Native Routines
|
||||
static nsresult CreateNativeDataObject(nsITransferable * aTransferable,
|
||||
IDataObject ** aDataObj);
|
||||
IDataObject ** aDataObj,
|
||||
nsIURI * uri);
|
||||
static nsresult SetupNativeDataObject(nsITransferable * aTransferable,
|
||||
IDataObject * aDataObj);
|
||||
static nsresult GetDataFromDataObject(IDataObject * aDataObject,
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Blake Ross <blaker@netscape.com>
|
||||
* Brodie Thiesfield <brofield@jellycan.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* David Gardiner <david.gardiner@unisa.edu.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -104,16 +105,21 @@ EXTERN_C GUID CDECL CLSID_nsDataObj =
|
||||
//-----------------------------------------------------
|
||||
// construction
|
||||
//-----------------------------------------------------
|
||||
nsDataObj::nsDataObj()
|
||||
nsDataObj::nsDataObj(nsIURI * uri)
|
||||
: m_cRef(0), mTransferable(nsnull)
|
||||
{
|
||||
m_cRef = 0;
|
||||
mTransferable = nsnull;
|
||||
mDataFlavors = new nsVoidArray();
|
||||
m_enumFE = new CEnumFormatEtc(32);
|
||||
|
||||
m_enumFE->AddRef();
|
||||
|
||||
m_enumFE = new CEnumFormatEtc(32);
|
||||
m_enumFE->AddRef();
|
||||
if (uri) {
|
||||
|
||||
// A URI was obtained, so pass this through to the DataObject
|
||||
// so it can create a SourceURL for CF_HTML flavour
|
||||
uri->GetSpec(mSourceURL);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// destruction
|
||||
//-----------------------------------------------------
|
||||
@ -1189,8 +1195,18 @@ nsDataObj :: BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML )
|
||||
const char* const endHTMLPrefix = "\r\nEndHTML:";
|
||||
const char* const startFragPrefix = "\r\nStartFragment:";
|
||||
const char* const endFragPrefix = "\r\nEndFragment:";
|
||||
const char* const startSourceURLPrefix = "\r\nSourceURL:";
|
||||
const char* const endFragTrailer = "\r\n";
|
||||
|
||||
// Do we already have mSourceURL from a drag?
|
||||
if (mSourceURL.IsEmpty()) {
|
||||
nsAutoString url;
|
||||
ExtractShortcutURL(url);
|
||||
|
||||
AppendUTF16toUTF8(url, mSourceURL);
|
||||
}
|
||||
|
||||
const PRInt32 kSourceURLLength = mSourceURL.Length();
|
||||
const PRInt32 kNumberLength = strlen(numPlaceholder);
|
||||
|
||||
const PRInt32 kTotalHeaderLen = strlen(startHTMLPrefix) +
|
||||
@ -1198,6 +1214,8 @@ nsDataObj :: BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML )
|
||||
strlen(startFragPrefix) +
|
||||
strlen(endFragPrefix) +
|
||||
strlen(endFragTrailer) +
|
||||
(kSourceURLLength > 0 ? strlen(startSourceURLPrefix) : 0) +
|
||||
kSourceURLLength +
|
||||
(4 * kNumberLength);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(htmlHeaderString, "<html><body>\r\n");
|
||||
@ -1237,6 +1255,9 @@ nsDataObj :: BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML )
|
||||
clipboardString.Append(endFragPrefix);
|
||||
clipboardString.Append(nsPrintfCString("%08u", endFragOffset));
|
||||
|
||||
clipboardString.Append(startSourceURLPrefix);
|
||||
clipboardString.Append(mSourceURL);
|
||||
|
||||
clipboardString.Append(endFragTrailer);
|
||||
|
||||
clipboardString.Append(htmlHeaderString);
|
||||
|
@ -47,6 +47,7 @@
|
||||
//#include "Ddforw.h"
|
||||
#include "nsString.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#define MAX_FORMATS 32
|
||||
|
||||
@ -73,9 +74,9 @@ class nsITransferable;
|
||||
*/
|
||||
class nsDataObj : public IDataObject
|
||||
{
|
||||
public: // construction, destruction
|
||||
nsDataObj();
|
||||
~nsDataObj();
|
||||
public: // construction, destruction
|
||||
nsDataObj(nsIURI *uri = nsnull);
|
||||
~nsDataObj();
|
||||
|
||||
public: // IUnknown methods - see iunknown.h for documentation
|
||||
STDMETHODIMP_(ULONG) AddRef ();
|
||||
@ -182,6 +183,9 @@ class nsDataObj : public IDataObject
|
||||
// munge our HTML data to win32's CF_HTML spec. Will null terminate
|
||||
nsresult BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML ) ;
|
||||
|
||||
// Used for the SourceURL part of CF_HTML
|
||||
nsCString mSourceURL;
|
||||
|
||||
nsString mStringData;
|
||||
|
||||
BOOL FormatsMatch(const FORMATETC& source, const FORMATETC& target) const;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Mike Pinkerton (pinkerton@netscape.com)
|
||||
* Mark Hammond (MarkH@ActiveState.com)
|
||||
* David Gardiner <david.gardiner@unisa.edu.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -53,6 +54,7 @@
|
||||
#include "nsNativeDragSource.h"
|
||||
#include "nsClipboard.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsDataObjCollection.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
@ -89,6 +91,15 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupport
|
||||
nsBaseDragService::InvokeDragSession ( aDOMNode, anArrayTransferables, aRegion, aActionType );
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Try and get source URI of the items that are being dragged
|
||||
nsIURI *uri = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mSourceDocument));
|
||||
if (doc) {
|
||||
uri = doc->GetDocumentURI();
|
||||
}
|
||||
|
||||
PRUint32 numItemsToDrag = 0;
|
||||
rv = anArrayTransferables->Count(&numItemsToDrag);
|
||||
if ( !numItemsToDrag )
|
||||
@ -112,7 +123,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupport
|
||||
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
|
||||
if ( trans ) {
|
||||
nsRefPtr<IDataObject> dataObj;
|
||||
if ( NS_SUCCEEDED(nsClipboard::CreateNativeDataObject(trans, getter_AddRefs(dataObj))) ) {
|
||||
if ( NS_SUCCEEDED(nsClipboard::CreateNativeDataObject(trans, getter_AddRefs(dataObj), uri)) ) {
|
||||
dataObjCollection->AddDataObject(dataObj);
|
||||
}
|
||||
else
|
||||
@ -125,7 +136,7 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupport
|
||||
anArrayTransferables->GetElementAt(0, getter_AddRefs(supports));
|
||||
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
|
||||
if ( trans ) {
|
||||
if ( NS_FAILED(nsClipboard::CreateNativeDataObject(trans, getter_AddRefs(itemToDrag))) )
|
||||
if ( NS_FAILED(nsClipboard::CreateNativeDataObject(trans, getter_AddRefs(itemToDrag), uri)) )
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} // else dragging a single object
|
||||
|
Loading…
x
Reference in New Issue
Block a user