Dragging links to desktop creates internet shortcut files. bug#37410, r=pavlov

This commit is contained in:
pinkerton%netscape.com 2000-06-05 00:34:11 +00:00
Родитель 905f0087f8
Коммит 30b99ea6b0
4 изменённых файлов: 141 добавлений и 62 удалений

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

@ -407,7 +407,15 @@ nsDataObj :: GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG
if ( fileGroupDescHand ) {
LPFILEGROUPDESCRIPTOR fileGroupDesc = NS_REINTERPRET_CAST(LPFILEGROUPDESCRIPTOR, ::GlobalLock(fileGroupDescHand));
char* url = "http://www.dvdresource.com"; // TEMP!
#if 0
nsAutoString url;
if ( NS_FAILED(ExtractURL(url)) )
return E_OUTOFMEMORY;
char* urlStr = url.ToNewCString(); // XXX what about unicode urls?!?!
if ( !urlStr )
return E_OUTOFMEMORY;
#endif
char* urlStr = strdup("TEMP URL FILENAME");
// one file in the file descriptor block
fileGroupDesc->cItems = 1;
@ -416,12 +424,15 @@ nsDataObj :: GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG
// create the filename string -- |.URL| extensions imply an internet shortcut file. Make
// sure the filename isn't too long as to blow out the array, and still have enough room
// for the |.URL| suffix.
int urlLength = strlen(url) > MAX_PATH - 5 ? MAX_PATH - 5 : strlen(url);
url[urlLength] = nsnull;
sprintf(fileGroupDesc->fgd[0].cFileName, "%s.URL", url);
int urlLength = strlen(urlStr);
int trimmedLen = urlLength > MAX_PATH - 5 ? MAX_PATH - 5 : urlLength;
urlStr[trimmedLen] = nsnull;
sprintf(fileGroupDesc->fgd[0].cFileName, "%s.URL", urlStr);
nsMemory::Free(urlStr);
::GlobalUnlock ( fileGroupDescHand );
aSTG.hGlobal = fileGroupDescHand;
aSTG.tymed = TYMED_HGLOBAL;
}
else
result = E_OUTOFMEMORY;
@ -442,20 +453,27 @@ nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG )
{
HRESULT result = S_OK;
char* url = "foopy"; // TEMP!
nsAutoString url;
if ( NS_FAILED(ExtractURL(url)) )
return E_OUTOFMEMORY;
char* urlStr = url.ToNewCString(); // XXX what about unicode urls?!?!
if ( !urlStr )
return E_OUTOFMEMORY;
// setup format structure
FORMATETC fmetc = { 0, NULL, DVASPECT_CONTENT, 0, TYMED_HGLOBAL };
fmetc.cfFormat = RegisterClipboardFormat ( CFSTR_FILECONTENTS );
// create a global memory area and build up the file contents w/in it
static const char* shortcutPrefix = "[InternetShortcut]\nURL=";
HGLOBAL hGlobalMemory = ::GlobalAlloc(GMEM_SHARE, strlen(shortcutPrefix) + strlen(url) + 1);
static int prefixLen = strlen(shortcutPrefix);
HGLOBAL hGlobalMemory = ::GlobalAlloc(GMEM_SHARE, prefixLen + strlen(urlStr) + 1);
if ( hGlobalMemory ) {
char* contents = NS_REINTERPRET_CAST(char*, ::GlobalLock(hGlobalMemory));
sprintf( contents, "%s%s", shortcutPrefix, url );
sprintf( contents, "%s%s", shortcutPrefix, urlStr );
::GlobalUnlock(hGlobalMemory);
aSTG.hGlobal = hGlobalMemory;
aSTG.tymed = TYMED_HGLOBAL;
}
else
result = E_OUTOFMEMORY;
@ -663,3 +681,31 @@ void nsDataObj::SetTransferable(nsITransferable * aTransferable)
return;
}
//
// ExtractURL
//
// Roots around in the transferable for the appropriate flavor that indicates
// a url and pulls it out. Used mostly for creating internet shortcuts on the desktop.
//
nsresult
nsDataObj :: ExtractURL ( nsString & outURL )
{
NS_ASSERTION ( mTransferable, "We'd don't have a good transferable" );
nsresult rv = NS_ERROR_FAILURE;
PRUint32 len = 0;
nsCOMPtr<nsISupports> genericURL;
if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
nsCOMPtr<nsISupportsWString> urlObject ( do_QueryInterface(genericURL) );
if ( urlObject ) {
nsXPIDLString url;
urlObject->GetData ( getter_Copies(url) );
outURL = url;
rv = NS_OK;
}
} // if found flavor
return rv;
} // ExtractURL

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

