Bug 193053: drag and drop-related changes to allow for the dragging and copying of image bits, and to allow dragging into the file system. r=pinkerton/brade, sr=bryner/bz.

This commit is contained in:
sfraser%netscape.com 2003-04-18 20:20:04 +00:00
Родитель 8893b1e6fd
Коммит f3456b4697
15 изменённых файлов: 993 добавлений и 299 удалений

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

@ -40,6 +40,13 @@
class nsISelection;
class nsIDocument;
class nsIDOMNode;
class nsIDOMHTMLImageElement;
class nsIContent;
class nsIPresContext;
class nsIPresShell;
class nsIImageFrame;
class nsIImage;
class nsITransferable;
class nsCopySupport
@ -50,4 +57,17 @@ class nsCopySupport
static nsresult DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
PRBool *aDoPutOnClipboard);
static nsresult IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext);
// Get the selection, or entire document, in the format specified by the mime type
// (text/html or text/plain). If aSel is non-null, use it, otherwise get the entire
// doc.
static nsresult GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata);
static nsresult ImageCopy(nsIDOMHTMLImageElement* imageElement, PRInt16 aClipboardID);
protected:
// these are ripped from nsContentAreaDragDrop. This so needs factoring.
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImage);
};

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

@ -52,6 +52,7 @@ REQUIRES = xpcom \
xuldoc \
intl \
windowwatcher \
webbrowserpersist \
imglib2 \
uriloader \
webbrwsr \

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

@ -42,7 +42,6 @@
// Helper Classes
#include "nsString.h"
#include "nsXPIDLString.h"
// Interfaces needed to be included
#include "nsIDOMNSUIEvent.h"
@ -86,7 +85,7 @@
#include "nsINameSpaceManager.h"
#include "nsUnicharUtils.h"
#include "nsHTMLAtoms.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsIImage.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
@ -99,6 +98,8 @@
#include "nsIInterfaceRequestor.h"
#include "nsIDocumentEncoder.h"
#include "nsRange.h"
#include "nsIWebBrowserPersist.h"
#include "nsEscape.h"
NS_IMPL_ADDREF(nsContentAreaDragDrop)
@ -108,6 +109,7 @@ NS_INTERFACE_MAP_BEGIN(nsContentAreaDragDrop)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDragListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMDragListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMDragListener)
NS_INTERFACE_MAP_ENTRY(nsIFlavorDataProvider)
NS_INTERFACE_MAP_ENTRY(nsIDragDropHandler)
NS_INTERFACE_MAP_END
@ -155,7 +157,7 @@ nsContentAreaDragDrop::Detach()
//
// Subscribe to the events that will allow us to track drags.
//
NS_IMETHODIMP
nsresult
nsContentAreaDragDrop::AddDragListener()
{
nsresult rv = NS_ERROR_FAILURE;
@ -176,7 +178,7 @@ nsContentAreaDragDrop::AddDragListener()
//
// Unsubscribe from all the various drag events that we were listening to.
//
NS_IMETHODIMP
nsresult
nsContentAreaDragDrop::RemoveDragListener()
{
nsresult rv = NS_ERROR_FAILURE;
@ -304,7 +306,7 @@ nsContentAreaDragDrop::ExtractURLFromData(const nsACString & inFlavor, nsISuppor
return;
outURL.Truncate();
if ( inFlavor.Equals(kUnicodeMime) ) {
if ( inFlavor.Equals(kUnicodeMime) || inFlavor.Equals(kURLDataMime) ) {
// the data is regular unicode, just go with what we get. It may be a url, it
// may not be. *shrug*
nsCOMPtr<nsISupportsString> stringData(do_QueryInterface(inDataWrapper));
@ -374,12 +376,13 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEvent* inMouseEvent)
nsCOMPtr<nsITransferable> trans(do_CreateInstance("@mozilla.org/widget/transferable;1"));
if ( !trans )
return NS_ERROR_FAILURE;
// add the relevant flavors. order is important (highest fidelity to lowest)
trans->AddDataFlavor(kURLDataMime);
trans->AddDataFlavor(kURLMime);
trans->AddDataFlavor(kFileMime);
trans->AddDataFlavor(kUnicodeMime);
nsresult rv = session->GetData(trans, 0); // again, we only care about the first object
if ( NS_SUCCEEDED(rv) ) {
// if the client has provided an override callback, call it. It may
@ -980,6 +983,18 @@ nsContentAreaDragDrop::CreateTransferable(const nsAString & inURLString, const n
return NS_ERROR_FAILURE;
urlPrimitive->SetData(dragData);
trans->SetTransferData(kURLMime, urlPrimitive, dragData.Length() * sizeof(PRUnichar));
nsCOMPtr<nsISupportsString> urlDataPrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (!urlDataPrimitive)
return NS_ERROR_FAILURE;
urlDataPrimitive->SetData(inURLString);
trans->SetTransferData(kURLDataMime, urlDataPrimitive, inURLString.Length() * sizeof(PRUnichar));
nsCOMPtr<nsISupportsString> urlDescPrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (!urlDescPrimitive)
return NS_ERROR_FAILURE;
urlDescPrimitive->SetData(inTitleString);
trans->SetTransferData(kURLDescriptionMime, urlDescPrimitive, inTitleString.Length() * sizeof(PRUnichar));
}
// add the full html
@ -1007,6 +1022,26 @@ nsContentAreaDragDrop::CreateTransferable(const nsAString & inURLString, const n
return NS_ERROR_FAILURE;
ptrPrimitive->SetData(inImage);
trans->SetTransferData(kNativeImageMime, ptrPrimitive, sizeof(nsIImage*));
// assume the image comes from a file, and add a file promise. We register ourselves
// as a nsIFlavorDataProvider, and will use the GetFlavorData callback to save the
// image to disk.
trans->SetTransferData(kFilePromiseMime, NS_STATIC_CAST(nsIFlavorDataProvider*, this), nsITransferable::kFlavorHasDataProvider);
nsCOMPtr<nsISupportsString> imageUrlPrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (!imageUrlPrimitive)
return NS_ERROR_FAILURE;
imageUrlPrimitive->SetData(inImageSourceString);
trans->SetTransferData(kFilePromiseURLMime, imageUrlPrimitive, inImageSourceString.Length() * sizeof(PRUnichar));
// if not an anchor, add the image url
if (!inIsAnchor)
{
nsCOMPtr<nsISupportsString> urlDataPrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (!urlDataPrimitive)
return NS_ERROR_FAILURE;
urlDataPrimitive->SetData(inURLString);
trans->SetTransferData(kURLDataMime, urlDataPrimitive, inURLString.Length() * sizeof(PRUnichar));
}
}
*outTrans = trans;
@ -1318,3 +1353,127 @@ nsContentAreaDragDrop::GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImag
return CallGetInterface(ir.get(), outImage);
}
#if 0
#pragma mark -
#endif
// SaveURIToFile
// used on platforms where it's possible to drag items (e.g. images)
// into the file system
nsresult
nsContentAreaDragDrop::SaveURIToFileInDirectory(nsAString& inSourceURIString, nsILocalFile* inDestDirectory, nsILocalFile** outFile)
{
*outFile = nsnull;
nsresult rv;
// clone it because it belongs to the drag data, so we shouldn't mess with it
nsCOMPtr<nsIFile> clonedFile;
rv = inDestDirectory->Clone(getter_AddRefs(clonedFile));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILocalFile> destFile = do_QueryInterface(clonedFile);
if (!destFile) return NS_ERROR_NO_INTERFACE;
nsCOMPtr<nsIURI> sourceURI;
rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
if (!sourceURL) return NS_ERROR_NO_INTERFACE;
nsCAutoString fileName; // escaped, UTF-8
sourceURL->GetFileName(fileName);
if (fileName.IsEmpty())
return NS_ERROR_FAILURE; // this is an error; the URL must point to a file
NS_UnescapeURL(fileName);
NS_ConvertUTF8toUCS2 wideFileName(fileName);
// make the name safe for the filesystem
wideFileName.ReplaceChar(PRUnichar('/'), PRUnichar('_'));
wideFileName.ReplaceChar(PRUnichar('\\'), PRUnichar('_'));
wideFileName.ReplaceChar(PRUnichar(':'), PRUnichar('_'));
rv = destFile->Append(wideFileName);
if (NS_FAILED(rv)) return rv;
rv = destFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
if (NS_FAILED(rv)) return rv;
// we rely on the fact that the WPB is refcounted by the channel etc,
// so we don't keep a ref to it. It will die when finished.
nsCOMPtr<nsIWebBrowserPersist> persist = do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupports> fileAsSupports = do_QueryInterface(destFile);
rv = persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, fileAsSupports);
if (NS_FAILED(rv)) return rv;
*outFile = destFile;
NS_ADDREF(*outFile);
return NS_OK;
}
// This is our nsIFlavorDataProvider callback. There are several assumptions here that
// make this work:
//
// 1. Someone put a kFilePromiseURLMime flavor into the transferable with the source
// URI of the file to save (as a string). We did that above.
//
// 2. Someone put a kFilePromiseDirectoryMime flavor into the transferable with
// an nsILocalFile for the directory we are to save in. That has to be done
// by platform-specific code (in widget), which gets the destination directory
// from OS-specific drag information.
//
NS_IMETHODIMP
nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
{
NS_ENSURE_ARG_POINTER(aData && aDataLen);
*aData = nsnull;
*aDataLen = 0;
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
if (strcmp(aFlavor, kFilePromiseMime) == 0)
{
// get the URI from the kFilePromiseURLMime flavor
NS_ENSURE_ARG(aTransferable);
nsCOMPtr<nsISupports> urlPrimitive;
PRUint32 dataSize = 0;
aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
if (!srcUrlPrimitive) return NS_ERROR_FAILURE;
nsAutoString sourceURLString;
srcUrlPrimitive->GetData(sourceURLString);
if (sourceURLString.IsEmpty())
return NS_ERROR_FAILURE;
// get the target directory from the kFilePromiseDirectoryMime flavor
nsCOMPtr<nsISupports> dirPrimitive;
dataSize = 0;
aTransferable->GetTransferData(kFilePromiseDirectoryMime, getter_AddRefs(dirPrimitive), &dataSize);
nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
if (!destDirectory) return NS_ERROR_FAILURE;
// now save the file
nsCOMPtr<nsILocalFile> destFile;
rv = SaveURIToFileInDirectory(sourceURLString, destDirectory, getter_AddRefs(destFile));
// send back an nsILocalFile
if (NS_SUCCEEDED(rv))
{
CallQueryInterface(destFile, aData);
*aDataLen = sizeof(nsILocalFile*);
}
}
return rv;
}

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

@ -45,6 +45,7 @@
#include "nsIDragDropHandler.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMEventReceiver.h"
#include "nsITransferable.h"
class nsIDOMNode;
class nsISelection;
@ -54,9 +55,10 @@ class nsIPresShell;
class nsIPresContext;
class nsIContent;
class nsIDocument;
class nsIURI;
class nsILocalFile;
class nsISimpleEnumerator;
// {1f34bc80-1bc7-11d6-a384-d705dd0746fc}
#define NS_CONTENTAREADRAGDROP_CID \
{ 0x1f34bc80, 0x1bc7, 0x11d6, { 0xa3, 0x84, 0xd7, 0x05, 0xdd, 0x07, 0x46, 0xfc } }
@ -71,11 +73,14 @@ class nsISimpleEnumerator;
// to drag and drop. Registers itself with the DOM with AddChromeListeners()
// and removes itself with RemoveChromeListeners().
//
class nsContentAreaDragDrop : public nsIDOMDragListener, public nsIDragDropHandler
class nsContentAreaDragDrop : public nsIDOMDragListener,
public nsIDragDropHandler,
public nsIFlavorDataProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDRAGDROPHANDLER
NS_DECL_NSIFLAVORDATAPROVIDER
nsContentAreaDragDrop ( ) ;
virtual ~nsContentAreaDragDrop ( ) ;
@ -91,8 +96,8 @@ public:
private:
// Add/remove the relevant listeners
NS_IMETHOD AddDragListener();
NS_IMETHOD RemoveDragListener();
nsresult AddDragListener();
nsresult RemoveDragListener();
// utility routines
static void FindFirstAnchor(nsIDOMNode* inNode, nsIDOMNode** outAnchor);
@ -110,6 +115,8 @@ private:
// if inNode is null, use the selection from the window
static nsresult SerializeNodeOrSelection(const char* inMimeType, PRUint32 inFlags,
nsIDOMWindow* inWindow, nsIDOMNode* inNode, nsAString& outResultString);
static nsresult SaveURIToFileInDirectory(nsAString& inSourceURIString, nsILocalFile* inDestDirectory, nsILocalFile** outFile);
PRBool BuildDragData(nsIDOMEvent* inMouseEvent, nsAString & outURLString, nsAString & outTitleString,
nsAString & outHTMLString, nsAString & outImageSourceString, nsIImage** outImage, PRBool* outIsAnchor);

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

@ -52,6 +52,7 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIDOMRange.h"
#include "nsIFrame.h"
#include "nsIDocShell.h"
#include "nsIClipboardDragDropHooks.h"
@ -70,6 +71,17 @@
//static NS_DEFINE_CID(kUBidiUtilCID, NS_UNICHARBIDIUTIL_CID);
#endif
// image copy stuff
#include "nsIDOMHTMLImageElement.h"
#include "nsLayoutAtoms.h"
#include "nsIImageLoadingContent.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
@ -379,3 +391,121 @@ nsresult nsCopySupport::IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc
return NS_OK;
}
nsresult
nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDocumentEncoder> docEncoder;
nsCAutoString encoderContractID(NS_DOC_ENCODER_CONTRACTID_BASE);
encoderContractID.Append(aMimeType);
docEncoder = do_CreateInstance(encoderContractID.get());
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
PRUint32 flags = aFlags;
if (aMimeType.Equals("text/plain"))
flags |= nsIDocumentEncoder::OutputPreformatted;
NS_ConvertASCIItoUCS2 unicodeMimeType(aMimeType);
rv = docEncoder->Init(aDoc, unicodeMimeType, flags);
if (NS_FAILED(rv)) return rv;
if (aSel)
{
rv = docEncoder->SetSelection(aSel);
if (NS_FAILED(rv)) return rv;
}
// encode the selection
return docEncoder->EncodeToString(outdata);
}
nsresult
nsCopySupport::ImageCopy(nsIDOMHTMLImageElement* imageElement, PRInt16 aClipboardID)
{
nsresult rv;
nsCOMPtr<nsIDOMNode> imageNode = do_QueryInterface(imageElement, &rv);
if (NS_FAILED(rv)) return rv;
if (!imageNode) return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> image;
rv = GetImageFromDOMNode(imageNode, getter_AddRefs(image));
if (NS_FAILED(rv)) return rv;
if (!image) return NS_ERROR_FAILURE;
// Get the Clipboard
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
if (NS_FAILED(rv)) return rv;
if (!clipboard) return NS_ERROR_FAILURE;
// Create a transferable for putting data on the Clipboard
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!trans) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
if (!ptrPrimitive) return NS_ERROR_FAILURE;
ptrPrimitive->SetData(image);
trans->SetTransferData(kNativeImageMime, ptrPrimitive, sizeof(nsISupports*));
// put the transferable on the clipboard
return clipboard->SetData(trans, nsnull, aClipboardID);
}
//
// GetImage
//
// Given a dom node that's an image, finds the nsIImage associated with it.
//
// XXX see also nsContentAreaDragDrop, and factor!
nsresult
nsCopySupport::GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImage)
{
NS_ENSURE_ARG_POINTER(outImage);
*outImage = nsnull;
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(inNode));
if (!content) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<imgIRequest> imgRequest;
content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(imgRequest));
if (!imgRequest) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<imgIContainer> imgContainer;
imgRequest->GetImage(getter_AddRefs(imgContainer));
if (!imgContainer) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<gfxIImageFrame> imgFrame;
imgContainer->GetFrameAt(0, getter_AddRefs(imgFrame));
if (!imgFrame) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(imgFrame);
if (!ir) {
return NS_ERROR_NOT_AVAILABLE;
}
return CallGetInterface(ir.get(), outImage);
}

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

