зеркало из https://github.com/mozilla/gecko-dev.git
1368 строки
44 KiB
C++
1368 строки
44 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) 1996 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
|
||
|
||
|
||
// CMessageView.cp
|
||
|
||
#include "CMessageView.h"
|
||
|
||
#include "CMailNewsContext.h"
|
||
#include "CBrowserContext.h"
|
||
|
||
#include "resgui.h"
|
||
#include "Netscape_Constants.h"
|
||
#include "MailNewsgroupWindow_Defines.h"
|
||
|
||
#include "CNewsSubscriber.h"
|
||
#include "UMessageLibrary.h"
|
||
#include "UMailFolderMenus.h"
|
||
#include "CMailFolderButtonPopup.h"
|
||
#include "CMailProgressWindow.h"
|
||
#include "CHTMLClickRecord.h"
|
||
#include "CHyperScroller.h"
|
||
#include "UOffline.h"
|
||
|
||
#include "msg_srch.h"
|
||
|
||
#include "uprefd.h"
|
||
#include "libi18n.h" // for INTL_CanAutoSelect proto
|
||
#include "secnav.h"
|
||
#include "CMessageAttachmentView.h"
|
||
#include "CApplicationEventAttachment.h"
|
||
#include "macutil.h" // TrySetCursor
|
||
#include "uerrmgr.h" // GetPString prototype
|
||
#include "ufilemgr.h"
|
||
#include "URobustCreateWindow.h"
|
||
#include "CUrlDispatcher.h"
|
||
#include "UDeferredTask.h"
|
||
|
||
#include "shist.h"
|
||
#include "prefapi.h"
|
||
|
||
#include "CURLDispatcher.h"
|
||
// The msglib callbacks
|
||
// The call backs
|
||
extern "C"
|
||
{
|
||
|
||
void MacFe_AttachmentCount(MSG_Pane *messagepane, void* closure,
|
||
int32 numattachments, XP_Bool finishedloading);
|
||
void MacFe_UserWantsToSeeAttachments(MSG_Pane* messagepane, void* closure);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MacFe_AttachmentCount(MSG_Pane *messagepane, void* /*closure*/,
|
||
int32 numattachments, XP_Bool finishedloading)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
MWContext * context = MSG_GetContext( messagepane);
|
||
CMessageView* messageView =dynamic_cast<CMessageView*>( context->fe.newView);
|
||
|
||
if( messageView )
|
||
{
|
||
LWindow* window = LWindow::FetchWindowObject(messageView->GetMacPort());
|
||
|
||
CMessageAttachmentView* attachmentView =
|
||
dynamic_cast<CMessageAttachmentView*>(window->FindPaneByID('MATv'));
|
||
|
||
if( attachmentView )
|
||
{
|
||
#if 0 // code automatically shows attachment pane
|
||
// should be disabled when the attachment button works
|
||
if( numattachments >0 )
|
||
attachmentView->Show();
|
||
#endif
|
||
if( finishedloading || attachmentView->IsVisible() )
|
||
{
|
||
attachmentView->SetMessageAttachmentList(messagepane, numattachments);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void MacFe_UserWantsToSeeAttachments(MSG_Pane* messagepane, void* /*closure*/)
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
MWContext * context = MSG_GetContext( messagepane);
|
||
CMessageView* messageView =dynamic_cast<CMessageView*>( context->fe.newView);
|
||
|
||
if( messageView )
|
||
{
|
||
LWindow* window = LWindow::FetchWindowObject(messageView->GetMacPort());
|
||
|
||
CMessageAttachmentView* attachmentView =
|
||
dynamic_cast<CMessageAttachmentView*>(window->FindPaneByID('MATv'));
|
||
if( attachmentView )
|
||
attachmentView->ToggleVisibility();
|
||
}
|
||
}
|
||
|
||
MSG_MessagePaneCallbacks MsgPaneCallBacks = {
|
||
MacFe_AttachmentCount,
|
||
MacFe_UserWantsToSeeAttachments
|
||
};
|
||
|
||
#pragma mark -
|
||
|
||
//========================================================================================
|
||
class CDeferredMessageViewTask
|
||
//========================================================================================
|
||
: public CDeferredTask
|
||
{
|
||
public:
|
||
CDeferredMessageViewTask(CMessageView* inView);
|
||
protected:
|
||
Boolean AvailableForDeferredTask() const;
|
||
// data
|
||
protected:
|
||
CMessageView* mMessageView;
|
||
UInt32 mEarliestExecuteTime;
|
||
}; // class CDeferredLoadKeyTask
|
||
|
||
// It's expensive to load a message, and if the user is nervously clicking
|
||
// on multiple messages we only want to load the last one.
|
||
#define LOAD_MESSAGE_DELAY 15 // was GetDblTime()
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredMessageViewTask::CDeferredMessageViewTask(CMessageView* inView)
|
||
//----------------------------------------------------------------------------------------
|
||
: mMessageView(inView)
|
||
, mEarliestExecuteTime(::TickCount() + LOAD_MESSAGE_DELAY)
|
||
{
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
Boolean CDeferredMessageViewTask::AvailableForDeferredTask() const
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// Wait till any pending URLs are finished
|
||
CNSContext* context = mMessageView->GetContext();
|
||
if (!context)
|
||
return false;
|
||
if (XP_IsContextBusy((MWContext*)(*context)))
|
||
return false;
|
||
if (CMailProgressWindow::GetModal())
|
||
return false; // wait until other modal tasks are done.
|
||
// Wait for the earliest execute time.
|
||
if (::TickCount() < mEarliestExecuteTime)
|
||
return false;
|
||
return true;
|
||
} // CDeferredMessageViewTask::AvailableForDeferredTask
|
||
|
||
#pragma mark -
|
||
|
||
//========================================================================================
|
||
class CDeferredLoadKeyTask
|
||
//========================================================================================
|
||
: public CDeferredMessageViewTask
|
||
{
|
||
public:
|
||
CDeferredLoadKeyTask(
|
||
CMessageView* inView,
|
||
MSG_FolderInfo* inFolder,
|
||
MessageKey inKey);
|
||
protected:
|
||
virtual ExecuteResult ExecuteSelf();
|
||
// data
|
||
protected:
|
||
MSG_FolderInfo* mFolderToLoadAtIdle;
|
||
MessageKey mMessageToLoadAtIdle;
|
||
}; // class CDeferredLoadKeyTask
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredLoadKeyTask::CDeferredLoadKeyTask(
|
||
CMessageView* inView,
|
||
MSG_FolderInfo* inFolder,
|
||
MessageKey inKey)
|
||
//----------------------------------------------------------------------------------------
|
||
: CDeferredMessageViewTask(inView)
|
||
, mFolderToLoadAtIdle(inFolder)
|
||
, mMessageToLoadAtIdle(inKey)
|
||
{
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredTask::ExecuteResult CDeferredLoadKeyTask::ExecuteSelf()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (!AvailableForDeferredTask())
|
||
return eWaitStayFront;
|
||
mMessageView->ShowMessage(
|
||
CMailNewsContext::GetMailMaster(),
|
||
mFolderToLoadAtIdle,
|
||
mMessageToLoadAtIdle,
|
||
true);
|
||
return eDoneDelete;
|
||
} // CDeferredLoadKeyTask::ExecuteSelf
|
||
|
||
#pragma mark -
|
||
|
||
//========================================================================================
|
||
class CDeferredLoadURLTask
|
||
//========================================================================================
|
||
: public CDeferredMessageViewTask
|
||
{
|
||
public:
|
||
CDeferredLoadURLTask(
|
||
CMessageView* inView,
|
||
const char* inURLToLoadAtIdle);
|
||
virtual ~CDeferredLoadURLTask();
|
||
protected:
|
||
virtual ExecuteResult ExecuteSelf();
|
||
// data
|
||
protected:
|
||
const char* mURLToLoadAtIdle;
|
||
}; // class CDeferredLoadURLTask
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredLoadURLTask::CDeferredLoadURLTask(
|
||
CMessageView* inView,
|
||
const char* inURLToLoadAtIdle)
|
||
//----------------------------------------------------------------------------------------
|
||
: CDeferredMessageViewTask(inView)
|
||
, mURLToLoadAtIdle(XP_STRDUP(inURLToLoadAtIdle))
|
||
{
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredLoadURLTask::~CDeferredLoadURLTask()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
XP_FREEIF((char*)mURLToLoadAtIdle);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
CDeferredTask::ExecuteResult CDeferredLoadURLTask::ExecuteSelf()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
if (!AvailableForDeferredTask())
|
||
return eWaitStayFront;
|
||
mMessageView->ShowURLMessage(mURLToLoadAtIdle, true);
|
||
return eDoneDelete;
|
||
} // CDeferredLoadURLTask::ExecuteSelf
|
||
|
||
#pragma mark -
|
||
|
||
//----------------------------------------------------------------------------
|
||
CMessageView::CMessageView(LStream* inStream)
|
||
// ---------------------------------------------------------------------------
|
||
#ifdef INHERIT_FROM_BROWSERVIEW
|
||
: CBrowserView(inStream)
|
||
#else
|
||
: CHTMLView(inStream)
|
||
#endif
|
||
, mMessagePane(nil)
|
||
, mMasterCommander(nil)
|
||
, mClosing(false)
|
||
, mAttachmentView(nil)
|
||
, mLoadingNakedURL(false)
|
||
, mMotionPendingCommand((MSG_MotionType)-1)
|
||
, mDeferredCloseTask(nil)
|
||
{
|
||
} // CMessageView::CMessageView
|
||
|
||
// ---------------------------------------------------------------------------
|
||
CMessageView::~CMessageView()
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
mClosing = true;
|
||
|
||
if (mMessagePane)
|
||
{
|
||
MSG_SetMessagePaneCallbacks( mMessagePane, NULL, NULL);
|
||
MSG_DestroyPane(mMessagePane);
|
||
}
|
||
} // CMessageView::~CMessageView
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::FinishCreateSelf()
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Inherited::FinishCreateSelf();
|
||
SetDefaultScrollMode(LO_SCROLL_YES); // always display scrollbars
|
||
SetEraseBackground(FALSE); // don't erase background when browsing mails
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
Boolean CMessageView::IsDueToCloseLater() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
return mDeferredCloseTask != nil;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::SetDueToCloseLater()
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
mDeferredCloseTask = CDeferredCloseTask::DeferredClose(this);
|
||
}
|
||
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ShowMessage(
|
||
MSG_Master* inMsgMaster,
|
||
MSG_FolderInfo* inMsgFolderInfo,
|
||
MessageKey inMessageKey,
|
||
Boolean inLoadNow)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
// There has to be a folder, unless we're clearing the message.
|
||
Assert_(inMsgMaster && (inMsgFolderInfo || inMessageKey == MSG_MESSAGEKEYNONE));
|
||
if (!inLoadNow)
|
||
{
|
||
CDeferredLoadKeyTask* task = new CDeferredLoadKeyTask(this, inMsgFolderInfo, inMessageKey);
|
||
CDeferredTaskManager::Post1(task, this);
|
||
return;
|
||
}
|
||
if (!mMessagePane)
|
||
{
|
||
mMessagePane = ::MSG_CreateMessagePane(*mContext, inMsgMaster);
|
||
ThrowIfNULL_(mMessagePane);
|
||
::MSG_SetFEData(mMessagePane, CMailCallbackManager::Get());
|
||
CMailCallbackListener::SetPane( mMessagePane );
|
||
::MSG_SetMessagePaneCallbacks( mMessagePane, &MsgPaneCallBacks, NULL);
|
||
|
||
}
|
||
if (inMessageKey != GetCurMessageKey())
|
||
{
|
||
if( mAttachmentView )
|
||
{
|
||
mAttachmentView->ClearMessageAttachmentView();
|
||
mAttachmentView->Hide();
|
||
}
|
||
// ::SetCursor(*::GetCursor(watchCursor));
|
||
mLoadingNakedURL = false;
|
||
|
||
if (::MSG_LoadMessage(mMessagePane, inMsgFolderInfo, inMessageKey) != 0)
|
||
{
|
||
CloseLater();
|
||
throw (OSErr)memFullErr;
|
||
}
|
||
if (inMessageKey == MSG_MESSAGEKEYNONE)
|
||
ClearMessageArea(); // please read comments in that routine.
|
||
}
|
||
} // CMessageView::ShowMessage
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ClearMessageArea()
|
||
// MSG_LoadMessage, with MSG_MESSAGEKEYNONE calls msg_ClearMessageArea, which
|
||
// has a bug (drawing the background in grey). So I just changed MSG_LoadMessage() to
|
||
// do nothing for XP_MAC except set its m_Key to MSG_MESSAGEKEYNONE and exit. This transfers
|
||
// the responsibility for clearing the message area to the front end. So far, so good.
|
||
//
|
||
// Now, it's no good just painting the area, because the next refresh will redraw using the
|
||
// existing history entry. So somehow we have to remove the history entry.
|
||
// There's no API for doing this, except calling SHIST_AddDocument with an entry whose
|
||
// address string is null or empty.
|
||
//
|
||
// If this state of affairs changes, this code will break, but I put in asserts to
|
||
// notify us about it. 98/01/21
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if ( XP_IsContextBusy((MWContext*)(*mContext)) ) // #107826
|
||
return;
|
||
LO_DiscardDocument(*mContext); // Necessary cleanup. See also CThreadView::UpdateHistoryEntry().
|
||
// To create a URL_Struct, you have to pass a non-null string for the address, or it returns nil.
|
||
// Next-best thing is an empty string, which works.
|
||
URL_Struct* url = NET_CreateURLStruct("", NET_NORMAL_RELOAD);
|
||
Assert_(url);
|
||
History_entry* newEntry = ::SHIST_CreateHistoryEntry(url, "Nobody Home");
|
||
XP_FREEIF(url);
|
||
Assert_(newEntry);
|
||
// Using an empty address string will cause "AddDocument" to do a removal of the old entry,
|
||
// then delete the new entry, and exit.
|
||
::SHIST_AddDocument(*mContext, newEntry);
|
||
Assert_(!mContext->GetCurrentHistoryEntry()); // Yay! That was the point of all this.
|
||
Refresh();
|
||
// HTMLView will now clear the background on redraw.
|
||
} // CMessageView::ClearMessageArea
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::AdjustCursorSelf(Point inPortPt, const EventRecord& inMacEvent)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (GetCurMessageKey() == MSG_MESSAGEKEYNONE)
|
||
::SetCursor(&qd.arrow);
|
||
else if (mContext && XP_IsContextBusy((MWContext*)(*mContext)))
|
||
::SetCursor(*::GetCursor(watchCursor));
|
||
else
|
||
Inherited::AdjustCursorSelf(inPortPt, inMacEvent);
|
||
} // CMessageView::AdjustCursorSelf
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ShowURLMessage(
|
||
const char* inURL,
|
||
Boolean inLoadNow)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Assert_(inURL);
|
||
if (!inLoadNow)
|
||
{
|
||
CDeferredLoadURLTask* task = new CDeferredLoadURLTask(this, inURL);
|
||
CDeferredTaskManager::Post1(task, this);
|
||
return;
|
||
}
|
||
if (!mMessagePane)
|
||
{
|
||
mMessagePane = MSG_CreateMessagePane(*mContext, CMailNewsContext::GetMailMaster());
|
||
ThrowIfNULL_(mMessagePane);
|
||
MSG_SetFEData(mMessagePane, CMailCallbackManager::Get());
|
||
CMailCallbackListener::SetPane( mMessagePane );
|
||
MSG_SetMessagePaneCallbacks(mMessagePane, &MsgPaneCallBacks, NULL);
|
||
}
|
||
::SetCursor(*::GetCursor(watchCursor));
|
||
SetDefaultCSID(mContext->GetDefaultCSID());
|
||
URL_Struct* urls = NET_CreateURLStruct(inURL, NET_DONT_RELOAD);
|
||
ThrowIfNULL_(urls);
|
||
urls->msg_pane = mMessagePane;
|
||
mContext->SwitchLoadURL(urls, FO_CACHE_AND_PRESENT);
|
||
mLoadingNakedURL = true; // so we can synthesise FE_PaneChanged on AllConnectionsComplete.
|
||
//FE_PaneChanged(GetMessagePane(), false, MSG_PaneNotifyMessageLoaded, 0);
|
||
|
||
} // CMessageView::ShowURLMessage
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ShowSearchMessage(
|
||
MSG_Master *inMsgMaster,
|
||
MSG_ResultElement *inResult,
|
||
Boolean inNoFolder)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Assert_(inMsgMaster);
|
||
if (!mMessagePane)
|
||
{
|
||
mMessagePane = MSG_CreateMessagePane(*mContext, inMsgMaster);
|
||
ThrowIfNULL_(mMessagePane);
|
||
MSG_SetFEData(mMessagePane, CMailCallbackManager::Get());
|
||
}
|
||
mLoadingNakedURL = inNoFolder;
|
||
MSG_SearchError error = MSG_OpenResultElement(inResult, mMessagePane);
|
||
if ( error != SearchError_Success ) {
|
||
if ( (error == SearchError_OutOfMemory) || (error == SearchError_NullPointer) ) {
|
||
FailOSErr_(memFullErr);
|
||
} else {
|
||
FailOSErr_(paramErr);
|
||
}
|
||
}
|
||
} // CMessageView::ShowSearchMessage
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::FileMessageToSelectedPopupFolder(const char *ioFolderName,
|
||
Boolean inMoveMessages)
|
||
// File selected messages to the specified BE folder. If inMoveMessages is true, move
|
||
// the messages, otherwise copy them.
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
#ifdef Debug_Signal
|
||
const char *curName = ::MSG_GetFolderNameFromID(GetFolderInfo());
|
||
Assert_(strcasecomp(curName, ioFolderName) != 0);
|
||
// Specified folder should not be the same as this folder
|
||
#endif // Debug_Signal
|
||
|
||
if ( GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP )
|
||
inMoveMessages = false;
|
||
|
||
MSG_ViewIndex index = GetCurMessageViewIndex();
|
||
if ( inMoveMessages ) {
|
||
::MSG_MoveMessagesInto(GetMessagePane(), &index, 1, ioFolderName);
|
||
} else {
|
||
::MSG_CopyMessagesInto(GetMessagePane(), &index, 1, ioFolderName);
|
||
}
|
||
} // CThreadWindow::FileMessagesToSelectedPopupFolder
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::YieldToMaster()
|
||
// An ugly solution, but after trying many, it's the only one that worked.
|
||
// make sure this view isn't target if there's a thread view in the same window.
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (mMasterCommander)
|
||
SwitchTarget(mMasterCommander);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ClickSelf(const SMouseDownEvent& where)
|
||
// make sure a message view isn't target if there's a thread view.
|
||
// 97/10/21. In Gromit (v5.0), we don't do this any more.
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Inherited::ClickSelf(where);
|
||
// YieldToMaster();
|
||
} // CMessageView::ClickSelf
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::FindCommandStatus(
|
||
CommandT inCommand,
|
||
Boolean& outEnabled,
|
||
Boolean& outUsesMark,
|
||
Char16& outMark,
|
||
Str255 outName)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
outUsesMark = false;
|
||
outEnabled = false;
|
||
if (mClosing) // don't respond to BE callbacks when being destroyed
|
||
return;
|
||
// Need to this up here other wise the HTMLView gets a crack at this command
|
||
if( inCommand == cmd_SecurityInfo )
|
||
{
|
||
if( mMessagePane )
|
||
outEnabled = ( GetCurMessageKey() != MSG_MESSAGEKEYNONE );
|
||
return;
|
||
}
|
||
|
||
if (mMessagePane && mContext)
|
||
{
|
||
if (XP_IsContextBusy((MWContext*)(*mContext)))
|
||
{
|
||
// Disable everything except the "stop" button
|
||
// (and cmd_About: kludge for BUG#68886)
|
||
//
|
||
// It is of course really bad that the recalculation
|
||
// of command status is being short-circuited like this.
|
||
// TODO: Someone should fix this the right way.
|
||
if (inCommand == cmd_Stop)
|
||
{
|
||
outEnabled = true;
|
||
::GetIndString(outName, STOP_STRING_LIST, STOP_LOADING_INDEX );
|
||
}
|
||
else if (inCommand == cmd_About)
|
||
{
|
||
outEnabled = true;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
switch (inCommand)
|
||
{
|
||
// Should always be enabled
|
||
case cmd_SubscribeNewsgroups:
|
||
outEnabled = true;
|
||
return;
|
||
|
||
case cmd_ViewSource:
|
||
case cmd_DocumentInfo:
|
||
if (GetCurMessageKey() == MSG_MESSAGEKEYNONE)
|
||
return;
|
||
break;
|
||
|
||
case cmd_Stop:
|
||
{
|
||
// Note that the context is not busy, but "stop" might mean "stop animations"
|
||
if (mContext->IsContextLooping())
|
||
{
|
||
outEnabled = true;
|
||
::GetIndString(outName, STOP_STRING_LIST, STOP_ANIMATIONS_INDEX );
|
||
}
|
||
return;
|
||
}
|
||
|
||
} // switch
|
||
if (inCommand >= ENCODING_BASE && inCommand < ENCODING_CEILING)
|
||
{
|
||
// yeah, I know, this code isn't pretty, but I copied and
|
||
// pasted this from Akbar (v3.0)
|
||
outEnabled = true;
|
||
outUsesMark = true;
|
||
|
||
Int16 csid = CPrefs::CmdNumToDocCsid( inCommand );
|
||
outMark = (csid == mContext->GetDefaultCSID()) ? checkMark : ' ';
|
||
return;
|
||
}
|
||
if (mLoadingNakedURL)
|
||
{
|
||
// Do NOT allow any message library commands
|
||
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark,
|
||
outMark, outName);
|
||
return;
|
||
}
|
||
if (UMessageLibrary::FindMessageLibraryCommandStatus(
|
||
GetMessagePane(),
|
||
NULL,
|
||
0,
|
||
inCommand,
|
||
outEnabled,
|
||
outUsesMark,
|
||
outMark,
|
||
outName))
|
||
return;
|
||
MSG_MotionType cmd = UMessageLibrary::GetMotionType(inCommand);
|
||
if (UMessageLibrary::IsValidMotion(cmd))
|
||
{
|
||
XP_Bool selectable;
|
||
outEnabled = (
|
||
mMessagePane
|
||
&& MSG_NavigateStatus(mMessagePane, cmd, GetCurMessageViewIndex(), &selectable, NULL) == 0
|
||
&& selectable
|
||
);
|
||
outUsesMark = false;
|
||
return;
|
||
}
|
||
else if ( (inCommand == cmd_MoveMailMessages) || (inCommand == cmd_CopyMailMessages) ||
|
||
CMailFolderSubmenu::IsMailFolderCommand(&inCommand) )
|
||
{
|
||
// Mail folder commands
|
||
outEnabled = true;
|
||
return;
|
||
}
|
||
}
|
||
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark,
|
||
outMark, outName);
|
||
} // CMessageView::FindCommandStatus
|
||
|
||
// ---------------------------------------------------------------------------
|
||
Boolean CMessageView::ObeyMotionCommand(MSG_MotionType cmd)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (!mMessagePane) return false;
|
||
Assert_(UMessageLibrary::IsValidMotion(cmd));
|
||
try
|
||
{
|
||
MSG_ViewIndex resultIndex;
|
||
MessageKey resultKey;
|
||
MSG_FolderInfo* finfo;
|
||
if (MSG_ViewNavigate(
|
||
mMessagePane,
|
||
cmd,
|
||
GetCurMessageViewIndex(),
|
||
&resultKey,
|
||
&resultIndex,
|
||
NULL,
|
||
&finfo) == 0)
|
||
{
|
||
/*ThrowIfError_(MSG_LoadMessage(
|
||
mMessagePane,
|
||
finfo ? finfo : GetFolderInfo(),
|
||
resultKey));*/
|
||
if (resultKey != MSG_MESSAGEKEYNONE)
|
||
{
|
||
ShowMessage(
|
||
CMailNewsContext::GetMailMaster(),
|
||
finfo ? finfo : GetFolderInfo(),
|
||
resultKey);
|
||
}
|
||
else if ( finfo != NULL )
|
||
{
|
||
switch( cmd )
|
||
{
|
||
case MSG_NextFolder:
|
||
case MSG_NextMessage:
|
||
mMotionPendingCommand = MSG_FirstMessage;
|
||
break;
|
||
case MSG_NextUnreadMessage:
|
||
case MSG_NextUnreadThread:
|
||
case MSG_NextUnreadGroup:
|
||
case MSG_LaterMessage:
|
||
case (MSG_MotionType)MSG_ToggleThreadKilled:
|
||
mMotionPendingCommand = MSG_NextUnreadMessage;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
MSG_LoadFolder( mMessagePane, finfo );
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
catch (...)
|
||
{
|
||
SysBeep(1);
|
||
}
|
||
return false;
|
||
|
||
} // CMessageView::ObeyMotionCommand
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
void CMessageView::CloseLater()
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// Oh, I wish:
|
||
//((MWContext*)*mContext)->msgCopyInfo->moveState.nextKeyToLoad = MSG_MESSAGEKEYNONE;
|
||
SetDueToCloseLater(); // delete me next time
|
||
StartIdling();
|
||
} // CMessageView::CloseLater
|
||
|
||
//----------------------------------------------------------------------------------------
|
||
Boolean CMessageView::MaybeCloseLater(CommandT inCommand)
|
||
// This checks that we are a stand-alone message window, then, according to the preference,
|
||
// marks the window for death on the next idle.
|
||
//----------------------------------------------------------------------------------------
|
||
{
|
||
// If we are not a stand-alone pane, don't do this. To detect if we're stand-alone, use
|
||
// mMasterCommander, which will be set to the thread view if we're in a multipane view.
|
||
if (mMasterCommander)
|
||
return false;
|
||
const char* prefName = nil;
|
||
if (inCommand == cmd_Clear)
|
||
prefName = "mail.close_message_window.on_delete";
|
||
else if (inCommand == cmd_MoveMailMessages || inCommand == cmd_CopyMailMessages)
|
||
prefName = "mail.close_message_window.on_file";
|
||
else
|
||
return false;
|
||
XP_Bool closeOption;
|
||
if (PREF_GetBoolPref("mail.close_message_window.on_delete", &closeOption) == PREF_NOERROR
|
||
&& closeOption)
|
||
{
|
||
CloseLater();
|
||
return true;
|
||
}
|
||
return false;
|
||
} // CMessageView::MaybeCloseLater
|
||
|
||
// ---------------------------------------------------------------------------
|
||
Boolean CMessageView::ObeyCommand(CommandT inCommand, void *ioParam)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (!mContext)
|
||
return false;
|
||
if (mClosing) // don't respond to BE callbacks when being destroyed
|
||
return false;
|
||
if (inCommand != cmd_Stop && XP_IsContextBusy((MWContext*)(*mContext)))
|
||
return false;
|
||
|
||
// If you're reading a discussion message, and you want to compose a new message, the new
|
||
// message is, by default, addressed to that discussion group... this test and reassignment
|
||
// are necessary to make this happen
|
||
if ( (inCommand == cmd_NewMailMessage) && (GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) ) {
|
||
inCommand = cmd_PostNew;
|
||
}
|
||
|
||
switch (inCommand)
|
||
{
|
||
case msg_TabSelect:
|
||
return (GetCurMessageKey()); // Allow selection only if a message is loaded.
|
||
case cmd_Stop:
|
||
{
|
||
TrySetCursor(watchCursor);
|
||
XP_InterruptContext(*mContext);
|
||
SetCursor( &qd.arrow );
|
||
return true;
|
||
}
|
||
|
||
// Implement this here instead of browser view since for browser windows we want
|
||
// the benefit of AE recording. The AE sending/receiving code is currenty in
|
||
// CBrowserWindow and we don't want the view to know about the window.
|
||
case cmd_Reload:
|
||
{
|
||
if (GetContext())
|
||
{
|
||
CBrowserContext* theTopContext = GetContext()->GetTopContext();
|
||
|
||
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) ||
|
||
CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey))
|
||
{
|
||
theTopContext->LoadHistoryEntry(CBrowserContext::index_Reload, true);
|
||
}
|
||
else
|
||
{
|
||
theTopContext->LoadHistoryEntry(CBrowserContext::index_Reload);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
break;
|
||
|
||
case cmd_SecurityInfo:
|
||
{
|
||
URL_Struct* url = MSG_ConstructUrlForMessage(GetMessagePane(), GetCurMessageKey());
|
||
SECNAV_SecurityAdvisor((MWContext*)*(GetContext()), url );
|
||
NET_FreeURLStruct(url);
|
||
return true;
|
||
}
|
||
|
||
case cmd_SubscribeNewsgroups:
|
||
{
|
||
MSG_Host* selectedHost = MSG_GetHostForFolder(GetFolderInfo());
|
||
CNewsSubscriber::DoSubscribeNewsGroup(selectedHost);
|
||
return true;
|
||
}
|
||
|
||
|
||
#if 0 // CHTMLView handles this
|
||
case cmd_SAVE_LINK_AS:
|
||
{
|
||
|
||
// Convert cmd_SAVE_LINK_AS to cmd_OPEN_LINK for an attachment link.
|
||
// This is a temporary fix for the issue that "Save link as" will save
|
||
// mime otherwise. A better solution would be to have a different command
|
||
// in the context menu (cmd_SAVE_ATTACHMENT_AS).
|
||
CHTMLClickRecord* cr = mCurrentClickRecord; // for brevity.
|
||
const char* url = cr->GetClickURL();
|
||
if (!strncasecomp (url, "mailbox:", 8))
|
||
{
|
||
if (XP_STRSTR(url, "?part=") || XP_STRSTR(url, "&part="))
|
||
{
|
||
// Yep, mail attachment.
|
||
URL_Struct* theURL = NET_CreateURLStruct( url, NET_DONT_RELOAD);
|
||
ThrowIfNULL_(theURL);
|
||
FSSpec locationSpec;
|
||
memset(&locationSpec, 0, sizeof(locationSpec));
|
||
CURLDispatcher::GetURLDispatcher()->DispatchToStorage(
|
||
theURL, locationSpec, FO_SAVE_AS, true);
|
||
return true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
}
|
||
#endif // 0
|
||
} // switch
|
||
Boolean cmdHandled = false;
|
||
MSG_CommandType cmd = UMessageLibrary::GetMSGCommand(inCommand);
|
||
if (UMessageLibrary::IsValidCommand(cmd))
|
||
{
|
||
// If there is a the thread view (we're not really supposed to know about it, :-) )
|
||
// then give it first crack.
|
||
if (mMasterCommander && mMasterCommander->ObeyCommand(inCommand, ioParam))
|
||
return true;
|
||
Boolean enabled; Boolean usesMark; Char16 mark; CStr255 commandName;
|
||
|
||
if (! UMessageLibrary::FindMessageLibraryCommandStatus(
|
||
GetMessagePane(),
|
||
(MSG_ViewIndex*)nil,
|
||
0,
|
||
inCommand, enabled, usesMark, mark, commandName)
|
||
|| !enabled)
|
||
return false;
|
||
try
|
||
{
|
||
if (cmd == MSG_GetNewMail || cmd == MSG_GetNextChunkMessages)
|
||
{
|
||
if (NET_IsOffline())
|
||
{
|
||
// Bug #105393. This fails unhelpfully if the user is offline. There
|
||
// used to be a test for this here, but for some reason it was
|
||
// removed. This being so, the newly agreed-upon fix is that, if
|
||
// the user requests new messages while offline, we should instead
|
||
// present the "Go Online" dialog. See also CMailFlexTable.cp.
|
||
// - 98/02/10 jrm.
|
||
PREF_SetBoolPref("offline.download_discussions", cmd==MSG_GetNextChunkMessages);
|
||
PREF_SetBoolPref("offline.download_mail", cmd==MSG_GetNewMail);
|
||
UOffline::ObeySynchronizeCommand();
|
||
}
|
||
else
|
||
{
|
||
CMailProgressWindow::ObeyMessageLibraryCommand(
|
||
CMailProgressWindow::res_ID_modeless,
|
||
GetMessagePane(),
|
||
cmd,
|
||
commandName);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MSG_Command(GetMessagePane(), cmd, nil, 0);
|
||
MaybeCloseLater(inCommand);
|
||
}
|
||
}
|
||
catch(...)
|
||
{
|
||
}
|
||
cmdHandled = true;
|
||
}
|
||
if (!cmdHandled)
|
||
{
|
||
MSG_MotionType mcmd = UMessageLibrary::GetMotionType(inCommand);
|
||
if (UMessageLibrary::IsValidMotion(mcmd))
|
||
{
|
||
if (mMasterCommander) // give these to the thread view (for select after delete)
|
||
return mMasterCommander->ObeyCommand(inCommand, ioParam);
|
||
cmdHandled = ObeyMotionCommand(mcmd);
|
||
}
|
||
|
||
}
|
||
if (!cmdHandled)
|
||
{
|
||
// Mail folder commands. We come here either from a button (broadcast) or
|
||
// from a menu command (synthetic).
|
||
const char* folderPath = nil;
|
||
if (inCommand == cmd_MoveMailMessages || inCommand == cmd_CopyMailMessages)
|
||
{
|
||
// Button case
|
||
if ( ioParam )
|
||
folderPath = ::MSG_GetFolderNameFromID((MSG_FolderInfo*)ioParam);
|
||
}
|
||
else if (!CMailFolderSubmenu::IsMailFolderCommand(&inCommand, &folderPath)) // menu case
|
||
{
|
||
folderPath = nil; // any other case.
|
||
}
|
||
if (folderPath && *folderPath)
|
||
{
|
||
if (mMasterCommander) // give these to the thread view (for select after delete)
|
||
return mMasterCommander->ObeyCommand(inCommand, ioParam);
|
||
FileMessageToSelectedPopupFolder(
|
||
folderPath,
|
||
inCommand == cmd_MoveMailMessages);
|
||
MaybeCloseLater(inCommand);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!cmdHandled)
|
||
{
|
||
switch ( inCommand )
|
||
{
|
||
case cmd_SaveDefaultCharset:
|
||
{
|
||
Int32 default_csid = mContext->GetDefaultCSID();
|
||
CPrefs::SetLong(default_csid, CPrefs::DefaultCharSetID);
|
||
cmdHandled = true;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
{
|
||
if ( inCommand > ENCODING_BASE && inCommand < ENCODING_CEILING )
|
||
{
|
||
SetDefaultCSID(CPrefs::CmdNumToDocCsid(inCommand));
|
||
cmdHandled = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (!cmdHandled)
|
||
cmdHandled = Inherited::ObeyCommand(inCommand, ioParam);
|
||
return cmdHandled;
|
||
} // CMessageView::ObeyCommand
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::ListenToMessage(MessageT inMessage, void* ioParam)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
switch(inMessage)
|
||
{
|
||
case msg_NSCAllConnectionsComplete:
|
||
SetCursor(&UQDGlobals::GetQDGlobals()->arrow);
|
||
if (mLoadingNakedURL)
|
||
FE_PaneChanged(GetMessagePane(), false, MSG_PaneNotifyMessageLoaded, 0);
|
||
if( mMotionPendingCommand != (MSG_MotionType)-1 )
|
||
{
|
||
ObeyMotionCommand( mMotionPendingCommand );
|
||
mMotionPendingCommand = (MSG_MotionType)-1;
|
||
}
|
||
// Need to enable the menus since we may just have loaded a new message using imap
|
||
SetUpdateCommandStatus( true );
|
||
break;
|
||
|
||
/*
|
||
case cmd_SecurityInfo:
|
||
case cmd_Reload:
|
||
case cmd_Stop:
|
||
ObeyCommand(inMessage, ioParam);
|
||
return;
|
||
*/
|
||
|
||
default:
|
||
if (!IsOnDuty() || !ObeyCommand(inMessage, ioParam))
|
||
Inherited::ListenToMessage(inMessage, ioParam);
|
||
} // switch
|
||
|
||
CMailCallbackListener::ListenToMessage(inMessage, ioParam);
|
||
} // CMessageView::ListenToMessage
|
||
|
||
// ---------------------------------------------------------------------------
|
||
Boolean CMessageView::HandleKeyPress(const EventRecord& inKeyEvent)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (inKeyEvent.what == keyUp)
|
||
return false;
|
||
Char16 c = inKeyEvent.message & charCodeMask;
|
||
switch (c)
|
||
{
|
||
case char_Backspace:
|
||
case char_FwdDelete:
|
||
ObeyCommand(cmd_Clear, NULL);
|
||
return true;
|
||
|
||
case char_Space:
|
||
CHyperScroller* messageViewScroller = GetScroller();
|
||
Boolean shiftKeyDown = (inKeyEvent.modifiers & shiftKey) != 0;
|
||
|
||
if ( messageViewScroller )
|
||
{
|
||
if ( !shiftKeyDown && messageViewScroller->ScrolledToMaxVerticalExtent() )
|
||
{
|
||
CDeferredCommand* deferredGoCommand = new CDeferredCommand(mMasterCommander, cmd_NextMessage, NULL);
|
||
CDeferredTaskManager::Post1(deferredGoCommand, this);
|
||
return true;
|
||
}
|
||
|
||
if ( shiftKeyDown && messageViewScroller->ScrolledToMinVerticalExtent() )
|
||
{
|
||
CDeferredCommand* deferredGoCommand = new CDeferredCommand(mMasterCommander, cmd_PreviousMessage, NULL);
|
||
CDeferredTaskManager::Post1(deferredGoCommand, this);
|
||
return true;
|
||
}
|
||
}
|
||
// FALL THROUGH
|
||
|
||
default:
|
||
Inherited::HandleKeyPress(inKeyEvent);
|
||
return true;
|
||
} // switch
|
||
return false;
|
||
} // CMessageView::HandleKeyPress
|
||
|
||
// ---------------------------------------------------------------------------
|
||
MessageKey CMessageView::GetCurMessageKey() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
MessageKey result = MSG_MESSAGEKEYNONE;
|
||
if (mMessagePane && !mLoadingNakedURL)
|
||
::MSG_GetCurMessage(mMessagePane, NULL, &result, NULL);
|
||
return result;
|
||
} // CMessageView::GetCurMessageKey
|
||
|
||
// ---------------------------------------------------------------------------
|
||
MSG_FolderInfo* CMessageView::GetFolderInfo() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
MSG_FolderInfo* result = NULL;
|
||
if (mMessagePane)
|
||
::MSG_GetCurMessage(mMessagePane, &result, NULL, NULL);
|
||
return result;
|
||
} // CMessageView::GetFolderInfo
|
||
|
||
// ---------------------------------------------------------------------------
|
||
MSG_ViewIndex CMessageView::GetCurMessageViewIndex() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
MSG_ViewIndex result;
|
||
::MSG_GetCurMessage(mMessagePane, NULL, NULL, &result);
|
||
return result;
|
||
} // CMessageView::GetCurMessageViewIndex
|
||
|
||
// ---------------------------------------------------------------------------
|
||
uint32 CMessageView::GetFolderFlags() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
MSG_FolderInfo* folderInfo = GetFolderInfo();
|
||
if (folderInfo)
|
||
{
|
||
MSG_FolderLine folderLine;
|
||
MSG_GetFolderLineById(CMailNewsContext::GetMailMaster(), folderInfo, &folderLine);
|
||
return folderLine.flags;
|
||
}
|
||
return 0;
|
||
} // CMessageView::GetFolderFlags
|
||
|
||
// ---------------------------------------------------------------------------
|
||
uint32 CMessageView::GetCurMessageFlags() const
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
MessageKey key = GetCurMessageKey();
|
||
if (key != MSG_MESSAGEKEYNONE)
|
||
{
|
||
MSG_MessageLine info;
|
||
::MSG_GetThreadLineById(mMessagePane, key, &info);
|
||
return info.flags;
|
||
}
|
||
return 0;
|
||
} // CMessageView::GetCurMessageFlags
|
||
|
||
enum { MSG_PaneNotifyOKToLoadNewMessage = 999 }; // also in msgmpane.cpp
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::PaneChanged(
|
||
MSG_Pane*,
|
||
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
|
||
int32 value)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
switch (inNotifyCode)
|
||
{
|
||
case MSG_PaneNotifyOKToLoadNewMessage:
|
||
*(XP_Bool*)value = !IsDueToCloseLater();
|
||
return;
|
||
case MSG_PaneNotifyFolderLoaded:
|
||
/*if (mMotionPendingCommand != (MSG_MotionType)-1)
|
||
{
|
||
ObeyMotionCommand( mMotionPendingCommand );
|
||
mMotionPendingCommand = (MSG_MotionType)-1;
|
||
}*/
|
||
break;
|
||
|
||
case MSG_PaneNotifyMessageLoaded:
|
||
if (!mMasterCommander)
|
||
{
|
||
// If we're in a a stand-alone message window, we're responsible for
|
||
// this. Otherwise, the thread view is.
|
||
if (MSG_GetBacktrackState(GetMessagePane()) == MSG_BacktrackIdle)
|
||
{
|
||
MSG_AddBacktrackMessage(
|
||
GetMessagePane(),
|
||
GetFolderInfo(),
|
||
GetCurMessageKey());
|
||
}
|
||
else
|
||
MSG_SetBacktrackState(GetMessagePane(), MSG_BacktrackIdle);
|
||
// Need to enable the menus since we may just have loaded a new message using imap
|
||
SetUpdateCommandStatus(true);
|
||
}
|
||
break;
|
||
case MSG_PaneNotifyFolderDeleted:
|
||
if ((MSG_FolderInfo*)value != GetFolderInfo())
|
||
break;
|
||
// else fall through
|
||
case MSG_PaneNotifyMessageDeleted:
|
||
// As of 98/01/23, this notification is never received.
|
||
LWindow* win = LWindow::FetchWindowObject(GetMacPort());
|
||
if (win)
|
||
win->AttemptClose();
|
||
break;
|
||
case MSG_PaneNotifyCopyFinished:
|
||
// This means that a copy that was run in this messagepane has completed.
|
||
MaybeCloseLater(cmd_MoveMailMessages);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
} // CMessageView::PaneChanged
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::SetContext(CBrowserContext* inNewContext)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (mAttachmentView)
|
||
{
|
||
mAttachmentView->ClearMessageAttachmentView(); // before we destroy the pane!
|
||
mAttachmentView->Hide();
|
||
}
|
||
// If this is a "set to nil" call, then we must call MSG_DestroyPane
|
||
// before calling the inherited method, because MSG_Lib will attempt
|
||
// to call back into the context during destruction....
|
||
if (!inNewContext && mMessagePane)
|
||
{
|
||
// Interrupting the context later after the message pane is destroyed can
|
||
// cause problems.
|
||
// Bug #106218 (crash closing before load finished).
|
||
// Before calling interrupt context, make sure it doesn't call us back. Previously,
|
||
// this next call was after the call to XP_InterruptContext() -- jrm 98/02/13
|
||
::MSG_SetMessagePaneCallbacks(mMessagePane, NULL, NULL);
|
||
if( mContext )
|
||
XP_InterruptContext(*mContext);
|
||
::MSG_DestroyPane(mMessagePane);
|
||
mMessagePane = nil;
|
||
}
|
||
Inherited::SetContext(inNewContext);
|
||
} // CMessageView::SetContext
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::InstallBackgroundColor()
|
||
// Overridden to use a white background
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
// <20> install the user's default solid background color & pattern
|
||
memset(&mBackgroundColor, 0xFF, sizeof(mBackgroundColor)); // white is default
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::SetBackgroundColor(
|
||
Uint8 /*inRed*/,
|
||
Uint8 /*inGreen*/,
|
||
Uint8 /*inBlue*/)
|
||
// Overridden to use a white background
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
// Do not allow the layout weenies to clobber mail message backgrounds.
|
||
Inherited::SetBackgroundColor(0xFF, 0xFF, 0xFF); // white is default
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
Boolean CMessageView::SetDefaultCSID(Int16 default_csid, Boolean forceRepaginate /* = false */)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
if (mContext && default_csid != mContext->GetDefaultCSID())
|
||
mContext->SetDocCSID(default_csid);
|
||
|
||
Inherited::SetDefaultCSID(default_csid); // <20><><EFBFBD> do we want the repaginate fix??
|
||
return true;
|
||
} // CMessageView::SetDefaultCSID
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::GetDefaultFileNameForSaveAs(URL_Struct* url, CStr31& defaultName)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
// Overridden by CMessageView to use the message subject.
|
||
MSG_MessageLine info;
|
||
MSG_GetThreadLineById(GetMessagePane(), GetCurMessageKey(), &info);
|
||
// remove useless and bad characters.
|
||
char buf[32];
|
||
char* dst = buf;
|
||
char* src = info.subject;
|
||
size_t len = strlen(src);
|
||
char* srcEnd = src + len - 1;
|
||
while (*srcEnd == ']')
|
||
{
|
||
*srcEnd-- = '\0';
|
||
len--;
|
||
}
|
||
while (true)
|
||
{
|
||
char* bracket = strchr(src, '[');
|
||
if (bracket)
|
||
{
|
||
len -= (bracket - src + 1);
|
||
src = bracket + 1;
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
|
||
char* lastPlaceInBuffer = buf+31;
|
||
char c;
|
||
do
|
||
{
|
||
c = *src++;
|
||
// rough stab at removing junk from the subject.
|
||
if (c == ':' || c == '[' || c == ']')
|
||
continue;
|
||
*dst++ = c;
|
||
} while (c && dst < lastPlaceInBuffer );
|
||
defaultName = buf; // CStr31 does the truncation.
|
||
if (defaultName.Length() == 0)
|
||
Inherited::GetDefaultFileNameForSaveAs(url, defaultName);
|
||
} // CMessageView::GetDefaultFileNameForSaveAs
|
||
|
||
|
||
// 97-06-18
|
||
// This method gets called when window changes size.
|
||
// Make sure we call mContext->Repaginate()
|
||
// In mail/news call reload method to NET_NORMAL_RELOAD
|
||
// ** NOTE: **
|
||
// This method goes around CHTMLView::AdaptToSuperFrameSize, so if that code
|
||
// changes, we should make the appropriate changes here also.
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::AdaptToSuperFrameSize(
|
||
// ---------------------------------------------------------------------------
|
||
Int32 inSurrWidthDelta,
|
||
Int32 inSurrHeightDelta,
|
||
Boolean inRefresh)
|
||
{
|
||
LView::AdaptToSuperFrameSize(inSurrWidthDelta, inSurrHeightDelta, inRefresh);
|
||
|
||
if (IsRootHTMLView())
|
||
{
|
||
if ((mContext != NULL) && ((inSurrWidthDelta != 0) || (inSurrHeightDelta != 0)))
|
||
mContext->Repaginate(NET_NORMAL_RELOAD);
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::DispatchURL(
|
||
URL_Struct* inURLStruct,
|
||
CNSContext* inTargetContext,
|
||
Boolean inDelay,
|
||
Boolean inForceCreate,
|
||
FO_Present_Types inOutputFormat)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Inherited::DispatchURL(inURLStruct, inTargetContext, inDelay, inForceCreate, inOutputFormat);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
void CMessageView::DispatchURL(CURLDispatchInfo* inDispatchInfo)
|
||
// ---------------------------------------------------------------------------
|
||
{
|
||
Boolean openBrowserWindow = true;
|
||
const char* urlOfLink = inDispatchInfo->GetURL();
|
||
|
||
char* mimeType = MimeGetURLContentType((MWContext *)(*mContext), urlOfLink);
|
||
|
||
if (mimeType)
|
||
{
|
||
CMimeMapper* mapper = CPrefs::sMimeTypes.FindMimeType( mimeType );
|
||
if (mapper)
|
||
switch (mapper->GetLoadAction()) {
|
||
case CMimeMapper::Save:
|
||
case CMimeMapper::Launch:
|
||
case CMimeMapper::Unknown:
|
||
openBrowserWindow = false;
|
||
break;
|
||
}
|
||
if (!XP_STRCMP( mimeType, MULTIPART_APPLEDOUBLE ))
|
||
openBrowserWindow = false;
|
||
|
||
XP_FREE(mimeType);
|
||
}
|
||
|
||
if (!openBrowserWindow) {
|
||
// Decide where to put the file...
|
||
CStr31 fileName;
|
||
OSErr err;
|
||
FSSpec parentFolder;
|
||
FSSpec destSpec;
|
||
|
||
fe_FileNameFromContext(*mContext, urlOfLink, fileName);
|
||
parentFolder = CPrefs::GetFilePrototype( CPrefs::DownloadFolder );
|
||
err = CFileMgr::UniqueFileSpec( parentFolder, fileName, destSpec );
|
||
ThrowIfError_(err);
|
||
|
||
|
||
|
||
inDispatchInfo->SetFileSpec(destSpec);
|
||
CBrowserContext* theContext = nil;
|
||
CDownloadProgressWindow* theProgressWindow = nil;
|
||
try
|
||
{
|
||
theContext = new CBrowserContext(MWContextSaveToDisk);
|
||
ThrowIfNULL_(theContext);
|
||
theProgressWindow = dynamic_cast<CDownloadProgressWindow*>(
|
||
URobustCreateWindow::CreateWindow(WIND_DownloadProgress, LCommander::GetTopCommander()));
|
||
ThrowIfNULL_(theProgressWindow);
|
||
|
||
theProgressWindow->SetWindowContext(theContext);
|
||
|
||
theProgressWindow->Show();
|
||
theProgressWindow->Select();
|
||
|
||
theContext->ImmediateLoadURL(inDispatchInfo->ReleaseURLStruct(), FO_CACHE_AND_PRESENT);
|
||
}
|
||
catch(...)
|
||
{
|
||
delete theContext;
|
||
delete theProgressWindow;
|
||
}
|
||
} else {
|
||
|
||
// Set target context to nil if we're not dispatching to an internal anchor
|
||
// so that we don't lay out into message view. An internal anchor will START
|
||
// with a '#'. Note that dispatching to a new window from a message view
|
||
// is never wrong. But loading weird stuff into the same message view IS.
|
||
if (!XP_STRCHR(urlOfLink, '#'))
|
||
inDispatchInfo->SetTargetContext(nil); // not an anchor of any kind
|
||
else if (urlOfLink[0] != '#') // If starts with '#', definitely internal - doesn't occur in practice.
|
||
{
|
||
// It's an anchor. But is it internal?
|
||
URL_Struct* urlStructForMessage = MSG_ConstructUrlForMessage(GetMessagePane(), GetCurMessageKey());
|
||
const char* urlForMessage = urlStructForMessage->address;
|
||
if (strstr(urlOfLink, urlForMessage) != urlOfLink)
|
||
{
|
||
// it's not a link to THIS message
|
||
inDispatchInfo->SetTargetContext(nil);
|
||
}
|
||
NET_FreeURLStruct(urlStructForMessage);
|
||
}
|
||
Inherited::DispatchURL(inDispatchInfo);
|
||
}
|
||
} // CMessageView::DispatchURL
|