Mozilla Cross-Reference mozilla1.8
mozilla/ widget/ src/ beos/ nsDragService.cpp
CVS Log
CVS Blame
CVS Graph
Diff file
Raw file
changes to
this file in
the last:
day
week
month
view using tree:
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
4  *
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/
9  *
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
13  * License.
14  *
15  * The Original Code is mozilla.org code.
16  *
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.
21  *
22  * Contributor(s):
23  *   Pierre Phaneuf <pp@ludusdesign.com>
24  *   Paul Ashford
25  *   Fredrik Holmqvist <thesuckiestemail@yahoo.se>
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40 
41 #include <stdio.h>
42 #include "nsDragService.h"
43 #include "nsIDocument.h"
44 #include "nsIRegion.h"
45 #include "nsITransferable.h"
46 #include "nsIServiceManager.h"
47 #include "nsISupportsPrimitives.h"
48 #include "nsVoidArray.h"
49 #include "nsXPIDLString.h"
50 #include "nsPrimitiveHelpers.h"
51 #include "nsUnitConversion.h"
52 #include "nsWidgetsCID.h"
53 #include "nsCRT.h"
54 
55 // if we want to do Image-dragging, also need to change Makefile.in
56 // to add
57 // 		-I$(topsrcdir)/gfx/src/beos \
58 // in INCLUDES
59 // and bug 294234 to be done.
60 // #include "nsIImage.h"
61 // #include "nsIImageBeOS.h"
62 //#include <Bitmap.h>
63 
64 #include <AppDefs.h>
65 #include <TypeConstants.h>
66 #include <DataIO.h>
67 #include <Mime.h>
68 #include <Rect.h>
69 #include <Region.h>
70 #include <String.h>
71 #include <View.h>
72 
73 #include "prlog.h"
74 #include "nsIPresShell.h"
75 #include "nsPresContext.h"
76 #include "nsIFrame.h"
77 #include "nsIView.h"
78 #include "nsIWidget.h"
79   
80 static NS_DEFINE_CID(kCDragServiceCID,   NS_DRAGSERVICE_CID);
81   
82 static PRLogModuleInfo *sDragLm = NULL;
83 
84 static nsIFrame*
85 GetPrimaryFrameFor(nsIDOMNode *aDOMNode)
86 {
87     nsCOMPtr<nsIContent> aContent = do_QueryInterface(aDOMNode);
88     if (nsnull == aContent)
89         return nsnull;
90 
91     nsIDocument* doc = aContent->GetCurrentDoc();
92     if (nsnull == doc)
93         return nsnull;
94     nsIPresShell* presShell = doc->GetShellAt(0);
95     if ( nsnull == presShell) 
96         return nsnull;
97     nsIFrame *frame;
98     presShell->GetPrimaryFrameFor(aContent, &frame);
99 	return frame;
100 }
101 
102 static bool 
103 IsInternalDrag(BMessage * aMsg)
104 {
105     BString orig;
106     // We started this drag if originater is 'BeZilla'
107     return (nsnull != aMsg && B_OK == aMsg->FindString("be:originator", &orig) &&
108 	    0 == orig.Compare("BeZilla"));
109 }
110 
111 NS_IMPL_THREADSAFE_ISUPPORTS4(nsDragService, nsIDragService,
112                               nsIDragService_1_8_BRANCH, nsIDragSession,
113                               nsIDragSessionBeOS)
114 //NS_IMPL_THREADSAFE_ISUPPORTS1(nsBaseDragService, nsIDragSessionBeOS)
115 
116 //-------------------------------------------------------------------------
117 //
118 // DragService constructor
119 // Enable logging: 'export NSPR_LOG_MODULES=nsDragService:5'
120 //-------------------------------------------------------------------------
121 nsDragService::nsDragService()
122 {
123     // set up our logging module
124     if (!sDragLm)
125         sDragLm = PR_NewLogModule("nsDragService");
126     PR_LOG(sDragLm, PR_LOG_DEBUG, ("\n\nnsDragService::nsDragService"));
127 
128     mDragMessage = NULL;
129     mCanDrop = PR_FALSE;
130 }
131 
132 //-------------------------------------------------------------------------
133 //
134 // DragService destructor
135 //
136 //-------------------------------------------------------------------------
137 nsDragService::~nsDragService()
138 {
139     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService"));
140     ResetDragInfo();
141 }
142 
143 //-------------------------------------------------------------------------
144 //
145 // nsIDragService : InvokeDragSession
146 //
147 // Called when a drag is being initiated from within mozilla 
148 // The code here gets the BView, the dragRect, builds the DragMessage and 
149 // starts the drag.
150 //
151 //-------------------------------------------------------------------------
152 NS_IMETHODIMP
153 nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode,
154                                   nsISupportsArray * aArrayTransferables,
155                                   nsIScriptableRegion * aRegion,
156                                   PRUint32 aActionType)
157 {
158     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::InvokeDragSession"));
159     nsresult rv = nsBaseDragService::InvokeDragSession(aDOMNode,
160                                                        aArrayTransferables,
161                                                        aRegion, aActionType);
162     NS_ENSURE_SUCCESS(rv, rv);
163 
164     ResetDragInfo();       
165     // make sure that we have an array of transferables to use
166     if (nsnull == aArrayTransferables)
167         return NS_ERROR_INVALID_ARG;
168 
169     // set our reference to the transferables.  this will also addref
170     // the transferables since we're going to hang onto this beyond the
171     // length of this call
172     mSourceDataItems = aArrayTransferables;
173 
174     // Get a box or a bitmap to drag
175     bool haveRect = false;
176     BRect dragRect;
177 	
178     if (nsnull != aRegion)
179     {
180         PRInt32 aX, aY, aWidth, aHeight;
181         // TODO. Region may represent multiple rects - when dragging multiple items.
182         aRegion->GetBoundingBox(&aX, &aY, &aWidth, &aHeight);
183         dragRect.Set( aX, aY, aX + aWidth, aY + aHeight);
184         haveRect = true;
185         // does this need to be offset?
186     } 
187     
188     // Get the frame for this content node (note: frames are not refcounted)
189     nsIFrame *aFrame = GetPrimaryFrameFor(aDOMNode);
190     if (nsnull == aFrame)
191         return PR_FALSE;
192     
193     // Now that we have the frame, we have to convert its coordinates into global screen
194     // coordinates.
195     nsRect aRect = aFrame->GetRect();
196 
197     // Find offset from our view
198     nsIView *containingView = nsnull;
199     nsPoint viewOffset(0,0);
200     aFrame->GetOffsetFromView(viewOffset, &containingView);
201     NS_ASSERTION(containingView, "No containing view!");
202     if (nsnull == containingView)
203         return PR_FALSE;
204 
205     // get the widget associated with the containing view. 
206     nsPoint aWidgetOffset;
207     nsCOMPtr<nsIWidget> aWidget = containingView->GetNearestWidget(&aWidgetOffset);
208     if (nsnull == aWidget)
209         return PR_FALSE;
210 
211     BView *view = (BView *) aWidget->GetNativeData(NS_NATIVE_WIDGET);
212     // Don't have the rect yet, try to get it from the dom node
213     if (nsnull==haveRect)
214     {
215         float t2p =  aFrame->GetPresContext()->TwipsToPixels(); 
216         // GetOffsetFromWidget() actually returns the _parent's_ offset from its widget, so we
217         // still have to add in the offset to |containingView|'s parent ourselves.
218         nsPoint aViewPos = containingView->GetPosition();
219     
220         // Shift our offset rect by offset into our view, the view's offset to its parent, and
221         // the parent's offset to the closest widget. Then convert that to global coordinates. 
222         // Recall that WidgetToScreen() will give us the global coordinates of the rectangle we 
223         // give it, but it expects  everything to be in pixels.
224         nsRect screenOffset;
225         screenOffset.MoveBy ( NSTwipsToIntPixels(aWidgetOffset.x + aViewPos.x + viewOffset.x, t2p),
226                             NSTwipsToIntPixels(aWidgetOffset.y + aViewPos.y + viewOffset.y, t2p));
227         aWidget->WidgetToScreen ( screenOffset, screenOffset );
228 
229         dragRect.Set(screenOffset.x, screenOffset.y, 
230 		             screenOffset.x + NSTwipsToIntPixels(aRect.width, t2p),
231 		             screenOffset.y + NSTwipsToIntPixels(aRect.height, t2p));
232         haveRect = true;
233     }
234 
235     mDragAction = aActionType;
236     mDragMessage = CreateDragMessage();
237 
238     if (!view || !mDragMessage)
239         return PR_FALSE;
240         
241     // Set the original click location, how to get this or is it needed ?
242     // sourceMessage->AddPoint("click_location", mPoint);
243     
244     if (!view->LockLooper())
245         return PR_FALSE;
246         
247     // Well, let's just use the view frame, maybe?
248     if (!haveRect) 
249     {
250         dragRect = view->Frame();
251         // do we need to offset?
252     }
253         
254     PR_LOG(sDragLm, PR_LOG_DEBUG, ("invoking mDragView->DragMessage"));
255     bool noBitmap = true;
256 
257 //This is the code for image-dragging, currently disabled. See comments in beginning of file.
258 # ifdef 0
259     do
260     {
261         PRUint32 dataSize;
262         PRUint32 noItems;
263         mSourceDataItems->Count(&noItems);
264         if (noItems!=1) 
265         {
266             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Transferables are not ==1, no drag bitmap!"));
267             break;
268         }
269         
270         nsCOMPtr<nsISupports> genericItem;
271         aArrayTransferables->GetElementAt(0, getter_AddRefs(genericItem));
272         nsCOMPtr<nsITransferable> aTransferable (do_QueryInterface(genericItem));
273         
274         nsCOMPtr<nsISupports> genericDataWrapper;
275         nsresult rv = aTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper), &dataSize);
276         if (NS_FAILED(rv))
277         {
278             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get nativeimage, no drag bitmap!"));
279             break;
280         }
281 
282         nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive (do_QueryInterface(genericDataWrapper));
283         if (ptrPrimitive == NULL) 
284         {
285             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get ptrPrimitive, no drag bitmap!"));
286             break;
287         }
288 
289         nsCOMPtr<nsISupports> genericData;
290         ptrPrimitive->GetData(getter_AddRefs(genericData));
291         if (genericData == NULL) 
292         {
293             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get data, no drag bitmap!"));
294             break;
295         }
296 
297         //dependent on bug 294234 and how it's implemented. This code was for attachment 183634.
298         nsCOMPtr<nsIImageBeOS> image (do_QueryInterface(genericData));
299         if (image == NULL)
300         {
301             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get nsImage, no drag bitmap!"));
302             break;
303         }
304 
305         BBitmap *aBitmap;
306         image->GetBitmap(&aBitmap);
307         if (aBitmap==NULL || !aBitmap->IsValid()) {
308             PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get BBitmap, no drag bitmap %s!", aBitmap==NULL?"(null)":"(not valid)" ));
309             break;        
310         }
311 
312         view->DragMessage(mDragMessage, aBitmap, B_OP_OVER, BPoint(-4,-4), view); 
313         noBitmap = false;
314     } while(false);
315 # endif    
316     
317     if (noBitmap) 
318         view->DragMessage(mDragMessage, dragRect, view);
319     
320     StartDragSession();
321     view->UnlockLooper();
322     return NS_OK;
323 }
324 
325 //-------------------------------------------------------------------------
326 //
327 // nsIDragService : StartDragSession
328 //
329 // We overwrite this so we can log it
330 //
331 //-------------------------------------------------------------------------
332 NS_IMETHODIMP
333 nsDragService::StartDragSession()
334 {
335     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::StartDragSession()"));
336     return nsBaseDragService::StartDragSession();
337 }
338 
339 //-------------------------------------------------------------------------
340 //
341 // nsIDragService : EndDragSession
342 //
343 // We overwrite this so we can log it
344 //
345 //-------------------------------------------------------------------------
346 NS_IMETHODIMP
347 nsDragService::EndDragSession()
348 {
349     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::EndDragSession()"));
350     //Don't reset drag info, keep it until there is a new drag, in case a negotiated drag'n'drop wants the info.
351     //We need the draginfo as we are ending starting the dragsession
352     //on entering/exiting different views (nsWindows) now.
353     //That way the dragsession is always ended when we go outside mozilla windows, but we do throw away the 
354     // mSourceDocument and mSourceNode. We do hold on to the nsTransferable if it was a internal drag. 
355     //ResetDragInfo();
356     return nsBaseDragService::EndDragSession();
357 }
358 
359 //-------------------------------------------------------------------------
360 //
361 // nsIDragSession : SetCanDrop
362 //
363 // We overwrite this so we can log it
364 //
365 //-------------------------------------------------------------------------
366 NS_IMETHODIMP
367 nsDragService::SetCanDrop(PRBool aCanDrop)
368 {
369     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::SetCanDrop(%s)",
370                                   aCanDrop == PR_TRUE?"TRUE":"FALSE"));
371     return nsBaseDragService::SetCanDrop(aCanDrop);
372 }
373 
374 
375 //-------------------------------------------------------------------------
376 //
377 // nsIDragSession : GetCanDrop
378 //
379 // We overwrite this so we can log it
380 //
381 //-------------------------------------------------------------------------
382 NS_IMETHODIMP
383 nsDragService::GetCanDrop(PRBool *aCanDrop)
384 {
385     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetCanDrop()"));
386     return nsBaseDragService::GetCanDrop(aCanDrop);
387 }
388 
389 //-------------------------------------------------------------------------
390 //
391 // nsIDragSession : GetNumDropItems
392 //
393 // Gets the number of items currently being dragged
394 //
395 //-------------------------------------------------------------------------
396 NS_IMETHODIMP
397 nsDragService::GetNumDropItems(PRUint32 * aNumItems)
398 {
399     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems()"));
400     if (nsnull == mDragMessage)
401     {
402         *aNumItems = 0;
403         PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems(): WARNING! No dragmessage"));
404         return NS_OK;
405     } 
406     // Did we start this drag?
407     if (IsInternalDrag(mDragMessage))
408         mSourceDataItems->Count(aNumItems);
409     else
410         // The only thing native that I can think of that may have multiple items
411         // would be file references, DND-docs don't say anything about multiple items.
412         *aNumItems = 1;
413 
414 
415     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems():%d", *aNumItems));
416     return NS_OK;
417 }
418 
419 
420 //-------------------------------------------------------------------------
421 //
422 // nsIDragSession : GetData
423 //
424 // Copies the data at the given index into the given nsITransferable
425 //
426 // This is usually called on Drop, but can be called before that
427 //
428 //-------------------------------------------------------------------------
429 NS_IMETHODIMP
430 nsDragService::GetData(nsITransferable * aTransferable, PRUint32 aItemIndex)
431 {
432     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetData %d", aItemIndex));
433 
434     if (nsnull==mDragMessage)
435         return NS_ERROR_INVALID_ARG;
436 
437     // get flavor list that includes all acceptable flavors (including
438     // ones obtained through conversion). Flavors are nsISupportsStrings
439     // so that they can be seen from JS.
440     nsresult rv = NS_ERROR_FAILURE;
441     nsCOMPtr<nsISupportsArray> flavorList;
442     rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
443     if (NS_FAILED(rv))
444         return rv;
445 
446     // count the number of flavors
447     PRUint32 cnt;
448     flavorList->Count (&cnt);
449 
450     nsCOMPtr<nsISupports> genericWrapper;
451     nsCOMPtr<nsISupportsCString> currentFlavor;
452     nsXPIDLCString flavorStr;
453     nsCOMPtr<nsISupports> genericItem;   
454     nsCOMPtr<nsISupports> data;
455     PRUint32 tmpDataLen = 0;
456     for (unsigned int i= 0; i < cnt; ++i )
457     {
458         flavorList->GetElementAt(i, getter_AddRefs(genericWrapper));
459         currentFlavor = do_QueryInterface(genericWrapper);
460         if (!currentFlavor)
461             continue;
462         currentFlavor->ToString(getter_Copies(flavorStr));
463         
464         PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData trying to get transfer data for %s",
465                         (const char *)flavorStr));
466                         
467         if (IsInternalDrag(mDragMessage))
468         {
469             mSourceDataItems->GetElementAt(aItemIndex, getter_AddRefs(genericItem));
470             nsCOMPtr<nsITransferable> item (do_QueryInterface(genericItem));
471             if (!item)
472                 continue;
473             rv = item->GetTransferData(flavorStr, getter_AddRefs(data), &tmpDataLen);
474             if (NS_FAILED(rv))
475                 continue;
476             PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData setting data."));
477             return aTransferable->SetTransferData(flavorStr, data, tmpDataLen);
478         } 
479         else
480         {
481             //Check if transfer message is simple_data or older type of DND
482             //Check if message has data else continue
483             //Negotiate for data (if possible) or get data
484         	 //set and return
485         }
486     }
487     PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData failed"));
488     return NS_ERROR_FAILURE;
489 }
490 
491 
492 //-------------------------------------------------------------------------
493 //
494 // nsIDragSession : IsDataFlavorSupported
495 //
496 // Tells whether the given flavor is supported by the current drag object
497 //
498 // Called on MouseOver events
499 //
500 //-------------------------------------------------------------------------
501 NS_IMETHODIMP
502 nsDragService::IsDataFlavorSupported (const char *aDataFlavor,
503                                       PRBool *_retval)
504 {
505     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported %s", aDataFlavor));
506     if (!_retval)
507         return NS_ERROR_INVALID_ARG;
508 
509     // set this to no by default
510     *_retval = PR_FALSE;
511 
512     // check to make sure that we have a drag object set, here
513     if (nsnull == mDragMessage) {
514         PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: IsDataFlavorSupported called without a valid drag context!"));
515         return NS_OK;
516     }
517 
518     if (IsInternalDrag(mDragMessage))
519     {
520         PRUint32 numDragItems = 0;
521         // if we don't have mDataItems we didn't start this drag so it's
522         // an external client trying to fool us.
523         if (nsnull == mSourceDataItems)
524             return NS_OK;
525         mSourceDataItems->Count(&numDragItems);
526         if (0 == numDragItems)
527             PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: Number of dragged items is zero!"));
528 
529         // For all dragged items compare their flavors to the one wanted. If there is a match DataFlavor is supported.
530         nsCOMPtr<nsISupports> genericItem;
531         nsCOMPtr <nsISupportsArray> flavorList;
532         PRUint32 numFlavors;
533         for (PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex)
534         {
535             mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
536             nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
537             if (nsnull == currItem)
538                 continue;
539             currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
540             if (nsnull == flavorList)
541                 continue;
542             flavorList->Count( &numFlavors );
543             
544             nsCOMPtr<nsISupports> genericWrapper;
545             nsXPIDLCString flavorStr;
546             for ( PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex ) {
547                 flavorList->GetElementAt (flavorIndex, getter_AddRefs(genericWrapper));
548                 nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryInterface(genericWrapper);
549                 if (nsnull == currentFlavor)
550                     continue;
551                 currentFlavor->ToString ( getter_Copies(flavorStr) );
552                 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported checking %s against %s", (const char *)flavorStr, aDataFlavor));
553                 if (0 != strcmp(flavorStr, aDataFlavor))
554                     continue;
555                 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported Got the flavor!"));
556                 *_retval = PR_TRUE;
557                 return NS_OK;
558             }
559         }
560     }
561     else 
562     {
563         PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: Native drag not implemented."));
564         // TODO: implement native checking
565     }
566     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported FALSE"));
567     return NS_OK;
568 }
569 
570 //-------------------------------------------------------------------------
571 //
572 // nsDragServoce : CreateDragMessage
573 //
574 // Builds the drag message needed for BeOS negotiated DND.
575 //
576 //-------------------------------------------------------------------------
577 BMessage *
578 nsDragService::CreateDragMessage()
579 {
580     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetInitialDragMessage"));
581     if (nsnull == mSourceDataItems)
582         return NULL;
583     
584     unsigned int numDragItems = 0;
585     mSourceDataItems->Count(&numDragItems);
586     
587     BMessage * returnMsg = new BMessage(B_SIMPLE_DATA);
588     
589     returnMsg->AddString("be:originator", "BeZilla");
590     returnMsg->AddString("be:clip_name","BeZilla Drag Item");
591   
592     if (mDragAction & DRAGDROP_ACTION_COPY)
593         returnMsg->AddInt32("be:actions",B_COPY_TARGET);
594     if (mDragAction & DRAGDROP_ACTION_MOVE)
595         returnMsg->AddInt32("be:actions",B_MOVE_TARGET);
596     if (mDragAction & DRAGDROP_ACTION_LINK)
597         returnMsg->AddInt32("be:actions",B_LINK_TARGET);
598   
599     // Check to see if we're dragging > 1 item.  If we are then we use
600     // an internal only type.
601     if (numDragItems > 1)
602     {
603         PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Dragging a list of items ..."));
604 //        returnMsg->AddString("be:types", gMimeListType);
605 //        returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
606 //        returnMsg->AddString("be:filetypes", gMimeListType);
607 //        returnMsg->AddString("be:type_descriptions", gMimeListType);        
608         return returnMsg;
609     }
610 
611     PRBool addedType = PR_FALSE;
612 
613     nsCOMPtr<nsISupports> genericItem;
614     nsCOMPtr <nsISupportsArray> flavorList;
615     PRUint32 numFlavors;
616     nsCOMPtr<nsISupports> genericWrapper;
617     nsXPIDLCString flavorStr;
618 
619     for (unsigned int itemIndex = 0; itemIndex < numDragItems; ++itemIndex)
620     {
621         mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
622         nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
623         if (nsnull == currItem) 
624             continue;
625 
626         currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
627         if (nsnull == flavorList)
628             continue;
629         flavorList->Count( &numFlavors );
630         for (PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex )
631         {
632             flavorList->GetElementAt(flavorIndex, getter_AddRefs(genericWrapper));
633             nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryInterface(genericWrapper);
634             if (nsnull == currentFlavor)
635                 continue;
636             currentFlavor->ToString ( getter_Copies(flavorStr) );
637             
638             PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Adding a flavor to our message: %s",flavorStr.get()));
639             
640             type_code aCode;
641             if (B_OK == returnMsg->GetInfo(flavorStr.get(), &aCode))
642                 continue;
643             returnMsg->AddString("be:types",flavorStr.get());
644             
645             //returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
646             returnMsg->AddString("be:filetypes",flavorStr.get());
647             returnMsg->AddString("be:type_descriptions",flavorStr.get());
648             
649             addedType = PR_TRUE;            
650             // Check to see if this is text/unicode.  If it is, add
651             // text/plain since we automatically support text/plain if
652             // we support text/unicode.
653             //tqh: but this may cause duplicates?
654             if (0 == strcmp(flavorStr, kUnicodeMime))
655             {
656                 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Adding a TextMime for the UnicodeMime"));
657                 returnMsg->AddString("be:types",kTextMime);
658                 //returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
659                 returnMsg->AddString("be:filetypes",kTextMime);
660                 returnMsg->AddString("be:type_descriptions",kTextMime);
661             }
662         }
663     }
664     
665     if (addedType) {
666         returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
667     }
668     returnMsg->PrintToStream();
669     // If we did not add a type, we can't drag
670     NS_ASSERTION(addedType == PR_TRUE, "No flavor/mime in the drag message!");
671     return returnMsg;
672 }
673 
674 //-------------------------------------------------------------------------
675 //
676 // nsIDragSessionBeOS : UpdateDragMessageIfNeeded
677 //
678 // Updates the drag message from the old one if we enter a mozilla view with
679 // a dragmessage from outside. IE one where "be:originator"-key != "BeZilla"
680 //
681 //-------------------------------------------------------------------------
682 NS_IMETHODIMP
683 nsDragService::UpdateDragMessageIfNeeded(BMessage *aDragMessage)
684 {
685     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::UpdateDragMessageIfNeeded()"));
686     if (aDragMessage == mDragMessage) 
687         return NS_OK;
688     
689     // Did we start this drag?
690     //It's already set properly by InvokeDragSession, so don't do anything and avoid throwing away
691     //mSourceDataItems
692     if (IsInternalDrag(aDragMessage))
693         return NS_OK;
694 
695     PR_LOG(sDragLm, PR_LOG_DEBUG, ("updating."));
696     ResetDragInfo();
697     mDragMessage = aDragMessage;
698     return NS_OK;
699 }
700 
701 
702 //-------------------------------------------------------------------------
703 //
704 // nsIDragSessionBeOS : TransmitData
705 //
706 // When a negotiated drag'n'drop to another app occurs nsWindow
707 // calls this method with the other apps message which contains
708 // the info on what data the app wants. This function checks the 
709 // message and transmits the data to the app, thereby ending the
710 // drag'n'drop to another app.
711 //-------------------------------------------------------------------------
712 NS_IMETHODIMP
713 nsDragService::TransmitData(BMessage *aNegotiationReply)
714 {
715     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::TransmitData()"));
716 /*
717     unsigned int numDragItems = 0;
718     mSourceDataItems->Count(&numDragItems);
719     
720     returnMsg->AddString("be:originator", "BeZilla");
721     returnMsg->AddString("be:clip_name","BeZilla Drag Item");
722   
723     // Check to see if we're dragging > 1 item.  If we are then we use
724     // an internal only type.
725     if (numDragItems > 1)
726     {
727         PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Dragging a list of items ..."));
728         delete aNegotiationReply;
729         return;
730     }
731     BMessage aReply = new BMessage(B_MIME_DATA);
732     char * aMimeType;
733     aNegotiationReply->FindString("be:types", &aMimeType);
734      nsCOMPtr<nsITransferable> item;
735      item->addDataFlavor(aMimeType);
736     GetData(item, 0);
737     aReply->AddData(aMimeType, item->);
738   */  
739     aNegotiationReply->PrintToStream();
740     delete aNegotiationReply;
741     return NS_OK;
742 }
743 
744 //-------------------------------------------------------------------------
745 //
746 // nsIDragService : ResetDragInfo
747 //
748 // Resets the stored drag information.
749 //
750 //-------------------------------------------------------------------------
751 void
752 nsDragService::ResetDragInfo()
753 {
754     PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::ResetDragInfo()"));
755     if (nsnull != mDragMessage) delete mDragMessage;
756     mDragMessage = NULL;
757     mSourceDataItems = NULL;
758 }
759 
760 const char *
761 nsDragService::FlavorToBeMime(const char * flavor)
762 {
763     //text/plain ok
764     //text/unicode -> text/plain
765     if (0 == strcmp(flavor,kUnicodeMime)) return kTextMime;    
766     //text/html ok
767     //AOLMAIL ignore!!     
768     //image/png ok
769     //image/jpg
770     if (0 == strcmp(flavor,kJPEGImageMime)) return "image/jpeg";
771     //image/gif ok
772     //application/x-moz-file
773     if (0 == strcmp(flavor,kFileMime)) return "application/octet-stream";
774     //text/x-moz-url (only support this as a filetype (Be bookmark))
775     if (0 == strcmp(flavor,kURLMime)) return "application/x-vnd.Be-bookmark";
776     //text/x-moz-url-data - we need to read data to find out what type of URL.
777     //text/x-moz-url-desc - a url-description (same as title?)
778     //kNativeImageMime - don't support as BeOS image
779     //kNativeHTMLMime - don't support on BeOS side
780     //kFilePromiseURLMime
781     //kFilePromiseDestFilename
782     //kFilePromiseMime
783     //kFilePromiseDirectoryMime
784     
785 //    if (0==strcmp(flavor,kUnicodeMime))
786 }
787