@ -52,6 +52,7 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIDOMRange.h"
#include "nsIFrame.h"
#include "nsIDocShell.h"
#include "nsIClipboardDragDropHooks.h"
@ -70,6 +71,17 @@
//static NS_DEFINE_CID(kUBidiUtilCID, NS_UNICHARBIDIUTIL_CID);
#endif
// image copy stuff
#include "nsIDOMHTMLImageElement.h"
#include "nsLayoutAtoms.h"
#include "nsIImageLoadingContent.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
@ -379,3 +391,121 @@ nsresult nsCopySupport::IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc
return NS_OK;
}
nsresult
nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDocumentEncoder> docEncoder;
nsCAutoString encoderContractID(NS_DOC_ENCODER_CONTRACTID_BASE);
encoderContractID.Append(aMimeType);
docEncoder = do_CreateInstance(encoderContractID.get());
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
PRUint32 flags = aFlags;
if (aMimeType.Equals("text/plain"))
flags |= nsIDocumentEncoder::OutputPreformatted;
NS_ConvertASCIItoUCS2 unicodeMimeType(aMimeType);
rv = docEncoder->Init(aDoc, unicodeMimeType, flags);
if (NS_FAILED(rv)) return rv;
if (aSel)
{
rv = docEncoder->SetSelection(aSel);
if (NS_FAILED(rv)) return rv;
}
// encode the selection
return docEncoder->EncodeToString(outdata);
}
nsresult
nsCopySupport::ImageCopy(nsIDOMHTMLImageElement* imageElement, PRInt16 aClipboardID)
{
nsresult rv;
nsCOMPtr<nsIDOMNode> imageNode = do_QueryInterface(imageElement, &rv);
if (NS_FAILED(rv)) return rv;
if (!imageNode) return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> image;
rv = GetImageFromDOMNode(imageNode, getter_AddRefs(image));
if (NS_FAILED(rv)) return rv;
if (!image) return NS_ERROR_FAILURE;
// Get the Clipboard
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
if (NS_FAILED(rv)) return rv;
if (!clipboard) return NS_ERROR_FAILURE;
// Create a transferable for putting data on the Clipboard
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!trans) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
if (!ptrPrimitive) return NS_ERROR_FAILURE;
ptrPrimitive->SetData(image);
trans->SetTransferData(kNativeImageMime, ptrPrimitive, sizeof(nsISupports*));
// put the transferable on the clipboard
return clipboard->SetData(trans, nsnull, aClipboardID);
}
//
// GetImage
//
// Given a dom node that's an image, finds the nsIImage associated with it.
//
// XXX see also nsContentAreaDragDrop, and factor!
nsresult
nsCopySupport::GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImage)
{
NS_ENSURE_ARG_POINTER(outImage);
*outImage = nsnull;
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(inNode));
if (!content) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<imgIRequest> imgRequest;
content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(imgRequest));
if (!imgRequest) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<imgIContainer> imgContainer;
imgRequest->GetImage(getter_AddRefs(imgContainer));
if (!imgContainer) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<gfxIImageFrame> imgFrame;
imgContainer->GetFrameAt(0, getter_AddRefs(imgFrame));
if (!imgFrame) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(imgFrame);
if (!ir) {
return NS_ERROR_NOT_AVAILABLE;
}
return CallGetInterface(ir.get(), outImage);
}

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

