2001-09-28 20:14:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
1999-03-23 15:37:34 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/NPL/
|
1999-03-23 15:37:34 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
1999-03-23 15:37:34 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2000-02-04 00:39:15 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2000-08-03 22:05:09 +00:00
|
|
|
* Sean Echevarria <sean@beatnik.com>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
#include "nsClipboard.h"
|
|
|
|
#include <OLE2.h>
|
1999-05-07 19:55:45 +00:00
|
|
|
#include <SHLOBJ.H>
|
2000-08-03 22:05:09 +00:00
|
|
|
#include <INTSHCUT.H>
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-04-17 13:49:39 +00:00
|
|
|
#include "nsCOMPtr.h"
|
1999-03-23 15:37:34 +00:00
|
|
|
#include "nsDataObj.h"
|
|
|
|
#include "nsIClipboardOwner.h"
|
1999-05-13 21:53:57 +00:00
|
|
|
#include "nsString.h"
|
1999-04-01 14:40:52 +00:00
|
|
|
#include "nsIFormatConverter.h"
|
1999-04-17 13:49:39 +00:00
|
|
|
#include "nsITransferable.h"
|
1999-08-25 08:35:06 +00:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsISupportsPrimitives.h"
|
1999-09-04 20:04:26 +00:00
|
|
|
#include "nsXPIDLString.h"
|
2001-09-29 08:28:41 +00:00
|
|
|
#include "nsReadableUtils.h"
|
1999-09-22 00:40:14 +00:00
|
|
|
#include "nsPrimitiveHelpers.h"
|
2001-01-23 01:09:58 +00:00
|
|
|
#include "nsImageClipboard.h"
|
1999-03-23 21:26:41 +00:00
|
|
|
#include "nsIWidget.h"
|
|
|
|
#include "nsIComponentManager.h"
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
|
1999-05-07 19:55:45 +00:00
|
|
|
#include "nsVoidArray.h"
|
2002-01-08 01:31:25 +00:00
|
|
|
#include "nsNetUtil.h"
|
1999-05-07 19:55:45 +00:00
|
|
|
|
1999-07-09 19:39:22 +00:00
|
|
|
#include "nsIImage.h"
|
|
|
|
|
2000-08-03 00:47:36 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// nsClipboard constructor
|
|
|
|
//
|
|
|
|
//-------------------------------------------------------------------------
|
1999-03-26 15:43:48 +00:00
|
|
|
nsClipboard::nsClipboard() : nsBaseClipboard()
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
1999-03-26 15:43:48 +00:00
|
|
|
//NS_INIT_REFCNT();
|
1999-03-23 21:26:41 +00:00
|
|
|
mIgnoreEmptyNotification = PR_FALSE;
|
1999-03-26 15:43:48 +00:00
|
|
|
mWindow = nsnull;
|
1999-03-23 21:26:41 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// nsClipboard destructor
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
nsClipboard::~nsClipboard()
|
|
|
|
{
|
1999-03-23 21:26:41 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-09-04 20:04:26 +00:00
|
|
|
UINT nsClipboard::GetFormat(const char* aMimeStr)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
1999-09-04 20:04:26 +00:00
|
|
|
nsCAutoString mimeStr ( CBufDescriptor(NS_CONST_CAST(char*,aMimeStr), PR_TRUE, PL_strlen(aMimeStr)+1) );
|
1999-03-26 15:43:48 +00:00
|
|
|
UINT format = 0;
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2000-05-02 22:39:08 +00:00
|
|
|
if (mimeStr.Equals(kTextMime))
|
1999-03-26 15:43:48 +00:00
|
|
|
format = CF_TEXT;
|
2000-05-02 22:39:08 +00:00
|
|
|
else if (mimeStr.Equals(kUnicodeMime))
|
1999-03-26 15:43:48 +00:00
|
|
|
format = CF_UNICODETEXT;
|
2000-05-02 22:39:08 +00:00
|
|
|
else if (mimeStr.Equals(kJPEGImageMime))
|
1999-05-04 23:14:57 +00:00
|
|
|
format = CF_DIB;
|
2000-05-02 22:39:08 +00:00
|
|
|
else if (mimeStr.Equals(kFileMime))
|
1999-05-04 23:14:57 +00:00
|
|
|
format = CF_HDROP;
|
2000-05-02 22:39:08 +00:00
|
|
|
else if (mimeStr.Equals(kURLMime))
|
|
|
|
format = CF_UNICODETEXT;
|
|
|
|
else
|
1999-09-04 20:04:26 +00:00
|
|
|
format = ::RegisterClipboardFormat(aMimeStr);
|
2000-05-02 22:39:08 +00:00
|
|
|
|
1999-03-26 15:43:48 +00:00
|
|
|
return format;
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-04-17 13:49:39 +00:00
|
|
|
nsresult nsClipboard::CreateNativeDataObject(nsITransferable * aTransferable, IDataObject ** aDataObj)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
1999-04-06 20:25:09 +00:00
|
|
|
if (nsnull == aTransferable) {
|
1999-03-23 15:37:34 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-05-04 23:14:57 +00:00
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
// Create our native DataObject that implements
|
|
|
|
// the OLE IDataObject interface
|
1999-04-06 20:25:09 +00:00
|
|
|
nsDataObj * dataObj;
|
|
|
|
dataObj = new nsDataObj();
|
1999-05-04 23:14:57 +00:00
|
|
|
dataObj->AddRef();
|
|
|
|
|
|
|
|
// No set it up with all the right data flavors & enums
|
|
|
|
nsresult res = SetupNativeDataObject(aTransferable, dataObj);
|
|
|
|
if (NS_OK == res) {
|
|
|
|
*aDataObj = dataObj;
|
|
|
|
} else {
|
|
|
|
delete dataObj;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDataObject * aDataObj)
|
|
|
|
{
|
|
|
|
if (nsnull == aTransferable || nsnull == aDataObj) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDataObj * dObj = NS_STATIC_CAST(nsDataObj *, aDataObj);
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
// Now give the Transferable to the DataObject
|
|
|
|
// for getting the data out of it
|
1999-05-04 23:14:57 +00:00
|
|
|
dObj->SetTransferable(aTransferable);
|
1999-04-06 20:25:09 +00:00
|
|
|
|
|
|
|
// Get the transferable list of data flavors
|
1999-08-25 08:35:06 +00:00
|
|
|
nsCOMPtr<nsISupportsArray> dfList;
|
|
|
|
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(dfList));
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-04-01 14:40:52 +00:00
|
|
|
// Walk through flavors that contain data and register them
|
|
|
|
// into the DataObj as supported flavors
|
1999-03-23 15:37:34 +00:00
|
|
|
PRUint32 i;
|
1999-08-25 08:35:06 +00:00
|
|
|
PRUint32 cnt;
|
|
|
|
dfList->Count(&cnt);
|
1999-05-13 04:56:04 +00:00
|
|
|
for (i=0;i<cnt;i++) {
|
1999-08-25 08:35:06 +00:00
|
|
|
nsCOMPtr<nsISupports> genericFlavor;
|
|
|
|
dfList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
|
|
|
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
|
|
|
if ( currentFlavor ) {
|
1999-09-04 20:04:26 +00:00
|
|
|
nsXPIDLCString flavorStr;
|
|
|
|
currentFlavor->ToString(getter_Copies(flavorStr));
|
1999-08-25 08:35:06 +00:00
|
|
|
UINT format = GetFormat(flavorStr);
|
1999-03-26 15:43:48 +00:00
|
|
|
|
2001-01-23 01:09:58 +00:00
|
|
|
// Now tell the native IDataObject about both our mime type and
|
|
|
|
// the native data format
|
1999-03-23 15:37:34 +00:00
|
|
|
FORMATETC fe;
|
1999-04-17 13:49:39 +00:00
|
|
|
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
1999-08-25 08:35:06 +00:00
|
|
|
dObj->AddDataFlavor(flavorStr, &fe);
|
2000-01-29 20:24:50 +00:00
|
|
|
|
2000-05-02 22:39:08 +00:00
|
|
|
// Do various things internal to the implementation, like map one
|
|
|
|
// flavor to another or add additional flavors based on what's required
|
|
|
|
// for the win32 impl.
|
2000-02-22 22:40:38 +00:00
|
|
|
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
|
2000-05-02 22:39:08 +00:00
|
|
|
// if we find text/unicode, also advertise text/plain (which we will convert
|
|
|
|
// on our own in nsDataObj::GetText().
|
2001-01-23 01:09:58 +00:00
|
|
|
FORMATETC textFE;
|
|
|
|
SET_FORMATETC(textFE, CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
|
|
|
dObj->AddDataFlavor(kTextMime, &textFE);
|
2000-05-02 22:39:08 +00:00
|
|
|
}
|
2001-02-20 23:27:57 +00:00
|
|
|
else if ( strcmp(flavorStr, kHTMLMime) == 0 ) {
|
|
|
|
// if we find text/html, also advertise win32's html flavor (which we will convert
|
|
|
|
// on our own in nsDataObj::GetText().
|
|
|
|
FORMATETC htmlFE;
|
|
|
|
SET_FORMATETC(htmlFE, ::RegisterClipboardFormat("HTML Format"), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
|
|
|
dObj->AddDataFlavor(kHTMLMime, &htmlFE);
|
|
|
|
}
|
2001-01-23 01:09:58 +00:00
|
|
|
else if ( strcmp(flavorStr, kURLMime) == 0 ) {
|
2000-05-02 22:39:08 +00:00
|
|
|
// if we're a url, in addition to also being text, we need to register
|
|
|
|
// the "file" flavors so that the win32 shell knows to create an internet
|
|
|
|
// shortcut when it sees one of these beasts.
|
2001-01-23 01:09:58 +00:00
|
|
|
FORMATETC shortcutFE;
|
|
|
|
SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
|
|
|
|
dObj->AddDataFlavor(kURLMime, &shortcutFE);
|
|
|
|
SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
|
|
|
|
dObj->AddDataFlavor(kURLMime, &shortcutFE);
|
2000-05-03 09:16:39 +00:00
|
|
|
#ifdef CFSTR_SHELLURL
|
2001-01-23 01:09:58 +00:00
|
|
|
SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_SHELLURL), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
|
|
|
|
dObj->AddDataFlavor(kURLMime, &shortcutFE);
|
2000-05-03 09:16:39 +00:00
|
|
|
#endif
|
2000-01-29 20:24:50 +00:00
|
|
|
}
|
2001-01-23 01:09:58 +00:00
|
|
|
else if ( strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 ||
|
|
|
|
strcmp(flavorStr, kGIFImageMime) == 0 ) {
|
|
|
|
// if we're an image, register the native bitmap flavor
|
|
|
|
FORMATETC imageFE;
|
|
|
|
SET_FORMATETC(imageFE, CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
|
|
|
|
dObj->AddDataFlavor(flavorStr, &imageFE);
|
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
}
|
1999-04-01 14:40:52 +00:00
|
|
|
|
1999-04-06 20:25:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
2000-04-14 02:52:58 +00:00
|
|
|
NS_IMETHODIMP nsClipboard::SetNativeClipboardData ( PRInt32 aWhichClipboard )
|
1999-04-06 20:25:09 +00:00
|
|
|
{
|
2000-04-14 02:52:58 +00:00
|
|
|
if ( aWhichClipboard != kGlobalClipboard )
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
1999-04-06 20:25:09 +00:00
|
|
|
mIgnoreEmptyNotification = PR_TRUE;
|
|
|
|
|
|
|
|
// make sure we have a good transferable
|
|
|
|
if (nsnull == mTransferable) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the native clipboard
|
2000-01-08 00:28:32 +00:00
|
|
|
::OleSetClipboard(NULL);
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-04-06 20:25:09 +00:00
|
|
|
IDataObject * dataObj;
|
2000-08-19 19:30:52 +00:00
|
|
|
if ( NS_SUCCEEDED(CreateNativeDataObject(mTransferable, &dataObj)) ) { // this add refs
|
|
|
|
::OleSetClipboard(dataObj);
|
|
|
|
dataObj->Release();
|
1999-04-06 20:25:09 +00:00
|
|
|
}
|
1999-03-23 15:37:34 +00:00
|
|
|
|
1999-03-23 21:26:41 +00:00
|
|
|
mIgnoreEmptyNotification = PR_FALSE;
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-04-06 20:25:09 +00:00
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-04-17 13:49:39 +00:00
|
|
|
nsresult nsClipboard::GetGlobalData(HGLOBAL aHGBL, void ** aData, PRUint32 * aLen)
|
1999-04-06 20:25:09 +00:00
|
|
|
{
|
1999-12-07 22:45:01 +00:00
|
|
|
// Allocate a new memory buffer and copy the data from global memory.
|
|
|
|
// Recall that win98 allocates to nearest DWORD boundary.
|
1999-04-06 20:25:09 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
if (aHGBL != NULL) {
|
1999-12-07 22:45:01 +00:00
|
|
|
LPSTR lpStr = (LPSTR)::GlobalLock(aHGBL);
|
|
|
|
DWORD allocSize = ::GlobalSize(aHGBL);
|
2000-06-03 09:46:12 +00:00
|
|
|
char* data = NS_STATIC_CAST(char*, nsMemory::Alloc(allocSize));
|
1999-12-07 22:45:01 +00:00
|
|
|
if ( data ) {
|
|
|
|
nsCRT::memcpy ( data, lpStr, allocSize );
|
|
|
|
|
|
|
|
::GlobalUnlock(aHGBL);
|
|
|
|
*aData = data;
|
|
|
|
*aLen = allocSize;
|
|
|
|
result = NS_OK;
|
1999-04-06 20:25:09 +00:00
|
|
|
}
|
1999-12-07 22:45:01 +00:00
|
|
|
}
|
|
|
|
else {
|
1999-04-23 14:38:27 +00:00
|
|
|
// We really shouldn't ever get here
|
|
|
|
// but just in case
|
1999-04-06 20:25:09 +00:00
|
|
|
*aData = nsnull;
|
|
|
|
*aLen = 0;
|
|
|
|
LPVOID lpMsgBuf;
|
|
|
|
|
|
|
|
FormatMessage(
|
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL,
|
|
|
|
GetLastError(),
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
|
|
(LPTSTR) &lpMsgBuf,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
// Display the string.
|
|
|
|
MessageBox( NULL, (const char *)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
|
|
|
|
|
|
|
|
// Free the buffer.
|
|
|
|
LocalFree( lpMsgBuf );
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
1999-04-23 14:38:27 +00:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
2000-04-26 01:04:13 +00:00
|
|
|
nsresult nsClipboard::GetNativeDataOffClipboard(nsIWidget * aWindow, UINT /*aIndex*/, UINT aFormat, void ** aData, PRUint32 * aLen)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
|
|
|
HGLOBAL hglb;
|
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
|
1999-03-23 21:26:41 +00:00
|
|
|
HWND nativeWin = nsnull;//(HWND)aWindow->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
if (::OpenClipboard(nativeWin)) {
|
1999-03-23 15:37:34 +00:00
|
|
|
hglb = ::GetClipboardData(aFormat);
|
1999-04-06 20:25:09 +00:00
|
|
|
result = GetGlobalData(hglb, aData, aLen);
|
1999-03-23 15:37:34 +00:00
|
|
|
::CloseClipboard();
|
|
|
|
}
|
1999-04-06 20:25:09 +00:00
|
|
|
return result;
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-07-09 19:39:22 +00:00
|
|
|
static void DisplayErrCode(HRESULT hres)
|
|
|
|
{
|
2001-03-08 05:12:30 +00:00
|
|
|
#if defined(DEBUG_rods) || defined(DEBUG_pinkerton)
|
1999-07-09 19:39:22 +00:00
|
|
|
if (hres == E_INVALIDARG) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("E_INVALIDARG\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == E_UNEXPECTED) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("E_UNEXPECTED\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == E_OUTOFMEMORY) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("E_OUTOFMEMORY\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == DV_E_LINDEX ) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("DV_E_LINDEX\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == DV_E_FORMATETC) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("DV_E_FORMATETC\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == DV_E_TYMED) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("DV_E_TYMED\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == DV_E_DVASPECT) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("DV_E_DVASPECT\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == OLE_E_NOTRUNNING) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("OLE_E_NOTRUNNING\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == STG_E_MEDIUMFULL) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("STG_E_MEDIUMFULL\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == DV_E_CLIPFORMAT) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("DV_E_CLIPFORMAT\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else
|
|
|
|
if (hres == S_OK) {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("S_OK\n");
|
1999-07-09 19:39:22 +00:00
|
|
|
} else {
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("****** DisplayErrCode 0x%X\n", hres);
|
1999-07-09 19:39:22 +00:00
|
|
|
}
|
|
|
|
#endif
|
2001-03-08 05:12:30 +00:00
|
|
|
}
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-05-04 23:14:57 +00:00
|
|
|
static HRESULT FillSTGMedium(IDataObject * aDataObject, UINT aFormat, LPFORMATETC pFE, LPSTGMEDIUM pSTM, DWORD aTymed)
|
1999-04-06 20:25:09 +00:00
|
|
|
{
|
1999-05-04 23:14:57 +00:00
|
|
|
SET_FORMATETC(*pFE, aFormat, 0, DVASPECT_CONTENT, -1, aTymed);
|
1999-04-06 20:25:09 +00:00
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
// Starting by querying for the data to see if we can get it as from global memory
|
1999-05-04 23:14:57 +00:00
|
|
|
HRESULT hres = S_FALSE;
|
1999-07-09 19:39:22 +00:00
|
|
|
hres = aDataObject->QueryGetData(pFE);
|
|
|
|
DisplayErrCode(hres);
|
|
|
|
if (S_OK == hres) {
|
1999-05-04 23:14:57 +00:00
|
|
|
hres = aDataObject->GetData(pFE, pSTM);
|
1999-07-09 19:39:22 +00:00
|
|
|
DisplayErrCode(hres);
|
|
|
|
}
|
|
|
|
return hres;
|
|
|
|
}
|
1999-04-06 20:25:09 +00:00
|
|
|
|
1999-05-04 23:14:57 +00:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
2000-04-26 01:04:13 +00:00
|
|
|
nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT aIndex, UINT aFormat, void ** aData, PRUint32 * aLen)
|
1999-05-04 23:14:57 +00:00
|
|
|
{
|
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
2000-04-26 01:04:13 +00:00
|
|
|
*aData = nsnull;
|
|
|
|
*aLen = 0;
|
1999-05-04 23:14:57 +00:00
|
|
|
|
2000-04-26 01:04:13 +00:00
|
|
|
if ( !aDataObject )
|
1999-05-04 23:14:57 +00:00
|
|
|
return result;
|
|
|
|
|
|
|
|
UINT format = aFormat;
|
|
|
|
HRESULT hres = S_FALSE;
|
|
|
|
|
|
|
|
// XXX at the moment we only support global memory transfers
|
|
|
|
// It is here where we will add support for native images
|
|
|
|
// and IStream
|
|
|
|
FORMATETC fe;
|
|
|
|
STGMEDIUM stm;
|
|
|
|
hres = FillSTGMedium(aDataObject, format, &fe, &stm, TYMED_HGLOBAL);
|
|
|
|
|
1999-07-09 19:39:22 +00:00
|
|
|
// Currently this is only handling TYMED_HGLOBAL data
|
|
|
|
// For Text, Dibs, Files, and generic data (like HTML)
|
1999-05-04 23:14:57 +00:00
|
|
|
if (S_OK == hres) {
|
2001-12-17 22:51:39 +00:00
|
|
|
static CLIPFORMAT fileDescriptorFlavor = ::RegisterClipboardFormat( CFSTR_FILEDESCRIPTOR );
|
|
|
|
static CLIPFORMAT fileFlavor = ::RegisterClipboardFormat( CFSTR_FILECONTENTS );
|
1999-05-04 23:14:57 +00:00
|
|
|
switch (stm.tymed) {
|
2000-05-02 22:39:08 +00:00
|
|
|
case TYMED_HGLOBAL:
|
1999-05-04 23:14:57 +00:00
|
|
|
{
|
|
|
|
switch (fe.cfFormat) {
|
1999-11-18 02:40:49 +00:00
|
|
|
case CF_TEXT:
|
1999-05-04 23:14:57 +00:00
|
|
|
{
|
1999-12-07 22:45:01 +00:00
|
|
|
// Get the data out of the global data handle. The size we return
|
|
|
|
// should not include the null because the other platforms don't
|
|
|
|
// use nulls, so just return the length we get back from strlen(),
|
|
|
|
// since we know CF_TEXT is null terminated. Recall that GetGlobalData()
|
|
|
|
// returns the size of the allocated buffer, not the size of the data
|
|
|
|
// (on 98, these are not the same) so we can't use that.
|
|
|
|
PRUint32 allocLen = 0;
|
|
|
|
if ( NS_SUCCEEDED(GetGlobalData(stm.hGlobal, aData, &allocLen)) ) {
|
|
|
|
*aLen = nsCRT::strlen ( NS_REINTERPRET_CAST(char*, *aData) );
|
|
|
|
result = NS_OK;
|
1999-05-04 23:14:57 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2000-05-02 22:39:08 +00:00
|
|
|
case CF_UNICODETEXT:
|
1999-11-18 02:40:49 +00:00
|
|
|
{
|
1999-12-07 22:45:01 +00:00
|
|
|
// Get the data out of the global data handle. The size we return
|
|
|
|
// should not include the null because the other platforms don't
|
|
|
|
// use nulls, so just return the length we get back from strlen(),
|
|
|
|
// since we know CF_UNICODETEXT is null terminated. Recall that GetGlobalData()
|
|
|
|
// returns the size of the allocated buffer, not the size of the data
|
|
|
|
// (on 98, these are not the same) so we can't use that.
|
|
|
|
PRUint32 allocLen = 0;
|
|
|
|
if ( NS_SUCCEEDED(GetGlobalData(stm.hGlobal, aData, &allocLen)) ) {
|
|
|
|
*aLen = nsCRT::strlen(NS_REINTERPRET_CAST(PRUnichar*, *aData)) * 2;
|
|
|
|
result = NS_OK;
|
1999-11-18 02:40:49 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
1999-05-04 23:14:57 +00:00
|
|
|
case CF_DIB :
|
|
|
|
{
|
1999-07-09 19:39:22 +00:00
|
|
|
HGLOBAL hGlobal = stm.hGlobal;
|
|
|
|
BYTE * pGlobal = (BYTE *)::GlobalLock (hGlobal) ;
|
|
|
|
BITMAPV4HEADER * header = (BITMAPV4HEADER *)pGlobal;
|
|
|
|
|
2001-01-23 01:09:58 +00:00
|
|
|
nsImageFromClipboard converter ( header );
|
|
|
|
nsIImage* image;
|
|
|
|
converter.GetImage ( &image ); // addrefs for us, don't release
|
|
|
|
if ( image ) {
|
|
|
|
*aData = image;
|
|
|
|
*aLen = sizeof(nsIImage*);
|
|
|
|
result = NS_OK;
|
1999-07-09 19:39:22 +00:00
|
|
|
}
|
2001-01-23 01:09:58 +00:00
|
|
|
|
|
|
|
::GlobalUnlock (hGlobal) ;
|
1999-05-04 23:14:57 +00:00
|
|
|
} break;
|
|
|
|
|
1999-05-07 19:55:45 +00:00
|
|
|
case CF_HDROP :
|
|
|
|
{
|
2000-04-26 01:04:13 +00:00
|
|
|
// in the case of a file drop, multiple files are stashed within a
|
|
|
|
// single data object. In order to match mozilla's D&D apis, we
|
|
|
|
// just pull out the file at the requested index, pretending as
|
|
|
|
// if there really are multiple drag items.
|
|
|
|
HDROP dropFiles = (HDROP) ::GlobalLock(stm.hGlobal);
|
|
|
|
|
|
|
|
UINT numFiles = ::DragQueryFile(dropFiles, 0xFFFFFFFF, NULL, 0);
|
|
|
|
NS_ASSERTION ( numFiles > 0, "File drop flavor, but no files...hmmmm" );
|
|
|
|
NS_ASSERTION ( aIndex < numFiles, "Asked for a file index out of range of list" );
|
1999-05-07 19:55:45 +00:00
|
|
|
if (numFiles > 0) {
|
2000-04-26 01:04:13 +00:00
|
|
|
UINT fileNameLen = ::DragQueryFile(dropFiles, aIndex, nsnull, 0);
|
2000-06-03 09:46:12 +00:00
|
|
|
char* buffer = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(fileNameLen + 1));
|
2000-04-26 01:04:13 +00:00
|
|
|
if ( buffer ) {
|
|
|
|
::DragQueryFile(dropFiles, aIndex, buffer, fileNameLen + 1);
|
|
|
|
*aData = buffer;
|
|
|
|
*aLen = fileNameLen;
|
|
|
|
result = NS_OK;
|
1999-05-07 19:55:45 +00:00
|
|
|
}
|
2000-04-26 01:04:13 +00:00
|
|
|
else
|
|
|
|
result = NS_ERROR_OUT_OF_MEMORY;
|
1999-05-07 19:55:45 +00:00
|
|
|
}
|
2000-04-26 01:04:13 +00:00
|
|
|
::GlobalUnlock (stm.hGlobal) ;
|
|
|
|
|
1999-05-07 19:55:45 +00:00
|
|
|
} break;
|
|
|
|
|
1999-07-09 19:39:22 +00:00
|
|
|
default: {
|
2000-05-02 23:58:49 +00:00
|
|
|
if ( fe.cfFormat == fileDescriptorFlavor || fe.cfFormat == fileFlavor ) {
|
2000-05-02 22:39:08 +00:00
|
|
|
NS_WARNING ( "Mozilla doesn't yet understand how to read this type of file flavor" );
|
2000-08-17 04:19:14 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Get the data out of the global data handle. The size we return
|
|
|
|
// should not include the null because the other platforms don't
|
|
|
|
// use nulls, so just return the length we get back from strlen(),
|
|
|
|
// since we know CF_UNICODETEXT is null terminated. Recall that GetGlobalData()
|
|
|
|
// returns the size of the allocated buffer, not the size of the data
|
|
|
|
// (on 98, these are not the same) so we can't use that.
|
|
|
|
//
|
|
|
|
// NOTE: we are assuming that anything that falls into this default case
|
|
|
|
// is unicode. As we start to get more kinds of binary data, this
|
|
|
|
// may become an incorrect assumption. Stay tuned.
|
|
|
|
PRUint32 allocLen = 0;
|
|
|
|
if ( NS_SUCCEEDED(GetGlobalData(stm.hGlobal, aData, &allocLen)) ) {
|
|
|
|
*aLen = nsCRT::strlen(NS_REINTERPRET_CAST(PRUnichar*, *aData)) * 2;
|
|
|
|
result = NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2000-05-02 22:39:08 +00:00
|
|
|
} break;
|
1999-05-04 23:14:57 +00:00
|
|
|
} // switch
|
|
|
|
} break;
|
|
|
|
|
1999-07-09 19:39:22 +00:00
|
|
|
case TYMED_GDI:
|
|
|
|
{
|
2001-06-20 05:48:45 +00:00
|
|
|
#ifdef DEBUG
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("*********************** TYMED_GDI\n");
|
2001-06-20 05:48:45 +00:00
|
|
|
#endif
|
1999-07-09 19:39:22 +00:00
|
|
|
} break;
|
|
|
|
|
1999-05-04 23:14:57 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
} //switch
|
2000-05-08 23:26:06 +00:00
|
|
|
|
|
|
|
ReleaseStgMedium(&stm);
|
1999-04-06 20:25:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-04-17 13:49:39 +00:00
|
|
|
nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject,
|
2000-04-26 01:04:13 +00:00
|
|
|
UINT anIndex,
|
1999-04-17 13:49:39 +00:00
|
|
|
nsIWidget * aWindow,
|
|
|
|
nsITransferable * aTransferable)
|
1999-03-23 15:37:34 +00:00
|
|
|
{
|
|
|
|
// make sure we have a good transferable
|
1999-08-25 08:35:06 +00:00
|
|
|
if ( !aTransferable )
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
1999-04-06 20:25:09 +00:00
|
|
|
|
1999-08-25 08:35:06 +00:00
|
|
|
nsresult res = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// get flavor list that includes all flavors that can be written (including ones
|
|
|
|
// obtained through conversion)
|
|
|
|
nsCOMPtr<nsISupportsArray> flavorList;
|
|
|
|
res = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
|
|
|
|
if ( NS_FAILED(res) )
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-03-23 15:37:34 +00:00
|
|
|
|
|
|
|
// Walk through flavors and see which flavor is on the clipboard them on the native clipboard,
|
|
|
|
PRUint32 i;
|
1999-08-25 08:35:06 +00:00
|
|
|
PRUint32 cnt;
|
|
|
|
flavorList->Count(&cnt);
|
1999-05-13 04:56:04 +00:00
|
|
|
for (i=0;i<cnt;i++) {
|
1999-08-25 08:35:06 +00:00
|
|
|
nsCOMPtr<nsISupports> genericFlavor;
|
|
|
|
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
|
|
|
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
|
|
|
if ( currentFlavor ) {
|
1999-09-04 20:04:26 +00:00
|
|
|
nsXPIDLCString flavorStr;
|
|
|
|
currentFlavor->ToString(getter_Copies(flavorStr));
|
1999-08-25 08:35:06 +00:00
|
|
|
UINT format = GetFormat(flavorStr);
|
1999-03-23 15:37:34 +00:00
|
|
|
|
2000-08-03 00:47:36 +00:00
|
|
|
// Try to get the data using the desired flavor. This might fail, but all is
|
|
|
|
// not lost.
|
|
|
|
void* data = nsnull;
|
|
|
|
PRUint32 dataLen = 0;
|
2000-02-01 22:26:21 +00:00
|
|
|
PRBool dataFound = PR_FALSE;
|
1999-04-17 13:49:39 +00:00
|
|
|
if (nsnull != aDataObject) {
|
2000-04-26 01:04:13 +00:00
|
|
|
if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aDataObject, anIndex, format, &data, &dataLen)) )
|
2000-02-01 22:26:21 +00:00
|
|
|
dataFound = PR_TRUE;
|
1999-12-09 19:50:50 +00:00
|
|
|
}
|
|
|
|
else if (nsnull != aWindow) {
|
2000-04-26 01:04:13 +00:00
|
|
|
if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aWindow, anIndex, format, &data, &dataLen)) )
|
2000-02-01 22:26:21 +00:00
|
|
|
dataFound = PR_TRUE;
|
1999-08-25 08:35:06 +00:00
|
|
|
}
|
2000-08-03 00:47:36 +00:00
|
|
|
|
|
|
|
// This is our second chance to try to find some data, having not found it
|
|
|
|
// when directly asking for the flavor. Let's try digging around in other
|
|
|
|
// flavors to help satisfy our craving for data.
|
2000-02-01 22:26:21 +00:00
|
|
|
if ( !dataFound ) {
|
2000-08-03 00:47:36 +00:00
|
|
|
if ( strcmp(flavorStr, kUnicodeMime) == 0 )
|
|
|
|
dataFound = FindUnicodeFromPlainText ( aDataObject, anIndex, &data, &dataLen );
|
|
|
|
else if ( strcmp(flavorStr, kURLMime) == 0 )
|
|
|
|
dataFound = FindURLFromLocalFile ( aDataObject, anIndex, &data, &dataLen );
|
2000-02-01 22:26:21 +00:00
|
|
|
} // if we try one last ditch effort to find our data
|
|
|
|
|
2000-08-03 00:47:36 +00:00
|
|
|
// Hopefully by this point we've found it and can go about our business
|
2000-02-01 22:26:21 +00:00
|
|
|
if ( dataFound ) {
|
1999-12-09 19:50:50 +00:00
|
|
|
nsCOMPtr<nsISupports> genericDataWrapper;
|
2000-08-03 00:47:36 +00:00
|
|
|
if ( strcmp(flavorStr, kFileMime) == 0 ) {
|
|
|
|
// we have a file path in |data|. Create an nsLocalFile object.
|
|
|
|
char* filepath = NS_REINTERPRET_CAST(char*, data);
|
|
|
|
nsCOMPtr<nsILocalFile> file;
|
|
|
|
if ( NS_SUCCEEDED(NS_NewLocalFile(filepath, PR_FALSE, getter_AddRefs(file))) )
|
|
|
|
genericDataWrapper = do_QueryInterface(file);
|
|
|
|
}
|
|
|
|
else {
|
2000-04-26 01:04:13 +00:00
|
|
|
// we probably have some form of text. The DOM only wants LF, so convert from Win32 line
|
|
|
|
// endings to DOM line endings.
|
|
|
|
PRInt32 signedLen = NS_STATIC_CAST(PRInt32, dataLen);
|
|
|
|
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &data, &signedLen );
|
|
|
|
dataLen = signedLen;
|
|
|
|
|
|
|
|
nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) );
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" );
|
1999-12-09 19:50:50 +00:00
|
|
|
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLen);
|
|
|
|
|
2000-06-03 09:46:12 +00:00
|
|
|
nsMemory::Free ( NS_REINTERPRET_CAST(char*, data) );
|
2000-02-01 22:26:21 +00:00
|
|
|
res = NS_OK;
|
2000-04-26 01:04:13 +00:00
|
|
|
|
|
|
|
// we found one, get out of the loop
|
1999-12-02 23:18:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
1999-12-02 23:18:23 +00:00
|
|
|
} // foreach flavor
|
|
|
|
|
1999-04-17 13:49:39 +00:00
|
|
|
return res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2000-08-03 00:47:36 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// FindURLFromLocalFile
|
|
|
|
//
|
|
|
|
// we are looking for text/unicode and we failed to find it on the clipboard first,
|
|
|
|
// try again with text/plain. If that is present, convert it to unicode.
|
|
|
|
//
|
|
|
|
PRBool
|
|
|
|
nsClipboard :: FindUnicodeFromPlainText ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen )
|
|
|
|
{
|
|
|
|
PRBool dataFound = PR_FALSE;
|
|
|
|
|
|
|
|
// we are looking for text/unicode and we failed to find it on the clipboard first,
|
|
|
|
// try again with text/plain. If that is present, convert it to unicode.
|
|
|
|
nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kTextMime), outData, outDataLen);
|
|
|
|
if ( NS_SUCCEEDED(loadResult) && *outData ) {
|
|
|
|
const char* castedText = NS_REINTERPRET_CAST(char*, *outData);
|
|
|
|
PRUnichar* convertedText = nsnull;
|
|
|
|
PRInt32 convertedTextLen = 0;
|
|
|
|
nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode ( castedText, *outDataLen,
|
|
|
|
&convertedText, &convertedTextLen );
|
|
|
|
if ( convertedText ) {
|
|
|
|
// out with the old, in with the new
|
|
|
|
nsMemory::Free(*outData);
|
|
|
|
*outData = convertedText;
|
|
|
|
*outDataLen = convertedTextLen * sizeof(PRUnichar);
|
|
|
|
dataFound = PR_TRUE;
|
|
|
|
}
|
|
|
|
} // if plain text data on clipboard
|
|
|
|
|
|
|
|
return dataFound;
|
|
|
|
|
|
|
|
} // FindUnicodeFromPlainText
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// FindURLFromLocalFile
|
|
|
|
//
|
|
|
|
// we are looking for a URL and couldn't find it, try again with looking for
|
|
|
|
// a local file. If we have one, it may either be a normal file or an internet shortcut.
|
|
|
|
// In both cases, however, we can get a URL (it will be a file:// url in the
|
|
|
|
// local file case).
|
|
|
|
//
|
|
|
|
PRBool
|
|
|
|
nsClipboard :: FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, void** outData, PRUint32* outDataLen )
|
|
|
|
{
|
|
|
|
PRBool dataFound = PR_FALSE;
|
|
|
|
|
|
|
|
nsresult loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kFileMime), outData, outDataLen);
|
|
|
|
if ( NS_SUCCEEDED(loadResult) && *outData ) {
|
2000-08-03 22:05:09 +00:00
|
|
|
// we have a file path in |data|. Is it an internet shortcut or a normal file?
|
2000-08-03 00:47:36 +00:00
|
|
|
char* filepath = NS_REINTERPRET_CAST(char*, *outData);
|
2000-08-03 22:05:09 +00:00
|
|
|
if ( IsInternetShortcut(filepath) ) {
|
|
|
|
char* buffer = nsnull;
|
|
|
|
|
|
|
|
ResolveShortcut ( filepath, &buffer );
|
|
|
|
if ( buffer ) {
|
|
|
|
// convert it to unicode and pass it out
|
|
|
|
nsMemory::Free(*outData);
|
|
|
|
nsAutoString urlUnicode;
|
|
|
|
urlUnicode.AssignWithConversion( buffer );
|
2001-09-29 08:28:41 +00:00
|
|
|
*outData = ToNewUnicode(urlUnicode);
|
2000-08-03 22:05:09 +00:00
|
|
|
*outDataLen = strlen(buffer) * sizeof(PRUnichar);
|
|
|
|
nsMemory::Free(buffer);
|
|
|
|
|
|
|
|
dataFound = PR_TRUE;
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
2000-08-03 22:05:09 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// we have a normal file, use some Necko objects to get our file path
|
|
|
|
nsCOMPtr<nsILocalFile> file;
|
2001-06-21 22:02:47 +00:00
|
|
|
if ( NS_SUCCEEDED(NS_NewLocalFile(filepath, PR_FALSE, getter_AddRefs(file))) ) {
|
2002-01-08 01:31:25 +00:00
|
|
|
nsXPIDLCString urlSpec;
|
|
|
|
NS_GetURLSpecFromFile(file, getter_Copies(urlSpec));
|
2000-08-03 00:47:36 +00:00
|
|
|
|
|
|
|
// convert it to unicode and pass it out
|
|
|
|
nsMemory::Free(*outData);
|
|
|
|
nsAutoString urlSpecUnicode;
|
|
|
|
urlSpecUnicode.AssignWithConversion( urlSpec );
|
2001-09-29 08:28:41 +00:00
|
|
|
*outData = ToNewUnicode(urlSpecUnicode);
|
2001-06-21 22:02:47 +00:00
|
|
|
*outDataLen = strlen(urlSpec.get()) * sizeof(PRUnichar);
|
2000-08-03 00:47:36 +00:00
|
|
|
dataFound = PR_TRUE;
|
2001-06-21 22:02:47 +00:00
|
|
|
|
2000-08-03 22:05:09 +00:00
|
|
|
}
|
|
|
|
} // else regular file
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return dataFound;
|
|
|
|
} // FindURLFromLocalFile
|
|
|
|
|
|
|
|
|
2000-08-03 22:05:09 +00:00
|
|
|
//
|
|
|
|
// ResolveShortcut
|
|
|
|
//
|
|
|
|
// Use some Win32 mumbo-jumbo to read in the shortcut file and parse out the URL
|
|
|
|
// in references
|
|
|
|
//
|
2000-08-03 00:47:36 +00:00
|
|
|
void
|
2000-08-03 22:05:09 +00:00
|
|
|
nsClipboard :: ResolveShortcut ( const char* inFileName, char** outURL )
|
2000-08-03 00:47:36 +00:00
|
|
|
{
|
2000-08-17 00:02:38 +00:00
|
|
|
// IUniformResourceLocator isn't supported by VC5 (bless its little heart)
|
|
|
|
#if _MSC_VER >= 1200
|
2000-08-03 00:47:36 +00:00
|
|
|
HRESULT result;
|
|
|
|
|
2000-08-03 22:05:09 +00:00
|
|
|
IUniformResourceLocator* urlLink = nsnull;
|
|
|
|
result = ::CoCreateInstance ( CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
|
|
|
|
IID_IUniformResourceLocator, (void**)&urlLink );
|
|
|
|
if ( SUCCEEDED(result) && urlLink ) {
|
|
|
|
IPersistFile* urlFile = nsnull;
|
|
|
|
result = urlLink->QueryInterface (IID_IPersistFile, (void**)&urlFile );
|
|
|
|
if ( SUCCEEDED(result) && urlFile ) {
|
2000-08-03 00:47:36 +00:00
|
|
|
WORD wideFileName[MAX_PATH];
|
|
|
|
::MultiByteToWideChar ( CP_ACP, 0, inFileName, -1, wideFileName, MAX_PATH );
|
2000-08-03 22:05:09 +00:00
|
|
|
|
|
|
|
result = urlFile->Load(wideFileName, STGM_READ);
|
|
|
|
if (SUCCEEDED(result) ) {
|
|
|
|
LPSTR lpTemp = nsnull;
|
|
|
|
|
|
|
|
result = urlLink->GetURL(&lpTemp);
|
|
|
|
if ( SUCCEEDED(result) && lpTemp ) {
|
|
|
|
*outURL = PL_strdup (lpTemp);
|
|
|
|
|
|
|
|
// free the string that GetURL alloc'd
|
|
|
|
IMalloc* pMalloc;
|
|
|
|
result = SHGetMalloc(&pMalloc);
|
|
|
|
if ( SUCCEEDED(result) ) {
|
|
|
|
pMalloc->Free(lpTemp);
|
|
|
|
pMalloc->Release();
|
|
|
|
}
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-03 22:05:09 +00:00
|
|
|
urlFile->Release();
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
2000-08-03 22:05:09 +00:00
|
|
|
urlLink->Release();
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
2000-08-17 00:02:38 +00:00
|
|
|
#endif
|
2000-08-03 00:47:36 +00:00
|
|
|
} // ResolveShortcut
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// IsInternetShortcut
|
|
|
|
//
|
|
|
|
// A file is an Internet Shortcut if it ends with .URL
|
|
|
|
//
|
|
|
|
PRBool
|
|
|
|
nsClipboard :: IsInternetShortcut ( const char* inFileName )
|
|
|
|
{
|
|
|
|
if ( strstr(inFileName, ".URL") || strstr(inFileName, ".url") )
|
|
|
|
return PR_TRUE;
|
|
|
|
else
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
} // IsInternetShortcut
|
|
|
|
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
2001-01-23 01:09:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsClipboard::GetNativeClipboardData ( nsITransferable * aTransferable, PRInt32 aWhichClipboard )
|
1999-04-17 13:49:39 +00:00
|
|
|
{
|
|
|
|
// make sure we have a good transferable
|
2001-01-23 01:09:58 +00:00
|
|
|
if ( !aTransferable || aWhichClipboard != kGlobalClipboard )
|
1999-04-17 13:49:39 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsresult res;
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
// This makes sure we can use the OLE functionality for the clipboard
|
1999-04-17 13:49:39 +00:00
|
|
|
IDataObject * dataObj;
|
|
|
|
if (S_OK == ::OleGetClipboard(&dataObj)) {
|
1999-04-23 14:38:27 +00:00
|
|
|
// Use OLE IDataObject for clipboard operations
|
2000-04-26 01:04:13 +00:00
|
|
|
res = GetDataFromDataObject(dataObj, 0, nsnull, aTransferable);
|
2001-01-23 01:09:58 +00:00
|
|
|
dataObj->Release();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// do it the old manual way
|
2000-04-26 01:04:13 +00:00
|
|
|
res = GetDataFromDataObject(nsnull, 0, mWindow, aTransferable);
|
1999-04-17 13:49:39 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-03-23 21:26:41 +00:00
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
1999-03-23 21:26:41 +00:00
|
|
|
static void PlaceDataOnClipboard(PRUint32 aFormat, char * aData, int aLength)
|
|
|
|
{
|
|
|
|
HGLOBAL hGlobalMemory;
|
|
|
|
PSTR pGlobalMemory;
|
|
|
|
|
|
|
|
PRInt32 size = aLength + 1;
|
|
|
|
|
|
|
|
if (aLength) {
|
|
|
|
// Copy text to Global Memory Area
|
|
|
|
hGlobalMemory = (HGLOBAL)::GlobalAlloc(GHND, size);
|
|
|
|
if (hGlobalMemory != NULL) {
|
|
|
|
pGlobalMemory = (PSTR) ::GlobalLock(hGlobalMemory);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
char * s = aData;
|
|
|
|
PRInt32 len = aLength;
|
|
|
|
for (i=0;i< len;i++) {
|
|
|
|
*pGlobalMemory++ = *s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put data on Clipboard
|
|
|
|
::GlobalUnlock(hGlobalMemory);
|
|
|
|
::SetClipboardData(aFormat, hGlobalMemory);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-04-23 14:38:27 +00:00
|
|
|
//-------------------------------------------------------------------------
|
2000-04-14 02:52:58 +00:00
|
|
|
NS_IMETHODIMP nsClipboard::ForceDataToClipboard ( PRInt32 aWhichClipboard )
|
1999-03-23 21:26:41 +00:00
|
|
|
{
|
2000-08-19 19:30:52 +00:00
|
|
|
::OleFlushClipboard();
|
1999-03-23 21:26:41 +00:00
|
|
|
::CloseClipboard();
|
|
|
|
|
|
|
|
return NS_OK;
|
1999-03-23 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
1999-09-17 02:43:08 +00:00
|
|
|
//-------------------------------------------------------------------------
|
2000-04-14 02:52:58 +00:00
|
|
|
NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(nsISupportsArray *aFlavorList, PRInt32 aWhichClipboard,
|
1999-09-17 02:43:08 +00:00
|
|
|
PRBool *_retval)
|
|
|
|
{
|
|
|
|
*_retval = PR_FALSE;
|
2000-04-14 02:52:58 +00:00
|
|
|
if ( aWhichClipboard != kGlobalClipboard )
|
|
|
|
return NS_OK;
|
|
|
|
|
1999-09-17 02:43:08 +00:00
|
|
|
PRUint32 cnt;
|
|
|
|
aFlavorList->Count(&cnt);
|
2000-05-02 22:39:08 +00:00
|
|
|
for ( PRUint32 i = 0;i < cnt; ++i ) {
|
1999-09-17 02:43:08 +00:00
|
|
|
nsCOMPtr<nsISupports> genericFlavor;
|
|
|
|
aFlavorList->GetElementAt (i, getter_AddRefs(genericFlavor));
|
|
|
|
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
|
|
|
|
if (currentFlavor) {
|
|
|
|
nsXPIDLCString flavorStr;
|
|
|
|
currentFlavor->ToString(getter_Copies(flavorStr));
|
2000-02-01 22:26:21 +00:00
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
if ( strcmp(flavorStr, kTextMime) == 0 )
|
|
|
|
NS_WARNING ( "DO NOT USE THE text/plain DATA FLAVOR ANY MORE. USE text/unicode INSTEAD" );
|
|
|
|
#endif
|
|
|
|
|
1999-09-17 02:43:08 +00:00
|
|
|
UINT format = GetFormat(flavorStr);
|
|
|
|
if (::IsClipboardFormatAvailable(format)) {
|
|
|
|
*_retval = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2000-02-01 22:26:21 +00:00
|
|
|
else {
|
2000-08-03 00:47:36 +00:00
|
|
|
// We haven't found the exact flavor the client asked for, but maybe we can
|
|
|
|
// still find it from something else that's on the clipboard...
|
2000-02-01 22:26:21 +00:00
|
|
|
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
|
2000-08-03 00:47:36 +00:00
|
|
|
// client asked for unicode and it wasn't present, check if we have CF_TEXT.
|
|
|
|
// We'll handle the actual data substitution in the data object.
|
2000-02-01 22:26:21 +00:00
|
|
|
if ( ::IsClipboardFormatAvailable(GetFormat(kTextMime)) )
|
|
|
|
*_retval = PR_TRUE;
|
2000-08-03 00:47:36 +00:00
|
|
|
}
|
2000-02-01 22:26:21 +00:00
|
|
|
}
|
1999-09-17 02:43:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|