1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsDragService.h"
39 #include "nsITransferable.h"
41 #include "nsClipboard.h"
42 #include "nsIRegion.h"
43 #include "nsISupportsPrimitives.h"
44 #include "nsPrimitiveHelpers.h"
46 #include "nsXPIDLString.h"
48 #include "nsWidgetsCID.h"
50 char *nsDragService::mDndEvent
= NULL
;
51 int nsDragService::mDndEventLen
;
53 #define kMimeCustom "text/_moz_htmlcontext"
55 nsDragService::nsDragService()
62 mTransportFile
= nsnull
;
65 nsDragService::~nsDragService()
67 if( mNativeCtrl
) PtReleaseTransportCtrl( mNativeCtrl
);
68 if( mFlavourStr
) free( mFlavourStr
);
69 if( mTransportFile
) {
70 unlink( mTransportFile
);
71 free( mTransportFile
);
75 NS_IMETHODIMP
nsDragService::SetNativeDndData( PtWidget_t
*widget
, PhEvent_t
*event
) {
78 mDndEventLen
= sizeof( PhEvent_t
) + event
->num_rects
* sizeof( PhRect_t
) + event
->data_len
;
79 mDndEvent
= ( char * ) malloc( mDndEventLen
);
81 memcpy( mDndEvent
, (char*)event
, mDndEventLen
);
85 NS_IMETHODIMP
nsDragService::SetDropData( char *data
) {
87 if( mRawData
) free( mRawData
);
89 /* data is the filename used for passing the data */
90 FILE *fp
= fopen( data
, "r" );
92 fread( &n
, sizeof( PRUint32
), 1, fp
);
93 mRawData
= ( char * ) malloc( n
);
94 if( !mRawData
) { fclose( fp
); return NS_ERROR_FAILURE
; }
96 fseek( fp
, 0, SEEK_SET
);
97 fread( mRawData
, 1, n
, fp
);
104 /* remove this function with the one from libph.so, when it becomes available */
105 int CancelDrag( PhRid_t rid
, unsigned input_group
)
111 memset( &ev
, 0, sizeof(ev
) );
112 ev
.hdr
.type
= Ph_EV_DRAG
;
113 ev
.hdr
.emitter
.rid
= Ph_DEV_RID
;
114 ev
.hdr
.flags
= Ph_EVENT_INCLUSIVE
| Ph_EMIT_TOWARD
;
115 ev
.hdr
.data_len
= sizeof( ev
.drag
);
116 ev
.hdr
.subtype
= Ph_EV_DRAG_COMPLETE
;
117 ev
.hdr
.input_group
= input_group
;
119 return PhEmit( &ev
.hdr
, NULL
, &ev
.drag
);
123 //-------------------------------------------------------------------------
125 nsDragService::InvokeDragSession (nsIDOMNode
*aDOMNode
,
126 nsISupportsArray
* aArrayTransferables
,
127 nsIScriptableRegion
* aRegion
,
128 PRUint32 aActionType
)
131 printf( "nsDragService::InvokeDragSession\n" );
133 nsresult rv
= nsBaseDragService::InvokeDragSession(aDOMNode
,
135 aRegion
, aActionType
);
136 NS_ENSURE_SUCCESS(rv
, rv
);
138 if(!aArrayTransferables
) return NS_ERROR_INVALID_ARG
;
140 /* this will also addref the transferables since we're going to hang onto this beyond the length of this call */
141 mSourceDataItems
= aArrayTransferables
;
143 PRUint32 numDragItems
= 0;
144 mSourceDataItems
->Count(&numDragItems
);
145 if ( ! numDragItems
) return NS_ERROR_FAILURE
;
147 /* cancel a previous drag ( PhInitDrag ) if one is in place */
148 CancelDrag( PtWidgetRid( mDndWidget
), ((PhEvent_t
*)mDndEvent
)->input_group
);
150 mActionType
= aActionType
;
152 PRUint32 pDataLen
= sizeof( PRUint32
) + sizeof( PRUint32
), totalItems
= 0;
153 char *pdata
= ( char * ) malloc( pDataLen
); /* we reserve space for a total size and totalItems */
154 if( !pdata
) return NS_ERROR_FAILURE
;
157 for(PRUint32 itemIndex
= 0; itemIndex
< numDragItems
; ++itemIndex
) {
158 nsCOMPtr
<nsISupports
> genericItem
;
159 mSourceDataItems
->GetElementAt(itemIndex
, getter_AddRefs(genericItem
));
160 nsCOMPtr
<nsITransferable
> currItem (do_QueryInterface(genericItem
));
162 nsCOMPtr
<nsISupportsArray
> flavorList
;
163 currItem
->FlavorsTransferableCanExport(getter_AddRefs(flavorList
));
166 flavorList
->Count( &numFlavors
);
167 for( PRUint32 flavorIndex
= 0; flavorIndex
< numFlavors
; ++flavorIndex
) {
168 nsCOMPtr
<nsISupports
> genericWrapper
;
169 flavorList
->GetElementAt (flavorIndex
, getter_AddRefs(genericWrapper
));
170 nsCOMPtr
<nsISupportsCString
> currentFlavor
;
171 currentFlavor
= do_QueryInterface(genericWrapper
);
173 nsXPIDLCString flavorStr
;
174 currentFlavor
->ToString ( getter_Copies(flavorStr
) );
175 const char *FlavourStr
= ( const char * ) flavorStr
;
176 nsCOMPtr
<nsISupports
> data
;
177 PRUint32 tmpDataLen
= 0;
178 rv
= currItem
->GetTransferData( FlavourStr
, getter_AddRefs(data
), &tmpDataLen
);
179 if( NS_SUCCEEDED( rv
) ) {
180 /* insert FlavourStr, data into the PtTransportCtrl_t */
181 int len
= sizeof( PRUint32
) + sizeof( PRUint32
) + strlen( FlavourStr
) + 1 + tmpDataLen
;
182 /* we reserve space for itemIndex|tmpDataLen|flavorStr|data */
183 len
= ( ( len
+ 3 ) / 4 ) * 4;
184 pdata
= ( char * ) realloc( pdata
, len
+ pDataLen
);
186 char *p
= pdata
+ pDataLen
;
187 PRUint32
*d
= ( PRUint32
* ) p
;
188 d
[0] = itemIndex
; /* copy itemIndex*/
189 d
[1] = tmpDataLen
; /* copy PRUint32 tmpDataLen */
190 strcpy( p
+ sizeof( PRUint32
) + sizeof( PRUint32
), FlavourStr
); /* copy flavorStr */
193 nsPrimitiveHelpers::CreateDataFromPrimitive ( FlavourStr
, data
, &mem_data
, tmpDataLen
);
195 memcpy( p
+ sizeof( PRUint32
) + sizeof( PRUint32
) + strlen( FlavourStr
) + 1, mem_data
, tmpDataLen
); /* copy the data */
207 PRUint32
*p
= ( PRUint32
* ) pdata
;
210 mNativeCtrl
= PtCreateTransportCtrl( );
212 if( !mTransportFile
) mTransportFile
= strdup( (char*) tmpnam( NULL
) );
214 FILE *fp
= fopen( mTransportFile
, "w" );
215 fwrite( pdata
, 1, pDataLen
, fp
);
219 PtTransportType( mNativeCtrl
, "Mozilla", "dnddata", 1, Ph_TRANSPORT_INLINE
, "string", (void*)mTransportFile
, 0, 0 );
220 PtInitDnd( mNativeCtrl
, mDndWidget
, (PhEvent_t
*)mDndEvent
, NULL
, 0 );
228 //-------------------------------------------------------------------------
229 NS_IMETHODIMP
nsDragService::GetNumDropItems (PRUint32
* aNumItems
)
236 //-------------------------------------------------------------------------
237 NS_IMETHODIMP
nsDragService::GetData (nsITransferable
* aTransferable
, PRUint32 aItemIndex
) {
238 nsresult rv
= NS_ERROR_FAILURE
;
239 nsCOMPtr
<nsISupports
> genericDataWrapper
;
242 PRUint32
*d
= ( PRUint32
* ) mRawData
, totalItems
= d
[1];
243 PRUint32 i
, pdataLen
= sizeof( PRUint32
) + sizeof( PRUint32
);
245 /* search for aItemIndex */
246 for( i
=0; i
<totalItems
; i
++ ) {
247 char *p
= mRawData
+ pdataLen
;
248 PRUint32
*d
= ( PRUint32
* ) p
;
250 char *flavorStr
= p
+ sizeof( PRUint32
) + sizeof( PRUint32
);
251 PRUint32 this_len
= sizeof( PRUint32
) + sizeof( PRUint32
) + strlen( flavorStr
) + 1 + d
[1];
252 this_len
= ( ( this_len
+ 3 ) / 4 ) * 4;
253 char *raw_data
= flavorStr
+ strlen( flavorStr
) + 1;
255 if( d
[0] == aItemIndex
&& !strcmp( mFlavourStr
, flavorStr
) ) {
256 nsPrimitiveHelpers::CreatePrimitiveForData( flavorStr
, raw_data
, d
[1], getter_AddRefs( genericDataWrapper
) );
257 rv
= aTransferable
->SetTransferData( flavorStr
, genericDataWrapper
, d
[1] );
261 pdataLen
+= this_len
;
267 //-------------------------------------------------------------------------
268 NS_IMETHODIMP
nsDragService::IsDataFlavorSupported(const char *aDataFlavor
, PRBool
*_retval
)
270 if (!aDataFlavor
|| !_retval
)
271 return NS_ERROR_FAILURE
;
273 // set this to no by default
277 if( !strcmp( aDataFlavor
, kMimeCustom
) ) ask
= kHTMLMime
;
278 else ask
= aDataFlavor
;
280 if(!mSourceDataItems
) return NS_OK
;
281 PRUint32 numDragItems
= 0;
282 mSourceDataItems
->Count(&numDragItems
);
283 for(PRUint32 itemIndex
= 0; itemIndex
< numDragItems
; ++itemIndex
) {
284 nsCOMPtr
<nsISupports
> genericItem
;
285 mSourceDataItems
->GetElementAt(itemIndex
, getter_AddRefs(genericItem
));
286 nsCOMPtr
<nsITransferable
> currItem (do_QueryInterface(genericItem
));
288 nsCOMPtr
<nsISupportsArray
> flavorList
;
289 currItem
->FlavorsTransferableCanExport(getter_AddRefs(flavorList
));
292 flavorList
->Count( &numFlavors
);
293 for( PRUint32 flavorIndex
= 0; flavorIndex
< numFlavors
; ++flavorIndex
) {
294 nsCOMPtr
<nsISupports
> genericWrapper
;
295 flavorList
->GetElementAt (flavorIndex
, getter_AddRefs(genericWrapper
));
296 nsCOMPtr
<nsISupportsCString
> currentFlavor
;
297 currentFlavor
= do_QueryInterface(genericWrapper
);
299 nsXPIDLCString flavorStr
;
300 currentFlavor
->ToString ( getter_Copies(flavorStr
) );
301 if(strcmp(flavorStr
, ask
) == 0) {
303 if( mFlavourStr
) free( mFlavourStr
);
304 mFlavourStr
= strdup( ask
);
316 nsDragService::SourceEndDrag(void)
318 // this just releases the list of data items that we provide
319 mSourceDataItems
= 0;