mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +00:00
721 lines
21 KiB
C++
721 lines
21 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "CBrowserView.h"
|
|
|
|
// need these for various routine calls
|
|
#include "CHTMLClickrecord.h"
|
|
#include "msgcom.h"
|
|
#include "proto.h"
|
|
#include "RandomFrontEndCrap.h"
|
|
#include "CBrowserContext.h"
|
|
#include "CBookmarksAttachment.h"
|
|
#include "ufilemgr.h"
|
|
#include "CURLDispatcher.h"
|
|
#include "CEditorWindow.h" // cmd_EditFrame
|
|
#include "secnav.h"
|
|
#include "ntypes.h"
|
|
#include "shist.h"
|
|
#include "macutil.h"
|
|
#include "CViewUtils.h"
|
|
#include "CApplicationEventAttachment.h"
|
|
#include "uerrmgr.h" // GetPString prototype
|
|
#include "CTargetFramer.h"
|
|
|
|
extern "C" {
|
|
#include "layout.h"
|
|
}
|
|
|
|
// ¥¥¥ I don't want to include this, but I need the ID of the popup menu
|
|
#include "resgui.h"
|
|
|
|
#include "CMochaHacks.h"
|
|
|
|
class CBrowserViewDoDragReceiveMochaCallback;
|
|
|
|
void MochaDragDrop(MWContext* inContext, CBrowserViewDoDragReceiveMochaCallback * cb, Point inDragMouse, short inDragModifiers );
|
|
Boolean HasFTPUpload(CBrowserContext * context);
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
CBrowserView::CBrowserView(LStream* inStream)
|
|
: CHTMLView(inStream)
|
|
{
|
|
}
|
|
|
|
CBrowserView::~CBrowserView()
|
|
{
|
|
}
|
|
|
|
void
|
|
CBrowserView::MoveBy(
|
|
Int32 inHorizDelta,
|
|
Int32 inVertDelta,
|
|
Boolean inRefresh)
|
|
{
|
|
Inherited::MoveBy(inHorizDelta, inVertDelta, inRefresh);
|
|
if (mContext != NULL && (inHorizDelta || inVertDelta))
|
|
{
|
|
SPoint32 location;
|
|
GetFrameLocation(location);
|
|
CMochaHacks::SendMoveEvent(*mContext, location.h, location.v);
|
|
}
|
|
}
|
|
|
|
/* BeTarget and DontBeTarget enable and disable the drawing of the selection.
|
|
This has the effect of not drawing the text as selected when the view is
|
|
not currently the target. Using LO_ClearSelection instead would have
|
|
the same effect, but the selection wouldn't be recovered when the target
|
|
is given back to the view (as in, when its window is deactivated then
|
|
reactivated).
|
|
*/
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ BeTarget
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
CBrowserView::BeTarget() {
|
|
|
|
LO_HighlightSelection (*mContext, TRUE);
|
|
ExecuteAttachments(CTargetFramer::msg_BecomingTarget, this);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ DontBeTarget
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
CBrowserView::DontBeTarget() {
|
|
|
|
// LO_ClearSelection (*mContext);
|
|
LO_HighlightSelection (*mContext, FALSE);
|
|
ExecuteAttachments(CTargetFramer::msg_ResigningTarget, this);
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
//
|
|
#pragma mark --- COMMANDER OVERRIDES ---
|
|
//
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserView::FindCommandStatus(CommandT inCommand,
|
|
Boolean &outEnabled,
|
|
Boolean &outUsesMark,
|
|
Char16 &outMark,
|
|
Str255 outName)
|
|
{
|
|
if (::StillDown())
|
|
{
|
|
if (FindCommandStatusForContextMenu(inCommand, outEnabled,outUsesMark, outMark, outName))
|
|
return;
|
|
}
|
|
MWContext *mwcontext;
|
|
outUsesMark = false;
|
|
|
|
CBrowserWindow *browserWindow = dynamic_cast<CBrowserWindow *>(CViewUtils::GetTopMostSuperView(this));
|
|
Boolean isHTMLHelp = browserWindow ? browserWindow->IsHTMLHelp() : false;
|
|
|
|
// Restricted targets are Netcaster things, right?
|
|
#ifdef MOZ_NETCAST
|
|
// Disable commands which don't apply to restricted targets, at the request of javascript.
|
|
// No special distinction needed for floaters here.
|
|
if (browserWindow &&
|
|
browserWindow->CommandsAreDisabled() &&
|
|
inCommand == cmd_EditFrame)
|
|
{
|
|
outEnabled = false;
|
|
return;
|
|
}
|
|
#endif // MOZ_NETCAST
|
|
switch (inCommand)
|
|
{
|
|
#ifdef EDITOR
|
|
case cmd_EditFrame:
|
|
mwcontext = *GetContext();
|
|
if (mwcontext && !(XP_IsContextBusy(mwcontext)) && !Memory_MemoryIsLow())
|
|
{
|
|
// we must have a frameset if this context has a non-grid parent
|
|
if ( XP_GetNonGridContext( mwcontext ) != mwcontext )
|
|
outEnabled = true && !isHTMLHelp;
|
|
}
|
|
break;
|
|
#endif // EDITOR
|
|
|
|
// case cmd_SecurityInfo:
|
|
// case cmd_DocumentInfo:
|
|
// outEnabled = true;
|
|
// break;
|
|
|
|
case cmd_FTPUpload:
|
|
outEnabled = HasFTPUpload( GetContext() ) && !isHTMLHelp;
|
|
break;
|
|
|
|
default:
|
|
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Boolean CBrowserView::ObeyCommand(CommandT inCommand, void* ioParam)
|
|
{
|
|
Boolean cmdHandled = false;
|
|
|
|
switch (inCommand)
|
|
{
|
|
#ifdef EDITOR
|
|
case cmd_EditFrame:
|
|
CEditorWindow::MakeEditWindowFromBrowser( *GetContext() );
|
|
break;
|
|
#endif // EDITOR
|
|
|
|
// case cmd_SecurityInfo:
|
|
// mwcontext = *GetContext();
|
|
// if (mwcontext)
|
|
// {
|
|
// URL_Struct* url =
|
|
// SHIST_CreateURLStructFromHistoryEntry(
|
|
// mwcontext,
|
|
// GetContext()->GetCurrentHistoryEntry()
|
|
// );
|
|
// if (url)
|
|
// SECNAV_SecurityAdvisor(mwcontext,url);
|
|
// }
|
|
// break;
|
|
|
|
case cmd_FTPUpload:
|
|
{
|
|
// NOTE - the backend currently only supports uploading the data fork
|
|
// of a file. A planned feature of 5.0 is to support MacBinary
|
|
// encoding during the upload process. To this end the routine
|
|
// UStdDialogs::AskUploadAsDataOrMacBin has been created to prompt
|
|
// for the desired upload mode in place of the call to
|
|
// StandardGetFile below.
|
|
FSSpec spec;
|
|
History_entry * he = GetContext()->GetCurrentHistoryEntry();
|
|
char * fileURL = CFileMgr::EncodedPathNameFromFSSpec(spec, TRUE);
|
|
OSType myTypes[3];
|
|
StandardFileReply myReply;
|
|
UDesktop::Deactivate();
|
|
StandardGetFile(NULL, -1, myTypes, &myReply);
|
|
UDesktop::Activate();
|
|
if (myReply.sfGood)
|
|
{
|
|
URL_Struct * request = NET_CreateURLStruct(he->address, NET_SUPER_RELOAD);
|
|
char ** newFileList = (char **) XP_ALLOC(2 * sizeof(char*));
|
|
ThrowIfNil_(request);
|
|
ThrowIfNil_(newFileList);
|
|
request->method = URL_POST_METHOD;
|
|
|
|
newFileList[0] = CFileMgr::EncodedPathNameFromFSSpec(myReply.sfFile, TRUE);
|
|
ThrowIfNil_(newFileList[0]);
|
|
newFileList[1] = NULL;
|
|
request->files_to_post = newFileList;
|
|
GetContext()->SwitchLoadURL( request, FO_CACHE_AND_PRESENT );
|
|
}
|
|
}
|
|
break;
|
|
|
|
// case cmd_DocumentInfo:
|
|
// URL_Struct* aboutURL = NET_CreateURLStruct( "about:document", NET_DONT_RELOAD );
|
|
// if ( aboutURL )
|
|
// CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext, aboutURL, FO_CACHE_AND_PRESENT, false, 1010, false);
|
|
// break;
|
|
|
|
default:
|
|
cmdHandled = Inherited::ObeyCommand(inCommand, ioParam);
|
|
break;
|
|
}
|
|
|
|
return cmdHandled;
|
|
}
|
|
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
//
|
|
#pragma mark --- CONTEXTUAL POPUP ---
|
|
//
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
Boolean CBrowserView::FindCommandStatusForContextMenu(
|
|
CommandT inCommand,
|
|
Boolean &outEnabled,
|
|
Boolean &/*outUsesMark*/,
|
|
Char16 &/*outMark*/,
|
|
Str255 /*outName*/)
|
|
{
|
|
// We come here only if a CContextMenuAttachment is installed. (This is the new way).
|
|
// Return true if we want to bypass standard status processing.
|
|
if (!mCurrentClickRecord)
|
|
return false;
|
|
CHTMLClickRecord& cr = *mCurrentClickRecord; // for brevity.
|
|
Boolean isAnchor = FALSE;
|
|
Boolean isImage = FALSE;
|
|
if (cr.mElement)
|
|
{
|
|
isAnchor = cr.IsAnchor();
|
|
isImage = cr.mElement->type == LO_IMAGE
|
|
&& NET_URL_Type(mContext->GetCurrentURL()) != FTP_TYPE_URL;
|
|
}
|
|
|
|
CBrowserWindow *browserWindow = dynamic_cast<CBrowserWindow *>(CViewUtils::GetTopMostSuperView(this));
|
|
Boolean isHTMLHelp = browserWindow ? browserWindow->IsHTMLHelp() : false;
|
|
// We're overloading command disabling to handle menu items too.
|
|
Boolean commandsAreDisabled = browserWindow ? browserWindow->CommandsAreDisabled() : false;
|
|
|
|
switch (inCommand)
|
|
{
|
|
case cmd_NEW_WINDOW_WITH_FRAME:
|
|
outEnabled = ((MWContext (*mContext)).is_grid_cell
|
|
&& (mContext->GetCurrentHistoryEntry() != NULL)) && !isHTMLHelp;
|
|
return true;
|
|
case cmd_OPEN_LINK:
|
|
outEnabled = isAnchor && !commandsAreDisabled;
|
|
return true;
|
|
case cmd_AddToBookmarks:
|
|
if (isAnchor)
|
|
outEnabled = !isHTMLHelp;
|
|
return true; // for now, only have a "add bookmark for this link" command.
|
|
// return isAnchor; // we don't know unless it's an anchor
|
|
case cmd_NEW_WINDOW:
|
|
#ifdef MOZ_MAIL_NEWS
|
|
Boolean newWindowProhibited = ::MSG_NewWindowProhibited(*mContext, cr.mClickURL);
|
|
#else
|
|
// MSG_NewWindowProhibited doesn't exist in a non-mail/news world so just say
|
|
// we don't prohibit creating a new window
|
|
Boolean newWindowProhibited = false;
|
|
#endif // MOZ_MAIL_NEWS
|
|
outEnabled = !newWindowProhibited && isAnchor && !isHTMLHelp;
|
|
return true;
|
|
case cmd_SAVE_LINK_AS:
|
|
outEnabled = isAnchor && !IsMailToLink(cr.mClickURL) && !isHTMLHelp;
|
|
return true; // we don't know unless it's an anchor
|
|
case cmd_COPY_LINK_LOC:
|
|
outEnabled = (isAnchor && mCurrentClickRecord->mClickURL.length() > 0) && !isHTMLHelp;
|
|
return true;
|
|
case cmd_VIEW_IMAGE:
|
|
outEnabled = isImage && !isHTMLHelp && !commandsAreDisabled;
|
|
return true;
|
|
case cmd_SAVE_IMAGE_AS:
|
|
case cmd_COPY_IMAGE:
|
|
case cmd_COPY_IMAGE_LOC:
|
|
outEnabled = isImage && !isHTMLHelp;
|
|
return true;
|
|
case cmd_LOAD_IMAGE:
|
|
outEnabled = isImage && !commandsAreDisabled;
|
|
return true;
|
|
}
|
|
return false; // we don't know about it
|
|
} // CBrowserView::FindCommandStatusForContextMenu
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
//
|
|
#pragma mark --- DRAG AND DROP ---
|
|
//
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
// Drag and drop is now reflected into javascript. On drag drop, the browser view
|
|
// packages the URLs received into a new event and sends it to javascript with a
|
|
// callback. If javascript lets us have the drop, the callback dispatches the URLs.
|
|
|
|
|
|
|
|
Boolean CBrowserView::DragIsAcceptable(DragReference inDragRef)
|
|
{
|
|
Boolean doAccept = false;
|
|
DragAttributes theAttributes = {0};
|
|
|
|
(void) GetDragAttributes(inDragRef, &theAttributes);
|
|
doAccept = !(theAttributes & kDragInsideSenderWindow);
|
|
|
|
if (doAccept)
|
|
{
|
|
doAccept = Inherited::DragIsAcceptable(inDragRef);
|
|
}
|
|
|
|
return doAccept;
|
|
}
|
|
|
|
|
|
|
|
Boolean CBrowserView::ItemIsAcceptable(DragReference inDragRef, ItemReference inItemRef)
|
|
{
|
|
FlavorFlags theFlags;
|
|
Boolean doAccept = false;
|
|
|
|
doAccept |= (::GetFlavorFlags(inDragRef, inItemRef, 'TEXT', &theFlags) == noErr);
|
|
doAccept |= (::GetFlavorFlags(inDragRef, inItemRef, flavorTypeHFS, &theFlags) == noErr);
|
|
|
|
return doAccept;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
void CBrowserView::ReceiveDragItem(DragReference inDragRef,
|
|
DragAttributes inDragAttrs,
|
|
ItemReference inItemRef,
|
|
Rect& inItemBounds) // In local coordinates
|
|
{
|
|
FlavorFlags theFlags;
|
|
OSErr anError = noErr;
|
|
URL_Struct* request = nil;
|
|
|
|
anError = ::GetFlavorFlags(inDragRef, inItemRef, 'TEXT', &theFlags);
|
|
if (anError == noErr)
|
|
{
|
|
long theDataSize = 0;
|
|
char* theData = nil;
|
|
|
|
::GetFlavorDataSize(inDragRef, inItemRef, 'TEXT', &theDataSize);
|
|
if (theDataSize > 255) // ¥¥¥Êare there any limits to the URL string length?
|
|
{
|
|
theDataSize = 255;
|
|
}
|
|
|
|
theData = (char*) ::NewPtr(theDataSize+1);
|
|
// assert(theData != nil);
|
|
|
|
::GetFlavorData(inDragRef, inItemRef, 'TEXT', theData, &theDataSize, nil);
|
|
theData[theDataSize] = 0;
|
|
|
|
request = NET_CreateURLStruct(theData, NET_DONT_RELOAD);
|
|
// assert(request != nil);
|
|
|
|
::DisposePtr(theData);
|
|
}
|
|
|
|
anError = ::GetFlavorFlags(inDragRef, inItemRef, flavorTypeHFS, &theFlags);
|
|
if (anError == noErr)
|
|
{
|
|
long theDataSize = 0;
|
|
HFSFlavor theData;
|
|
char* localURL;
|
|
|
|
::GetFlavorDataSize(inDragRef, inItemRef, flavorTypeHFS, &theDataSize);
|
|
::GetFlavorData(inDragRef, inItemRef, flavorTypeHFS, &theData, &theDataSize, nil);
|
|
localURL = CFileMgr::GetURLFromFileSpec(theData.fileSpec);
|
|
// assert(localURL != nil);
|
|
|
|
request = NET_CreateURLStruct(localURL, NET_DONT_RELOAD);
|
|
// assert(request != nil);
|
|
|
|
XP_FREE(localURL);
|
|
}
|
|
|
|
if (request != nil)
|
|
{
|
|
XP_MEMSET(&request->savedData, 0, sizeof(SHIST_SavedData));
|
|
CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext, request, FO_CACHE_AND_PRESENT, false);
|
|
}
|
|
}
|
|
*/
|
|
|
|
/*
|
|
* CBrowserViewDoDragReceiveMochaCallback
|
|
* callback for DoDragReceive
|
|
*/
|
|
class CBrowserViewDoDragReceiveMochaCallback : public CMochaEventCallback
|
|
{
|
|
public:
|
|
CBrowserViewDoDragReceiveMochaCallback( CBrowserView * view, XP_List* inRequestList, char** inURLArray)
|
|
: fBrowserView(view), fRequestList(inRequestList), fURLArray(inURLArray) {}
|
|
|
|
virtual void Complete(MWContext *,
|
|
LO_Element * , int32 /*type*/, ETEventStatus status)
|
|
{
|
|
if (status == EVENT_OK)
|
|
{
|
|
fBrowserView->DoDragReceiveCallback(fRequestList );
|
|
}
|
|
else if (status == EVENT_PANIC || status == EVENT_CANCEL)
|
|
{
|
|
// free the URL_Structs we created in DoDragReceive since they weren't dispatched.
|
|
for (int i = 1; i <= XP_ListCount(fRequestList); i++)
|
|
{
|
|
URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(fRequestList, i);
|
|
NET_FreeURLStruct(request);
|
|
}
|
|
}
|
|
XP_ListDestroy(fRequestList);
|
|
XP_FREE(fURLArray);
|
|
}
|
|
|
|
int LengthURLArray() { return XP_ListCount(fRequestList); }
|
|
|
|
char** GetURLArray() { return fURLArray; }
|
|
|
|
private:
|
|
CBrowserView * fBrowserView;
|
|
XP_List* fRequestList;
|
|
char** fURLArray;
|
|
};
|
|
|
|
// This is handled through a callback from javascript now.
|
|
// Creates a list of the URL_Structs to process in the callback because the DragReference
|
|
// will no longer be valid.
|
|
void
|
|
CBrowserView::DoDragReceive(DragReference inDragRef)
|
|
{
|
|
// This gets freed in the callback.
|
|
XP_List* requestList = XP_ListNew();
|
|
if ( !requestList ) return;
|
|
|
|
FlavorFlags theFlags;
|
|
OSErr anError = noErr;
|
|
URL_Struct* request = nil;
|
|
|
|
Uint16 itemCount; // Number of Items in Drag
|
|
::CountDragItems(inDragRef, &itemCount);
|
|
|
|
for (Uint16 item = 1; item <= itemCount; item++)
|
|
{
|
|
ItemReference itemRef;
|
|
::GetDragItemReferenceNumber(inDragRef, item, &itemRef);
|
|
|
|
// First check if this has a TEXT flavor. If so, this is either a URL dragged from
|
|
// another app or a text clipping dragged from the desktop. Either way, we need
|
|
// to guarantee that we don't try below to read the drop as an HFSFlavor
|
|
// (which a clipping also has).
|
|
anError = ::GetFlavorFlags(inDragRef, itemRef, 'TEXT', &theFlags);
|
|
if (anError == noErr)
|
|
{
|
|
long theDataSize = 0;
|
|
char* theData = nil;
|
|
|
|
::GetFlavorDataSize(inDragRef, itemRef, 'TEXT', &theDataSize);
|
|
if (theDataSize > 255) // ¥¥¥Êare there any limits to the URL string length?
|
|
theDataSize = 255;
|
|
|
|
theData = (char*) ::NewPtr(theDataSize+1);
|
|
// assert(theData != nil);
|
|
|
|
if (theData != NULL)
|
|
{
|
|
::GetFlavorData(inDragRef, itemRef, 'TEXT', theData, &theDataSize, nil);
|
|
theData[theDataSize] = 0;
|
|
|
|
request = NET_CreateURLStruct(theData, NET_DONT_RELOAD);
|
|
if (request != NULL) XP_ListAddObjectToEnd(requestList, request);
|
|
// assert(request != nil);
|
|
|
|
::DisposePtr(theData);
|
|
}
|
|
|
|
} // if has TEXT flavor
|
|
else
|
|
{
|
|
// if this item was not a clipping or dragged text, then process it as an HTML
|
|
// file
|
|
long theDataSize = 0;
|
|
HFSFlavor theData;
|
|
char* localURL;
|
|
Boolean ignore1, ignore2;
|
|
|
|
::GetFlavorDataSize(inDragRef, itemRef, flavorTypeHFS, &theDataSize);
|
|
anError = ::GetFlavorData(inDragRef, itemRef, flavorTypeHFS, &theData, &theDataSize, nil);
|
|
if (anError == badDragFlavorErr)
|
|
anError = GetHFSFlavorFromPromise (inDragRef, itemRef, &theData, true);
|
|
|
|
if (anError == noErr)
|
|
{
|
|
if (HasFTPUpload(GetContext()))
|
|
{
|
|
History_entry * he = GetContext()->GetCurrentHistoryEntry();
|
|
|
|
if (!request)
|
|
{
|
|
request = NET_CreateURLStruct(he->address, NET_SUPER_RELOAD);
|
|
request->method = URL_POST_METHOD;
|
|
}
|
|
|
|
QueueFTPUpload(theData.fileSpec, request);
|
|
}
|
|
else
|
|
{
|
|
// if there's an error resolving the alias, the local file url will refer to the alias itself.
|
|
::ResolveAliasFile(&theData.fileSpec, true, &ignore1, &ignore2);
|
|
localURL = CFileMgr::GetURLFromFileSpec(theData.fileSpec);
|
|
// assert(localURL != nil);
|
|
|
|
if (localURL != NULL)
|
|
{
|
|
request = NET_CreateURLStruct(localURL, NET_DONT_RELOAD);
|
|
if (request != NULL) XP_ListAddObjectToEnd(requestList, request);
|
|
// assert(request != nil);
|
|
|
|
XP_FREE(localURL);
|
|
}
|
|
}
|
|
|
|
} // if we are sure this is a file.
|
|
|
|
} // if not a clipping or text
|
|
|
|
} // for each drag item
|
|
|
|
// After all that, do we have any files to post?
|
|
if (HasFTPUpload(GetContext()) && request->files_to_post)
|
|
XP_ListAddObjectToEnd(requestList, request);
|
|
|
|
if (requestList != NULL)
|
|
{
|
|
int numItems = XP_ListCount(requestList);
|
|
int size = sizeof(char*) * (numItems + 1);
|
|
char ** urlArray = (char**)XP_ALLOC(size);
|
|
XP_ASSERT(urlArray);
|
|
|
|
int i;
|
|
for (i = 0; i < numItems; i++)
|
|
{
|
|
// the URL_Struct already has the url allocated so use that.
|
|
URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(requestList, i+1); // XP_Lists are 1-indexed
|
|
urlArray[i] = request->address;
|
|
}
|
|
urlArray[i] = 0;
|
|
|
|
Point dragMouse;
|
|
short dragModifiers;
|
|
|
|
::GetDragMouse(inDragRef, &dragMouse, NULL);
|
|
::GetDragModifiers(inDragRef, &dragModifiers, NULL, NULL);
|
|
MochaDragDrop(*mContext,
|
|
new CBrowserViewDoDragReceiveMochaCallback(this, requestList, urlArray),
|
|
dragMouse,
|
|
dragModifiers);
|
|
|
|
} // if requestList has things to process
|
|
|
|
} // CBrowserView :: DoDragReceive
|
|
|
|
|
|
// Dispatch the urls collected in DoDragReceive.
|
|
// This is executed if javascript lets us have the event.
|
|
void
|
|
CBrowserView::DoDragReceiveCallback(XP_List* inRequestList)
|
|
{
|
|
for (int i = 1; i <= XP_ListCount(inRequestList); i++)
|
|
{
|
|
URL_Struct* request = (URL_Struct *)XP_ListGetObjectNum(inRequestList, i);
|
|
if (request != nil)
|
|
{
|
|
XP_MEMSET(&request->savedData, 0, sizeof(SHIST_SavedData));
|
|
//CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext->GetTopContext(mContext),
|
|
//request, FO_CACHE_AND_PRESENT, false);
|
|
|
|
// We need this to be delayed so that we can confirm ftp drag & drop since we can't confirm
|
|
//inside the drag handler
|
|
// CURLDispatcher::GetURLDispatcher()->DispatchToView(mContext->GetTopContext(mContext),
|
|
//request, FO_CACHE_AND_PRESENT, false, 1010, true);
|
|
CURLDispatcher::DispatchURL(request, mContext->GetTopContext(), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mocha allows drag receive to be cancelled, so send a dragdrop message.
|
|
void
|
|
MochaDragDrop(MWContext* inContext, CBrowserViewDoDragReceiveMochaCallback * cb, Point inDragMouse, short inDragModifiers)
|
|
{
|
|
JSEvent* event = XP_NEW_ZAP(JSEvent);
|
|
|
|
if (event != NULL)
|
|
{
|
|
// event's data field is an array of urls.
|
|
|
|
event->type = EVENT_DRAGDROP;
|
|
event->data = (void *)cb->GetURLArray();
|
|
event->dataSize = cb->LengthURLArray();
|
|
event->screenx = inDragMouse.h;
|
|
event->screeny = inDragMouse.v - ::GetMBarHeight();
|
|
event->modifiers = CMochaHacks::MochaModifiers(inDragModifiers);
|
|
ET_SendEvent( inContext, 0, event, CMochaEventCallback::MochaCallback, cb );
|
|
}
|
|
}
|
|
|
|
|
|
// True if we might be able to do FTP upload.
|
|
Boolean HasFTPUpload(CBrowserContext * context)
|
|
{
|
|
History_entry * he = context->GetCurrentHistoryEntry();
|
|
return (he &&
|
|
!strncasecomp(he->address, "ftp", 3) &&
|
|
he->address[strlen(he->address)-1] == '/' );
|
|
}
|
|
|
|
|
|
// Adds file for FTP file upload
|
|
void CBrowserView::QueueFTPUpload(const FSSpec & spec, URL_Struct* request)
|
|
{
|
|
FSSpec theResolvedSpec = spec;
|
|
Boolean isFolder;
|
|
Boolean wasAliased;
|
|
|
|
// If we drop the whole HD, allow bailout
|
|
if (CmdPeriod())
|
|
return;
|
|
|
|
// If it's an alias to a folder - skip it!
|
|
if (::ResolveAliasFile(&theResolvedSpec, TRUE, &isFolder, &wasAliased) == noErr && isFolder && wasAliased)
|
|
return;
|
|
|
|
// If it is a folder, add it recursively
|
|
if (CFileMgr::IsFolder(spec))
|
|
{
|
|
FSSpec newSpec;
|
|
FInfo dummy;
|
|
Boolean dummy2;
|
|
CFileIter iter((FSSpec&)spec);
|
|
while (iter.Next(newSpec, dummy, dummy2))
|
|
QueueFTPUpload(newSpec, request);
|
|
return;
|
|
}
|
|
|
|
// We want to use the resolved alias spec here so we get the right file name
|
|
char * fileURL = CFileMgr::EncodedPathNameFromFSSpec(theResolvedSpec, TRUE);
|
|
|
|
// Add file argument to the URL struct (queued up as the fLatentRequest
|
|
|
|
// Duplicate the current file list
|
|
int newFilePos = 0;
|
|
char ** newFileList;
|
|
if (request->files_to_post)
|
|
while (request->files_to_post[newFilePos] != NULL)
|
|
newFilePos++;
|
|
|
|
newFileList = (char **) XP_ALLOC((newFilePos+2) * sizeof(char*));
|
|
ThrowIfNil_(newFileList);
|
|
|
|
for (int i = 0; i < newFilePos; i++)
|
|
newFileList[i] = request->files_to_post[i];
|
|
|
|
// Add the new member
|
|
newFileList[newFilePos] = fileURL;
|
|
newFileList[newFilePos + 1] = NULL;
|
|
|
|
if (request->files_to_post)
|
|
XP_FREE(request->files_to_post);
|
|
|
|
request->files_to_post = newFileList;
|
|
|
|
}
|