Files
Mozilla/mozilla/widget/src/photon/nsDragService.cpp
timeless%mozdev.org e9f54b6bb1 Bug 299100 remove useless references to nsVoidArray
widget
r=darin sr=darin a=asa


git-svn-id: svn://10.0.0.236/trunk@175469 18797224-902f-48f8-a5cc-f745e15eee43
2005-07-01 04:40:31 +00:00

332 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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.
*
* The Original Code is mozilla.org code.
*
* 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.
*
* Contributor(s):
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDragService.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsClipboard.h"
#include "nsIRegion.h"
#include "nsISupportsPrimitives.h"
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsWidgetsCID.h"
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
char *nsDragService::mDndEvent = NULL;
int nsDragService::mDndEventLen;
#define kMimeCustom "text/_moz_htmlcontext"
//-------------------------------------------------------------------------
//
// DragService constructor
//
//-------------------------------------------------------------------------
nsDragService::nsDragService()
{
mDndWidget = nsnull;
mDndEvent = nsnull;
mNativeCtrl = nsnull;
mRawData = nsnull;
mFlavourStr = nsnull;
mTransportFile = nsnull;
}
//-------------------------------------------------------------------------
//
// DragService destructor
//
//-------------------------------------------------------------------------
nsDragService::~nsDragService()
{
if( mNativeCtrl ) PtReleaseTransportCtrl( mNativeCtrl );
if( mFlavourStr ) free( mFlavourStr );
if( mTransportFile ) {
unlink( mTransportFile );
free( mTransportFile );
}
}
NS_IMETHODIMP nsDragService::SetNativeDndData( PtWidget_t *widget, PhEvent_t *event ) {
mDndWidget = widget;
if( !mDndEvent ) {
mDndEventLen = sizeof( PhEvent_t ) + event->num_rects * sizeof( PhRect_t ) + event->data_len;
mDndEvent = ( char * ) malloc( mDndEventLen );
}
memcpy( mDndEvent, (char*)event, mDndEventLen );
return NS_OK;
}
NS_IMETHODIMP nsDragService::SetDropData( char *data ) {
if( mRawData ) free( mRawData );
/* data is the filename used for passing the data */
FILE *fp = fopen( data, "r" );
PRUint32 n;
fread( &n, sizeof( PRUint32 ), 1, fp );
mRawData = ( char * ) malloc( n );
if( !mRawData ) { fclose( fp ); return NS_ERROR_FAILURE; }
fseek( fp, 0, SEEK_SET );
fread( mRawData, 1, n, fp );
fclose( fp );
return NS_OK;
}
/* remove this function with the one from libph.so, when it becomes available */
int CancelDrag( PhRid_t rid, unsigned input_group )
{
struct dragevent {
PhEvent_t hdr;
PhDragEvent_t drag;
} ev;
memset( &ev, 0, sizeof(ev) );
ev.hdr.type = Ph_EV_DRAG;
ev.hdr.emitter.rid = Ph_DEV_RID;
ev.hdr.flags = Ph_EVENT_INCLUSIVE | Ph_EMIT_TOWARD;
ev.hdr.data_len = sizeof( ev.drag );
ev.hdr.subtype = Ph_EV_DRAG_COMPLETE;
ev.hdr.input_group = input_group;
ev.drag.rid = rid;
return PhEmit( &ev.hdr, NULL, &ev.drag );
}
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode,
nsISupportsArray * aArrayTransferables,
nsIScriptableRegion * aRegion,
PRUint32 aActionType)
{
#ifdef DEBUG
printf( "nsDragService::InvokeDragSession\n" );
#endif
nsBaseDragService::InvokeDragSession (aDOMNode, aArrayTransferables, aRegion, aActionType);
if(!aArrayTransferables) return NS_ERROR_INVALID_ARG;
/* this will also addref the transferables since we're going to hang onto this beyond the length of this call */
mSourceDataItems = aArrayTransferables;
PRUint32 numDragItems = 0;
mSourceDataItems->Count(&numDragItems);
if ( ! numDragItems ) return NS_ERROR_FAILURE;
/* cancel a previous drag ( PhInitDrag ) if one is in place */
CancelDrag( PtWidgetRid( mDndWidget ), ((PhEvent_t*)mDndEvent)->input_group );
mActionType = aActionType;
PRUint32 pDataLen = sizeof( PRUint32 ) + sizeof( PRUint32 ), totalItems = 0;
char *pdata = ( char * ) malloc( pDataLen ); /* we reserve space for a total size and totalItems */
if( !pdata ) return NS_ERROR_FAILURE;
for(PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex) {
nsCOMPtr<nsISupports> genericItem;
mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
if(currItem) {
nsCOMPtr <nsISupportsArray> flavorList;
currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
if(flavorList) {
PRUint32 numFlavors;
flavorList->Count( &numFlavors );
for( PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex ) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt (flavorIndex, getter_AddRefs(genericWrapper));
nsCOMPtr<nsISupportsCString> currentFlavor;
currentFlavor = do_QueryInterface(genericWrapper);
if(currentFlavor) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
const char *FlavourStr = ( const char * ) flavorStr;
nsCOMPtr<nsISupports> data;
PRUint32 tmpDataLen = 0;
nsresult rv = currItem->GetTransferData( FlavourStr, getter_AddRefs(data), &tmpDataLen );
if( NS_SUCCEEDED( rv ) ) {
/* insert FlavourStr, data into the PtTransportCtrl_t */
int len = sizeof( PRUint32 ) + sizeof( PRUint32 ) + strlen( FlavourStr ) + 1 + tmpDataLen;
/* we reserve space for itemIndex|tmpDataLen|flavorStr|data */
len = ( ( len + 3 ) / 4 ) * 4;
pdata = ( char * ) realloc( pdata, len + pDataLen );
if( pdata ) {
char *p = pdata + pDataLen;
PRUint32 *d = ( PRUint32 * ) p;
d[0] = itemIndex; /* copy itemIndex*/
d[1] = tmpDataLen; /* copy PRUint32 tmpDataLen */
strcpy( p + sizeof( PRUint32 ) + sizeof( PRUint32 ), FlavourStr ); /* copy flavorStr */
void *mem_data;
nsPrimitiveHelpers::CreateDataFromPrimitive ( FlavourStr, data, &mem_data, tmpDataLen );
memcpy( p + sizeof( PRUint32 ) + sizeof( PRUint32 ) + strlen( FlavourStr ) + 1, mem_data, tmpDataLen ); /* copy the data */
pDataLen += len;
totalItems++;
}
}
}
}
}
}
}
if( totalItems ) {
PRUint32 *p = ( PRUint32 * ) pdata;
p[0] = pDataLen;
p[1] = totalItems;
mNativeCtrl = PtCreateTransportCtrl( );
if( !mTransportFile ) mTransportFile = strdup( (char*) tmpnam( NULL ) );
FILE *fp = fopen( mTransportFile, "w" );
fwrite( pdata, 1, pDataLen, fp );
fclose( fp );
free( pdata );
PtTransportType( mNativeCtrl, "Mozilla", "dnddata", 1, Ph_TRANSPORT_INLINE, "string", (void*)mTransportFile, 0, 0 );
PtInitDnd( mNativeCtrl, mDndWidget, (PhEvent_t*)mDndEvent, NULL, 0 );
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
{
*aNumItems = 1;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 aItemIndex ) {
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsISupports> genericDataWrapper;
if( mRawData ) {
PRUint32 *d = ( PRUint32 * ) mRawData, totalItems = d[1];
PRUint32 i, pdataLen = sizeof( PRUint32 ) + sizeof( PRUint32 );
/* search for aItemIndex */
for( i=0; i<totalItems; i++ ) {
char *p = mRawData + pdataLen;
PRUint32 *d = ( PRUint32 * ) p;
char *flavorStr = p + sizeof( PRUint32 ) + sizeof( PRUint32 );
PRUint32 this_len = sizeof( PRUint32 ) + sizeof( PRUint32 ) + strlen( flavorStr ) + 1 + d[1];
this_len = ( ( this_len + 3 ) / 4 ) * 4;
char *raw_data = flavorStr + strlen( flavorStr ) + 1;
if( d[0] == aItemIndex && !strcmp( mFlavourStr, flavorStr ) ) {
nsPrimitiveHelpers::CreatePrimitiveForData( flavorStr, raw_data, d[1], getter_AddRefs( genericDataWrapper ) );
rv = aTransferable->SetTransferData( flavorStr, genericDataWrapper, d[1] );
break;
}
pdataLen += this_len;
}
}
return rv;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
if (!aDataFlavor || !_retval)
return NS_ERROR_FAILURE;
// set this to no by default
*_retval = PR_FALSE;
const char *ask;
if( !strcmp( aDataFlavor, kMimeCustom ) ) ask = kHTMLMime;
else ask = aDataFlavor;
if(!mSourceDataItems) return NS_OK;
PRUint32 numDragItems = 0;
mSourceDataItems->Count(&numDragItems);
for(PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex) {
nsCOMPtr<nsISupports> genericItem;
mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
if(currItem) {
nsCOMPtr <nsISupportsArray> flavorList;
currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
if(flavorList) {
PRUint32 numFlavors;
flavorList->Count( &numFlavors );
for( PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex ) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt (flavorIndex, getter_AddRefs(genericWrapper));
nsCOMPtr<nsISupportsCString> currentFlavor;
currentFlavor = do_QueryInterface(genericWrapper);
if(currentFlavor) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
if(strcmp(flavorStr, ask) == 0) {
*_retval = PR_TRUE;
if( mFlavourStr ) free( mFlavourStr );
mFlavourStr = strdup( ask );
}
}
}
}
}
}
return NS_OK;
}
void
nsDragService::SourceEndDrag(void)
{
// this just releases the list of data items that we provide
mSourceDataItems = 0;
}