@ -138,6 +138,8 @@ class nsDataObj : public IDataObject
virtual HRESULT GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) ;
virtual HRESULT GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) ;
nsresult ExtractURL ( nsString & outURL ) ;
nsString mStringData;
BOOL FormatsMatch(const FORMATETC& source, const FORMATETC& target) const;

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

@ -65,33 +65,47 @@ nsDragService::~nsDragService()
NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType)
{
nsresult rv;
PRUint32 cnt;
rv = anArrayTransferables->Count(&cnt);
if (NS_FAILED(rv)) return rv;
if (cnt == 0) {
PRUint32 numItemsToDrag = 0;
rv = anArrayTransferables->Count(&numItemsToDrag);
if ( !numItemsToDrag )
return NS_ERROR_FAILURE;
}
// The clipboard class contains some static utility methods
// that we can use to create an IDataObject from the transferable
nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
IDataObject * dataObj = nsnull;
PRUint32 i;
for (i=0;i<cnt;i++) {
// if we're dragging more than one item, we need to create a "collection" object to fake out
// the OS. This collection contains one |IDataObject| for each transerable. If there is just
// the one (most cases), only pass around the native |IDataObject|.
IDataObject* itemToDrag = nsnull;
if ( numItemsToDrag > 1 ) {
nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
IDataObject* dataObj = nsnull;
for ( PRUint32 i=0; i<numItemsToDrag; ++i ) {
nsCOMPtr<nsISupports> supports;
anArrayTransferables->GetElementAt(i, getter_AddRefs(supports));
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
if ( trans ) {
if ( NS_SUCCEEDED(nsClipboard::CreateNativeDataObject(trans, &dataObj)) ) {
dataObjCollection->AddDataObject(dataObj);
NS_IF_RELEASE(dataObj);
}
else
return NS_ERROR_FAILURE;
}
}
itemToDrag = NS_STATIC_CAST ( IDataObject*, dataObjCollection );
} // if dragging multiple items
else {
nsCOMPtr<nsISupports> supports;
anArrayTransferables->GetElementAt(i, getter_AddRefs(supports));
anArrayTransferables->GetElementAt(0, getter_AddRefs(supports));
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
if ( trans ) {
nsClipboard::CreateNativeDataObject(trans, &dataObj);
dataObjCollection->AddDataObject(dataObj);
NS_IF_RELEASE(dataObj);
if ( NS_FAILED(nsClipboard::CreateNativeDataObject(trans, &itemToDrag)) )
return NS_ERROR_FAILURE;
}
}
StartInvokingDragSession((IDataObject *)dataObjCollection, aActionType);
return NS_OK;
} // else dragging a single object
return StartInvokingDragSession ( itemToDrag, aActionType );
}
//-------------------------------------------------------------------------
@ -101,9 +115,10 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
// implements the IDataObject interface (for OLE)
NS_IF_RELEASE(mNativeDragSrc);
mNativeDragSrc = (IDropSource *)new nsNativeDragSource();
if (nsnull != mNativeDragSrc) {
mNativeDragSrc->AddRef();
}
if ( !mNativeDragSrc )
return NS_ERROR_OUT_OF_MEMORY;
mNativeDragSrc->AddRef();
// Now figure out what the native drag effect should be
DWORD dropRes;
@ -118,7 +133,7 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
effects |= DROPEFFECT_LINK;
}
mDragAction = aActionType;
mDragAction = aActionType; //XXX not sure why we bother to cache this, it can change during the drag
mDoingDrag = PR_TRUE;
// Call the native D&D method
@ -132,12 +147,7 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
{
// First check to see if the mDataObject is is Collection of IDataObjects
UINT format = nsClipboard::GetFormat(MULTI_MIME);
FORMATETC fe;
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
if ( mDataObject->QueryGetData(&fe) == S_OK ) {
// If it is the get the number of items in the collection
if ( IsCollectionObject(mDataObject) ) {
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
if ( dataObjCol )
*aNumItems = dataObjCol->GetNumDataObjects();
@ -170,34 +180,25 @@ NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32
// This typcially happens on a drop, the target would be asking
// for it's transferable to be filled in
// Use a static clipboard utility method for this
if ( nsnull == mDataObject ) {
if ( !mDataObject )
return NS_ERROR_FAILURE;
}
// First check to see if the mDataObject is is Collection of IDataObjects
UINT format = nsClipboard::GetFormat(MULTI_MIME);
FORMATETC fe;
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
// if it is a single object then get the data for it
if (S_OK != mDataObject->QueryGetData(&fe)) {
// Since there is only one object, they better be asking for item "0"
if (anItem == 0) {
return nsClipboard::GetDataFromDataObject(mDataObject, anItem, nsnull, aTransferable);
} else {
return NS_ERROR_FAILURE;
}
}
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
if ( dataObjCol ) {
if ( IsCollectionObject(mDataObject) ) {
// multiple items, use |anItem| as an index into our collection
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
PRUint32 cnt = dataObjCol->GetNumDataObjects();
if (anItem >= 0 && anItem < cnt) {
IDataObject * dataObj = dataObjCol->GetDataObjectAt(anItem);
return nsClipboard::GetDataFromDataObject(dataObj, 0, nsnull, aTransferable);
}
}
else {
// Since there is only one object, they better be asking for item "0"
if (anItem == 0)
return nsClipboard::GetDataFromDataObject(mDataObject, anItem, nsnull, aTransferable);
else
return NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
}
@ -226,13 +227,10 @@ NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBo
*_retval = PR_FALSE;
// Check to see if the mDataObject is a collection of IDataObjects or just a
// single (which would be the case if something came from an external app).
FORMATETC fe;
UINT format = nsClipboard::GetFormat(MULTI_MIME);
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
if ( mDataObject->QueryGetData(&fe) == S_OK ) {
UINT format = 0;
if ( IsCollectionObject(mDataObject) ) {
// We know we have one of our special collection objects.
format = nsClipboard::GetFormat(aDataFlavor);
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL | TYMED_FILE | TYMED_GDI);
@ -278,3 +276,32 @@ NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession ** aSession)
NS_ADDREF(*aSession);
return NS_OK;
}
//
// IsCollectionObject
//
// Determine if this is a single |IDataObject| or one of our private collection
// objects. We know the difference because our collection object will respond to supporting
// the private |MULTI_MIME| format.
//
PRBool
nsDragService :: IsCollectionObject ( IDataObject* inDataObj )
{
PRBool isCollection = PR_FALSE;
// setup the format object to ask for the MULTI_MIME format. We only need to do this once
static UINT sFormat = 0;
static FORMATETC sFE;
if ( !sFormat ) {
sFormat = nsClipboard::GetFormat(MULTI_MIME);
SET_FORMATETC(sFE, sFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
}
// ask the object if it supports it. If yes, we have a collection object
if ( inDataObj->QueryGetData(&sFE) == S_OK )
isCollection = PR_TRUE;
return isCollection;
} // IsCollectionObject

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

@ -54,6 +54,10 @@ public:
NS_IMETHOD StartInvokingDragSession(IDataObject * aDataObj, PRUint32 aActionType);
protected:
// determine if we have a single data object or one of our private collections
PRBool IsCollectionObject ( IDataObject* inDataObj ) ;
IDropSource * mNativeDragSrc;
nsNativeDragTarget * mNativeDragTarget;
IDataObject * mDataObject;