@ -40,6 +40,13 @@
class nsISelection;
class nsIDocument;
class nsIDOMNode;
class nsIDOMHTMLImageElement;
class nsIContent;
class nsIPresContext;
class nsIPresShell;
class nsIImageFrame;
class nsIImage;
class nsITransferable;
class nsCopySupport
@ -50,4 +57,17 @@ class nsCopySupport
static nsresult DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
PRBool *aDoPutOnClipboard);
static nsresult IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, PRBool *aIsPlainTextContext);
// Get the selection, or entire document, in the format specified by the mime type
// (text/html or text/plain). If aSel is non-null, use it, otherwise get the entire
// doc.
static nsresult GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata);
static nsresult ImageCopy(nsIDOMHTMLImageElement* imageElement, PRInt16 aClipboardID);
protected:
// these are ripped from nsContentAreaDragDrop. This so needs factoring.
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImage);
};

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

@ -29,24 +29,66 @@
// these probably shouldn't live here, but in some central repository shared
// by the entire app.
#define kTextMime "text/plain"
#define kUnicodeMime "text/unicode"
#define kHTMLMime "text/html"
#define kAOLMailMime "AOLMAIL"
#define kPNGImageMime "image/png"
#define kJPEGImageMime "image/jpg"
#define kGIFImageMime "image/gif"
#define kFileMime "application/x-moz-file"
#define kURLMime "text/x-moz-url"
#define kNativeImageMime "application/x-moz-nativeimage"
#define kNativeHTMLMime "application/x-moz-nativehtml"
#define kTextMime "text/plain"
#define kUnicodeMime "text/unicode"
#define kHTMLMime "text/html"
#define kAOLMailMime "AOLMAIL"
#define kPNGImageMime "image/png"
#define kJPEGImageMime "image/jpg"
#define kGIFImageMime "image/gif"
#define kFileMime "application/x-moz-file"
#define kURLMime "text/x-moz-url" // data contains url\ntitle
#define kURLDataMime "text/x-moz-url-data" // data contains url only
#define kURLDescriptionMime "text/x-moz-url-desc" // data contains description
#define kNativeImageMime "application/x-moz-nativeimage"
#define kNativeHTMLMime "application/x-moz-nativehtml"
// the source URL for a file promise
#define kFilePromiseURLMime "application/x-moz-file-promise-url"
// a dataless flavor used to interact with the OS during file drags
#define kFilePromiseMime "application/x-moz-file-promise"
// a synthetic flavor, put into the transferable once we know the destination directory of a file drag
#define kFilePromiseDirectoryMime "application/x-moz-file-promise-dir"
%}
/**
* nsIFlavorDataProvider allows a flavor to 'promise' data later,
* supplying the data lazily.
*
* To use it, call setTransferData, passing the flavor string,
* a nsIFlavorDataProvider QI'd to nsISupports, and a data size of 0.
*
* When someone calls getTransferData later, if the data size is
* stored as 0, the nsISupports will be QI'd to nsIFlavorDataProvider,
* and its getFlavorData called.
*
*/
interface nsITransferable;
[scriptable, uuid(7E225E5F-711C-11D7-9FAE-000393636592)]
interface nsIFlavorDataProvider : nsISupports
{
/**
* Retrieve the data from this data provider.
*
* @param aTransferable (in parameter) the transferable we're being called for.
* @param aFlavor (in parameter) the flavor of data to retrieve
* @param aData the data. Some variant of class in nsISupportsPrimitives.idl
* @param aDataLen the length of the data
*/
void getFlavorData(in nsITransferable aTransferable, in string aFlavor, out nsISupports aData, out unsigned long aDataLen);
};
[scriptable, uuid(8B5314BC-DB01-11d2-96CE-0060B0FB9956)]
interface nsITransferable : nsISupports
{
const long kFlavorHasDataProvider = 0;
/**
* Computes a list of flavors (mime types as nsISupportsCString) that the transferable
* can export, either through intrinsic knowledge or output data converters.
@ -99,8 +141,9 @@ interface nsITransferable : nsISupports
* will maintain its own copy the data, so it is not necessary to do that beforehand.
*
* @param aFlavor the flavor of data that is being set
* @param aData the data, some variant of class in nsISupportsPrimitives.idl
* @param aDataLen the length of the data
* @param aData the data, some variant of class in nsISupportsPrimitives.idl,
* or an nsIFlavorDataProvider (see above)
* @param aDataLen the length of the data, or 0 if passing a nsIFlavorDataProvider
*/
void setTransferData ( in string aFlavor, in nsISupports aData, in unsigned long aDataLen ) ;

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

@ -211,13 +211,19 @@ nsClipboard :: SetNativeClipboardData ( PRInt32 aWhichClipboard )
}
} // if unicode
else if ( strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 ||
strcmp(flavorStr, kGIFImageMime) == 0 ) {
strcmp(flavorStr, kGIFImageMime) == 0 || strcmp(flavorStr, kNativeImageMime) == 0 ) {
// we have an image, which is in the transferable as an nsIImage. Convert it
// to PICT (PicHandle) and put those bits on the clipboard. The actual size
// of the picture is the size of the handle, not sizeof(Picture).
nsCOMPtr<nsISupports> imageSupports;
errCode = mTransferable->GetTransferData ( flavorStr, getter_AddRefs(imageSupports), &dataSize );
nsCOMPtr<nsIImageMac> image ( do_QueryInterface(imageSupports) );
nsCOMPtr<nsISupports> transferSupports;
errCode = mTransferable->GetTransferData ( flavorStr, getter_AddRefs(transferSupports), &dataSize );
nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_QueryInterface(transferSupports));
nsCOMPtr<nsIImageMac> image;
if (ptrPrimitive) {
nsCOMPtr<nsISupports> primitiveData;
ptrPrimitive->GetData(getter_AddRefs(primitiveData));
image = do_QueryInterface(primitiveData);
}
if ( image ) {
PicHandle picture = nsnull;
image->ConvertToPICT ( &picture );

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

@ -55,11 +55,10 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsCRT.h"
#include "nsPrimitiveHelpers.h"
#include "nsILocalFileMac.h"
#include "nsWatchTask.h"
#include "nsLinebreakConverter.h"
// rjc
#include <Gestalt.h>
@ -74,10 +73,16 @@
#include "nsPoint.h"
#include "nsIWidget.h"
#include "nsCarbonHelpers.h"
#include "nsGfxUtils.h"
// file save stuff
#include "nsNetUtil.h"
#include "nsILocalFileMac.h"
#ifdef MOZ_XUL
#include "nsIXULContent.h"
#endif
#include "nsIDOMElement.h"
#include "nsIImageMac.h"
#include "nsIImage.h"
@ -96,7 +101,10 @@ NS_IMPL_QUERY_INTERFACE3(nsDragService, nsIDragService, nsIDragSession, nsIDragS
// DragService constructor
//
nsDragService::nsDragService()
: mDragRef(0), mDataItems(nsnull), mImageDraggingSupported(PR_FALSE), mDragSendDataUPP(nsnull)
: mDragSendDataUPP(nsnull)
, mDragRef(0)
, mDataItems(nsnull)
, mImageDraggingSupported(PR_FALSE)
{
#if USE_TRANSLUCENT_DRAGS
// check if the Drag Manager supports image dragging
@ -123,7 +131,7 @@ nsDragService::~nsDragService()
PRBool
nsDragService :: ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outScreenRect )
nsDragService::ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outScreenRect )
{
NS_ASSERTION ( aDOMNode, "Oopps, no DOM node" );
@ -165,7 +173,6 @@ nsDragService :: ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outSc
//
nsRect aRect(0,0,0,0);
nsIView *parentView = nsnull;
aFrame->GetRect(aRect);
// Find offset from our view
@ -218,7 +225,7 @@ nsDragService :: ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outSc
// Do all the work to kick it off.
//
NS_IMETHODIMP
nsDragService :: InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTransferableArray, nsIScriptableRegion * aDragRgn, PRUint32 aActionType)
nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTransferableArray, nsIScriptableRegion * aDragRgn, PRUint32 aActionType)
{
::InitCursor();
nsBaseDragService::InvokeDragSession ( aDOMNode, aTransferableArray, aDragRgn, aActionType );
@ -232,10 +239,6 @@ nsDragService :: InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTr
printf("**** created drag ref %ld\n", theDragRef);
#endif
// add the flavors from the transferables. Cache this array for the send data proc
mDataItems = aTransferableArray;
RegisterDragItemsAndFlavors ( aTransferableArray ) ;
Rect frameRect = { 0, 0, 0, 0 };
RgnHandle theDragRgn = ::NewRgn();
::RectRgn(theDragRgn, &frameRect);
@ -253,6 +256,10 @@ printf("**** created drag ref %ld\n", theDragRef);
else
BuildDragRegion ( aDragRgn, aDOMNode, theDragRgn );
// add the flavors from the transferables. Cache this array for the send data proc
mDataItems = aTransferableArray;
RegisterDragItemsAndFlavors(aTransferableArray, theDragRgn);
// we have to synthesize the native event because we may be called from JavaScript
// through XPConnect. In that case, we only have a DOM event and no way to
// get to the native event. As a consequence, we just always fake it.
@ -307,7 +314,7 @@ printf("**** disposing drag ref %ld\n", theDragRef);
// Returns PR_TRUE if the region is something that can be used with SetDragImage()
//
PRBool
nsDragService :: BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* inNode, RgnHandle ioDragRgn )
nsDragService::BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* inNode, RgnHandle ioDragRgn )
{
PRBool retVal = PR_TRUE;
nsCOMPtr<nsIRegion> geckoRegion;
@ -377,13 +384,17 @@ nsDragService :: BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* in
// requested.
//
void
nsDragService :: RegisterDragItemsAndFlavors ( nsISupportsArray * inArray )
nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray* inArray, RgnHandle inDragRgn)
{
const FlavorFlags flags = 0;
unsigned int numDragItems = 0;
Rect dragRgnBounds = {0, 0, 0, 0};
if (inDragRgn)
GetRegionBounds(inDragRgn, &dragRgnBounds);
PRUint32 numDragItems = 0;
inArray->Count ( &numDragItems ) ;
for ( int itemIndex = 0; itemIndex < numDragItems; ++itemIndex ) {
for ( PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex ) {
nsMimeMapperMac theMapper;
nsCOMPtr<nsISupports> genericItem;
@ -394,25 +405,39 @@ nsDragService :: RegisterDragItemsAndFlavors ( nsISupportsArray * inArray )
if ( NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))) ) {
PRUint32 numFlavors;
flavorList->Count ( &numFlavors );
for ( int flavorIndex = 0; flavorIndex < numFlavors; ++flavorIndex ) {
for ( PRUint32 flavorIndex = 0; flavorIndex < numFlavors; ++flavorIndex ) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr);
::AddDragItemFlavor ( mDragRef, itemIndex, macOSFlavor, NULL, 0, flags );
// If we advertise text/unicode, then make sure we add 'TEXT' to the list
// of flavors supported since we will do the conversion ourselves in GetDataForFlavor()
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
theMapper.MapMimeTypeToMacOSType(kTextMime);
::AddDragItemFlavor ( mDragRef, itemIndex, 'TEXT', NULL, 0, flags );
::AddDragItemFlavor ( mDragRef, itemIndex, 'styl', NULL, 0, flags );
}
}
if ( currentFlavor ) {
nsCAutoString flavorStr;
currentFlavor->GetData(flavorStr);
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr.get());
if (macOSFlavor == kDragFlavorTypePromiseHFS) {
// we got kFilePromiseMime
// kDragFlavorTypePromiseHFS is special. See http://developer.apple.com/technotes/tn/tn1085.html
PromiseHFSFlavor promiseData;
promiseData.fileType = 0; // let the file extension prevail!
promiseData.fileCreator = 0;
promiseData.fdFlags = 0;
promiseData.promisedFlavor = kDragPromisedFlavor;
::AddDragItemFlavor(mDragRef, itemIndex, kDragFlavorTypePromiseHFS, &promiseData, sizeof(promiseData), flavorNotSaved);
::AddDragItemFlavor(mDragRef, itemIndex, kDragPromisedFlavor, NULL, 0, flavorNotSaved);
}
else
::AddDragItemFlavor(mDragRef, itemIndex, macOSFlavor, NULL, 0, flags);
// If we advertise text/unicode, then make sure we add 'TEXT' to the list
// of flavors supported since we will do the conversion ourselves in GetDataForFlavor()
if ( strcmp(flavorStr.get(), kUnicodeMime) == 0 ) {
theMapper.MapMimeTypeToMacOSType(kTextMime);
::AddDragItemFlavor ( mDragRef, itemIndex, 'TEXT', NULL, 0, flags );
::AddDragItemFlavor ( mDragRef, itemIndex, 'styl', NULL, 0, flags );
}
}
} // foreach flavor in item
} // if valid flavor list
@ -428,6 +453,8 @@ nsDragService :: RegisterDragItemsAndFlavors ( nsISupportsArray * inArray )
::AddDragItemFlavor ( mDragRef, itemIndex, nsMimeMapperMac::MappingFlavor(),
mapping, mappingLen, flags );
nsCRT::free ( mapping );
::SetDragItemBounds(mDragRef, itemIndex, &dragRgnBounds);
}
} // foreach drag item
@ -443,7 +470,7 @@ nsDragService :: RegisterDragItemsAndFlavors ( nsISupportsArray * inArray )
// stop as soon as we find a match.
//
NS_IMETHODIMP
nsDragService :: GetData ( nsITransferable * aTransferable, PRUint32 aItemIndex )
nsDragService::GetData ( nsITransferable * aTransferable, PRUint32 aItemIndex )
{
nsresult errCode = NS_ERROR_FAILURE;
@ -473,33 +500,33 @@ nsDragService :: GetData ( nsITransferable * aTransferable, PRUint32 aItemIndex
// implicitly handles conversions.
PRUint32 cnt;
flavorList->Count ( &cnt );
for ( int i = 0; i < cnt; ++i ) {
for (PRUint32 i = 0; i < cnt; ++i) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( i, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor ) {
// find MacOS flavor (but don't add it if it's not there)
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr, PR_FALSE);
nsCAutoString flavorStr;
currentFlavor->GetData(flavorStr);
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr.get(), PR_FALSE);
#if DEBUG_DD
printf("looking for data in type %s, mac flavor %ld\n", NS_STATIC_CAST(const char*,flavorStr), macOSFlavor);
printf("looking for data in type %s, mac flavor %ld\n", flavorStr.get(), macOSFlavor);
#endif
// check if it is present in the current drag item.
FlavorFlags unused;
PRBool dataFound = PR_FALSE;
void* dataBuff;
void* dataBuff = nsnull;
PRInt32 dataSize = 0;
if ( macOSFlavor && ::GetFlavorFlags(mDragRef, itemRef, macOSFlavor, &unused) == noErr ) {
nsresult loadResult = ExtractDataFromOS(mDragRef, itemRef, macOSFlavor, &dataBuff, &dataSize);
if ( NS_SUCCEEDED(loadResult) && dataBuff )
dataFound = PR_TRUE;
if ( NS_SUCCEEDED(loadResult) && dataBuff )
dataFound = PR_TRUE;
}
else {
// if we are looking for text/unicode and we fail to find it on the clipboard first,
// if we are looking for text/unicode and we fail to find it on the clipboard first,
// try again with text/plain. If that is present, convert it to unicode.
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
if ( strcmp(flavorStr.get(), kUnicodeMime) == 0 ) {
if ( ::GetFlavorFlags(mDragRef, itemRef, 'TEXT', &unused) == noErr ) {
// if 'styl' is available, we can get a script of the first run
@ -554,19 +581,35 @@ printf("looking for data in type %s, mac flavor %ld\n", NS_STATIC_CAST(const cha
} // else we try one last ditch effort to find our data
if ( dataFound ) {
nsCOMPtr<nsISupports> genericDataWrapper;
if ( strcmp(flavorStr, kFileMime) == 0 ) {
nsCOMPtr<nsISupports> genericDataWrapper;
if ( strcmp(flavorStr.get(), kFileMime) == 0 ) {
// we have a HFSFlavor struct in |dataBuff|. Create an nsLocalFileMac object.
HFSFlavor* fileData = NS_REINTERPRET_CAST(HFSFlavor*, dataBuff);
NS_ASSERTION ( sizeof(HFSFlavor) == dataSize, "Ooops, we realy don't have a HFSFlavor" );
NS_ASSERTION ( sizeof(HFSFlavor) == dataSize, "Ooops, we really don't have a HFSFlavor" );
nsCOMPtr<nsILocalFileMac> file;
if ( NS_SUCCEEDED(NS_NewLocalFileWithFSSpec(&fileData->fileSpec, PR_TRUE, getter_AddRefs(file))) )
genericDataWrapper = do_QueryInterface(file);
}
else if ((strcmp(flavorStr.get(), kURLDataMime) == 0) || (strcmp(flavorStr.get(), kURLDescriptionMime) == 0)) {
// need to convert platform data to unicode
const char* castedText = NS_REINTERPRET_CAST(char*, dataBuff);
PRUnichar* convertedText = nsnull;
PRInt32 convertedTextLen = 0;
nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode(castedText, dataSize,
&convertedText, &convertedTextLen);
if (convertedText)
{
nsMemory::Free(dataBuff);
dataBuff = convertedText;
dataSize = convertedTextLen * 2;
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr.get(), (void *)dataBuff, dataSize, getter_AddRefs(genericDataWrapper));
}
}
else {
// we probably have some form of text. The DOM only wants LF, so convert k
// from MacOS line endings to DOM line endings.
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &dataBuff, NS_REINTERPRET_CAST(int*, &dataSize) );
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr.get(), &dataBuff, NS_REINTERPRET_CAST(int*, &dataSize));
unsigned char *dataPtr = (unsigned char *) dataBuff;
#if TARGET_CARBON
@ -582,15 +625,14 @@ printf("looking for data in type %s, mac flavor %ld\n", NS_STATIC_CAST(const cha
dataPtr += sizeof(PRUnichar);
}
#endif
nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, (void *) dataPtr, dataSize, getter_AddRefs(genericDataWrapper) );
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr.get(), (void *) dataPtr, dataSize, getter_AddRefs(genericDataWrapper));
}
// put it into the transferable.
errCode = aTransferable->SetTransferData ( flavorStr, genericDataWrapper, dataSize );
#ifdef NS_DEBUG
errCode = aTransferable->SetTransferData(flavorStr.get(), genericDataWrapper, dataSize);
#ifdef NS_DEBUG
if ( errCode != NS_OK ) printf("nsDragService:: Error setting data into transferable\n");
#endif
#endif
nsMemory::Free ( dataBuff );
errCode = NS_OK;
@ -618,7 +660,7 @@ printf("looking for data in type %s, mac flavor %ld\n", NS_STATIC_CAST(const cha
// ¥¥¥Êand index to this API
//
NS_IMETHODIMP
nsDragService :: IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
if ( !_retval )
return NS_ERROR_INVALID_ARG;
@ -670,7 +712,7 @@ nsDragService :: IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
// Returns the number of drop items present in the current drag.
//
NS_IMETHODIMP
nsDragService :: GetNumDropItems ( PRUint32 * aNumItems )
nsDragService::GetNumDropItems ( PRUint32 * aNumItems )
{
// we have to put it into a short first because that's what the MacOS API's expect.
// After it's in a short, getting it into a long is no problem. Oh well.
@ -690,7 +732,7 @@ nsDragService :: GetNumDropItems ( PRUint32 * aNumItems )
// current dragRef w/out resorting to knowing the internals of the implementation
//
NS_IMETHODIMP
nsDragService :: SetDragReference ( DragReference aDragRef )
nsDragService::SetDragReference ( DragReference aDragRef )
{
mDragRef = aDragRef;
return NS_OK;
@ -712,16 +754,16 @@ nsDragService :: SetDragReference ( DragReference aDragRef )
// and pass that along.
//
pascal OSErr
nsDragService :: DragSendDataProc ( FlavorType inFlavor, void* inRefCon, ItemReference inItemRef,
DragReference inDragRef )
nsDragService::DragSendDataProc(FlavorType inFlavor, void* inRefCon, ItemReference inItemRef,
DragReference inDragRef)
{
OSErr retVal = noErr;
nsDragService* self = NS_STATIC_CAST(nsDragService*, inRefCon);
NS_ASSERTION ( self, "Refcon not set correctly for DragSendDataProc" );
if ( self ) {
nsDragService* dragService = NS_STATIC_CAST(nsDragService*, inRefCon);
NS_ASSERTION ( dragService, "Refcon not set correctly for DragSendDataProc" );
if (dragService) {
void* data = nsnull;
PRUint32 dataSize = 0;
retVal = self->GetDataForFlavor ( self->mDataItems, inDragRef, inItemRef, inFlavor, &data, &dataSize );
retVal = dragService->GetDataForFlavor(dragService->mDataItems, inDragRef, inItemRef, inFlavor, &data, &dataSize);
if ( retVal == noErr ) {
// make the data accessable to the DragManager
retVal = ::SetDragItemFlavorData ( inDragRef, inItemRef, inFlavor, data, dataSize, 0 );
@ -750,141 +792,210 @@ nsDragService :: DragSendDataProc ( FlavorType inFlavor, void* inRefCon, ItemRef
// wouldn't have been allowed to look for unicode.
//
OSErr
nsDragService :: GetDataForFlavor ( nsISupportsArray* inDragItems, DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, void** outData, unsigned int* outDataSize )
nsDragService::GetDataForFlavor(nsISupportsArray* inDragItems, DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, void** outData, unsigned int* outDataSize)
{
if ( !inDragItems || !inDragRef )
return paramErr;
*outData = nsnull;
*outDataSize = 0;
OSErr retVal = noErr;
nsresult rv;
// (assumes that the items were placed into the transferable as nsITranferable*'s, not nsISupports*'s.)
nsCOMPtr<nsISupports> genericItem;
inDragItems->GetElementAt ( inItemIndex, getter_AddRefs(genericItem) );
nsCOMPtr<nsITransferable> item ( do_QueryInterface(genericItem) );
if ( item ) {
nsCAutoString mimeFlavor;
inDragItems->GetElementAt(inItemIndex, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> item(do_QueryInterface(genericItem));
if (!item) return cantGetFlavorErr;
// create a mime mapper to help us out based on data in a special flavor for this item.
char* mappings = LookupMimeMappingsForItem(inDragRef, inItemIndex) ;
nsMimeMapperMac theMapper ( mappings );
theMapper.MapMacOSTypeToMimeType ( inFlavor, mimeFlavor );
nsMemory::Free ( mappings );
char* mappings = LookupMimeMappingsForItem(inDragRef, inItemIndex);
nsMimeMapperMac theMapper(mappings);
nsCAutoString mimeFlavor;
theMapper.MapMacOSTypeToMimeType(inFlavor, mimeFlavor);
nsMemory::Free(mappings);
// if someone was asking for text/plain, lookup unicode instead so we can convert it.
PRBool needToDoConversionToPlainText = PR_FALSE;
const char* actualFlavor = mimeFlavor.get();
if ( strcmp(mimeFlavor.get(), kTextMime) == 0 || inFlavor == 'styl' )
{
actualFlavor = kUnicodeMime;
needToDoConversionToPlainText = PR_TRUE;
}
else if (strcmp(actualFlavor, kURLDataMime) == 0)
{
needToDoConversionToPlainText = PR_TRUE;
}
else if (strcmp(actualFlavor, kURLDescriptionMime) == 0)
{
needToDoConversionToPlainText = PR_TRUE;
}
else if (strcmp(actualFlavor, kFilePromiseMime) == 0)
{
/* Here's how file dragging works:
// if someone was asking for text/plain, lookup unicode instead so we can convert it.
PRBool needToDoConversionToPlainText = PR_FALSE;
const char* actualFlavor = mimeFlavor.get();
if ( strcmp(mimeFlavor.get(),kTextMime) == 0 ||
inFlavor == 'styl' ) {
actualFlavor = kUnicodeMime;
needToDoConversionToPlainText = PR_TRUE;
}
else
actualFlavor = mimeFlavor.get();
Drag code adds a kFilePromiseMime flavor to the transferable, with an
nsIFlavorDataProvider.
It also adds a kFilePromiseURLMime flavor, with a string containing the source
url.
We map that to the OS drag flavor kDragFlavorTypePromiseHFS, which promises
the flavor kDragPromisedFlavor. The OS asks for kDragPromisedFlavor, and we
map that back to kFilePromiseMime.
When asked for kFilePromiseMime data (here), we figure out the drop location from
the OS, and set that as an nsILocalFile on the kFilePromiseDirectoryMime flavor. We then
call GetTransferData() for the kFilePromiseMime flavor, which triggers
the nsIFlavorDataProvider to do the save.
*/
nsCOMPtr<nsILocalFile> dropDirectory;
OSErr err = GetHFSPromiseDropDirectory(inDragRef, inItemIndex, inFlavor, getter_AddRefs(dropDirectory));
if (err != noErr) return err;
// now add a flavor to the transferable
nsCOMPtr<nsISupports> localFileISupports = do_QueryInterface(dropDirectory);
item->SetTransferData(kFilePromiseDirectoryMime, localFileISupports, sizeof(nsILocalFile*));
// now request the kFilePromiseMime data, which will invoke the data provider
// If successful, the returned data is a reference to the resulting file.
nsCOMPtr<nsISupports> fileDataPrimitive;
PRUint32 dataSize = 0;
rv = item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize);
if (NS_FAILED(rv)) return cantGetFlavorErr;
// if we successfully saved, tell the Drag Manager
nsCOMPtr<nsILocalFile> resultFile = do_QueryInterface(fileDataPrimitive);
if (resultFile)
return SetDropFileInDrag(inDragRef, inItemIndex, inFlavor, resultFile);
// something went wrong.
return cantGetFlavorErr;
}
else if (strcmp(actualFlavor, kNativeImageMime) == 0)
{
PRUint32 dataSize = 0;
nsCOMPtr<nsISupports> transferSupports;
rv = item->GetTransferData(actualFlavor, getter_AddRefs(transferSupports), &dataSize);
if (NS_FAILED(rv)) return cantGetFlavorErr;
nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_QueryInterface(transferSupports));
if (!ptrPrimitive) return cantGetFlavorErr;
nsCOMPtr<nsISupports> primitiveData;
ptrPrimitive->GetData(getter_AddRefs(primitiveData));
nsCOMPtr<nsIImageMac> image = do_QueryInterface(primitiveData);
if (!image) return cantGetFlavorErr;
*outDataSize = 0;
nsCOMPtr<nsISupports> data;
if ( NS_SUCCEEDED(item->GetTransferData(actualFlavor, getter_AddRefs(data), outDataSize)) ) {
if ( strcmp(actualFlavor, kNativeImageMime) == 0 ) {
// unwrap the image from its nsISupportsPrimitive wrapper
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(data));
nsCOMPtr<nsIImage> image;
ptr->GetData(getter_AddRefs(image));
// we have an image, which is in the transferable as an nsIImage. Convert it
// to PICT (PicHandle) and put those bits on the clipboard. The actual size
// of the picture is the size of the handle, not sizeof(Picture).
nsCOMPtr<nsIImageMac> imageMac ( do_QueryInterface(image) );
if ( imageMac ) {
PicHandle picture = nsnull;
imageMac->ConvertToPICT ( &picture );
*outDataSize = ::GetHandleSize((Handle)picture);
*outData = nsMemory::Alloc(*outDataSize);
::HLock((Handle)picture);
::BlockMoveData(*picture, *outData, *outDataSize);
::HUnlock((Handle)picture);
::KillPicture(picture);
}
else
NS_WARNING ( "Image isn't an nsIImageMac in transferable" );
}
else {
nsPrimitiveHelpers::CreateDataFromPrimitive ( actualFlavor, data, outData, *outDataSize );
// if required, do the extra work to convert unicode to plain text and replace the output
// values with the plain text.
if ( needToDoConversionToPlainText ) {
char* plainTextData = nsnull;
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, *outData);
PRInt32 plainTextLen = 0;
nsresult rv =
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText ( castedUnicode, *outDataSize / 2, &plainTextData, &plainTextLen );
PicHandle picture = nsnull;
image->ConvertToPICT(&picture);
if (!picture) return cantGetFlavorErr;
ScriptCodeRun *scriptCodeRuns = nsnull;
PRInt32 scriptRunOutLen;
// if characters are not mapped from Unicode then try native API to convert to
// available script
if (rv == NS_ERROR_UENC_NOMAPPING) {
if (plainTextData) {
nsMemory::Free(plainTextData);
plainTextData = nsnull;
}
rv = nsMacNativeUnicodeConverter::ConvertUnicodetoScript(castedUnicode,
*outDataSize / sizeof(PRUnichar),
&plainTextData,
&plainTextLen,
&scriptCodeRuns,
&scriptRunOutLen);
}
else if (NS_SUCCEEDED(rv)) {
// create a single run with the default system script
scriptCodeRuns = NS_REINTERPRET_CAST(ScriptCodeRun*,
nsMemory::Alloc(sizeof(ScriptCodeRun)));
if (scriptCodeRuns) {
scriptCodeRuns[0].offset = 0;
scriptCodeRuns[0].script = (ScriptCode) ::GetScriptManagerVariable(smSysScript);
scriptRunOutLen = 1;
}
}
if ( plainTextData && *outData ) {
nsMemory::Free(*outData);
*outData = nsnull;
*outDataSize = 0;
if (inFlavor != 'styl') {
*outData = plainTextData;
*outDataSize = plainTextLen;
}
else {
nsMemory::Free(plainTextData); // discard 'TEXT'
char *stylData;
PRInt32 stylLen;
// create 'styl' from the script runs
if (scriptCodeRuns) {
rv = CreateStylFromScriptRuns(scriptCodeRuns,
scriptRunOutLen,
&stylData,
&stylLen);
if (NS_SUCCEEDED(rv)) {
*outData = stylData;
*outDataSize = stylLen;
}
}
}
}
else
retVal = cantGetFlavorErr;
if (scriptCodeRuns)
nsMemory::Free(scriptCodeRuns);
}
}
PRInt32 pictSize = ::GetHandleSize((Handle)picture);
char* pictData = nsnull;
if (pictSize > 0)
pictData = (char*)nsMemory::Alloc(pictSize);
if (pictData) {
::BlockMoveData(*picture, pictData, pictSize); // doesn't move memory
*outData = (void*)pictData;
*outDataSize = pictSize;
retVal = noErr;
}
else
retVal = cantGetFlavorErr;
} // if valid item
::KillPicture(picture);
return retVal;
}
nsCOMPtr<nsISupports> data;
if (NS_SUCCEEDED(item->GetTransferData(actualFlavor, getter_AddRefs(data), outDataSize)))
{
nsPrimitiveHelpers::CreateDataFromPrimitive ( actualFlavor, data, outData, *outDataSize );
// Convert unix to mac linebreaks, since mac linebreaks are required for clipboard compatibility.
// I'm making the assumption here that the substitution will be entirely in-place, since both
// types of line breaks are 1-byte.
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, *outData);
nsLinebreakConverter::ConvertUnicharLineBreaksInSitu(&castedUnicode,
nsLinebreakConverter::eLinebreakUnix,
nsLinebreakConverter::eLinebreakMac,
*outDataSize / sizeof(PRUnichar), nsnull);
// if required, do the extra work to convert unicode to plain text and replace the output
// values with the plain text.
if ( needToDoConversionToPlainText ) {
char* plainTextData = nsnull;
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, *outData);
PRInt32 plainTextLen = 0;
nsresult rv =
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText ( castedUnicode, *outDataSize / 2, &plainTextData, &plainTextLen );
ScriptCodeRun *scriptCodeRuns = nsnull;
PRInt32 scriptRunOutLen;
// if characters are not mapped from Unicode then try native API to convert to
// available script
if (rv == NS_ERROR_UENC_NOMAPPING) {
if (plainTextData) {
nsMemory::Free(plainTextData);
plainTextData = nsnull;
}
rv = nsMacNativeUnicodeConverter::ConvertUnicodetoScript(castedUnicode,
*outDataSize / sizeof(PRUnichar),
&plainTextData,
&plainTextLen,
&scriptCodeRuns,
&scriptRunOutLen);
}
else if (NS_SUCCEEDED(rv)) {
// create a single run with the default system script
scriptCodeRuns = NS_REINTERPRET_CAST(ScriptCodeRun*,
nsMemory::Alloc(sizeof(ScriptCodeRun)));
if (scriptCodeRuns) {
scriptCodeRuns[0].offset = 0;
scriptCodeRuns[0].script = (ScriptCode) ::GetScriptManagerVariable(smSysScript);
scriptRunOutLen = 1;
}
}
if ( plainTextData && *outData ) {
nsMemory::Free(*outData);
*outData = nsnull;
*outDataSize = 0;
if (inFlavor != 'styl') {
*outData = plainTextData;
*outDataSize = plainTextLen;
}
else {
nsMemory::Free(plainTextData); // discard 'TEXT'
char *stylData;
PRInt32 stylLen;
// create 'styl' from the script runs
if (scriptCodeRuns) {
rv = CreateStylFromScriptRuns(scriptCodeRuns,
scriptRunOutLen,
&stylData,
&stylLen);
if (NS_SUCCEEDED(rv)) {
*outData = stylData;
*outDataSize = stylLen;
}
}
}
}
else
retVal = cantGetFlavorErr;
if (scriptCodeRuns)
nsMemory::Free(scriptCodeRuns);
}
}
return retVal;
@ -901,7 +1012,7 @@ nsDragService :: GetDataForFlavor ( nsISupportsArray* inDragItems, DragReference
// Caller is responsible for deleting the memory.
//
char*
nsDragService :: LookupMimeMappingsForItem ( DragReference inDragRef, ItemReference inItemRef )
nsDragService::LookupMimeMappingsForItem ( DragReference inDragRef, ItemReference inItemRef )
{
char* mapperData = nsnull;
PRInt32 mapperSize = 0;
@ -939,7 +1050,7 @@ nsDragService :: LookupMimeMappingsForItem ( DragReference inDragRef, ItemRefere
// the data for whatever reason.
//
nsresult
nsDragService :: ExtractDataFromOS ( DragReference inDragRef, ItemReference inItemRef, ResType inFlavor,
nsDragService::ExtractDataFromOS ( DragReference inDragRef, ItemReference inItemRef, ResType inFlavor,
void** outBuffer, PRInt32* outBuffSize )
{
if ( !outBuffer || !outBuffSize || !inFlavor )
@ -985,7 +1096,7 @@ nsDragService :: ExtractDataFromOS ( DragReference inDragRef, ItemReference inIt
//
nsresult
nsDragService :: StartDragSession ( )
nsDragService::StartDragSession ( )
{
nsWatchTask::GetTask().Suspend();
@ -993,7 +1104,7 @@ nsDragService :: StartDragSession ( )
}
nsresult
nsDragService :: EndDragSession ( )
nsDragService::EndDragSession ( )
{
nsWatchTask::GetTask().Resume();
@ -1008,7 +1119,7 @@ nsDragService :: EndDragSession ( )
// drag action changes based on modifier keys
//
NS_IMETHODIMP
nsDragService :: SetDragAction ( PRUint32 anAction )
nsDragService::SetDragAction ( PRUint32 anAction )
{
const PRInt32 kCopyCursorID = 144;
const PRInt32 kLinkCursorID = 145;
@ -1032,3 +1143,66 @@ nsDragService :: SetDragAction ( PRUint32 anAction )
return nsBaseDragService::SetDragAction(anAction);
}
#pragma mark -
// Utility routines for dragging files to the Finder
static OSErr GetDropDirectory(DragReference dragRef, FSSpecPtr fssOut)
{
OSErr err;
AEDesc dropLocAlias = { typeNull, nil };
err = ::GetDropLocation(dragRef, &dropLocAlias);
if (err != noErr) return err;
if (dropLocAlias.descriptorType != typeAlias)
return paramErr;
AEDesc dropLocFSS = { typeNull, nil };
if ((err = ::AECoerceDesc(&dropLocAlias, typeFSS, &dropLocFSS)) == noErr)
{
err = ::AEGetDescData(&dropLocFSS, fssOut, sizeof(FSSpec));
(void)::AEDisposeDesc(&dropLocFSS);
}
if (dropLocAlias.dataHandle)
(void)::AEDisposeDesc(&dropLocAlias);
return err;
}
OSErr nsDragService::GetHFSPromiseDropDirectory(DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, nsILocalFile** outDir)
{
// get the promise data
PromiseHFSFlavor promiseData;
Size dataSize = sizeof(promiseData);
OSErr err = ::GetFlavorData(inDragRef, inItemIndex, kDragFlavorTypePromiseHFS, &promiseData, &dataSize, 0);
if (err != noErr) return err;
FSSpec dropLocation;
err = GetDropDirectory(inDragRef, &dropLocation);
if (err != noErr) return err;
nsCOMPtr<nsILocalFileMac> dropFolderSpec;
nsresult rv = NS_NewLocalFileWithFSSpec(&dropLocation, PR_FALSE, getter_AddRefs(dropFolderSpec));
if (NS_FAILED(rv)) return fnfErr;
CallQueryInterface(dropFolderSpec, outDir);
return noErr;
}
OSErr
nsDragService::SetDropFileInDrag(DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, nsILocalFile* inFile)
{
nsCOMPtr<nsILocalFileMac> targetFileMac = do_QueryInterface(inFile);
if (!targetFileMac) return paramErr;
FSSpec targetFileSpec;
nsresult rv = targetFileMac->GetFSSpec(&targetFileSpec);
if (NS_FAILED(rv)) return paramErr;
return ::SetDragItemFlavorData(inDragRef, inItemIndex, inFlavor, &targetFileSpec, sizeof(FSSpec), 0);
}

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

@ -54,8 +54,7 @@
#include <Drag.h>
#include <MacWindows.h>
class nsNativeDragTarget;
class nsILocalFile;
class nsDragService : public nsBaseDragService, public nsIDragSessionMac
{
@ -85,7 +84,7 @@ private:
char* LookupMimeMappingsForItem ( DragReference inDragRef, ItemReference itemRef ) ;
void RegisterDragItemsAndFlavors ( nsISupportsArray * inArray ) ;
void RegisterDragItemsAndFlavors ( nsISupportsArray * inArray, RgnHandle inDragRgn ) ;
PRBool BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* inNode, RgnHandle ioDragRgn ) ;
OSErr GetDataForFlavor ( nsISupportsArray* inDragItems, DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, void** outData, unsigned int * outSize ) ;
@ -95,16 +94,22 @@ private:
// compute a screen rect from the frame associated with the given dom node
PRBool ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outScreenRect ) ;
OSErr GetHFSPromiseDropDirectory(DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, nsILocalFile** outDir);
OSErr SetDropFileInDrag(DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, nsILocalFile* inFile);
// callback for the MacOS DragManager when a drop site asks for data
static pascal OSErr DragSendDataProc ( FlavorType inFlavor, void* inRefCon,
ItemReference theItemRef, DragReference inDragRef ) ;
PRBool mImageDraggingSupported;
DragSendDataUPP mDragSendDataUPP;
DragReference mDragRef; // reference to _the_ drag. There can be only one.
nsISupportsArray* mDataItems; // cached here for when we start the drag so the
// DragSendDataProc has access to them.
// ONLY VALID DURING A DRAG STARTED WITHIN THIS APP.
PRBool mImageDraggingSupported;
}; // class nsDragService

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

@ -51,7 +51,13 @@
#include <Drag.h>
#include <Scrap.h>
nsMimeMapperMac :: nsMimeMapperMac ( const char* inMappings )
enum {
kScrapFlavorTypeURL = FOUR_CHAR_CODE('url '),
kScrapFlavorTypeURLDesc = FOUR_CHAR_CODE('urld')
};
nsMimeMapperMac::nsMimeMapperMac ( const char* inMappings )
: mCounter(0)
{
if (inMappings && strlen(inMappings) )
@ -59,7 +65,7 @@ nsMimeMapperMac :: nsMimeMapperMac ( const char* inMappings )
}
nsMimeMapperMac :: ~nsMimeMapperMac ( )
nsMimeMapperMac::~nsMimeMapperMac ( )
{
}
@ -76,7 +82,7 @@ nsMimeMapperMac :: ~nsMimeMapperMac ( )
// be exported along with the data.
//
ResType
nsMimeMapperMac :: MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIfNotPresent )
nsMimeMapperMac::MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIfNotPresent )
{
ResType format = 0;
@ -101,9 +107,15 @@ nsMimeMapperMac :: MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIf
else if ( PL_strcmp(aMimeStr, kTextMime) == 0 )
format = kScrapFlavorTypeText;
else if ( PL_strcmp(aMimeStr, kFileMime) == 0 )
format = flavorTypeHFS;
format = kDragFlavorTypeHFS;
else if ( PL_strcmp(aMimeStr, kFilePromiseMime) == 0 )
format = kDragFlavorTypePromiseHFS;
else if ( PL_strcmp(aMimeStr, kNativeImageMime) == 0 )
format = kScrapFlavorTypePicture;
else if ( PL_strcmp(aMimeStr, kURLDataMime) == 0 )
format = kScrapFlavorTypeURL;
else if ( PL_strcmp(aMimeStr, kURLDescriptionMime) == 0 )
format = kScrapFlavorTypeURLDesc;
#if NOT_YET
else if ( PL_strcmp(aMimeStr, kPNGImageMime) == 0 )
format = kScrapFlavorTypePicture;
@ -140,13 +152,17 @@ nsMimeMapperMac :: MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIf
// we probably won't get a match in that case.
//
void
nsMimeMapperMac :: MapMacOSTypeToMimeType ( ResType inMacType, nsCAutoString & outMimeStr )
nsMimeMapperMac::MapMacOSTypeToMimeType ( ResType inMacType, nsCAutoString & outMimeStr )
{
switch ( inMacType ) {
case kScrapFlavorTypeText: outMimeStr = kTextMime; break;
case kScrapFlavorTypeUnicode: outMimeStr = kUnicodeMime; break;
case flavorTypeHFS: outMimeStr = kFileMime; break;
case kScrapFlavorTypeText: outMimeStr = kTextMime; break;
case kScrapFlavorTypeUnicode: outMimeStr = kUnicodeMime; break;
case kDragFlavorTypeHFS: outMimeStr = kFileMime; break;
case kDragFlavorTypePromiseHFS: outMimeStr = kFilePromiseMime; break;
case kDragPromisedFlavor: outMimeStr = kFilePromiseMime; break;
case kScrapFlavorTypeURL: outMimeStr = kURLDataMime; break;
case kScrapFlavorTypeURLDesc: outMimeStr = kURLDescriptionMime; break;
// if someone gives us PICT (or we could have put it there), use
// the native image mime type.
@ -191,7 +207,7 @@ nsMimeMapperMac :: MapMacOSTypeToMimeType ( ResType inMacType, nsCAutoString & o
// NOTE: we make the assumption that the data is NULL terminated.
//
void
nsMimeMapperMac :: ParseMappings ( const char* inMappings )
nsMimeMapperMac::ParseMappings ( const char* inMappings )
{
if ( !inMappings )
return;
@ -222,7 +238,7 @@ nsMimeMapperMac :: ParseMappings ( const char* inMappings )
// the null at the end of the string.
//
char*
nsMimeMapperMac :: ExportMapping ( short * outLength ) const
nsMimeMapperMac::ExportMapping ( short * outLength ) const
{
NS_WARN_IF_FALSE ( outLength, "No out param provided" );
if ( outLength )

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

@ -50,13 +50,7 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
// nsIHTMLConverter
NS_IMETHOD GetInputDataFlavors(nsISupportsArray **_retval) ;
NS_IMETHOD GetOutputDataFlavors(nsISupportsArray **_retval) ;
NS_IMETHOD CanConvert(const char *aFromDataFlavor, const char *aToDataFlavor, PRBool *_retval) ;
NS_IMETHOD Convert(const char *aFromDataFlavor, nsISupports *aFromData, PRUint32 aDataLen,
const char *aToDataFlavor, nsISupports **aToData, PRUint32 *aDataToLen) ;
NS_DECL_NSIFORMATCONVERTER
protected:

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

@ -318,32 +318,23 @@ nsTransferable::~nsTransferable()
// account any converter that may be registered. This list consists of
// nsISupportsCString objects so that the flavor list can be accessed from JS.
//
NS_IMETHODIMP
nsTransferable :: GetTransferDataFlavors(nsISupportsArray ** aDataFlavorList)
nsresult
nsTransferable::GetTransferDataFlavors(nsISupportsArray ** aDataFlavorList)
{
if (!aDataFlavorList)
return NS_ERROR_INVALID_ARG;
nsresult rv = NS_NewISupportsArray ( aDataFlavorList );
if (NS_FAILED(rv)) return rv;
nsresult rv = NS_OK;
NS_NewISupportsArray ( aDataFlavorList );
if ( *aDataFlavorList ) {
for ( PRInt32 i=0; i<mDataArray->Count(); ++i ) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
nsCOMPtr<nsISupportsCString> flavorWrapper;
rv = nsComponentManager::CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, nsnull,
NS_GET_IID(nsISupportsCString), getter_AddRefs(flavorWrapper));
if ( flavorWrapper ) {
flavorWrapper->SetData ( data->GetFlavor() );
nsCOMPtr<nsISupports> genericWrapper ( do_QueryInterface(flavorWrapper) );
(*aDataFlavorList)->AppendElement( genericWrapper );
}
for ( PRInt32 i=0; i<mDataArray->Count(); ++i ) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
nsCOMPtr<nsISupportsCString> flavorWrapper = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
if ( flavorWrapper ) {
flavorWrapper->SetData ( data->GetFlavor() );
nsCOMPtr<nsISupports> genericWrapper ( do_QueryInterface(flavorWrapper) );
(*aDataFlavorList)->AppendElement( genericWrapper );
}
}
else
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
return NS_OK;
}
@ -355,27 +346,39 @@ nsTransferable :: GetTransferDataFlavors(nsISupportsArray ** aDataFlavorList)
// accessable from JS.
//
NS_IMETHODIMP
nsTransferable :: GetTransferData(const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
nsTransferable::GetTransferData(const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
{
if ( !aFlavor || !aData ||!aDataLen )
return NS_ERROR_INVALID_ARG;
NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen);
PRBool found = PR_FALSE;
nsresult rv = NS_OK;
// first look and see if the data is present in one of the intrinsic flavors
PRInt32 i;
for ( i=0; i<mDataArray->Count(); ++i ) {
for (i = 0; i < mDataArray->Count(); ++i ) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
if ( data->GetFlavor().Equals(aFlavor) ) {
data->GetData(aData, aDataLen);
if (*aDataLen == kFlavorHasDataProvider) {
// do we have a data provider?
nsCOMPtr<nsIFlavorDataProvider> dataProvider = do_QueryInterface(*aData);
if (dataProvider) {
rv = dataProvider->GetFlavorData(this, aFlavor, aData, aDataLen);
if (NS_FAILED(rv))
break; // the provider failed. fall into the conveter code below.
}
}
if (*aData && *aDataLen > 0)
return NS_OK;
break;
}
}
PRBool found = PR_FALSE;
// if not, try using a format converter to get the requested flavor
if ( !found && mFormatConv ) {
for (i=0;i<mDataArray->Count();i++) {
if ( mFormatConv ) {
for (i = 0; i < mDataArray->Count(); ++i) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
PRBool canConvert = PR_FALSE;
mFormatConv->CanConvert(data->GetFlavor().get(), aFlavor, &canConvert);
@ -383,8 +386,18 @@ nsTransferable :: GetTransferData(const char *aFlavor, nsISupports **aData, PRUi
nsCOMPtr<nsISupports> dataBytes;
PRUint32 len;
data->GetData(getter_AddRefs(dataBytes), &len);
if (len == kFlavorHasDataProvider) {
// do we have a data provider?
nsCOMPtr<nsIFlavorDataProvider> dataProvider = do_QueryInterface(dataBytes);
if (dataProvider) {
rv = dataProvider->GetFlavorData(this, aFlavor, getter_AddRefs(dataBytes), &len);
if (NS_FAILED(rv))
break; // give up
}
}
mFormatConv->Convert(data->GetFlavor().get(), dataBytes, len, aFlavor, aData, aDataLen);
found = PR_TRUE;
break;
}
}
}
@ -401,8 +414,7 @@ nsTransferable :: GetTransferData(const char *aFlavor, nsISupports **aData, PRUi
NS_IMETHODIMP
nsTransferable::GetAnyTransferData(char **aFlavor, nsISupports **aData, PRUint32 *aDataLen)
{
if ( !aFlavor || !aData || !aDataLen )
return NS_ERROR_FAILURE;
NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen);
for ( PRInt32 i=0; i < mDataArray->Count(); ++i ) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
@ -425,12 +437,11 @@ nsTransferable::GetAnyTransferData(char **aFlavor, nsISupports **aData, PRUint32
NS_IMETHODIMP
nsTransferable::SetTransferData(const char *aFlavor, nsISupports *aData, PRUint32 aDataLen)
{
if ( !aFlavor )
return NS_ERROR_FAILURE;
NS_ENSURE_ARG(aFlavor);
// first check our intrinsic flavors to see if one has been registered.
PRInt32 i = 0;
for ( i=0; i<mDataArray->Count(); ++i ) {
for (i = 0; i < mDataArray->Count(); ++i) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
if ( data->GetFlavor().Equals(aFlavor) ) {
data->SetData ( aData, aDataLen );
@ -440,7 +451,7 @@ nsTransferable::SetTransferData(const char *aFlavor, nsISupports *aData, PRUint3
// if not, try using a format converter to find a flavor to put the data in
if ( mFormatConv ) {
for ( i=0; i<mDataArray->Count(); ++i) {
for (i = 0; i < mDataArray->Count(); ++i) {
DataStruct * data = (DataStruct *)mDataArray->ElementAt(i);
PRBool canConvert = PR_FALSE;
mFormatConv->CanConvert(aFlavor, data->GetFlavor().get(), &canConvert);
@ -470,7 +481,7 @@ nsTransferable::SetTransferData(const char *aFlavor, nsISupports *aData, PRUint3
// Adds a data flavor to our list with no data. Error if it already exists.
//
NS_IMETHODIMP
nsTransferable :: AddDataFlavor(const char *aDataFlavor)
nsTransferable::AddDataFlavor(const char *aDataFlavor)
{
if (GetDataForFlavor (mDataArray, aDataFlavor))
return NS_ERROR_FAILURE;
@ -512,11 +523,8 @@ nsTransferable::RemoveDataFlavor(const char *aDataFlavor)
NS_IMETHODIMP
nsTransferable::IsLargeDataSet(PRBool *_retval)
{
if ( !_retval )
return NS_ERROR_FAILURE;
NS_ENSURE_ARG_POINTER(_retval);
*_retval = PR_FALSE;
return NS_OK;
}
@ -527,7 +535,7 @@ nsTransferable::IsLargeDataSet(PRBool *_retval)
*/
NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter)
{
mFormatConv = dont_QueryInterface(aConverter);
mFormatConv = aConverter;
return NS_OK;
}
@ -538,15 +546,9 @@ NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter)
*/
NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
{
if ( !aConverter )
return NS_ERROR_FAILURE;
if ( mFormatConv ) {
*aConverter = mFormatConv;
NS_ADDREF(*aConverter);
} else
*aConverter = nsnull;
NS_ENSURE_ARG_POINTER(aConverter);
*aConverter = mFormatConv;
NS_IF_ADDREF(*aConverter);
return NS_OK;
}
@ -558,10 +560,9 @@ NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
// intrinsic knowledge or input data converters.
//
NS_IMETHODIMP
nsTransferable :: FlavorsTransferableCanImport(nsISupportsArray **_retval)
nsTransferable::FlavorsTransferableCanImport(nsISupportsArray **_retval)
{
if ( !_retval )
return NS_ERROR_INVALID_ARG;
NS_ENSURE_ARG_POINTER(_retval);
// Get the flavor list, and on to the end of it, append the list of flavors we
// can also get to through a converter. This is so that we can just walk the list
@ -602,10 +603,9 @@ nsTransferable :: FlavorsTransferableCanImport(nsISupportsArray **_retval)
// intrinsic knowledge or output data converters.
//
NS_IMETHODIMP
nsTransferable :: FlavorsTransferableCanExport(nsISupportsArray **_retval)
nsTransferable::FlavorsTransferableCanExport(nsISupportsArray **_retval)
{
if ( !_retval )
return NS_ERROR_INVALID_ARG;
NS_ENSURE_ARG_POINTER(_retval);
// Get the flavor list, and on to the end of it, append the list of flavors we
// can also get to through a converter. This is so that we can just walk the list

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

@ -62,23 +62,12 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
// nsITransferable
NS_IMETHOD FlavorsTransferableCanExport(nsISupportsArray **_retval) ;
NS_IMETHOD GetTransferData(const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen);
NS_IMETHOD GetAnyTransferData(char **aFlavor, nsISupports **aData, PRUint32 *aDataLen);
NS_IMETHOD IsLargeDataSet(PRBool *_retval);
NS_IMETHOD FlavorsTransferableCanImport(nsISupportsArray **_retval) ;
NS_IMETHOD SetTransferData(const char *aFlavor, nsISupports *aData, PRUint32 aDataLen);
NS_IMETHOD AddDataFlavor(const char *aDataFlavor) ;
NS_IMETHOD RemoveDataFlavor(const char *aDataFlavor) ;
NS_IMETHOD GetConverter(nsIFormatConverter * *aConverter);
NS_IMETHOD SetConverter(nsIFormatConverter * aConverter);
NS_DECL_NSITRANSFERABLE
protected:
// get flavors w/out converter
NS_IMETHOD GetTransferDataFlavors(nsISupportsArray** aDataFlavorList);
nsresult GetTransferDataFlavors(nsISupportsArray** aDataFlavorList);
nsVoidArray * mDataArray;
nsCOMPtr<nsIFormatConverter> mFormatConv;