NORMANDY_DDAY merge...

git-svn-id: svn://10.0.0.236/trunk@4478 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
spider 1998-06-25 05:50:45 +00:00
parent 9039d5a21d
commit d56dcfe52f
286 changed files with 97121 additions and 1604 deletions

View File

@ -0,0 +1,247 @@
/* -*- 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 "rosetta.h"
#include "CABContainerDialogs.h"
#include "ABcom.h"
#ifdef MOZ_NEWADDR
#include "xp_mcom.h"
#include "msgnet.h"
#include "prefapi.h"
#include "dirprefs.h"
#include "CValidEditField.h"
#include "RandomFrontEndCrap.h"
#include "pascalString.h"
#include "CTSMEditField.h"
#include "LGAPushButton.h"
#include "LGACheckbox.h"
#include "LGADialogBox.h"
#include "UmodalDialogs.h"
#include "PP_Messages.h"
#include "macgui.h"
CLDAPPropertyDialogManager::CLDAPPropertyDialogManager( DIR_Server* server, MSG_Pane* inPane )
{
StDialogHandler dialogHandler( eLDAPServerPropertiesDialogResID, NULL );
LGADialogBox* dialog = dynamic_cast<LGADialogBox*>( dialogHandler.GetDialog() ) ;
Assert_( dialog );
Setup( dialog, server );
if( dialog )
{
dialog->Show();
MessageT theMessage = msg_Nothing;
while ( (theMessage != msg_Cancel) && (theMessage != msg_OK) )
{
theMessage = dialogHandler.DoDialog();
switch( theMessage )
{
case cmd_HelpButton: // help button
// ShowHelp(mHelpTopic);
break;
// toggle the port numbers in the port field
case eGarbledBox:
Int32 value = eLDAPStandardPort;
if (mGarbledBox->GetValue())
value = eLDAPGarbledPort;
mPortNumber->SetValue(eLDAPGarbledPort);
break;
case eUpdateButton:
UpdateDirServerToUI ();
// The Net_ReplicationDirectory call requires that this flag be set
DIR_ForceFlag( mServer, DIR_REPLICATION_ENABLED, true );
NET_ReplicateDirectory( NULL, mServer );
break;
case msg_OK:
if( !UpdateDirServerToUI() )
theMessage = msg_Nothing;
break;
default:
break;
}
}
if ( theMessage == msg_OK )
{
// I think I am supposed to go context digging for the pane?
AB_UpdateDIRServerForContainerPane( inPane, mServer );
}
}
}
Boolean CLDAPPropertyDialogManager::UpdateDirServerToUI()
{
// first check to make sure that the two validated edit fields are ok. If not,
// then break out of here and don't accept the OK, forcing the user to
// fix them.
Boolean rtnValue = true;
if ( !MaxHitsValidationFunc(mPortNumber) || !PortNumberValidationFunc(mMaxHits) )
rtnValue = false;
XP_FREEIF(mServer->searchBase);
XP_FREEIF(mServer->serverName);
XP_FREEIF(mServer->description);
CStr255 pBuffer;
mDescription->GetDescriptor(pBuffer);
mServer->description = XP_STRDUP(CStr255( pBuffer ) );
mLdapServer->GetDescriptor(pBuffer);
mServer->serverName = XP_STRDUP(CStr255( pBuffer ));
mSearchRoot->GetDescriptor(pBuffer);
mServer->searchBase = XP_STRDUP(CStr255( pBuffer ));
DIR_ForceFlag( mServer, DIR_REPLICATION_ENABLED, mDownloadCheckBox->GetValue( ) );
mServer->port = mPortNumber->GetValue();
mServer->maxHits = mMaxHits->GetValue();
HG51388
mServer->savePassword = mSavePasswordBox->GetValue()? true: false;
DIR_SetServerFileName(mServer, mServer->serverName);
return rtnValue;
}
void CLDAPPropertyDialogManager::Setup( LGADialogBox* inDialog , DIR_Server *inServer )
{
mServer = inServer;
mDescription = (CTSMEditField *) inDialog->FindPaneByID(eDescriptionEditField);
XP_ASSERT(mDescription);
mLdapServer = (LEditField *) inDialog->FindPaneByID(eLDAPServerEditField);
XP_ASSERT(mLdapServer);
mSearchRoot = (LEditField *) inDialog->FindPaneByID(eSearchRootEditField);
XP_ASSERT(mSearchRoot);
mPortNumber = (CValidEditField *) inDialog->FindPaneByID(ePortNumberEditField);
XP_ASSERT(mPortNumber);
mMaxHits = (CValidEditField *) inDialog->FindPaneByID(eMaxHitsEditField);
XP_ASSERT(mMaxHits);
mGarbledBox = (LGACheckbox *) inDialog->FindPaneByID(eGarbledBox);
XP_ASSERT(mGarbledBox);
mSavePasswordBox = dynamic_cast<LGACheckbox *>(inDialog->FindPaneByID ( eSaveLDAPServerPasswordBox) );
Assert_( mSavePasswordBox );
mDownloadCheckBox = dynamic_cast<LGACheckbox* >( inDialog->FindPaneByID ( eDownloadCheckBox ) );
Assert_( mDownloadCheckBox );
UReanimator::LinkListenerToControls( inDialog, inDialog, eLDAPServerPropertiesDialogResID );
mPortNumber->SetValidationFunction(PortNumberValidationFunc);
mMaxHits->SetValidationFunction(MaxHitsValidationFunc);
mDescription->SetDescriptor(CStr255( mServer->description) );
mLdapServer->SetDescriptor(CStr255 (mServer->serverName ));
mSearchRoot->SetDescriptor(CStr255( mServer->searchBase ));
mDownloadCheckBox->SetValue( DIR_TestFlag( mServer, DIR_REPLICATION_ENABLED ) );
mPortNumber->SetValue(mServer->port);
mMaxHits->SetValue(mServer->maxHits);
HG51389
mSavePasswordBox->SetValue(mServer->savePassword ? 1: 0);
// If the directories are locked, disable everything but cancel so the user can't make any changes. This
// allows them to view the information but not edit it.
XP_Bool serversLocked = PREF_PrefIsLocked("ldap_1.number_of_directories");
if ( serversLocked )
{
inDialog->Disable();
LGAPushButton *canelButton = (LGAPushButton *)(inDialog->FindPaneByID('CnBt') );
XP_ASSERT(canelButton);
canelButton->Enable();
}
}
Boolean CLDAPPropertyDialogManager::PortNumberValidationFunc(CValidEditField *portNumber)
// Makes sure the port number field of the dialog is between 0 and 32767, but sets
// a reasonable default if the field is left blank.
{
Boolean result;
Str255 currentValue;
portNumber->GetDescriptor(currentValue);
if (!currentValue[0])
{
portNumber->SetValue(eLDAPStandardPort);
HG51387
portNumber->SelectAll();
result = false;
}
else
{
result = ConstrainEditField(portNumber, 0, 32767);
}
if (!result)
{
StPrepareForDialog prepare;
::StopAlert(1068, NULL);
}
return result;
}
Boolean CLDAPPropertyDialogManager::MaxHitsValidationFunc(CValidEditField *maxHits)
// Makes sure the max hits field of the dialog is between 1 and 65535.
{
Boolean result;
result = ConstrainEditField(maxHits, 1, 65535);
if (!result)
{
// If it was constrained to 1 then make it 100 instead.
if (1 == maxHits->GetValue() )
{
maxHits->SetValue(100);
maxHits->SelectAll();
}
StPrepareForDialog prepare;
::StopAlert(1069, NULL);
}
return result;
}
#pragma mark --CPABPropertyDialogManager--
CPABPropertyDialogManager::CPABPropertyDialogManager( DIR_Server *inServer, MSG_Pane* inPane )
{
StDialogHandler dialogHandler( ePABPropertyWindowID, NULL );
LGADialogBox* dialog = dynamic_cast<LGADialogBox*>( dialogHandler.GetDialog() ) ;
Assert_( dialog );
LGAEditField* nameField = dynamic_cast<LGAEditField*>( dialog->FindPaneByID( eNamePaneID ) );
nameField->SetDescriptor( CStr255 ( inServer->description ) );
MessageT theMessage = msg_Nothing;
while ( (theMessage != msg_Cancel) && (theMessage != msg_OK) )
{
theMessage = dialogHandler.DoDialog();
}
if ( theMessage == msg_OK )
{
XP_FREEIF( inServer->description );
CStr255 pBuffer;
nameField->GetDescriptor(pBuffer);
inServer->description = XP_STRDUP(CStr255( pBuffer ) );
AB_UpdateDIRServerForContainerPane( inPane, inServer );
}
}
#endif

View File

@ -0,0 +1,95 @@
/* -*- 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.
*/
typedef struct MSG_Pane MSG_Pane;
typedef struct DIR_Server DIR_Server;
class CValidEditField;
class LEditField;
class LGACheckbox;
class LGADialogBox;
class CTSMEditField;
//------------------------------------------------------------------------------
// ¥ CLDAPPropertyDialogManager
//------------------------------------------------------------------------------
class CLDAPPropertyDialogManager
{
public:
CLDAPPropertyDialogManager( DIR_Server* ioServer, MSG_Pane* inPane );
private:
Boolean UpdateDirServerToUI();
void Setup( LGADialogBox* inDialog , DIR_Server *inServer );
public:
// PUBLIC CONSTANTS
enum {
class_ID = 'LDSP',
eLDAPServerPropertiesDialogResID = 12002,
cmd_HelpButton = 3
};
// Port ID's
enum {
eLDAPStandardPort = 389,
eLDAPGarbledPort = 636
};
// Pane ID's for dialog
enum {
eDescriptionEditField = 10,
eLDAPServerEditField,
eSearchRootEditField,
ePortNumberEditField,
eMaxHitsEditField,
eGarbledBox = 20,
eSaveLDAPServerPasswordBox = 21,
eUpdateButton = 22,
eDownloadCheckBox = 23
};
static Boolean MaxHitsValidationFunc(CValidEditField *maxHits) ;
static Boolean PortNumberValidationFunc(CValidEditField *portNumber) ;
private:
const char* mHelpTopic; // help string for NetHelp
DIR_Server* mServer; // the LDAP server
CTSMEditField* mDescription; // Items in dialog
LEditField* mLdapServer;
LEditField* mSearchRoot;
CValidEditField* mPortNumber;
CValidEditField* mMaxHits;
LGACheckbox* mGarbledBox;
LGACheckbox* mSavePasswordBox;
LGACheckbox* mDownloadCheckBox;
};
//------------------------------------------------------------------------------
// ¥ CPABPropertyDialogManager
//------------------------------------------------------------------------------
class CPABPropertyDialogManager
{
enum { eNamePaneID = 'NmEd' };
enum { ePABPropertyWindowID = 8995 };
public:
CPABPropertyDialogManager( DIR_Server *inServer, MSG_Pane* inPane );
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,327 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CAddressBookViews.h
#include "CMailFlexTable.h"
#include "PascalString.h"
#include "abcom.h"
#include "dirprefs.h"
class CSearchEditField;
class LDividedView;
class LGAPushButton;
class CPatternProgressCaption;
// These should be replaced as there is a JS pref
enum { eDontCheckTypedown = 0xFFFFFFFF, eCheckTypedownInterval = 30 /* 1/2 sec */ , eNewTarget = 'NwTg'};
struct SAddressDelayedDragInfo;
#pragma mark CAddressBookPane
//------------------------------------------------------------------------------
// ¥ CAddressBookPane
//------------------------------------------------------------------------------
//
class CAddressBookPane : public CMailFlexTable, public LPeriodical
{
private:
typedef CMailFlexTable Inherited;
public:
enum EColType
{ // Sort column header ids
eTableHeaderBase = 'col0'
, eCol0 = eTableHeaderBase
, eCol1
, eCol2
, eCol3
, eCol4
, eCol5
, eCol6
};
enum
{ // Command sort
cmd_SortAscending = 'Ascd'
, cmd_SortDescending = 'Dscd'
};
enum
{
eInvalidCachedRowIDType = 0x7FFFFFFF
, eNewEntryID = 0x7FFFFFFF
, eInvalidEntryID = 0
};
enum
{ // Icon resource IDs
ics8_Person = 15260
, ics8_List = 15263
};
CAddressBookPane(LStream *inStream);
UInt32 SortTypeFromColumnType(EColType inColType);
AB_CommandType SortCommandFromColumnType(EColType inColType);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam);
virtual void FindCommandStatus(CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark,
Str255 outName);
virtual void DeleteSelection();
virtual AB_ContainerInfo* GetContainer( TableIndexT /* inRow */ ) { return mContainer; }
Boolean CurrentBookIsPersonalBook();
virtual void PaneChanged( MSG_Pane *inPane, MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode, int32 value);
virtual Boolean CellInitiatesDrag(const STableCell &/*inCell*/) const { return true; }
virtual Boolean ItemIsAcceptable( DragReference inDragRef, ItemReference inItemRef );
protected:
virtual void GetCellDisplayData(const STableCell &inCell, ResIDT &ioIcon, CStr255 &ioDisplayString );
virtual void DestroyMessagePane(MSG_Pane* inPane);
virtual void SpendTime(const EventRecord &inMacEvent);
virtual Boolean CellHasDropFlag(const STableCell &/*inCell*/, Boolean &/*outIsExpanded*/) const { return false; }
virtual void DrawCellContents(const STableCell &inCell, const Rect &inLocalRect);
AB_AttribID GetAttribForColumn( TableIndexT col );
virtual ResIDT GetIconID(TableIndexT inRow) const;
void DrawCellText( const STableCell& inCell, const Rect& inLocalRect, AB_AttribID inAttrib );
virtual void OpenRow(TableIndexT inRow);
void SetCellExpansion( const STableCell& inCell, Boolean inExpanded);
virtual Boolean RowCanAcceptDrop(
DragReference inDragRef,
TableIndexT inDropRow);
virtual Boolean RowCanAcceptDropBetweenAbove(
DragReference inDragRef,
TableIndexT inDropRow);
virtual void ReceiveDragItem(
DragReference inDragRef,
DragAttributes inDragAttrs,
ItemReference inItemRef,
Rect& inItemBounds);
protected:
AB_ContainerInfo* mContainer;
AB_CommandType mColumnSortCommand[7];
AB_AttribID mColumnAttribID[7];
// Delayed drag info
SAddressDelayedDragInfo *mDelayedDragInfo;
};
#pragma mark CAddressBookTableView
//------------------------------------------------------------------------------
// ¥ CAddressBookTableView
//------------------------------------------------------------------------------
//
class CAddressBookTableView : public CAddressBookPane
{
private:
typedef CAddressBookPane Inherited;
public:
enum { class_ID = 'AbTb' };
enum { eTableEditField = 'TbEd' };
CAddressBookTableView(LStream *inStream) :
CAddressBookPane(inStream),mIsLDAPSearching ( false ) {
};
virtual ~CAddressBookTableView();
Boolean LoadAddressBook( AB_ContainerInfo* inContainer, MWContext* inContext );
void SetColumnHeaders();
virtual void ChangeSort(const LTableHeader::SortChange *inSortChange);
void UpdateToTypedownText(CStr255 inTypedownText);
void ConferenceCall( );
void SetLDAPSearching( Boolean inIsSearching ) { mIsLDAPSearching = inIsSearching; }
char* GetFullAddress( TableIndexT inRow );
Boolean IsLDAPSearching() const { return mIsLDAPSearching; }
protected:
virtual void ChangeFinished(MSG_Pane *inPane, MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow, SInt32 inRowCount);
virtual void AddRowDataToDrag(TableIndexT inRow, DragReference inDragRef);
virtual void EnableStopButton(Boolean inBusy);
private:
Boolean mIsLDAPSearching;
};
#pragma mark CMailingListTableView
//------------------------------------------------------------------------------
// ¥ CMailingListTableView
//------------------------------------------------------------------------------
//
class CMailingListTableView : public CAddressBookPane
{
private:
typedef CAddressBookPane Inherited;
public:
enum { class_ID = 'AlTb' };
enum { // Broadcast messages
msg_EntriesAddedToList = 'EnAd' // this
, msg_EntriesRemovedFromList ='EnRe'
};
CMailingListTableView(LStream *inStream) :
CAddressBookPane(inStream) {
};
virtual ~CMailingListTableView();
void LoadMailingList( MSG_Pane* inPane );
virtual AB_ContainerInfo* GetContainer( TableIndexT inRow );
protected:
virtual void GetCellDisplayData(const STableCell &inCell, ResIDT& ioIcon, CStr255 &ioDisplayString );
virtual void DestroyMessagePane(MSG_Pane* inPane);
};
#pragma mark CAddressBookContainerView
//------------------------------------------------------------------------------
// ¥ CAddressBookContainerView
//------------------------------------------------------------------------------
//
class CAddressBookContainerView : public CAddressBookPane
{
private:
typedef CAddressBookPane Inherited;
public:
enum { class_ID = 'AcTb' };
// Place holders while I wait for the final art work
enum {
ics8_LDAP = CAddressBookPane::ics8_Person ,
ics8_List = CAddressBookPane::ics8_List ,
ics8_PAB = CAddressBookPane::ics8_Person
};
CAddressBookContainerView(LStream *inStream);
virtual ~CAddressBookContainerView();
void Setup( MWContext* inContext);
virtual AB_ContainerInfo* GetContainer( TableIndexT inRow );
void SetIndexToSelectOnLoad( Int32 index){ mDirectoryRowToLoad = index; }
protected:
virtual Boolean CellHasDropFlag( const STableCell& inCell, Boolean& outIsExpanded) const;
virtual UInt16 GetNestedLevel(TableIndexT inRow) const;
virtual ResIDT GetIconID(TableIndexT inRow) const;
void DrawCellText( const STableCell& inCell, const Rect& inLocalRect );
virtual void DrawCellContents( const STableCell& inCell, const Rect& inLocalRect );
virtual void DrawIconsSelf( const STableCell& inCell, IconTransformType inTransformType, const Rect& inIconRect) const;
private:
MWContext* mContext;
Int32 mDirectoryRowToLoad;
};
#pragma mark CAddressBookController
//------------------------------------------------------------------------------
// ¥ CAddressBookController
//------------------------------------------------------------------------------
//
class CAddressBookController:public LView,
public LListener, public LPeriodical, public LCommander
{
private:
typedef LView Inherited;
public:
enum { class_ID = 'AbCn' };
enum {
paneID_DirServers = 'DRSR' // CDirServersPopupMenu *, this
, paneID_Search = 'SRCH' // MSG_Pane *, search button
, paneID_Stop = 'STOP' // nil, stop button
, paneID_AddressBookTable = 'Tabl' // Address book table
, paneID_TypedownName = 'TYPE' // Typedown name search edit field in window
, paneID_SearchEnclosure = 'SCHE' // Enclosure for search items
, paneID_DividedView = 'A2Vw' // the divided view
, paneID_ContainerView = 'AcTb',
paneID_DirectoryName = 'DiCp' // Directory caption
};
CAddressBookController(LStream* inStream );
~CAddressBookController();
virtual void ReadStatus(LStream *inStatusData);
virtual void WriteStatus(LStream *outStatusData);
CAddressBookTableView* GetAddressBookTable() const { return mAddressBookTable; }
CAddressBookContainerView* GetAddressBookContainerView() const { return mABContainerView; }
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam);
virtual void FindCommandStatus(CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark,
Str255 outName);
protected:
virtual void FinishCreateSelf();
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
virtual void SpendTime(const EventRecord &inMacEvent);
virtual void ActivateSelf() {
StartRepeating();
Inherited::ActivateSelf();
}
virtual void DeactivateSelf() {
StopRepeating();
Inherited::DeactivateSelf();
}
public:
void SelectDirectoryServer( AB_ContainerInfo* inContainer );
void SetContext( MWContext* inContext) { mContext = inContext; }
protected:
void Search();
void StopSearch( );
protected:
MWContext* mContext;
UInt32 mNextTypedownCheckTime;
CSearchEditField* mTypedownName;
LDividedView* mDividedView;
CAddressBookTableView* mAddressBookTable;
CMailNewsContext* mAddressBookContext;
CAddressBookContainerView* mABContainerView;
LGAPushButton* mSearchButton;
LGAPushButton* mStopButton;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,299 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CAddressBookWindows.h
#pragma once
#include "abcom.H"
#ifdef MOZ_NEWADDR
class CComposeAddressTableView;
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "CMailNewsWindow.h"
#include "CMailNewsContext.h"
#include "LGADialogBox.h"
#include "MailNewsCallbacks.h"
class CSearchEditField;
class LBroadcasterEditField;
class CNamePropertiesWindow;
class CListPropertiesWindow;
class CMailingListTableView;
class CAddressBookController;
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
typedef struct DIR_Server DIR_Server;
typedef struct _XP_List XP_List;
typedef UInt32 ABID;
#pragma mark -
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
// Save window status version
static const UInt16 cAddressSaveWindowStatusVersion = 0x0219;
static const UInt16 cNamePropertiesSaveWindowStatusVersion = 0x0202;
static const UInt16 cListPropertiesSaveWindowStatusVersion = 0x0202;
#pragma mark -
extern "C"
{
int MacFe_ShowModelessPropertySheetForAB2( MSG_Pane * pane, MWContext* inContext);
int MacFE_ShowPropertySheetForDir(
DIR_Server* server, MWContext* context, MSG_Pane * srcPane, XP_Bool newDirectory );
}
class CAddressBookWindow;
class CAddressBookManager
{
public:
// Should be called when the application starts up
static void OpenAddressBookManager(void);
// Should be called when the application closes
static void CloseAddressBookManager(void);
static void ImportLDIF(const FSSpec& inSpec);
static CAddressBookWindow* ShowAddressBookWindow(void);
static XP_List *GetDirServerList(void);
static void SetDirServerList(XP_List *inList, Boolean inSavePrefs = true);
static DIR_Server *GetPersonalBook(void);
static void FailAddressError(Int32 inError);
private:
static void RegisterAddressBookClasses(void);
static int DirServerListChanged(const char*, void*)
{
CAddressBookManager::sDirServerListChanged = true;
return 0;
}
// Instance variables
static XP_List *sDirServerList;
static Boolean sDirServerListChanged;
};
class CAddressBookWindow : public CMailNewsWindow
{
private:
typedef CMailNewsWindow Inherited;
public:
enum { class_ID = 'AbWn', pane_ID = class_ID, res_ID = 8900 };
// IDs for panes in associated view, also messages that are broadcast to this object
enum {
paneID_DirServers = 'DRSR' // CDirServersPopupMenu *, this
, paneID_Search = 'SRCH' // MSG_Pane *, search button
, paneID_Stop = 'STOP' // nil, stop button
, paneID_AddressBookTable = 'Tabl' // Address book table
, paneID_TypedownName = 'TYPE' // Typedown name search edit field in window
, paneID_SearchEnclosure = 'SCHE' // Enclosure for search items
, paneID_AddressBookController = 'AbCn'
};
// Stream creator method
CAddressBookWindow(LStream *inStream) :
CMailNewsWindow(inStream, WindowType_Address),
mAddressBookController(nil)
{
SetPaneID(pane_ID);
SetRefreshAllWhenResized(false);
}
virtual ~CAddressBookWindow();
virtual ResIDT GetStatusResID() const { return res_ID; }
static MWContext *GetMailContext();
virtual CNSContext* CreateContext() const;
virtual CMailFlexTable* GetActiveTable();
CAddressBookController* GetAddressBookController() const { return mAddressBookController; }
protected:
// Overriden methods
virtual void FinishCreateSelf();
// Utility methods
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
virtual UInt16 GetValidStatusVersion() const { return cAddressSaveWindowStatusVersion; }
protected:
CAddressBookController *mAddressBookController;
};
class CAddressBookChildWindow : public LGADialogBox
{
private:
typedef LGADialogBox Inherited;
public:
CAddressBookChildWindow(LStream *inStream) :
Inherited (inStream), mMSGPane( NULL )
{
SetRefreshAllWhenResized(false);
}
virtual void UpdateBackendToUI() = 0L;
virtual void UpdateUIToBackend( MSG_Pane* inPane ) = 0L;
protected:
// Overriden methods
virtual void ListenToMessage(MessageT inMessage, void *ioParam = nil);
virtual void UpdateTitle()=0;
// Instance variables
MSG_Pane* mMSGPane;
};
class CListPropertiesWindow : public CAddressBookChildWindow {
private:
typedef CAddressBookChildWindow Inherited;
public:
enum { class_ID = 'LpWn', pane_ID = class_ID, res_ID = 8940 };
// IDs for panes in associated view, also messages that are broadcast to this object
enum {
paneID_Name = 'NAME'
, paneID_Nickname = 'NICK'
, paneID_Description = 'DESC'
, paneID_AddressBookListTable = 'Tabl' // Address book list table
};
CListPropertiesWindow(LStream *inStream);
virtual ~CListPropertiesWindow();
virtual void UpdateBackendToUI();
virtual void UpdateUIToBackend( MSG_Pane* inPane );
protected:
virtual void FinishCreateSelf();
virtual void DrawSelf();
virtual void UpdateTitle();
// Instance variables
CMailingListTableView *mAddressBookListTable;
CSearchEditField *mTitleField;
};
class CMailWindowCallbackListener: public CMailCallbackListener
{
void CMailWindowCallBackListener( LWindow* inWindow )
{
mWindow = inWindow;
}
private:
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
LWindow *mWindow;
};
//------------------------------------------------------------------------------
// ¥ CNamePropertiesWindow
//------------------------------------------------------------------------------
//
class CNamePropertiesWindow : public CAddressBookChildWindow
{
private:
typedef CAddressBookChildWindow Inherited;
public:
enum { class_ID = 'NpWn', pane_ID = class_ID, res_ID = 8930 };
// IDs for panes in associated view, also messages that are broadcast to this object
enum {
paneID_GeneralView = 'GNVW' // General preferences view
, paneID_FirstName = 'FNAM'
, paneID_LastName = 'LNAM'
, paneID_DisplayName = 'DNAM'
, paneID_EMail = 'EMAL'
, paneID_Nickname = 'NICK'
, paneID_Notes = 'NOTE'
, paneID_PrefersHTML = 'HTML'
, paneID_ContactView = 'CNVW' // Contact preferences view
, paneID_Company = 'COMP'
, paneID_Title = 'TITL'
, paneID_Department = 'DPRT'
, paneID_Address = 'ADDR'
, paneID_City = 'CITY'
, paneID_State = 'STAT'
, paneID_ZIP = 'ZIP '
, paneID_Country = 'Coun'
, paneID_WorkPhone = 'WPHO'
, paneID_FaxPhone = 'FPHO'
, paneID_PagerPhone = 'PPHO'
, paneID_HomePhone = 'HPHO'
, paneID_CelluarPhone = 'CPHO'
, paneID_SecurityView = 'SCVW' // Security preferences view
, paneID_CooltalkView = 'CLVW' // Cooltalk preferences view
, paneID_ConferenceAddress = 'CAED'
, paneID_ConferenceServer = 'CnPu'
, paneID_None = 'NONE'
};
enum { // Broadcast messages
paneID_ConferencePopup ='CoPU' // conference pop up button
};
CNamePropertiesWindow(LStream *inStream);
virtual void UpdateBackendToUI();
void UpdateUIToBackend( MSG_Pane *inPane );
void SetConferenceText( );
protected:
virtual void FinishCreateSelf();
virtual void ListenToMessage(MessageT inMessage, void *ioParam = nil);
virtual void UpdateTitle();
private:
int32 GetPaneAndAttribID( TableIndexT index, PaneIDT& outPaneID, AB_AttribID &outAttrib );
PaneIDT FindPaneForAttribute ( AB_AttribID inAttrib );
protected:
CMailWindowCallbackListener mCallBackListener;
LBroadcasterEditField *mFirstNameField;
LBroadcasterEditField *mLastNameField;
};
#endif // NEWADDR

View File

@ -0,0 +1,274 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CAddressPickerWindow.cp
#include "CAddressPickerWindow.h"
// #include "CAddressBookWindows.h"
#ifdef MOZ_NEWADDR
#include "SearchHelpers.h"
#include "CAddressBookViews.h"
#include "xp_Help.h"
#include "UStdDialogs.h"
#include "libi18n.h"
#include "CProgressListener.h"
#include "StBlockingDialogHandler.h"
#include "CKeyStealingAttachment.h"
// Code in the tables depends on recieving key up events hence this class
class StKeyUpDialogHandler : public StBlockingDialogHandler
{
public:
StKeyUpDialogHandler(
ResIDT inDialogResID,
LCommander* inSuper): StBlockingDialogHandler( inDialogResID, inSuper) {};
void EventKeyUp(const EventRecord &inMacEvent)
{
/* if it's a CKeyUpReceiver, send the key up. We used to send keyups to
* targets if a browser view was on duty, which had two disadvantages: it required
* any potential targets in a browser view to handle a key up, and sometimes
* the commander chain would be incorrect so key ups were sent to a target in a
* view that was not on duty.
*/
if (dynamic_cast<CKeyUpReceiver *>(sTarget))
sTarget->ProcessKeyPress(inMacEvent);
}
};
//------------------------------------------------------------------------------
// ¥ DoPickerDialog
//------------------------------------------------------------------------------
// Bring up and runs the picker dialog
//
void CAddressPickerWindow::DoPickerDialog( CComposeAddressTableView* initialTable )
{
StKeyUpDialogHandler handler ( 8990, nil );
CAddressPickerWindow* dialog = dynamic_cast< CAddressPickerWindow* >( handler.GetDialog() );
dialog->Setup( initialTable );
dialog->Show();
MessageT message;
do
{
message = handler.DoDialog();
} while ( message != eOkayButton && message != eCancelButton ) ;
}
//------------------------------------------------------------------------------
// ¥ CAddressPickerWindow
//------------------------------------------------------------------------------
//
CAddressPickerWindow::CAddressPickerWindow(LStream *inStream)
: Inherited( inStream ), CSaveWindowStatus( this ), mInitialTable( nil ), mPickerAddresses(nil),
mAddressBookController(nil), mProgressListener( nil ), mMailNewsContext ( nil ), mLastAction ( eToButton )
{
}
//------------------------------------------------------------------------------
// ¥ ~CAddressPickerWindow
//------------------------------------------------------------------------------
//
CAddressPickerWindow::~CAddressPickerWindow()
{
if (mMailNewsContext)
mMailNewsContext->RemoveUser(this);
delete mProgressListener;
}
//------------------------------------------------------------------------------
// ¥ Setup
//------------------------------------------------------------------------------
// Copies takes in a CComposeAddressTableView and copies its data to the picker bucket
// The passed in table will be updated if necessary when the window is closed
//
void CAddressPickerWindow::Setup( CComposeAddressTableView* initialTable )
{
// Copy the old table to the new one
Assert_( initialTable );
Assert_( mPickerAddresses );
TableIndexT numRows;
mInitialTable = initialTable;
initialTable->GetNumRows(numRows);
STableCell cell;
Uint32 size;
char* address = NULL;
for ( int32 i = 1; i <= numRows; i++ )
{
EAddressType type = initialTable->GetRowAddressType( i );
cell.row = i;
cell.col = 2;
size = sizeof(address);
initialTable->GetCellData(cell, &address, size);
mPickerAddresses->InsertNewRow( type, address, false );
}
}
//------------------------------------------------------------------------------
// ¥ FinishCreateSelf
//------------------------------------------------------------------------------
//
void CAddressPickerWindow::FinishCreateSelf()
{
Inherited::FinishCreateSelf();
mAddressBookController =
dynamic_cast< CAddressBookController* >(FindPaneByID( CAddressBookWindow::paneID_AddressBookController) ) ;
CSaveWindowStatus::FinishCreateWindow();
// Context creation
mMailNewsContext = new CMailNewsContext( MWContextAddressBook);
if (!mProgressListener)
mProgressListener = new CProgressListener(this, mMailNewsContext);
ThrowIfNULL_(mProgressListener);
// The progress listener should be "just a bit" lazy during network activity
mProgressListener->SetLaziness(CProgressListener::lazy_NotAtAll);
mMailNewsContext->AddListener(mProgressListener);
mMailNewsContext->AddUser(this);
mMailNewsContext->SetWinCSID(INTL_DocToWinCharSetID(mMailNewsContext->GetDefaultCSID()));
// Have the AddressBook Controller listen to the context
mMailNewsContext->AddListener(mAddressBookController);
mAddressBookController->SetContext( *mMailNewsContext );
mAddressBookController->GetAddressBookContainerView()->Setup( *mMailNewsContext );
mAddressBookController->GetAddressBookTable()->SetNotifyOnSelectionChange( true );
mAddressBookController->GetAddressBookTable()->StartBroadcasting();
mPickerAddresses = dynamic_cast< CComposeAddressTableView* >( FindPaneByID( 'Addr' ) );
FailNILRes_( mPickerAddresses );
(mAddressBookController->GetAddressBookTable() )->AddListener( this );
UReanimator::LinkListenerToControls(this, this,CAddressPickerWindow:: res_ID);
// Setup KeySnatcher for our fancy default button behavior
CKeyStealingAttachment* keyStealer = new CKeyStealingAttachment(this);
mAddressBookController->GetAddressBookTable()->AddAttachment(keyStealer);
mAddressBookController->GetAddressBookContainerView()->AddAttachment(keyStealer );
keyStealer->StealKey( char_Enter );
keyStealer->StealKey( char_Return );
// Adjust button state
ListenToMessage ( CStandardFlexTable::msg_SelectionChanged, nil );
}
//------------------------------------------------------------------------------
// ¥ ListenToMessage
//------------------------------------------------------------------------------
//
void CAddressPickerWindow::ListenToMessage(MessageT inMessage, void * /* ioParam */ )
{
switch( inMessage )
{
case eOkayButton:
SaveStatusInfo();
CComposeAddressTableStorage* oldTableStorage =dynamic_cast< CComposeAddressTableStorage*> (mInitialTable->GetTableStorage() );
mPickerAddresses->EndEditCell();
mInitialTable->SetTableStorage( mPickerAddresses->GetTableStorage() );
mInitialTable->Refresh();
mPickerAddresses->SetTableStorage( oldTableStorage );
break;
case eHelp:
ShowHelp( HELP_SELECT_ADDRESSES );
break;
case eToButton:
mLastAction = eToButton;
AddSelection ( eToType );
break;
case eCcButton:
mLastAction = eCcButton;
AddSelection ( eCcType );
break;
case eBccButton:
mLastAction = eBccButton;
AddSelection( eBccType );
break;
case ePropertiesButton:
break;
case CStandardFlexTable::msg_SelectionChanged:
Boolean enable = mAddressBookController->GetAddressBookTable()->GetSelectedRowCount() >0;
SetDefaultButton( mLastAction );
USearchHelper::EnableDisablePane( USearchHelper::FindViewControl( this ,eToButton ), enable, true );
USearchHelper::EnableDisablePane( USearchHelper::FindViewControl( this ,eCcButton ), enable, true );
USearchHelper::EnableDisablePane( USearchHelper::FindViewControl( this ,eBccButton ), enable, true );
USearchHelper::EnableDisablePane( USearchHelper::FindViewControl( this ,ePropertiesButton ), enable, true );
break;
default:
break;
}
}
//------------------------------------------------------------------------------
// ¥ AddSelection
//------------------------------------------------------------------------------
// Adds the table selection to the address bucket.
//
//
void CAddressPickerWindow::AddSelection( EAddressType inAddressType )
{
char* address = NULL;
Uint32 size= sizeof(address);
TableIndexT row = 0;
while ( mAddressBookController->GetAddressBookTable()->GetNextSelectedRow( row ) )
{
address = mAddressBookController->GetAddressBookTable()->GetFullAddress( row );
mPickerAddresses->InsertNewRow( inAddressType, address, false );
XP_FREE( address );
}
SetDefaultButton( eOkayButton );
}
//------------------------------------------------------------------------------
// ¥ ReadWindowStatus
//------------------------------------------------------------------------------
// Adjust the window to stored preferences.
//
void CAddressPickerWindow::ReadWindowStatus(LStream *inStatusData)
{
if ( inStatusData != nil )
{
mAddressBookController->ReadStatus( inStatusData );
}
}
//------------------------------------------------------------------------------
// ¥ WriteWindowStatus
//------------------------------------------------------------------------------
// Write window stored preferences.
//
void CAddressPickerWindow::WriteWindowStatus(LStream *outStatusData)
{
mAddressBookController->WriteStatus(outStatusData);
}
#endif //NEWADDR

View File

@ -0,0 +1,81 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CAddressPickerWindow.h
#pragma once
#include "abcom.h"
#ifdef MOZ_NEWADDR
#include "LGADialogBox.h"
#include "CSaveWindowStatus.h"
#include "CComposeAddressTableView.h"
class CAddressBookTableView;
class CAddressBookController;
class CMailNewsContext;
static const UInt16 cAddressPickerWindowStatusVersion = 0x006;
//------------------------------------------------------------------------------
// ¥ CAddressPickerWindow
//------------------------------------------------------------------------------
//
class CAddressPickerWindow : public LGADialogBox, public CSaveWindowStatus
{
public:
static void DoPickerDialog( CComposeAddressTableView* initialTable );
private:
typedef LGADialogBox Inherited;
public:
enum { class_ID = 'ApWn', pane_ID = class_ID, res_ID = 8990 };
// Control IDs
enum EButton {
eOkayButton = 'OkBt',
eCancelButton ='CnBt',
eHelp ='help',
eToButton = 'ToBt',
eCcButton = 'CcBt',
eBccButton = 'BcBt',
ePropertiesButton = 'PrBt'
} ;
CAddressPickerWindow(LStream *inStream);
~CAddressPickerWindow();
void Setup( CComposeAddressTableView* initialTable );
virtual ResIDT GetStatusResID() const { return res_ID; }
protected:
virtual void FinishCreateSelf();
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
void AddSelection( EAddressType inAddressType );
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
virtual UInt16 GetValidStatusVersion() const { return cAddressPickerWindowStatusVersion; }
private:
CComposeAddressTableView* mInitialTable;
CComposeAddressTableView* mPickerAddresses;
CAddressBookController* mAddressBookController;
CMailNewsContext* mMailNewsContext;
CProgressListener* mProgressListener;
EButton mLastAction;
};
#endif

View File

@ -0,0 +1,387 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CLDAPQueryDialog.cp
#include "CLDAPQueryDialog.h"
#include "pascalstring.h"
#include "LGAEditField.h"
#include "prefapi.h"
#include "SearchHelpers.h"
#include "resgui.h"
#include "xp_help.h"
//------------------------------------------------------------------------------
// ¥ CLDAPBasicHandler
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// ¥ Setup
//------------------------------------------------------------------------------
//
void CLDAPBasicHandler::Setup( MSG_Pane *inSearchPane, DIR_Server *inServer, LView *inView )
{
Assert_( inSearchPane != NULL );
Assert_( inServer != NULL );
Assert_(inView != NULL );
mView = inView;
int maxItems = 4;
// Get Basic Search attributes
MSG_SearchError error = MSG_GetBasicLdapSearchAttributes (
inServer, &mSearchAttributes[0], &maxItems);
// Update the captions to reflect their new attributes
for( int32 captionNumber = 0; captionNumber < maxItems; captionNumber++ )
{
LCaption* caption = dynamic_cast< LCaption*>( mView->FindPaneByID (eBasicSearchCaption+ captionNumber ) );
Assert_( caption );
caption->SetDescriptor ( CStr255(mSearchAttributes[ captionNumber ].name ));
}
}
//------------------------------------------------------------------------------
// ¥ GetSearchParameters
//------------------------------------------------------------------------------
// Get the current search parameters. outSearchParams must be able to hold at least
// 4 elements. Strings are output as c-strings.
//
Int32 CLDAPBasicHandler::GetSearchParameters(SearchLevelParamT* levelParam )
{
CStr255 valueString;
MSG_SearchOperator op = (MSG_SearchOperator) opContains;;
int maxItems = 4;
Int32 currentLevel = 0;
for( int32 i = 0; i < maxItems; i++ )
{
LGAEditField* editField = dynamic_cast< LGAEditField*>( mView->FindPaneByID (eBasicSearchTerm+ i ) );
Assert_( editField );
editField->GetDescriptor ( valueString );
if ( valueString.Length() )
{
levelParam[ currentLevel ].val.attribute = MSG_SearchAttribute( mSearchAttributes[ i ].attrib );
XP_STRCPY( levelParam[ currentLevel ].val.u.string, valueString );
levelParam[ currentLevel ].op = op;
levelParam[ currentLevel ].boolOp = true;
currentLevel++;
}
}
return currentLevel;
}
//------------------------------------------------------------------------------
// ¥ SetSearchParameters
//------------------------------------------------------------------------------
// This works by taking the first occurence of an Param whose attribute
// which matches a basic search criteria attribute.
//
void CLDAPBasicHandler::SetSearchParameters ( SearchLevelParamT* levelParam , int32 numLevels )
{
int maxItems = 4;
Int32 currentLevel = 0;
MSG_SearchAttribute attribute;
for( int32 basic = 0; basic < maxItems; basic++ )
{
attribute = MSG_SearchAttribute( mSearchAttributes[ basic ].attrib );
for ( int32 currentLevel = 0; currentLevel<numLevels; currentLevel++ )
{
if ( levelParam[ currentLevel ].val.attribute == attribute )
{
LGAEditField* editField = dynamic_cast< LGAEditField*>( mView->FindPaneByID (eBasicSearchTerm+ basic ) );
Assert_( editField );
editField->SetDescriptor( CStr255( levelParam[ currentLevel ].val.u.string) );
break;
}
}
}
}
//------------------------------------------------------------------------------
// ¥ Setup
//------------------------------------------------------------------------------
// Advanced Search Routines
// Most of the work is done by delagation to the Search Manager
//
void CLDAPAdvancedHandler::Setup( MSG_Pane *inSearchPane, DIR_Server *inServer, LView *inView )
{
Assert_( inSearchPane != NULL );
Assert_( inServer != NULL );
Assert_(inView != NULL );
mSearchFolders.InsertItemsAt(1, LArray::index_First, &inServer);
mSearchManager.InitSearchManager( inView, NULL, scopeLdapDirectory, & mSearchFolders );
}
//------------------------------------------------------------------------------
// ¥ GetSearchParameters
//------------------------------------------------------------------------------
//
Int32 CLDAPAdvancedHandler::GetSearchParameters ( SearchLevelParamT* levelParam )
{
mSearchManager.GetSearchParameters( levelParam );
return mSearchManager.GetNumVisibleLevels();
}
//------------------------------------------------------------------------------
// ¥ SetSearchParameters
//------------------------------------------------------------------------------
//
void CLDAPAdvancedHandler::SetSearchParameters ( SearchLevelParamT* levelParam , int32 numLevels )
{
mSearchManager.SetSearchParameters ( numLevels, levelParam );
}
//------------------------------------------------------------------------------
// ¥ ~CLDAPQueryDialog
//------------------------------------------------------------------------------
//
CLDAPQueryDialog::~CLDAPQueryDialog()
{
if( mMSGPane ) // If the search manager isn't initialized don't save the window data
{
PREF_SetBoolPref("mail.addr_book.useAdvancedSearch", mAdvancedSearch);
CSaveWindowStatus::SaveStatusInfo();
}
}
//------------------------------------------------------------------------------
// ¥ BuildQuery
//------------------------------------------------------------------------------
//
Boolean CLDAPQueryDialog::BuildQuery()
{
// Initial Search setup
Assert_( mMSGPane );
MSG_SearchFree ( mMSGPane );
MSG_SearchAlloc ( mMSGPane );
if( MSG_AddLdapScope( mMSGPane, mDirServer ) != SearchError_Success )
return false;
if( AddParametersToSearch( ) != SearchError_Success)
return false;
return true;
};
//------------------------------------------------------------------------------
// ¥ AddParametersToSearch
//------------------------------------------------------------------------------
//
MSG_SearchError CLDAPQueryDialog::AddParametersToSearch( )
{
Assert_(mMSGPane != nil);
MSG_SearchError error = SearchError_Success;
// Get the search parameters
StSearchDataBlock searchParams( mMaxLevels, StSearchDataBlock::eAllocateStrings);
SearchLevelParamT *curLevel = searchParams.GetData();
int32 numLevels = mHandler[ mAdvancedSearch ]->GetSearchParameters( curLevel );
// Add parameters to the search
for ( Int32 i=0; i< numLevels; i++ )
{
#ifdef FE_IMPLEMENTS_BOOLEAN_OR
error = MSG_AddSearchTerm(mMSGPane, curLevel[i].val.attribute, curLevel[i].op,
&curLevel[i].val, curLevel[i].boolOp, NULL ) ;
#else
error = MSG_AddSearchTerm(mMSGPane, curLevel[i].val.attribute, curLevel[i].op,
&curLevel[i].val) ;
#endif
if ( error != SearchError_Success )
break;
}
return error;
}
//------------------------------------------------------------------------------
// ¥ Setup
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::Setup( MSG_Pane* inPane, DIR_Server* inServer )
{
mMSGPane = inPane;
mDirServer = inServer;
// Set the name of the group box
LView* box = dynamic_cast<LView* >( FindPaneByID('ScBx') );
Assert_( box);
CStr255 name;
box->GetDescriptor( name );
name+= mDirServer->description;
box->SetDescriptor( name );
// Setup the Handlers
mBasicView = dynamic_cast<LView*>( box->FindPaneByID( eBasicEnclosure ) );
Assert_( mBasicView );
mHandler[ eBasic ]->Setup( inPane, inServer, mBasicView );
USearchHelper::LinkListenerToBroadcasters( mBasicView, this );
mAdvancedView = dynamic_cast<LView*>( box->FindPaneByID( eAdvancedEnclosure ) );
Assert_( mAdvancedView );
mHandler[ eAdvanced ]->Setup( inPane, inServer, mAdvancedView );
CLDAPAdvancedHandler* advancedLDAP = dynamic_cast<CLDAPAdvancedHandler*>(mHandler[ eAdvanced ]);
Assert_( advancedLDAP );
mSearchManager = advancedLDAP->GetSearchManager();
mSearchManager->AddListener( this );
XP_Bool isAdvanced = false;
if (PREF_GetBoolPref("mail.addr_book.useAdvancedSearch", &isAdvanced)== PREF_NOERROR )
mAdvancedSearch = isAdvanced;
CSaveWindowStatus::FinishCreateWindow();
mIsModified = false;
ShowHandler();
Show();
}
//------------------------------------------------------------------------------
// ¥ ListenToMessage
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::ListenToMessage(MessageT inMessage, void *ioParam)
{
switch( inMessage )
{
case paneID_Search:
BuildQuery();
break;
case CSearchManager::msg_SearchParametersResized:
ResizeWindowBy( 0, *((Int16 *) ioParam) );
break;
case CSearchEditField::msg_UserChangedText:
mIsModified = true;
break;
case msg_Help:
if ( mAdvancedSearch )
ShowHelp( HELP_SEARCH_LDAP_ADVANCED );
else
ShowHelp( HELP_SEARCH_LDAP_BASIC );
break;
case paneID_Advanced:
case paneID_Basic:
if ( !PREF_PrefIsLocked( "mail.addr_book.useAdvancedSearch") )
mAdvancedSearch = !mAdvancedSearch;
ShowHandler();
break;
};
}
//------------------------------------------------------------------------------
// ¥ FinishCreateSelf
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::FinishCreateSelf()
{
mHandler[ eBasic ] = new CLDAPBasicHandler;
mHandler[ eAdvanced ] = new CLDAPAdvancedHandler;
UReanimator::LinkListenerToControls( this, this, CLDAPQueryDialog::res_ID );
Inherited::FinishCreateSelf();
}
//------------------------------------------------------------------------------
// ¥ ShowHandler
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::ShowHandler()
{
Assert_ ( mSearchManager );
Int32 windowHeight = 130;
if ( mAdvancedSearch )
{
Int16 deltaLevels = 5 - mSearchManager->GetNumVisibleLevels();
windowHeight = 220 - deltaLevels * 23 ;
}
ResizeWindowTo ( 500, windowHeight );
// modify contents, always do when going from advanced to basic
// Only do when going from basic to advanced if there has been a modification
if ( mIsModified || !mAdvancedSearch)
{
StSearchDataBlock searchParams( mMaxLevels, StSearchDataBlock::eAllocateStrings);
SearchLevelParamT *curLevel = searchParams.GetData();
int32 numLevels = mHandler[ !mAdvancedSearch ]->GetSearchParameters( curLevel );
mHandler[ mAdvancedSearch ]->SetSearchParameters( curLevel, numLevels );
mIsModified = false;
}
// Swap the Buttons
USearchHelper::ShowHidePane( FindPaneByID(paneID_Advanced), !mAdvancedSearch);
USearchHelper::ShowHidePane( FindPaneByID( paneID_Basic ), mAdvancedSearch);
// Swap the panes
USearchHelper::ShowHidePane( mBasicView, !mAdvancedSearch);
USearchHelper::ShowHidePane( mAdvancedView, mAdvancedSearch);
}
//------------------------------------------------------------------------------
// ¥ ReadWindowStatus
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::ReadWindowStatus(LStream *inStatusData)
{
CSaveWindowStatus::ReadWindowStatus(inStatusData);
mSearchManager->ReadSavedSearchStatus(inStatusData);
}
//------------------------------------------------------------------------------
// ¥ WriteWindowStatus
//------------------------------------------------------------------------------
//
void CLDAPQueryDialog::WriteWindowStatus(LStream *outStatusData)
{
CSaveWindowStatus::WriteWindowStatus(outStatusData);
if( mAdvancedSearch == 0 )
{
mAdvancedSearch = true;
ShowHandler();
}
mSearchManager->WriteSavedSearchStatus(outStatusData);
}

View File

@ -0,0 +1,128 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CLDAPQueryDialog.h
#pragma once
#include "LGADialogBox.h"
#include "CSearchManager.h"
#include "CSaveWindowStatus.h"
//------------------------------------------------------------------------------
// ¥ CLDAPHandlerInterface
//------------------------------------------------------------------------------
// I am defining a simple interface for getting Search Parameters
// an alternative would have been to subclass CSearchManager
// but that class does a lot more than just building queries
//
class CLDAPHandlerInterface
{
public:
virtual void Setup( MSG_Pane *inSearchPane, DIR_Server *inServer, LView *inView ) = 0;
virtual Int32 GetSearchParameters ( SearchLevelParamT* levelParam ) = 0;
virtual void SetSearchParameters ( SearchLevelParamT* levelParam , int32 numLevels ) = 0;
protected:
LView * mView;
};
//------------------------------------------------------------------------------
// ¥ CLDAPBasicHandler
//------------------------------------------------------------------------------
// Handles building queries from basic search pane
//
class CLDAPBasicHandler: public CLDAPHandlerInterface
{
public:
enum { eBasicSearchTerm = 8965, eBasicSearchCaption = 8961 };
virtual void Setup( MSG_Pane *inSearchPane, DIR_Server *inServer, LView *inView );
virtual Int32 GetSearchParameters ( SearchLevelParamT* levelParam );
virtual void SetSearchParameters ( SearchLevelParamT* levelParam , int32 numLevels );
private:
MSG_SearchMenuItem mSearchAttributes[4]; // The names and attributes of the 4 editfields
};
//------------------------------------------------------------------------------
// ¥ CLDAPAdvancedHandler
//------------------------------------------------------------------------------
// Handles building queries from the advanced pane
//
class CLDAPAdvancedHandler: public CLDAPHandlerInterface
{
public:
virtual void Setup( MSG_Pane *inSearchPane, DIR_Server *inServer, LView *inView ) ;
virtual Int32 GetSearchParameters ( SearchLevelParamT* levelParam ) ;
virtual void SetSearchParameters ( SearchLevelParamT* levelParam , int32 numLevels ) ;
CSearchManager* GetSearchManager() { return &mSearchManager; }
private:
CSearchManager mSearchManager;
LArray mSearchFolders;
};
static const UInt16 cLDAPSaveWindowStatusVersion = 0x0214;
//------------------------------------------------------------------------------
// ¥ CLDAPQueryDialog
//------------------------------------------------------------------------------
// The query building dialog box
// if the user hits okay a query will be build for the given message pane
//
class CLDAPQueryDialog: public LGADialogBox, public CSaveWindowStatus
{
private:
typedef LGADialogBox Inherited;
public:
enum { class_ID = 'LdDb', res_ID = 8980 };
enum { eBasic = 0, eAdvanced = 1 };
enum { eBasicEnclosure = 'BaVw', eAdvancedEnclosure = 'PENC'};
enum { paneID_Search = 'SRCH', paneID_Advanced = 'AdBt', paneID_Basic = 'BaBt'};
CLDAPQueryDialog( LStream* inStream ): LGADialogBox( inStream ), CSaveWindowStatus ( this )
,mMaxLevels(5), mAdvancedSearch( 0 ),mSearchManager( NULL ),
mMSGPane(NULL ), mDirServer(NULL ), mIsModified( false) {};
~CLDAPQueryDialog();
void Setup( MSG_Pane* inPane, DIR_Server* inServer );
Boolean BuildQuery();
protected:
virtual void FinishCreateSelf();
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
// Status window
virtual ResIDT GetStatusResID() const { return res_ID; }
virtual UInt16 GetValidStatusVersion() const { return cLDAPSaveWindowStatusVersion; }
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
private:
void ShowHandler();
MSG_SearchError AddParametersToSearch();
CLDAPHandlerInterface* mHandler[2];
LView* mBasicView;
LView* mAdvancedView;
Int32 mAdvancedSearch;
Boolean mIsModified;
MSG_Pane* mMSGPane;
DIR_Server* mDirServer;
CSearchManager* mSearchManager;
Int32 mMaxLevels;
};

View File

@ -0,0 +1,414 @@
/* -*- 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.
*/
// CNameCompletionPicker.cp
#include "abcom.H"
#ifdef MOZ_NEWADDR
#include "CNameCompletionPicker.h"
#include "UStdDialogs.h"
#include "SearchHelpers.h"
#include "LGAPushButton.h"
LEditField* CNameCompletionPicker::mLastReceivedEditField = nil;
MSG_Pane* CNameCompletionPicker::mLastReceivedPickerPane = nil;
CMailNewsContext* CNameCompletionPicker::mLastReceivedContext = nil;
int CNameCompletionPicker::mLastReceivedNumResults = 0;
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable class [static]
//----------------------------------------------------------------------------
//
CNameCompletionTable::CNameCompletionTable(LStream* inStream )
: CMailFlexTable(inStream)
{
}
CNameCompletionTable::~CNameCompletionTable()
{
SetMessagePane(NULL);
// Do it here so that our DestroyMessagePane() is called.
// If we let the inherited CMailFlexTable do it, it will call
// its own DestroyMessagePane() because ours is already destroyed
// and the PickerPane will be deleted (which is something we
// don't want because it belongs to the CMailAddressEditField).
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::DestroyMessagePane
//----------------------------------------------------------------------------
// Don't delete the MSG_PickerPane: it belongs to the CMailAddressEditField
//
void CNameCompletionTable::DestroyMessagePane(MSG_Pane* /*inPane*/)
{
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::SetColumnHeaders
//----------------------------------------------------------------------------
//
void CNameCompletionTable::SetColumnHeaders()
{
LTableViewHeader* tableHeader = GetTableHeader();
PaneIDT headerPaneID;
// Column #1 = 'Type' is the container type (Address Book / LDAP server).
// Column #2 = 'Col0' is the entry type (User / Mailing list).
// The other columns have configurable headers.
for (short col = 2; col <= tableHeader->CountColumns(); col ++)
{
headerPaneID = tableHeader->GetColumnPaneID(col);
Int32 index = headerPaneID - eTableHeaderBase;
AB_ColumnInfo *info = AB_GetColumnInfoForPane(GetMessagePane(), AB_ColumnID(index));
LCaption* headerPane = dynamic_cast<LCaption*>(GetSuperView()->FindPaneByID(headerPaneID));
if (headerPane) headerPane->SetDescriptor(CStr255(info->displayString));
AB_FreeColumnInfo(info);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::SelectionChanged
//----------------------------------------------------------------------------
//
void CNameCompletionTable::SelectionChanged()
{
Inherited::SelectionChanged();
StartBroadcasting();
// Long story: the CTableKeyAttachment from CStandardFlexTable
// calls StopBroadcasting() on keyDown and StartBroadcasting()
// on keyUp. Problem: we are in a dialog and we never get keyUp's.
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::OpenRow
//----------------------------------------------------------------------------
//
void CNameCompletionTable::OpenRow(TableIndexT inRow)
{
if (IsValidRow(inRow))
{
BroadcastMessage(msg_OK, nil);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::GetCellDisplayData
//----------------------------------------------------------------------------
// Entirely copied from CMailingListTableView
//
void CNameCompletionTable::GetCellDisplayData(const STableCell &inCell, ResIDT& ioIcon, CStr255 &ioDisplayString)
{
ioIcon = 0;
ioDisplayString = "";
// Get the attribute corresponding to the current column
LTableViewHeader* tableHeader = GetTableHeader();
PaneIDT headerPaneID = tableHeader->GetColumnPaneID(inCell.col);
Int32 index = headerPaneID - eTableHeaderBase;
AB_ColumnInfo *info = AB_GetColumnInfoForPane(GetMessagePane(), AB_ColumnID(index));
AB_AttribID attrib = info->attribID;
AB_FreeColumnInfo(info);
// Get the data
uint16 numItems = 1;
AB_AttributeValue* value;
if (AB_GetEntryAttributesForPane(GetMessagePane(), inCell.row-1, &attrib, &value, &numItems) == AB_SUCCESS)
{
if (attrib == AB_attribEntryType)
{
ioIcon = (value->u.entryType == AB_MailingList ? 15263 : 15260);
}
else
{
ioDisplayString = value->u.string ;
}
AB_FreeEntryAttributeValue(value);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable::DrawCellContents
//----------------------------------------------------------------------------
// Mostly copied from CMailingListTableView
//
void CNameCompletionTable::DrawCellContents(const STableCell &inCell, const Rect &inLocalRect)
{
ResIDT iconID = 0;
PaneIDT cellType = GetCellDataType(inCell);
switch (cellType)
{
case 'Type':
AB_ContainerType container = AB_GetEntryContainerType(GetMessagePane(), inCell.row-1);
switch (container)
{
case AB_LDAPContainer: iconID = 15250; break; // remote folder
case AB_MListContainer: iconID = 15258; break; // address book
case AB_PABContainer: iconID = 15258; break; // address book
case AB_UnknownContainer: iconID = 0; break;
}
if (iconID)
DrawIconFamily(iconID, 16, 16, 0, inLocalRect);
break;
// case 'Col0':
// ...
// case 'Col6':
default:
CStr255 displayString;
GetCellDisplayData(inCell, iconID, displayString);
if (iconID)
DrawIconFamily(iconID, 16, 16, kTransformNone, inLocalRect);
else
DrawTextString(displayString, &mTextFontInfo, 0, inLocalRect);
break;
}
}
#pragma mark -
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::DisplayDialog [static]
//----------------------------------------------------------------------------
// Show the name completion dialog
//
int CNameCompletionPicker::DisplayDialog(LEditField* inEditField, MSG_Pane* inPane, CMailNewsContext* inContext, int inNumResults)
{
// put up dialog
mLastReceivedEditField = inEditField;
mLastReceivedPickerPane = inPane;
mLastReceivedContext = inContext;
mLastReceivedNumResults = inNumResults;
RegisterClass_(CNameCompletionPicker);
RegisterClass_(CNameCompletionTable);
StStdDialogHandler handler(CNameCompletionPicker::res_ID, NULL);
CNameCompletionPicker* dlog = (CNameCompletionPicker*)handler.GetDialog();
// run the dialog
MessageT message;
do
{
message = handler.DoDialog();
} while (message != msg_OK && message != msg_Cancel);
// return the result
STableCell aCell(0,0);
if (message == msg_OK)
aCell = dlog->GetActiveTable()->GetFirstSelectedCell();
// explicitly close the dialog to save its status
dlog->DoClose();
return (aCell.row);
}
#pragma mark -
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker class
//----------------------------------------------------------------------------
//
CNameCompletionPicker::CNameCompletionPicker(LStream *inStream)
: CMailNewsWindow(inStream, WindowType_NameCompletion)
{
}
CNameCompletionPicker::~CNameCompletionPicker()
{
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::FinishCreateSelf
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::FinishCreateSelf()
{
// transmit parameters from the Compose window to the list
ReceiveComposeWindowParameters();
mNameCompletionTable = dynamic_cast<CNameCompletionTable *>(USearchHelper::FindViewSubview(this, paneID_NameCompletionTable));
FailNILRes_(mNameCompletionTable);
mNameCompletionTable->ReceiveMessagePane(mPickerPane);
// finish create stuff
Inherited::FinishCreateSelf();
CSaveWindowStatus::FinishCreateWindow();
// prepare list
mNameCompletionTable->SetColumnHeaders();
mNameCompletionTable->SetRowCount();
STableCell cellToSelect(2, 1);
mNameCompletionTable->SelectCell(cellToSelect);
// default button
LGAPushButton * defaultBtn = dynamic_cast<LGAPushButton*>(FindPaneByID(paneID_OkButton));
if (defaultBtn) defaultBtn->SetDefaultButton(true, true);
mNameCompletionTable->AddListener(this);
// show window
this->Show();
this->Select();
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::DoClose
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::DoClose()
{
// Save table data and window position
SaveStatusInfo();
// Close window
Inherited::DoClose();
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::CalcStandardBoundsForScreen
//----------------------------------------------------------------------------
// Zoom in the vertical direction only.
//
void CNameCompletionPicker::CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const
{
LWindow::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
Rect contRect = UWindows::GetWindowContentRect(mMacWindowP);
outStdBounds.left = contRect.left;
outStdBounds.right = contRect.right;
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::ListenToMessage
//----------------------------------------------------------------------------
//
void CNameCompletionPicker::ListenToMessage(MessageT inMessage, void */*ioParam*/)
{
if (inMessage == msg_OK)
{
LControl* keyButton = (LControl*)FindPaneByID(paneID_OkButton);
keyButton->SimulateHotSpotClick(kControlButtonPart);
}
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::HandleKeyPress
//----------------------------------------------------------------------------
// Handle Escape and Cmd-Period (copied from LDialogBox)
//
Boolean CNameCompletionPicker::HandleKeyPress(const EventRecord &inKeyEvent)
{
Boolean keyHandled = false;
PaneIDT keyButtonID = 0;
switch (inKeyEvent.message & charCodeMask)
{
case char_Enter:
case char_Return:
keyButtonID = paneID_OkButton;
break;
case char_Escape:
if ((inKeyEvent.message & keyCodeMask) == vkey_Escape)
keyButtonID = paneID_CancelButton;
break;
default:
if (UKeyFilters::IsCmdPeriod(inKeyEvent))
keyButtonID = paneID_CancelButton;
else
keyHandled = LWindow::HandleKeyPress(inKeyEvent);
break;
}
if (keyButtonID != 0)
{
LControl* keyButton = (LControl*)FindPaneByID(keyButtonID);
keyButton->SimulateHotSpotClick(kControlButtonPart);
keyHandled = true;
}
return keyHandled;
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::ReadWindowStatus
//----------------------------------------------------------------------------
// Put the window next to the edit field and try to restore its last size.
//
void CNameCompletionPicker::ReadWindowStatus(LStream *inStatusData)
{
// get last window size
Rect savedBounds;
if (inStatusData != nil)
*inStatusData >> savedBounds;
else
{
GetPaneGlobalBounds(this, &savedBounds);
savedBounds.right = savedBounds.left + 320; //¥ TODO: remove these hard-coded values
}
// put the window at the right of the caret position in the edit field
TEHandle teH = mEditField->GetMacTEH();
short caretPos = (*teH)->selStart;
Rect actualBounds;
mEditField->CalcPortFrameRect(actualBounds);
mEditField->PortToGlobalPoint(topLeft(actualBounds));
actualBounds.top -= 44; //¥ TODO: remove these hard-coded values
actualBounds.left += (caretPos + 3) * 7; //¥ TODO:
actualBounds.bottom = actualBounds.top + (savedBounds.bottom - savedBounds.top);
actualBounds.right = actualBounds.left + (savedBounds.right - savedBounds.left);
VerifyWindowBounds(this, &actualBounds);
DoSetBounds(actualBounds);
// restore table data
if (inStatusData != nil)
mNameCompletionTable->ReadSavedTableStatus(inStatusData);
}
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker::WriteWindowStatus
//----------------------------------------------------------------------------
// Save window size and table data.
//
void CNameCompletionPicker::WriteWindowStatus(LStream *outStatusData)
{
CSaveWindowStatus::WriteWindowStatus(outStatusData);
mNameCompletionTable->WriteSavedTableStatus(outStatusData);
}
#endif //MOZ_NEWADDR

View File

@ -0,0 +1,135 @@
/* -*- 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.
*/
// CNameCompletionPicker.h
#pragma once
#include "abcom.H"
#ifdef MOZ_NEWADDR
#include "CMailNewsWindow.h"
//¥#include "CAddressBookViews.h"
#include "CMailFlexTable.h"
#include "msgcom.h"
#include "PascalString.h"
//----------------------------------------------------------------------------
// ¥ CNameCompletionTable class
//
//----------------------------------------------------------------------------
//
class CNameCompletionTable : public CMailFlexTable
{
public:
typedef CMailFlexTable Inherited;
enum { class_ID = 'NcVw', pane_ID = 'Tabl' };
enum EColType {
eTableHeaderBase = 'Col0' // Columns are called 'Col0', 'Col1', 'Col2' etc...
}; // but 'Col0' is not used (it used to contain the person/list icon)
public:
CNameCompletionTable(LStream *inStream);
virtual ~CNameCompletionTable();
void SetColumnHeaders();
virtual void DeleteSelection() {};
virtual void SelectionChanged();
virtual void OpenRow(TableIndexT inRow);
virtual void ReceiveMessagePane(MSG_Pane* inMsgPane) {SetMessagePane(inMsgPane);};
virtual void DestroyMessagePane( MSG_Pane* inPane );
protected:
virtual void GetCellDisplayData(const STableCell &inCell, ResIDT &ioIcon, CStr255 &ioDisplayString );
virtual void DrawCellContents(
const STableCell &inCell,
const Rect &inLocalRect);
};
//----------------------------------------------------------------------------
// ¥ CNameCompletionPicker class
//
//----------------------------------------------------------------------------
//
static const UInt16 cNameCompletionSaveWindowStatusVersion = 0x0200;
class CNameCompletionPicker : public CMailNewsWindow
, public LListener
{
public:
typedef CMailNewsWindow Inherited;
enum { class_ID = 'NcWn', pane_ID = class_ID, res_ID = 8970 };
enum {
paneID_OkButton = 'BtOk',
paneID_CancelButton = 'Canc',
paneID_NameCompletionTable = 'Tabl'
};
// Dialog handler
static int DisplayDialog(LEditField* inEditField, MSG_Pane* inPane, CMailNewsContext* inContext, int inNumResults);
// Stream creator method
CNameCompletionPicker(LStream *inStream);
virtual ~CNameCompletionPicker();
virtual ResIDT GetStatusResID() const { return res_ID; }
virtual CNSContext* CreateContext() const { return (CNSContext*)mLastReceivedContext; }
virtual void CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const;
virtual void DoClose();
virtual void ListenToMessage(
MessageT inMessage,
void *ioParam);
protected:
// Overriden methods
virtual void FinishCreateSelf();
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
// Utility methods
virtual CMailFlexTable* GetActiveTable() { return mNameCompletionTable; }
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
virtual UInt16 GetValidStatusVersion() const { return cNameCompletionSaveWindowStatusVersion;}
virtual void ReceiveComposeWindowParameters() {
mEditField = mLastReceivedEditField;
mPickerPane = mLastReceivedPickerPane;
mContext = mLastReceivedContext;
mNumResults = mLastReceivedNumResults;
}
// Instance variables
CNameCompletionTable *mNameCompletionTable;
LEditField* mEditField;
MSG_Pane* mPickerPane;
CMailNewsContext* mContext;
int mNumResults;
private:
static LEditField* mLastReceivedEditField;
static MSG_Pane* mLastReceivedPickerPane;
static CMailNewsContext* mLastReceivedContext;
static int mLastReceivedNumResults;
};
#endif //MOZ_NEWADDR

View File

@ -0,0 +1,151 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// UAddressBookUtilities.cp
#include "UAddressBookUtilities.h"
#ifdef MOZ_NEWADDR
#include "MailNewsgroupWindow_Defines.h"
#include "resgui.h"
#include "CMailFlexTable.h"
#include "UMailSelection.h"
#include "CAddressBookViews.h" // Need for pane ID's that should be fixed
//------------------------------------------------------------------------------
// ¥ GetABCommand
//------------------------------------------------------------------------------
// Convert a powerplant command into a AB_CommandType
//
AB_CommandType UAddressBookUtilites::GetABCommand( CommandT inCommand )
{
switch ( inCommand )
{
case cmd_NewMailMessage:
case cmd_ComposeMailMessage: return AB_NewMessageCmd;
case cmd_ImportAddressBook: return AB_ImportCmd;
case cmd_SaveAs: return AB_SaveCmd;
// case cmd_Close: return AB_CloseCmd;
case cmd_NewAddressBook: return AB_NewAddressBook;
case cmd_NewDirectory: return AB_NewLDAPDirectory;
case cmd_Undo: return AB_UndoCmd;
case cmd_Redo: return AB_RedoCmd;
case UAddressBookUtilites::cmd_DeleteEntry: return AB_DeleteCmd;
// case return AB_LDAPSearchCmd,
case CAddressBookPane::eCol0: return AB_SortByColumnID0;
case CAddressBookPane::eCol1: return AB_SortByColumnID1;
case CAddressBookPane::eCol2: return AB_SortByColumnID2;
case CAddressBookPane::eCol3: return AB_SortByColumnID3;
case CAddressBookPane::eCol4: return AB_SortByColumnID4;
case CAddressBookPane::eCol5: return AB_SortByColumnID5;
case CAddressBookPane::cmd_SortAscending: return AB_SortAscending;
case CAddressBookPane::cmd_SortDescending: return AB_SortDescending;
case cmd_NewAddressCard: return AB_AddUserCmd;
case cmd_NewAddressList: return AB_AddMailingListCmd;
case cmd_EditProperties: return AB_PropertiesCmd;
case cmd_ConferenceCall: return AB_CallCmd;
// case return AB_ImportLdapEntriesCmd
default: return AB_CommandType( invalid_command );
}
}
//------------------------------------------------------------------------------
// ¥ ABCommandStatus
//------------------------------------------------------------------------------
// Determine if a command should be enabled.
//
//
void UAddressBookUtilites::ABCommandStatus(
CMailFlexTable* inTable,
AB_CommandType inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
{
if( inCommand != UAddressBookUtilites::invalid_command )
{
XP_Bool selectable;
MSG_COMMAND_CHECK_STATE checkedState;
const char* display_string = nil;
XP_Bool plural;
// Get table selection
CMailSelection selection;
inTable->GetSelection(selection);
// Check command status
if ( AB_CommandStatusAB2(
inTable->GetMessagePane(),
inCommand,
(MSG_ViewIndex*)selection.GetSelectionList(),
selection.selectionSize,
&selectable,
&checkedState,
&display_string,
&plural)
>= 0)
{
outEnabled = (Boolean)selectable;
outUsesMark = true;
if (checkedState == MSG_Checked)
outMark = checkMark;
else
outMark = 0;
if (display_string && *display_string)
*(CStr255*)outName = display_string;
}
}
}
//------------------------------------------------------------------------------
// ¥ ABCommand
//------------------------------------------------------------------------------
// Execute a menu command
// NOTE: this takes a PowerPlant Command
//
Boolean UAddressBookUtilites::ABCommand( CMailFlexTable* inTable, AB_CommandType inCommand)
{
Assert_( inTable );
Boolean enabled, usesMark;
Char16 mark;
Str255 name;
if ( inCommand == invalid_command )
return AB_INVALID_COMMAND;
// Check to see if the command was enabled for this table
UAddressBookUtilites::ABCommandStatus( inTable, inCommand, enabled, usesMark, mark, name );
if ( !enabled )
return AB_INVALID_COMMAND;
// Get table Selection
CMailSelection selection;
inTable->GetSelection(selection);
// Execute the command
return AB_CommandAB2( inTable->GetMessagePane(), inCommand,
(MSG_ViewIndex*)selection.GetSelectionList(), selection.selectionSize );
}
#endif

View File

@ -0,0 +1,122 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// UAddressBookUtilities.h
#pragma once
#include "MailNewsAddressBook.h"
#include "abcom.h"
#ifdef MOZ_NEWADDR
class CMailFlexTable;
//------------------------------------------------------------------------------
// ¥ UAddressBookUtilites
//------------------------------------------------------------------------------
//
class UAddressBookUtilites
{
public:
enum { // Command IDs
cmd_NewAddressCard = 'NwCd' // New Card
, cmd_NewAddressList = 'NwLs' // New List
, cmd_NewAddressBook = 'NwAb'
, cmd_NewDirectory = 'NwDr'
, cmd_HTMLDomains = 'HtDm' // domains dialog.
, cmd_EditProperties = 'EdPr' // Edit properties for a list or card
, cmd_DeleteEntry = 'DeLe' // Delete list or card
, cmd_ComposeMailMessage = 'Cmps' // Compose a new mail message
, cmd_ConferenceCall = 'CaLL'
, cmd_ViewMyCard = 'vmyC'
, invalid_command = 0xFFFFFFFF
};
static AB_CommandType GetABCommand( CommandT inCommand );
static void ABCommandStatus(
CMailFlexTable* inTable, AB_CommandType inCommand,
Boolean &outEnabled, Boolean &outUsesMark,
Char16 &outMark, Str255 outName
);
static Boolean ABCommand( CMailFlexTable* inTable, AB_CommandType inCommand);
};
// The following stack based classes are designed to help with the memory managment
// of attributes return from the backend for the Continer and Entry attributes
//------------------------------------------------------------------------------
// ¥ StABEntryAttribute
//------------------------------------------------------------------------------
// Handles memory management for ABEntryAttributes
//
class StABEntryAttribute
{
public:
StABEntryAttribute ( MSG_Pane* inPane, MSG_ViewIndex inIndex, AB_AttribID inAttrib)
{
if(AB_GetEntryAttributeForPane ( inPane, inIndex-1, inAttrib , &mValue ) != AB_SUCCESS )
mValue = NULL;
}
StABEntryAttribute()
{
if ( mValue )
AB_FreeEntryAttributeValue ( mValue );
}
char* GetChar() const { return ( mValue ? mValue->u.string : NULL ); }
Int16 GetShort() const { return ( mValue ? mValue->u.shortValue : 0 ) ;}
XP_Bool GetBoolean() const { return ( mValue ? mValue->u.boolValue : false ); }
AB_EntryType GetEntryType() const { return( mValue ? mValue->u.entryType : AB_Person); }
private:
AB_AttributeValue *mValue ;
};
//------------------------------------------------------------------------------
// ¥ StABContainerAttribute
//------------------------------------------------------------------------------
// Handles memory management for ABEContainerAttributes
//
class StABContainerAttribute
{
public:
StABContainerAttribute ( MSG_Pane* inPane, MSG_ViewIndex inIndex, AB_ContainerAttribute inAttrib)
{
if( AB_GetContainerAttributeForPane ( inPane, inIndex-1, inAttrib , &mValue ) != AB_SUCCESS )
mValue = NULL;
}
StABContainerAttribute()
{
if ( mValue )
AB_FreeContainerAttribValue ( mValue );
}
char* GetChar() const {return( mValue ? mValue->u.string : NULL ); }
Int32 GetNumber() const { return( mValue ? mValue->u.number: 0 ) ;}
AB_ContainerInfo* GetContainerInfo() const { return( mValue ? mValue->u.container : NULL ); }
AB_ContainerType GetContainerType() const { return( mValue ? mValue->u.containerType : AB_PABContainer ); }
private:
AB_ContainerAttribValue *mValue ;
};
#endif

View File

@ -0,0 +1,3 @@
total 8
drwxr-xr-x 2 sfraser nuucp 4096 May 18 20:47 CVS
-rw-r--r-- 1 sfraser nuucp 0 May 18 20:48 temp.txt

View File

@ -0,0 +1,111 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CBiffButtonAttachment.cp
#include "CBiffButtonAttachment.h"
#include "LSharable.h"
#include "CButton.h"
#include "CCheckMailContext.h"
#include <LGAIconSuiteControl.h>
void SetIconState(LControl* inControl, ResIDT inID);
//======================================
#pragma mark --------- class CBiffButtonAttachment
//======================================
//-----------------------------------
CBiffButtonAttachment::CBiffButtonAttachment(LStream* inStream)
//-----------------------------------
: LAttachment(inStream)
, mButton(nil)
{
for (int i = MSG_BIFF_NewMail; i <= MSG_BIFF_Unknown; i++)
*inStream >> mResIDList[i];
SetMessage(msg_Nothing); // Don't bother calling me, ever.
LAttachable *host = LAttachable::GetDefaultAttachable();
mButton = dynamic_cast<LControl*>(host);
Assert_(mButton);
if (!mButton) return;
#ifndef MOZ_LITE
CCheckMailContext* theContext = CCheckMailContext::Get();
theContext->AddUser(this);
theContext->AddListener(this);
// Initialize the icon according to the current state!
SetIconState(mButton, mResIDList[theContext->GetState()]);
#endif // MOZ_LITE
} // CBiffButtonAttachment::CBiffButtonAttachment
//-----------------------------------
CBiffButtonAttachment::~CBiffButtonAttachment()
//-----------------------------------
{
#ifndef MOZ_LITE
CCheckMailContext* theContext = CCheckMailContext::Get();
theContext->RemoveListener(this);
theContext->RemoveUser(this);
#endif // MOZ_LITE
} // CBiffButtonAttachment::~CBiffButtonAttachment
//-----------------------------------
void SetIconState(LControl* inControl, ResIDT inID)
// sets the icon id of the control according to this.
//-----------------------------------
{
if (!inID)
return;
CButton* button = dynamic_cast<CButton*>(inControl);
if (button)
{
// CButton case
button->SetGraphicID(inID);
}
else
{
// LGAIconSuiteControl case (may need to support others later...)
LGAIconSuiteControl* lgaButton = dynamic_cast<LGAIconSuiteControl*>(inControl);
if (lgaButton)
lgaButton->SetIconResourceID(inID);
}
inControl->Refresh();
}
//-----------------------------------
void CBiffButtonAttachment::ListenToMessage(MessageT inMessage, void* ioParam)
//-----------------------------------
{
if (inMessage != CCheckMailContext::msg_MailNotificationState)
return;
SetIconState(mButton, mResIDList[*(MSG_BIFF_STATE*)ioParam]);
} // CBiffButtonAttachment::ListenToMessage
//-----------------------------------
void CBiffButtonAttachment::ExecuteSelf(
MessageT /* inMessage */,
void* /* ioParam */)
//-----------------------------------
{
// We have nothing to do, and because we set our message to msg_Nothing, we'll never
// be called. However, I don't want to export this empty method from PP just to satisfy
// the linker.
}

View File

@ -0,0 +1,50 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CBiffButtonAttachment.h
#pragma once
#include "LAttachment.h"
class LControl;
//======================================
class CBiffButtonAttachment : public LAttachment, public LListener
// Just attach this to a control. It will listen for biff broadcasts and
// set the icon id of its host button accordingly. There is no ExecuteSelf method,
// we are only using this attachment so we can add it in Constructor, and it
// will figure out which button it is attached to.
//======================================
{
public:
enum { class_ID = 'BfAt' };
CBiffButtonAttachment(LStream* inStream);
virtual ~CBiffButtonAttachment();
virtual void ListenToMessage(MessageT inMeesage, void* ioParam);
protected:
virtual void ExecuteSelf(
MessageT inMessage,
void *ioParam);
protected:
LControl* mButton;
ResIDT mResIDList[3]; // indexed by MSG_BIFF_STATE
}; // class CBiffButtonAttachment

View File

@ -0,0 +1,162 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CCaption.cp
#include "CCaption.h"
#include <LStream.h>
#include "PascalString.h"
#include <TextUtils.h>
#include <UGraphicsUtilities.h>
///////////////////////////////////////////////////////////////////
// constants
const short booleanStringResID = 901; // resource ID of the boolean strings in macfe.r
///////////////////////////////////////////////////////////////////
// CCaption
void CCaption::DrawSelf()
{
Rect frame;
CalcLocalFrameRect(frame);
StColorPenState theColorPenState;
StColorPenState::Normalize ();
StTextState theTextState;
Int16 just = UTextTraits::SetPortTextTraits(mTxtrID);
// ¥ Save off the text color as setup by the TextTrait
RGBColor textColor;
::GetForeColor(&textColor);
ApplyForeAndBackColors();
::RGBForeColor(&textColor);
// the following code adapted from LGARadioButton.cp
// ¥ Loop over any devices we might be spanning and handle the drawing
// appropriately for each devices screen depth
StDeviceLoop theLoop ( frame );
Int16 depth;
while ( theLoop.NextDepth ( depth ))
{
if ( depth < 4 ) // ¥ BLACK & WHITE
{
if ( !IsEnabled() )
{
// ¥ If the caption is dimmed then we use the grayishTextOr
// transfer mode to draw the text
::TextMode ( grayishTextOr );
}
}
else if ( depth >= 4 ) // ¥ COLOR
{
if ( !IsEnabled() )
{
// ¥ If the control is dimmed then we have to do our own version of the
// grayishTextOr as it does not appear to work correctly across
// multiple devices
RGBColor textColor2 = UGraphicsUtilities::Lighten( &textColor );
::TextMode ( srcOr );
::RGBForeColor ( &textColor2 );
}
}
UTextDrawing::DrawWithJustification((Ptr)&mText[1], mText[0], frame, just);
}
}
void CCaption::EnableSelf()
{
Draw( nil );
}
void CCaption::DisableSelf()
{
Draw( nil );
}
///////////////////////////////////////////////////////////////////
// CListenerCaption
// Default constructor
CListenerCaption::CListenerCaption( LStream *inStream ) : labelNum( default_menu_item ),
CCaption ( inStream )
{
}
// Default destructor
CListenerCaption::~CListenerCaption()
{
}
// Change label
void
CListenerCaption::ChangeText( const LabelNum& newLabelNum )
{
Str255 string;
::GetIndString( string, resourceID, newLabelNum );
// needs check and exception
SetDescriptor( string );
labelNum = newLabelNum;
}
// Return the label num
LabelNum
CListenerCaption::GetLabelNum() const
{
return labelNum;
}
// Return the label num
void
CListenerCaption::SetLabelNum( const LabelNum& newLabelNum )
{
labelNum = newLabelNum;
}
// Override of the ListenToMessage method
//
// *** Needs exceptions
//
void
CListenerCaption::ListenToMessage( MessageT inMessage, void *ioParam)
{
if( mMsg_changeText == inMessage )
{
LabelNum menuItem = *( static_cast< LabelNum* >( ioParam ) );
ChangeText( menuItem );
}
}
// Needs to be called before using this class
//
// *** Needs exceptions
//
void
CListenerCaption::Init( const short strResID, const MessageT& getNew_msg )
{
if( getNew_msg )
mMsg_changeText = getNew_msg;
if( strResID )
resourceID = strResID;
}

View File

@ -0,0 +1,86 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CCaption.h
#pragma once
#include <LCaption.h>
#include <LListener.h>
class LStream;
typedef Int32 LabelNum;
// CCaption
//
// Moved from meditdlg.cp to be used as base class for the Listener/Lcaption derived
// class ( CListenerCaption ).
//
// ----
//
// this class is draw a caption in a disabled state if appropriate
//
class CCaption : public LCaption
{
public:
enum { class_ID = 'CapD' };
CCaption( LStream* inStream ) : LCaption ( inStream ) {};
virtual void DrawSelf();
virtual void EnableSelf();
virtual void DisableSelf();
};
// CListenerCaption
//
// A simple label class that is also a listener. It listens to
// messages and changes its content (i.e. text ).
//
// *** The Init method needs to be called before this class can be used.
//
// *** Needs exceptions support
class CListenerCaption : public CCaption, public LListener
{
public:
enum { class_ID = 'CCap' }; // class id
enum { default_menu_item = 1 }; // initial defualt menu item
CListenerCaption( LStream *inStream );
virtual ~CListenerCaption();
virtual void Init( const short strResID, const MessageT& getNew_msg );
virtual void ChangeText( const LabelNum& newLabelNum );
virtual void ListenToMessage( MessageT inMessage, void *ioParam );
LabelNum GetLabelNum() const;
void SetLabelNum( const LabelNum& newLabelNum );
protected:
private:
LabelNum labelNum;
short resourceID;
MessageT mMsg_changeText;
};

View File

@ -0,0 +1,248 @@
/* -*- 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.
*/
// CCheckMailContext.cp
#include "CCheckMailContext.h"
// FE
#include "PascalString.h"
// XP
#include "prefapi.h"
extern "C" int GetBiffPrefs(const char* prefnode, void* instanceData);
//======================================
// class CCheckMailContext
//
// Context for biff, regular checking for mail.
// Should only be instantiated once.
//======================================
CCheckMailContext* CCheckMailContext::sCheckMailContext = nil;
//-----------------------------------
CCheckMailContext* CCheckMailContext::Get()
//-----------------------------------
{
if (!sCheckMailContext)
new CCheckMailContext();
return sCheckMailContext;
}
#if 0 // seems to be obsolete.
//-----------------------------------
extern "C" int GetBiffPrefs(const char* prefnode, void* /*instanceData*/)
//-----------------------------------
{
return 0;
}
#endif // 0
//-----------------------------------
CCheckMailContext::CCheckMailContext()
//-----------------------------------
: CMailNewsContext(MWContextBiff)
, mCheckMailState(MSG_BIFF_Unknown)
, mOutstandingNotification(false)
, mMailNotifyIcon(nil)
{
// should only create one
Assert_(sCheckMailContext == nil);
sCheckMailContext = this;
memset(&mNotification, 0, sizeof(NMRec));
}
//-----------------------------------
/* static */ void CCheckMailContext::Initialize(void* inUser)
//-----------------------------------
{
Boolean firstUser = (sCheckMailContext == nil);
CCheckMailContext* biff = CCheckMailContext::Get();
biff->AddUser(inUser); // must do before initialize call;
Assert_(sCheckMailContext);
if (firstUser)
MSG_BiffInit(*sCheckMailContext, MSG_GetPrefsForMaster(GetMailMaster()));
#if 0 // seems to be obsolete.
GetBiffPrefs(nil, nil);
PREF_RegisterCallback("mail.check_new_mail", GetBiffPrefs, this);
PREF_RegisterCallback("mail.check_time", GetBiffPrefs, this);
#endif // 0
} // CCheckMailContext::Initialize
//-----------------------------------
/* static */ void CCheckMailContext::Release(void* inUser)
//-----------------------------------
{
if (sCheckMailContext)
sCheckMailContext->RemoveUser(inUser); // and delete;
} // CCheckMailContext::Release
//-----------------------------------
CCheckMailContext::~CCheckMailContext()
//-----------------------------------
{
Assert_(sCheckMailContext == this);
MSG_BiffCleanupContext(*this);
sCheckMailContext = nil;
RemoveNotification();
}
#if 0
//-----------------------------------
void CCheckMailContext::SetState(MSG_BIFF_STATE state)
// Sets biff state and does all the ui fun to reflect the change
//-----------------------------------
{
Assert_(sCheckMailContext != nil);
sCheckMailContext->DoSetState(state);
}
#endif
//-----------------------------------
void CCheckMailContext::SuspendResume()
// End Mac notification of new mail, called on suspend/resume
//
// Actually "resets" notification in for the case
// where we've become the front process having
// posted a notification when not the front process.
//
// This allows us to move the blinking icon from the
// process menu to the apple menu when we become frontmost.
// NOT ANY MORE!!!
// This logic breaks when you want Dogbert to beep on new mail when
// it's in the background _or_ foreground. This logic also breaks
// when trying to move the blinking icon to the process menu on a suspend
// since we are still the foreground app.
//-----------------------------------
{
#if 0
if (sCheckMailContext)
sCheckMailContext->DoSuspendResume();
#endif
}
#if 0
//-----------------------------------
void CCheckMailContext::DoSuspendResume()
//-----------------------------------
{
RemoveNotification();
if (GetState() == MSG_BIFF_NewMail)
InstallNotification();
}
#endif
//-----------------------------------
void CCheckMailContext::SetState(MSG_BIFF_STATE state)
// Sets biff state and does all the ui fun to reflect the change
//-----------------------------------
{
if (state != GetState())
{
mCheckMailState = state;
BroadcastMessage(msg_MailNotificationState, &state);
// Flash notification icon
if (state == MSG_BIFF_NewMail)
InstallNotification();
else
RemoveNotification();
}
}
//-----------------------------------
void CCheckMailContext::RemoveNotification()
//-----------------------------------
{
if (mOutstandingNotification)
{
::NMRemove(&mNotification);
mOutstandingNotification = false;
}
if (mNotification.nmSound)
{
::DisposeHandle(mNotification.nmSound);
mNotification.nmSound = nil;
}
}
//-----------------------------------
void CCheckMailContext::InstallNotification()
// If we're not the front process, blink our icon in the process menu and beep.
// If we are the front process, blink our icon in the apple menu (no beep)
//-----------------------------------
{
if (!mOutstandingNotification)
{
ProcessSerialNumber front, current;
::GetCurrentProcess(&current);
::GetFrontProcess(&front);
Boolean mozillaIsInFront;
OSErr err = ::SameProcess(&current, &front, &mozillaIsInFront);
if (err == noErr)
{
if (mMailNotifyIcon == nil)
err = ::GetIconSuite(&mMailNotifyIcon, BIFF_NOTIFY_ICONSUITE, kSelectorSmall8Bit | kSelectorSmall1Bit);
if (err == noErr && mMailNotifyIcon != nil)
{
Handle soundToPlay = nil; // using nil will play no sound.
// if (!mozillaIsInFront) Always play sound if one specified
{
CStr31 soundName; // constructor initializes to empty.
#define USING_PREF_SOUND 1
#if USING_PREF_SOUND
char buffer[256];
int charsReturned = sizeof(buffer);
PREF_GetCharPref("mail.notification.sound", buffer, &charsReturned);
if (strlen(buffer) < sizeof(soundName))
soundName = buffer; // (PascalString takes care of conversion)
#else
soundName = "Quack";
#endif
soundToPlay = ::GetNamedResource('snd ', soundName);
if (soundToPlay)
{
::HNoPurge(soundToPlay);
::DetachResource(soundToPlay);
}
}
// set up the notification manager record
mNotification.qType = nmType;
mNotification.nmMark = (mozillaIsInFront) ? 0 : 1; // if we're the front process, blink in apple menu, else in process menu
mNotification.nmIcon = mMailNotifyIcon;
mNotification.nmSound = soundToPlay; // can be nil
mNotification.nmStr = nil; // no dialog
mNotification.nmResp = nil; // no callback
if ( ::NMInstall(&mNotification) == noErr)
mOutstandingNotification = true;
}
}
}
}

View File

@ -0,0 +1,64 @@
/* -*- 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.
*/
// CCheckMailContext.h
#pragma once
#include "CMailNewsContext.h"
//======================================
class CCheckMailContext : public CMailNewsContext
//======================================
{
public:
enum
{
BIFF_NOTIFY_ICONSUITE = 15242,
msg_MailNotificationState = 'malS'
};
private: // must call GetCheckMailContext
CCheckMailContext();
public:
static CCheckMailContext* Get();
static void SuspendResume();
static void Initialize(void* inUser);
static void Release(void* inUser);
void SetState(MSG_BIFF_STATE state);
MSG_BIFF_STATE GetState() const { return mCheckMailState; }
protected:
#if 0
void DoSuspendResume();
#endif
void RemoveNotification();
void InstallNotification(); // do fun mac stuff
virtual ~CCheckMailContext();
// -- Data --
protected:
static CCheckMailContext *sCheckMailContext;
MSG_BIFF_STATE mCheckMailState;
Boolean mOutstandingNotification;
NMRec mNotification;
Handle mMailNotifyIcon;
}; // class CCheckMailContext

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,298 @@
/* -*- 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.
*/
// CComposeAddressTableView.h
#pragma once
#include "abcom.h"
#include <LListener.h>
#include <LCommander.h>
#include <LTableView.h>
#include <UTableHelpers.h>
#include "MailNewsAddressBook.h"
#include "CTSMEditField.h"
#include "MailNewsCallbacks.h"
#include "CMailNewsContext.h"
#define kAddressTypeMenuID 10611
typedef enum {
eNoAddressType = 0,
eToType,
eCcType,
eBccType,
eReplyType,
eNewsgroupType,
eFollowupType
} EAddressType;
class ABook;
typedef struct DIR_Server DIR_Server;
#ifdef MOZ_NEWADDR
//======================================
class CMailAddressEditField : public CTSMEditField
, public CMailCallbackListener
//======================================
{
private:
typedef CTSMEditField Inherited;
public:
enum { class_ID = 'Aedt' };
CMailAddressEditField( LStream* inStream );
virtual ~CMailAddressEditField();
void Init();
virtual void FinishCreateSelf();
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
virtual void SpendTime(const EventRecord& inMacEvent);
virtual void UserChangedText(); // override to do address-book name completion.
virtual void StartNameCompletion();
virtual void SetNameCompletionResults(
int numResults,
char* displayString,
char* headerString,
char* expandHeaderString);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
const char* FinalizeEdit(); // user has tabbed out, etc. Returns Mallocked string.
protected:
static int NameCompletionBECallbackFunction(
AB_NameCompletionCookie* cookie,
int numResults,
void* FECookie);
//-----
// Data
//-----
protected:
UInt32 mTimeLastCall;
Boolean mIsCompletedName;
Boolean mNeedToAutoCompleteAtIdleTime;
CMailNewsContext* mMailNewsContext;
MSG_Pane* mPickerPane;
int mNumResults;
char* mDisplayString;
char* mHeaderString;
char* mExpandHeaderString;
};
#else //MOZ_NEWADDR
//======================================
class CMailAddressEditField : public CTSMEditField
// ,public LBroadcaster
//======================================
{
public:
enum { class_ID = 'Aedt' };
CMailAddressEditField( LStream* inStream );
virtual void FinishCreateSelf();
virtual void UserChangedText(); // override to do address-book name completion.
const char* FinalizeEdit(); // user has tabbed out, etc. Returns Mallocked string.
virtual Boolean HandleKeyPress( const EventRecord &inKeyEvent );
virtual void SpendTime( const EventRecord& inMacEvent );
void Init();
//protected:
// virtual void TakeOffDuty();
//-----
// Data
//-----
protected:
UInt32 mTimeLastCall;
ABook* mAddressBook;
DIR_Server* mDirServerList;
Boolean mIsCompletedName;
Boolean mCheckAddress;
ABID mEntryID;
};
#endif //MOZ_NEWADDR
const MessageT msg_AddressChanged ='AdCh';
//======================================
class CComposeAddressTableView : public LTableView,
public LCommander,
//public LListener,
public LDragAndDrop,
public LBroadcaster
//======================================
{
private:
typedef LTableView Inherited;
public:
enum { class_ID = 'AdTV' };
CComposeAddressTableView(LStream* inStream);
virtual ~CComposeAddressTableView() ;
virtual void FinishCreateSelf();
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam = nil);
void SetUpTableHelpers();
void AdjustColumnWidths();
virtual void ResizeFrameBy( Int16 inWidthDelta, Int16 inHeightDelta,
Boolean inRefresh);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
virtual Boolean ClickSelect( const STableCell &inCell,
const SMouseDownEvent &inMouseDown );
virtual void ClickSelf( const SMouseDownEvent &inMouseDown );
// virtual void ListenToMessage(MessageT inMessage, void* ioParam );
void InsertNewRow(Boolean inRefresh, Boolean inEdit );
void InsertNewRow(EAddressType inAddressType,
const char* inAddress, Boolean inEdit = false);
void FillInRow( Int32 row, EAddressType inAddressType, const char* inAddress);
void StartEditCell(const STableCell &inCell);
void EndEditCell();
STableCell GetEditCell() {return mEditCell;}
void CreateCompHeader(EAddressType inAddressType, LHandleStream& inStream);
// Drag and Drop
virtual void InsideDropArea( DragReference inDragRef);
virtual void LeaveDropArea(DragReference inDragRef);
virtual Boolean DragIsAcceptable(DragReference inDragRef);
virtual Boolean ItemIsAcceptable(DragReference inDragRef, ItemReference inItemRef );
virtual void ReceiveDragItem( DragReference inDragRef,
DragAttributes flags,
ItemReference inItemRef,
Rect& itemBounds);
void HiliteRow( TableIndexT inRow, Boolean inUnderline );
// utility functions for new compose window because attach view
// is inside a tab switcher
void AddDropAreaToWindow(LWindow* inWindow);
void RemoveDropAreaFromWindow(LWindow* inWindow);
// Commands
void DeleteSelection();
void SetSelectionAddressType( EAddressType inAddressType );
// utility functions
void GetNumRows(TableIndexT &inRowCount);
EAddressType GetRowAddressType( TableIndexT inRow );
void SetRowAddressType( TableIndexT inRow, EAddressType inAddressType );
void SetTextTraits( ResIDT textTraits );
protected:
void DirectInputToAddressColumn();
void StopInputToAddressColumn();
virtual void ClickCell(const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
virtual void DrawCell(const STableCell &inCell,
const Rect &inLocalRect);
virtual void DrawSelf();
Int32 FinalizeAddrCellEdit();
Int32 CommitRow( const char* inString, STableCell cell);
void HideEditField();
virtual void TakeOffDuty();
virtual Uint16 CalculateAddressTypeColumnWidth();
//------
// data
//------
protected:
CMailAddressEditField* mInputField;
STableCell mEditCell;
Boolean mCurrentlyAddedToDropList;
Boolean mAddressTypeHasFocus;
char *mTypedownTable;
RGBColor mDropColor;
TableIndexT mDropRow;
Boolean mIsDropBetweenFolders; // changing order
Boolean mDirty;
ResIDT mTextTraits;
};
//======================================
class CComposeAddressTableStorage : public LTableStorage
//======================================
{
public:
CComposeAddressTableStorage(LTableView* inTableView);
virtual ~CComposeAddressTableStorage();
virtual void SetCellData(
const STableCell &inCell,
const void *inDataPtr,
Uint32 inDataSize);
virtual void GetCellData(
const STableCell &inCell,
void *outDataPtr,
Uint32 &ioDataSize) const;
virtual Boolean FindCellData(
STableCell &outCell,
const void *inDataPtr,
Uint32 inDataSize) const;
virtual void InsertRows(
Uint32 inHowMany,
TableIndexT inAfterRow,
const void *inDataPtr,
Uint32 inDataSize);
virtual void InsertCols(
Uint32 /* inHowMany */,
TableIndexT /* inAfterCol */,
const void* /* inDataPtr */,
Uint32 /* inDataSize */) { };
virtual void RemoveRows(
Uint32 inHowMany,
TableIndexT inFromRow);
virtual void RemoveCols(
Uint32 /* inHowMany */,
TableIndexT /* inFromCol */) { };
virtual void GetStorageSize(
TableIndexT &outRows,
TableIndexT &outCols);
protected:
LArray* mAddrTypeArray;
LArray* mAddrStrArray;
};

View File

@ -0,0 +1,452 @@
/* -*- 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.
*/
// CComposeSession.cp
#include "CComposeSession.h"
#include "CMailNewsContext.h"
#include "CEditView.h"
// PowerPlant
#include <LHandleStream.h>
// XP
#include "proto.h" // for XP_InterruptContext
#include "addrbook.h"
//#include "aberror.h"
#include "edt.h"
#include "mime.h"
#include "libi18n.h"
#include "msg_srch.h" // needed for priority
// Mac FE
#include "uerrmgr.h" // ErrorManager
#include "resgui.h" // error string constants
#include "mailNewsgroupWindow_Defines.h" // Tmessages
int FE_QuoteCallback(void* closure, const char* data)
{
if (data)
{
CComposeSession* session = (CComposeSession*)closure;
// this causes a broadcast from session to compose window
// how do I return an error?
session->InsertQuoteText(data);
}
else
{
CComposeSession* session = (CComposeSession*)closure;
session->AutoQuoteDone();
}
return 0;
}
//-----------------------------------
CComposeSession::CComposeSession(Boolean inOpeningAsDraft)
//-----------------------------------
: mCompositionContext(nil),
mXPCompositionPane(nil),
mDontIgnoreAllConnectionsComplete(false),
mDownloadingAttachments(false),
mCloseWindowAfterSavingDraft(false),
mClosing(false),
mAutoQuoting( false ),
mOpeningAsDraft(inOpeningAsDraft)
{
}
//-----------------------------------
CComposeSession::~CComposeSession()
//-----------------------------------
{
if (mClosing)
return;
mClosing = true;
Stop();
if (mXPCompositionPane)
MSG_DestroyPane(mXPCompositionPane);
mXPCompositionPane = nil;
mCompositionContext->RemoveUser(this);
mCompositionContext->RemoveListener(this);
}
// ---------------------------------------------------------------------------
MSG_Pane* CComposeSession::CreateBackendData(MWContext* inOldContext,
MSG_CompositionFields* inCompositionFields)
// Create backend data associated with a compose session. This data consists
// of the MWContext and the MSG_CompositionPane object.
// ---------------------------------------------------------------------------
{
Try_ {
// if we can't allocate CMailCompositionContext, this object does us no good
mCompositionContext = new CMailCompositionContext();
mCompositionContext->AddListener(this);
mCompositionContext->CreateContextProgress();
mCompositionContext->AddUser(this);
mCompositionContext->WaitWhileBusy();
mXPCompositionPane = MSG_CreateCompositionPane(
*mCompositionContext,
inOldContext,
MSG_GetPrefsForMaster(CMailNewsContext::GetMailMaster()),
inCompositionFields,
CMailNewsContext::GetMailMaster());
// while we're here, set from field using preference
#if 0 // FIX: no need to: 'From' field is already set
if (mXPCompositionPane)
{
char * fromField = MIME_MakeFromField();
// FIX ME -- what do we do if there is an error?
int err = MSG_SetCompHeader(mXPCompositionPane,
MSG_FROM_HEADER_MASK,
fromField);
XP_FREE(fromField);
}
#endif
}
Catch_(e)
{
// There's a leak here: mCompositionPane will not be cleaned up.
// I couldn't work out how to do it, unless it's to call:
// MSG_MailCompositionAllConnectionsComplete(mXPCompositionPane);
Throw_(e);
}
EndCatch_
// I assume that we call this method shortly after creating
// the object itself, so mXPCompositionPane should be NULL before we
// enter this method
return mXPCompositionPane;
}
void CComposeSession::SetCompositionPaneFEData( void *data )
{
if (mXPCompositionPane)
{
// let's set the window here so we can send it a close message after sending the mail
MSG_SetFEData(mXPCompositionPane, data);
}
}
void CComposeSession::ListenToMessage(MessageT inMessage, void* ioParam)
{
if (mClosing)
return;
switch(inMessage)
{
case msg_NSCAllConnectionsComplete:
if (mDownloadingAttachments)
{
// we're done downloading attachments, now do send command
mDownloadingAttachments = false;
switch (mMessage){
case cmd_SaveDraft:
SaveDraftOrTemplate(inMessage, mCloseWindowAfterSavingDraft );
break;
case cmd_SaveTemplate:
SaveDraftOrTemplate(inMessage, false );
break;
default: // Handles SendNow and SendLater
SendMessage(mSendNow);
break;
}
}
else if (mDontIgnoreAllConnectionsComplete) // MOAN!
{
if (mXPCompositionPane)
{
// We need to call this to let backend know to delete mXPCompositionPane
// Backend will destroy mXPCompositionPane when ready, so we don't need to.
// We'll come here several times for HTML parts messages, so don't do
// anything final. The backend will call FE_DestroyCompositionContext when
// everything is REALLY complete. We'll close the window then.
MSG_MailCompositionAllConnectionsComplete(mXPCompositionPane);
}
}
break;
// pass on broadcast to listeners
default:
BroadcastMessage(inMessage, ioParam);
break;
}
}
void CComposeSession::SetMessageHeaderData(MSG_HEADER_SET inMessageHeaderType,
LHandleStream& inDataStream)
{
if (mXPCompositionPane)
{
Handle data = inDataStream.GetDataHandle();
StHandleLocker lock(data);
int err = MSG_SetCompHeader(mXPCompositionPane,inMessageHeaderType, *data);
// what do we do if there is an error?
}
}
const char* CComposeSession::GetMessageHeaderData(MSG_HEADER_SET inMessageHeaderType)
{
return MSG_GetCompHeader(mXPCompositionPane, inMessageHeaderType);
}
void CComposeSession::SetMessageBody(LHandleStream& inDataStream)
{
if (mXPCompositionPane)
{
Handle data = inDataStream.GetDataHandle();
StHandleLocker lock(data);
MSG_SetHTMLMarkup(mXPCompositionPane, false);
int err = MSG_SetCompBody(mXPCompositionPane, *data);
}
}
void CComposeSession::SetHTMLMessageBody()
{
if (mXPCompositionPane)
{
XP_HUGE_CHAR_PTR textp = nil;
EDT_SaveToBuffer(*mCompositionContext, &textp);
MSG_SetHTMLMarkup(mXPCompositionPane, true);
int err = MSG_SetCompBody(mXPCompositionPane, textp);
if (textp)
delete textp;
}
}
void CComposeSession::SendMessage(Boolean inSendNow)
{
mDontIgnoreAllConnectionsComplete = true;
mSendNow = inSendNow;
MSG_Command(mXPCompositionPane, inSendNow ? MSG_SendMessage : MSG_SendMessageLater, nil, nil);
}
const char* CComposeSession::GetSubject()
{
return MSG_GetCompHeader(mXPCompositionPane, MSG_SUBJECT_HEADER_MASK);
}
MSG_PRIORITY CComposeSession::GetPriority()
{
// Oh, no! msglib gives us a hard-coded string. What sort of consciousness
// can lead to this type of code. Let's hope that the linker can pool strings for us,
// so that this will only take up 20 extra bytes.
const char *priority = MSG_GetCompHeader( GetMSG_Pane(), MSG_PRIORITY_HEADER_MASK );
if( priority )
{
if (strcasestr(priority, "Normal") != NULL)
return MSG_NormalPriority;
else if (strcasestr(priority, "Lowest") != NULL)
return MSG_LowestPriority;
else if (strcasestr(priority, "Highest") != NULL)
return MSG_HighestPriority;
else if (strcasestr(priority, "High") != NULL ||
strcasestr(priority, "Urgent") != NULL)
return MSG_HighPriority;
else if (strcasestr(priority, "Low") != NULL ||
strcasestr(priority, "Non-urgent") != NULL)
return MSG_LowPriority;
else
return MSG_NoPriority;
}
return MSG_NoPriority;
}
const struct MSG_AttachmentData*
CComposeSession::GetAttachmentData()
{
return MSG_GetAttachmentList(mXPCompositionPane);
}
void CComposeSession::SetAttachmentList(MSG_AttachmentData* inAttachmentList)
{
try
{
mDownloadingAttachments = true;
int status = MSG_SetAttachmentList(mXPCompositionPane, inAttachmentList);
if (status) throw status;
}
catch (...)
{
mDownloadingAttachments = false;
throw;
}
}
void CComposeSession::InsertQuoteText(const char* text)
{
BroadcastMessage(msg_InsertQuoteText, (void*)text);
}
void CComposeSession::AutoQuoteDone()
{
if( mAutoQuoting )
BroadcastMessage(msg_AutoQuoteDone, NULL);
mAutoQuoting = false;
}
void CComposeSession::CheckForAutoQuote()
{
if (ShouldAutoQuote())
{
mAutoQuoting = true;
QuoteMessage();
}
}
void CComposeSession::QuoteMessage()
{
MSG_QuoteMessage(mXPCompositionPane, FE_QuoteCallback, this);
}
#if 0
// As far as I can tell, this never gets called.
void CComposeSession::QuoteInHTMLMessage( const char *text )
{
MWContext* context = (MWContext*)*mCompositionContext;
EDT_BeginOfDocument( context, false ); // before signature, if any.
// insert a blank line between message and quote
EDT_ReturnKey( context );
EDT_PasteQuote( context, (char *)text );
// move the insertion caret to the beginning (where it should be)
EDT_BeginOfDocument( context, false );
}
#endif
void CComposeSession::SetPriority(MSG_PRIORITY inPriority)
{
char priorityString[50];
MSG_GetUntranslatedPriorityName ( inPriority, priorityString, sizeof(priorityString));
MSG_SetCompHeader(
mXPCompositionPane,
MSG_PRIORITY_HEADER_MASK,
priorityString );
}
void CComposeSession::Stop()
{
// ignore all connections complete message from backend
mDontIgnoreAllConnectionsComplete = false;
XP_InterruptContext(*mCompositionContext);
mDownloadingAttachments = false;
}
void CComposeSession::SaveDraftOrTemplate(CommandT inCommand, Boolean inCloseWindow )
{
MSG_CommandType cmd;
if ( inCloseWindow )
{
Assert_(inCommand == cmd_SaveDraft);
cmd = MSG_SaveDraftThenClose;
mDontIgnoreAllConnectionsComplete = true;
}
else if (inCommand == cmd_SaveTemplate)
cmd = MSG_SaveTemplate;
else
cmd = MSG_SaveDraft;
MSG_Command(mXPCompositionPane, cmd , nil, nil);
}
int CComposeSession::SetCompBoolHeader(MSG_BOOL_HEADER_SET header,XP_Bool value)
{
return MSG_SetCompBoolHeader(mXPCompositionPane, header,value);
}
Uint32 GetAttachmentListLength(const MSG_AttachmentData* inAttachList);
Uint32 GetAttachmentListLength(const MSG_AttachmentData* inAttachList)
{
UInt32 result = 0;
if (inAttachList)
{
MSG_AttachmentData* iter = const_cast<MSG_AttachmentData*>(inAttachList);
while (iter->url != nil)
{
++result;
++iter;
}
}
return result;
}
Int16 CComposeSession::GetDefaultCSID()
{ // Delegate to mCompositionContext
if (mCompositionContext)
return mCompositionContext->GetDefaultCSID();
else
return 0;
}
void CComposeSession::SetDefaultCSID(Int16 default_csid)
{ // Delegate to mCompositionContext
Assert_(mCompositionContext);
if (mCompositionContext)
{
mCompositionContext->SetDefaultCSID(default_csid);
mCompositionContext->SetDocCSID(default_csid);
mCompositionContext->SetWinCSID(INTL_DocToWinCharSetID(default_csid));
}
}
int16 CComposeSession::GetWinCSID()
{
Assert_(mCompositionContext);
if (mCompositionContext)
return mCompositionContext->GetWinCSID();
else
return 0;
}
Boolean CComposeSession::NeedToSyncAttachmentList(MSG_AttachmentData* inAttachList)
{
Boolean result = false;
const MSG_AttachmentData* backendList = MSG_GetAttachmentList(mXPCompositionPane);
if ( (inAttachList != nil && backendList == nil) ||
(inAttachList == nil && backendList != nil) )
{ // easy case, one list is empty the other is not
result = true;
} else if (inAttachList != nil && backendList != nil)
{ // both lists are non-empty
// first check list lengths
Uint32 inLength = GetAttachmentListLength(inAttachList),
backendLength = GetAttachmentListLength(backendList);
if (inLength != backendLength)
// lengths are different
result = true;
else
{ // both same length, now check to see if both lists contain same data
MSG_AttachmentData *inIter = inAttachList,
*backendIter = const_cast<MSG_AttachmentData*>(backendList);
while (inIter->url != nil)
{
if (XP_STRCMP(inIter->url, backendIter->url))
{ // URL's are different, need to sync up lists
result = true;
break;
}
++inIter;
++backendIter;
}
}
}
return result;
}

View File

@ -0,0 +1,128 @@
/* -*- 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.
*/
// CComposeSession.h
#pragma once
// PowerPlant
#include <LListener.h>
// XP
#include "msgcom.h"
#include "structs.h" // mother of all structs (i.e. MWContext)
// MacFE
#include "CProgressBroadcaster.h"
#include "CMailComposeWindow.h" // for CMailCompositionContext
// quote function passed into MSG_QuoteMessage
extern "C"
{
int FE_QuoteCallback(void* closeure, const char* data);
}
class CComposeSession : public CProgressBroadcaster,
public LListener
{
public:
enum { msg_AllConnectionsComplete = 'ACnC',
msg_InsertQuoteText = 'InsQ',
msg_AutoQuoteDone = 'AQDn' };
CComposeSession(Boolean inOpeningAsDraft);
virtual ~CComposeSession();
virtual void ListenToMessage(MessageT inMessage,void *ioParam);
MSG_Pane* CreateBackendData(MWContext* inOldContext,
MSG_CompositionFields* inCompositionFields);
// get data
const char* GetSubject();
MSG_PRIORITY GetPriority();
const char* GetMessageHeaderData(MSG_HEADER_SET inMessageHeaderType);
const struct MSG_AttachmentData*
GetAttachmentData();
Boolean GetDownloadingAttachments() const { return mDownloadingAttachments; }
Boolean GetDeliveryInProgress() const { if ( mXPCompositionPane )
return MSG_DeliveryInProgress( mXPCompositionPane );
else
return false;
}
MSG_Pane* GetMSG_Pane() {return mXPCompositionPane;}
void MarkMSGPaneDestroyed() {mXPCompositionPane = nil;}
CMailCompositionContext* GetCompositionContext() {return mCompositionContext;}
Boolean GetAutoQuoting() { return mAutoQuoting; }
// set data
void SetMessageHeaderData(MSG_HEADER_SET inMessageHeaderType,
LHandleStream& inDataStream);
void SetAttachmentList(MSG_AttachmentData* inAttachmentList);
void SetPriority(MSG_PRIORITY inPriority);
void SetMessageBody(LHandleStream& inHandleStream);
void SetHTMLMessageBody();
void SetCompositionPaneFEData(void *data);
void SetMessage(MessageT command) {mMessage=command;};
int SetCompBoolHeader(MSG_BOOL_HEADER_SET header,XP_Bool value);
XP_Bool GetCompBoolHeader(MSG_BOOL_HEADER_SET header)
{ return MSG_GetCompBoolHeader(mXPCompositionPane, header);}
// quoting
void InsertQuoteText(const char* text);
void AutoQuoteDone();
Boolean ShouldAutoQuote() const
{ return !mOpeningAsDraft
&& ::MSG_ShouldAutoQuote(mXPCompositionPane);
}
void CheckForAutoQuote();
void QuoteInHTMLMessage(const char* text);
// actions
void WaitWhileContextBusy();
void SendMessage(Boolean inSendNow);
void SetSendNow(Boolean inSendNow) { mSendNow = inSendNow; }
void SetCloseWindow( Boolean inClose) { mCloseWindowAfterSavingDraft = inClose; }
void QuoteMessage();
void Stop();
void SaveDraftOrTemplate(CommandT inCommand, Boolean inCloseWindow);
// potpourri
Boolean NeedToSyncAttachmentList(MSG_AttachmentData* inAttachList);
// I18N stuff
virtual Int16 GetDefaultCSID(void);
virtual void SetDefaultCSID(Int16 defaultcsid);
int16 GetWinCSID();
protected:
CMailCompositionContext* mCompositionContext;
MSG_Pane* mXPCompositionPane;
// I must say, the reason why I have to do this...
Boolean mDontIgnoreAllConnectionsComplete;
// Double SIGH!
Boolean mDownloadingAttachments;
Boolean mSendNow;
MessageT mMessage;
Boolean mCloseWindowAfterSavingDraft;
Boolean mClosing;
Boolean mAutoQuoting;
Boolean mOpeningAsDraft;
};

View File

@ -0,0 +1,236 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CFolderThreadController.cp
#include "CFolderThreadController.h"
#include "CMessageFolderView.h"
#include "CThreadView.h"
#include "MailNewsgroupWindow_Defines.h"
#include "divview.h"
#include "CTargetFramer.h"
#include "CNetscapeWindow.h"
#include "resgui.h" // for cmd_ShowLocationBar
#include "prefapi.h"
const char* Pref_MailShowLocationBarFolders = "mailnews.chrome.show_url_bar.folders";
const char* Pref_MailShowLocationBarNoFolders = "mailnews.chrome.show_url_bar.nofolders";
//----------------------------------------------------------------------------------------
CFolderThreadController::CFolderThreadController(
LDividedView* inDividedView
, CNSContext* inThreadContext
, CMessageFolderView* inFolderView
, CThreadView* inThreadView
)
//----------------------------------------------------------------------------------------
: mDividedView(inDividedView)
, mThreadContext(inThreadContext)
, mFolderView(inFolderView)
, mThreadView(inThreadView)
{
Assert_(mDividedView);
Assert_(mThreadContext);
Assert_(mThreadView);
Assert_(mFolderView);
inDividedView->SetCollapseByDragging(true, true);
mDividedView->AddListener(this); // for msg_DividerChangedPosition
mFolderView->AddListener(this);
mFolderView->SetRightmostVisibleColumn(1); // hide the count columns
} // CFolderThreadController::CFolderThreadController
//----------------------------------------------------------------------------------------
CFolderThreadController::~CFolderThreadController()
//----------------------------------------------------------------------------------------
{
// See comment in FinishCreateSelf. Destroy the folder and thread views explicitly
// here, so that it's done in the right order. Because of the tab order requirement,
// LCommander::~LCommander would otherwise be deleting these in the opposite order
// to the tab order, namely message/thread/folder. Boom.
delete mFolderView;
mFolderView = nil;
delete mThreadView;
mThreadView = nil;
// The message view remains a subcommander, so will be deleted in the base class
// destructor.
} // CFolderThreadController::~CFolderThreadController
//----------------------------------------------------------------------------------------
void CFolderThreadController::FinishCreateSelf()
//----------------------------------------------------------------------------------------
{
// It's critical the order we do this. These are added to the end of the
// supercommander's subcommander list, and destroyed in the opposite order.
// Since we have to destroy in the order folder/thread/message, we would like to add
// here in the order message/thread/folder. But unfortunately, the order we add them
// also affects the tab order, which we would like to be folder/thread/message. So
// the order here is for the benefit of the tab order. See the destructor code above.
mFolderView->SetSuperCommander(this);
mThreadView->SetSuperCommander(this);
CTargetFramer* framer = new CTargetFramer();
mThreadView->AddAttachment(framer);
framer = new CTargetFramer();
mFolderView->AddAttachment(framer);
SetLatentSub(mFolderView);
mFolderView->SetFancyDoubleClick(true);
} // CFolderThreadController::FinishCreateSelf
//----------------------------------------------------------------------------------------
void CFolderThreadController::ListenToMessage(MessageT inMessage, void *ioParam)
//----------------------------------------------------------------------------------------
{
switch (inMessage)
{
case msg_DividerChangedPosition:
{
// Don't take any action during FinishCreate(): assume that the panes
// will be constructed in the same correct positions that they were saved in.
if (mDividedView->IsVisible() && (LDividedView*)ioParam == mDividedView)
NoteDividerChanged();
break;
}
case CStandardFlexTable::msg_SelectionChanged:
{
Assert_(ioParam == mFolderView);
MSG_FolderInfo* info = nil;
if (mFolderView->GetSelectedRowCount() == 1)
{
// See also CMessageFolderView::OpenRow
info = mFolderView->GetSelectedFolder();
CMessageFolder folder(info);
if (folder.IsMailServer()
|| folder.IsNewsHost()
|| !folder.CanContainThreads())
{
info = nil;
}
}
mThreadView->LoadMessageFolder(mThreadContext, info, false /* delay: don't load now */);
break;
}
default:
break;
}
} // CFolderThreadController::ListenToMessage
//----------------------------------------------------------------------------------------
void CFolderThreadController::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
//----------------------------------------------------------------------------------------
{
switch(inCommand)
{
case cmd_ToggleFolderPane:
outEnabled = (mDividedView != nil);
outUsesMark = false;
if (outEnabled && mDividedView->IsFirstPaneCollapsed())
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, SHOW_FOLDERPANE_STRING);
else
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, HIDE_FOLDERPANE_STRING);
break;
default:
LTabGroup::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
break;
}
} // CFolderThreadController::FindCommandStatus
//----------------------------------------------------------------------------------------
Boolean CFolderThreadController::ObeyCommand(
CommandT inCommand,
void *ioParam)
//----------------------------------------------------------------------------------------
{
switch (inCommand)
{
case cmd_ToggleFolderPane:
if (mDividedView)
mDividedView->ToggleFirstPane();
// force menu items to update show "Show" and "Hide" string changes are reflected
LCommander::SetUpdateCommandStatus(true);
return true;
case cmd_RelocateViewToFolder:
if (mFolderView)
mFolderView->SelectFolder((MSG_FolderInfo*)ioParam);
else
mThreadView->RelocateViewToFolder((MSG_FolderInfo*)ioParam);
return true;
case msg_TabSelect:
// Subcommanders (thread/folder/message) will kick this upstairs here.
return true;
}
return LTabGroup::ObeyCommand(inCommand, ioParam);
} // CFolderThreadController::ObeyCommand
//----------------------------------------------------------------------------------------
void CFolderThreadController::ReadStatus(LStream *inStatusData)
//----------------------------------------------------------------------------------------
{
mDividedView->RestorePlace(inStatusData);
} // CFolderThreadController::ReadWindowStatus
//----------------------------------------------------------------------------------------
void CFolderThreadController::WriteStatus(LStream *outStatusData)
//----------------------------------------------------------------------------------------
{
mDividedView->SavePlace(outStatusData);
} // CFolderThreadController::WriteWindowStatus
//----------------------------------------------------------------------------------------
void CFolderThreadController::NoteDividerChanged()
//----------------------------------------------------------------------------------------
{
Boolean foldersCollapsed = mDividedView->IsFirstPaneCollapsed();
const char* prefName = foldersCollapsed ?
Pref_MailShowLocationBarNoFolders
: Pref_MailShowLocationBarFolders;
XP_Bool doShow;
if (PREF_GetBoolPref(prefName, &doShow) != PREF_NOERROR)
{
// If the preference is not yet set, the default is to show iff folders are collapsed
doShow = foldersCollapsed;
}
// These commands will be handled by CMailNewsWindow. The values will be written out to the
// prefs file as a side effect of ToggleDragBar, using the virtual method
// GetLocationBarPrefName() which we have provided.
if (doShow)
ObeyCommand(cmd_ShowLocationBar, nil);
else
ObeyCommand(cmd_HideLocationBar, nil);
} // CFolderThreadController::NoteDividerChanged
//----------------------------------------------------------------------------------------
const char* CFolderThreadController::GetLocationBarPrefName() const
//----------------------------------------------------------------------------------------
{
if (!mDividedView)
return nil;
if (mDividedView->IsFirstPaneCollapsed())
return Pref_MailShowLocationBarNoFolders;
return Pref_MailShowLocationBarFolders;
}

View File

@ -0,0 +1,79 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CFolderThreadController.h
#include <LTabGroup.h>
#include <LListener.h>
class CMessageFolderView;
class CThreadView;
class CNSContext;
class LDividedView;
//======================================
class CFolderThreadController
: public LListener
, public LTabGroup
// This class is here to mediate between the folder pane and the thread pane in a 3-pane
// window. Its function is to allow the thread view class not to know anything about
// the folder view.
//======================================
{
public:
CFolderThreadController(
LDividedView* inDividedView
, CNSContext* inThreadContext
, CMessageFolderView* inFolderView
, CThreadView* inThreadView
);
virtual ~CFolderThreadController();
// LListener overrides:
protected:
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
// LCommander overrides:
protected:
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam);
// CSaveWindowStatus helpers:
public:
void ReadStatus(LStream *inStatusData);
void WriteStatus(LStream *outStatusData);
const char* GetLocationBarPrefName() const;
// Specials
public:
void FinishCreateSelf();
void NoteDividerChanged();
// Data
protected:
LDividedView* mDividedView;
CMessageFolderView* mFolderView;
CThreadView* mThreadView;
CNSContext* mThreadContext;
}; // class CFolderThreadController

View File

@ -0,0 +1,36 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "CKeyStealingAttachment.h"
//-----------------------------------
void CKeyStealingAttachment::ExecuteSelf(MessageT, void *ioParam)
//-----------------------------------
{
EventRecord* event = (EventRecord*)ioParam;
if ((event->what != keyDown) && (event->what != autoKey))
return;
char theKey = (char)(event->message & charCodeMask);
if (mKeysToSteal.FetchIndexOf(&theKey) != LArray::index_Bad)
{
mTarget->ProcessKeyPress(*event);
event->what = nullEvent; // prevent normal handling.
event->message = 0; // prevent normal handling.
}
} // CKeyStealingAttachment::ExecuteSelf

View File

@ -0,0 +1,43 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include <LAttachment.h>
//======================================
class CKeyStealingAttachment : public LAttachment
// This guy is added at the front of the attachment list in expanded mode, so that
// certain keypresses go to the message view instead of to the table view.
//======================================
{
public:
CKeyStealingAttachment(LCommander *inKeyTarget)
: LAttachment(msg_KeyPress)
, mKeysToSteal(sizeof(char))
, mTarget(inKeyTarget) {}
virtual void ExecuteSelf(MessageT inMessage, void *ioParam);
void StealKey(char keyToSteal)
{
mKeysToSteal.InsertItemsAt(
1,
LArray::index_Last,
&keyToSteal);
}
protected:
LCommander* mTarget;
LArray mKeysToSteal;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,305 @@
/* -*- 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.
*/
// CMailComposeWindow.h
#pragma once
// C/C++ headers
//#include <yvals.h>
// PowerPlant
#include <LListener.h>
#include <LBroadcaster.h>
#include <LEditField.h>
#include <LCommander.h>
#include <LHandleStream.h>
// Mail/News MacFE stuff
#include "CBrowserContext.h"
#include "CComposeAddressTableView.h"
//#include "VEditField.h"
#include "CTSMEditField.h"
// UI elements
#include "CMailNewsWindow.h"
#include "CPatternBevelView.h"
#include "CTabSwitcher.h"
// #include "CGrayBevelView.h"
// Netscape stuff
#include "msgcom.h"
#include "mattach.h"
#include "PascalString.h"
class CSimpleTextView;
extern "C" void FE_SecurityOptionsChanged( MWContext* context);
const MessageT msg_DeleteCompositionContext = 'DCmC';
const MessageT msg_FinalizeAddrCellEdit = 'FAdC';
const MessageT msg_RefreshAddrCellEdit = 'RfAC';
const MessageT msg_ActivatingAttachTab = 'AcAT';
const MessageT msg_DeactivatingAttachTab = 'DeAT';
const MessageT msg_ActivatingAddressTab = 'AcAD';
const MessageT msg_DeactivatingAddressTab = 'DeAD';
const MessageT msg_ActivatingOptionTab = 'AcOT';
const MessageT msg_DeactivatingOptionTab = 'DeOT';
const PaneIDT cSendButtonPaneID = 'Send';
const PaneIDT cSendLaterButtonPaneID = 'Sl8r';
const PaneIDT cQuoteButtonPaneID = 'Quot';
const PaneIDT cStopButtonPaneID = 'Stop';
const PaneIDT cAddressTab = 10611;
const PaneIDT cAttachTab = 10612;
const PaneIDT cOptionTab = 10617;
const PaneIDT cFormattingToolbar = 'HTbr';
const CommandT cmd_Attach = 'Batc';
const MessageT msg_ReturnRecipt = 'OtRe';
const MessageT msg_Garbled = 'OtEn';
// const MessageT msg_8BitEncoding = 'Ot8b';
const MessageT msg_Signed = 'OtSi';
const MessageT msg_UUEncode = 'OtUU';
const MessageT msg_HTMLAction = 'OtHa';
const CommandT cmd_AttachMyAddressBookCard = 'AtMA';
class CMailComposeWindow;
class CProgressListener;
class CComposeSession;
//======================================
class UComposeUtilities
//======================================
{
public:
static void WordWrap(Handle& inText,
Uint32 inTextLength,
LHandleStream& outTextStream);
static MSG_HEADER_SET GetMsgHeaderMaskFromAddressType(EAddressType inAddressType);
static MSG_PRIORITY GetMsgPriorityFromMenuItem(Int32 inMenuItem);
static void RegisterComposeClasses();
};
//======================================
class CMailCompositionContext : public CBrowserContext
//======================================
{
public:
CMailCompositionContext();
virtual ~CMailCompositionContext() {}
void Cleanup() { BroadcastMessage(msg_DeleteCompositionContext); }
virtual void AllConnectionsComplete(); // call this method
void CreateContextProgress();
};
//======================================
class CTabContainer : public CPatternBevelView
//======================================
{
private: typedef CPatternBevelView Inherited;
public:
enum { class_ID = 'C_TC' };
CTabContainer(LStream* inStream);
virtual ~CTabContainer() { };
virtual void DrawSelf();
virtual void DrawBeveledFrame();
};
//======================================
class CMailTabContainer : public CTabContainer
//=========================================
{
public:
CMailTabContainer(LStream* inStream);
virtual ~CMailTabContainer() { };
virtual void DrawBeveledFrame();
virtual void DrawSelf();
};
//======================================
class CMailComposeTabContainer : public CMailTabContainer
//======================================
{
private: typedef CTabContainer Inherited;
public:
enum { class_ID = 'CmTC' };
CMailComposeTabContainer(LStream* inStream);
virtual ~CMailComposeTabContainer() { };
virtual void FinishCreateSelf();
};
//======================================
class CMailAttachmentTabContainer : public CMailTabContainer
//======================================
{
private: typedef CTabContainer Inherited;
public:
enum { class_ID = 'AtTC' };
CMailAttachmentTabContainer(LStream* inStream);
virtual ~CMailAttachmentTabContainer() { };
virtual void FinishCreateSelf();
};
typedef struct TERec **TEHandle;
class CMailEditView;
//======================================
class CMailComposeWindow : public CMailNewsWindow,
public LBroadcaster,
public LListener,
public LPeriodical
//======================================
{
private:
typedef CMailNewsWindow Inherited;
public:
enum { class_ID = 'mail', res_ID = 10610, text_res_ID = 10614 }; // this is same class_ID as old compose window
// Index into mToolbarShown for tracking visibility of toolbars
// Start at 2 because CMailNewsWindow uses 0 and 1
enum { FORMATTING_TOOLBAR = 2};
enum { COMPOSE_BUTTON_BAR_ID = 10618};
CMailComposeWindow(LStream* inStream);
virtual ~CMailComposeWindow();
virtual void FinishCreateSelf();
MSG_Pane* CreateSession(MWContext* old_context,
MSG_CompositionFields* inCompositionFields,
const char* initialText,
Boolean inOpeningAsDraft);
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam);
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual void AttemptClose();
virtual Boolean AttemptQuitSelf(Int32 inSaveOption);
CComposeSession* GetComposeSession() { return mComposeSession; }
void HandleUpdateCompToolbar(); // from FE_UpdateCompToolbar.
virtual Boolean HandleTabKey(const EventRecord &inKeyEvent);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
void DoCloseLater();
virtual void SpendTime(const EventRecord &inMacEvent);
// I18N stuff
virtual Int16 DefaultCSIDForNewWindow(void);
virtual void SetDefaultCSID(Int16 default_csid);
protected:
void SetDefaultWebAttachmentURL();
void SendMessage(Boolean inSendNow);
void UpdateSendButton();
void SaveDraftOrTemplate(CommandT inCommand, Boolean inCloseWindow = false );
Boolean PrepareMessage(Boolean isDraft = false);
void SyncAddressLists();
void GetSubjectFromBackend();
void GetPriorityFromBackend();
void GetAttachmentsFromBackend();
void InitializeHTMLEditor(CMailEditView* inEditorView);
void GetAllCompHeaders();
void SetCompHeader(EAddressType inAddressType);
void GetCompHeader(EAddressType inAddressType);
void EnsureAtLeastOneAddressee();
void SetSensibleTarget();
char* GetSubject();
ExceptionCode InsertMessageCompositionText(const char* text, Boolean leaveCursorinFront = false);
void TargetMessageCompositionText();
Boolean NeedToSave();
Boolean AskIfUserWantsToClose();
virtual ResIDT GetStatusResID(void) const;
virtual UInt16 GetValidStatusVersion(void) const { return 0x0115; }
CComposeSession* mComposeSession;
CComposeAddressTableView* mAddressTableView;
CAttachmentList* mAttachmentList;
CAttachmentView* mAttachmentView;
CProgressListener* mProgressListener;
CMailEditView* mHTMLEditView; // nil unless HTML mode!
CSimpleTextView* mPlainEditView; // nil unless in PlainTextMode
Boolean mHeadersDirty; // The address, attachment
Boolean mHaveInitializedAttachmentsFromBE;
enum EInitializeState {
eUninitialized,
eComposeSessionIsSet,
eAboutURLLoading,
eDone };
EInitializeState mInitializeState;
Boolean mOnlineLastFindCommandStatus;
CStr255 mDefaultWebAttachmentURL;
CommandT mCurrentSaveCommand; // cmd_SaveDraft, cmd_SaveTemplate
}; // class CMailComposeWindow
//======================================
class CComposeTabSwitcher : public CTabSwitcher,
public LBroadcaster
//======================================
{
public:
enum { class_ID = 'CmTb' };
CComposeTabSwitcher(LStream* inStream);
virtual ~CComposeTabSwitcher() { };
virtual void ManuallySwitchToTab( int32 tabID);
virtual void DoPostLoad(LView* inLoadedPage, Boolean inWillCache);
virtual void DoPreDispose(LView* inLeavingPage, Boolean inWillCache);
};
//======================================
class CMailOptionTabContainer : public CMailTabContainer
//======================================
{
private: typedef CTabContainer Inherited;
public:
enum { class_ID = 'OpTC' };
CMailOptionTabContainer(LStream* inStream);
virtual ~CMailOptionTabContainer() { };
virtual void FinishCreateSelf();
};

View File

@ -0,0 +1,869 @@
/* -*- 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.
*/
#include "CMailFlexTable.h"
// PP
#include <UException.h>
#include <UModalDialogs.h>
#include "LFlexTableGeometry.h"
//#include "LTableRowSelector.h"
// Want a command number? They hide in several places...
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
#include "UMessageLibrary.h"
#include "CPrefsDialog.h"
#include "CNSContext.h"
#include "UMailSelection.h"
#include "uapp.h" // for UpdateMenus(). Ugh.
#include "CPaneEnabler.h"
#include "CMailNewsContext.h"
#include "UOffline.h"
#include "CBookmarksAttachment.h"
#include "CMailProgressWindow.h"
#include "macutil.h"
#include "prefapi.h"
// XP
#include "shist.h"
//-----------------------------------
CMailFlexTable::CMailFlexTable(LStream *inStream)
//-----------------------------------
: Inherited(inStream)
, mMsgPane(NULL)
, mMysticPlane(0)
, mStillLoading(false)
, mContext(nil)
, mFirstRowToRefresh(0)
, mLastRowToRefresh(0)
, mClosing(false)
{
*inStream >> mDragFlavor;
} // CMailFlexTable::CMailFlexTable
//-----------------------------------
CMailFlexTable::~CMailFlexTable()
//-----------------------------------
{
mClosing = true;
SetMessagePane(NULL);
} // CMailFlexTable::~CMailFlexTable
//-----------------------------------
void CMailFlexTable::DrawSelf()
//-----------------------------------
{
ApplyForeAndBackColors();
// This function is similar to what we had when the "Erase On Update"
// LWindow attribute was set in Constructor. This flag has been removed
// because it created a lot of flickers when browsing mails.
// The other objects in the Thread window continued to behave correctly
// but the CThreadView showed some update problems. Instead of fixing
// them as we are supposed to (ie. by invalidating and erasing only what
// needs to be redrawn), I prefered to emulate the way it used to work
// when "Erase On Update" was set. My apologies for this easy solution
// but we have something to ship next week.
// OK, I made it better by only erasing what was below the last cell (if anything).
// jrm 97/08/18
const STableCell bottomCell(mRows, 1);
Int32 cellLeft, cellTop, cellRight, cellBottom;
mTableGeometry->GetImageCellBounds(bottomCell, cellLeft, cellTop,
cellRight, cellBottom);
// Convert from image coordinates to port coordinates
cellBottom += mImageLocation.v;
Int32 frameBottom = mFrameLocation.v + mFrameSize.height;
if (cellBottom < frameBottom) // Note the "=", edge case for deleting the last row.
{
// erase everything
Rect frame;
CalcLocalFrameRect(frame);
frame.top = frame.bottom - (frameBottom - cellBottom);
::EraseRect(&frame);
}
// redraw everything
Inherited::DrawSelf();
} // CMailFlexTable::DrawSelf
//-----------------------------------
void CMailFlexTable::DestroyMessagePane(MSG_Pane* inPane )
//-----------------------------------
{
if (mContext)
XP_InterruptContext((MWContext*)*mContext);
CMailCallbackListener::SetPane(nil); // turn off callbacks
if ( GetMessagePane() != NULL )
::MSG_DestroyPane( inPane);
}// CMailFlexTable::DestroyMessagePane
//-----------------------------------
void CMailFlexTable::SetMessagePane(MSG_Pane* inPane)
//-----------------------------------
{
DestroyMessagePane( mMsgPane );
mMsgPane = inPane;
CMailCallbackListener::SetPane(inPane);
}
//-----------------------------------
void CMailFlexTable::SetRowCount()
// Queries the back end pane and sets the number of rows.
//-----------------------------------
{
TableIndexT rows, cols;
GetTableSize(rows, cols);
SInt32 diff = mMsgPane ? (::MSG_GetNumLines(mMsgPane) - rows) : -rows;
if (diff > 0)
InsertRows(diff, 1, NULL, 0, false);
else if (diff < 0)
RemoveRows(-diff, 1, false);
} // CMailFlexTable::SetRowCount()
#if 0
//======================================
class StProgressWindowHandler : public StDialogHandler
//======================================
{
private:
typedef StDialogHandler Inherited;
public:
};
#endif
static Boolean gCanceled = false;
static Boolean CancelCallback()
{
gCanceled = true;
return false;
}
//-----------------------------------
void CMailFlexTable::OpenSelection()
// Overrides the base class, in order to show progress.
//-----------------------------------
{
TableIndexT total = GetSelectedRowCount();
if (!total)
return;
if (total < 10)
{
Inherited::OpenSelection();
return;
}
TableIndexT selectedRow = 0;
StDialogHandler handler(CMailProgressWindow::res_ID_modal, LCommander::GetTopCommander());
CMailProgressWindow* pw = dynamic_cast<CMailProgressWindow*>(handler.GetDialog());
if (!pw)
throw memFullErr;
CStr255 description;
::GetIndString(description, 7099, 17);
pw->SetCancelCallback(CancelCallback);
CContextProgress progress;
progress.mAction = description;
progress.mTotal = total;
progress.mInitCount = 0;
progress.mPercent = 0;
progress.mRead = 0;
progress.mStartTime = ::TickCount();
gCanceled = false;
pw->Show();
pw->UpdatePort();
pw->ListenToMessage(msg_NSCProgressBegin, &progress);
while (GetNextSelectedRow(selectedRow) && !gCanceled)
{
// Handle plenty of events - activates, updates coming on strong...
for (int i = 1; i <= 20; i++)
{
handler.DoDialog();
if (gCanceled)
break;
}
OpenRow(selectedRow);
::GetIndString(description, 7099, 18);
::StringParamText(description, ++progress.mRead, progress.mTotal, 0, 0);
progress.mPercent = ((Int32)(progress.mRead) * 100/ total);
// progress.mMessage = description;
// pw->ListenToMessage(msg_NSCProgressUpdate, &progress);
// Someone turned off support for msg_NSCProgressUpdate, so:
pw->ListenToMessage(msg_NSCProgressMessageChanged, (char*)description);
pw->ListenToMessage(msg_NSCProgressPercentChanged, &progress.mPercent);
}
// No. Handler will delete! pw->ListenToMessage(msg_NSCAllConnectionsComplete, nil);
} // CMailFlexTable::OpenSelection
//-----------------------------------
Boolean CMailFlexTable::GetSelection(CMailSelection& selection)
// CStandardFlexTable has one-based lists which are lists of TableIndexT.
// CMailSelection requires zero-based lists which are lists of MSG_ViewIndex
// This routine clones and converts.
//-----------------------------------
{
selection.xpPane = mMsgPane;
// Assert, cuz we're going to cast and to convert an array in place!
Assert_(sizeof(TableIndexT) == sizeof(MSG_ViewIndex));
// if we've got a selection list, it's assumed up to date,
// so DON't convert it to a MSG_Index. When the selection changes, we just get
// rid of it (in SelectionChanged()) and set mSelectionList to NULL
Boolean usingCachedSelection = (mSelectionList != NULL);
selection.selectionList
= (MSG_ViewIndex*)Inherited::GetUpdatedSelectionList(
(TableIndexT&)selection.selectionSize);
if (!selection.selectionList)
return false;
if (usingCachedSelection)
return true;
// Have selection, not cached, so convert in place from 1-based to 0-based
MSG_ViewIndex* index = selection.selectionList;
for (TableIndexT i = 0; i < selection.selectionSize; i++, index++)
(*index)--;
return true;
} // CMailFlexTable::GetSelection
//-----------------------------------
const TableIndexT* CMailFlexTable::GetUpdatedSelectionList(TableIndexT& /*outSelectionSize*/)
// This override is here to stop people calling it. Mail table requires a different type
// for the index and a zero-based one at that!
//-----------------------------------
{
Assert_(false); // Use GetSelection() instead.
return NULL;
} // CMailFlexTable::GetUpdatedSelectionList
//----------------------------------------------------------------------------------------
void CMailFlexTable::AddSelectionToDrag(
DragReference inDragRef,
RgnHandle inDragRgn)
// Adds a single drag item, which is an array of the
// selected row indices.
// Throws drag manager errors.
//----------------------------------------------------------------------------------------
{
Inherited::AddSelectionToDrag(inDragRef, inDragRgn);
// Our drag data is just a pointer to a list of our selected items
// Danger: the list changes when the selection changes,
// so this pointer's lifetime is limited.
CMailSelection selection;
if (GetSelection(selection))
{
mDragFlavor = kMailNewsSelectionDragFlavor;
OSErr err = ::AddDragItemFlavor(inDragRef, eMailNewsSelectionDragItemRefNum,
mDragFlavor, &selection, sizeof(selection), flavorSenderOnly);
ThrowIfOSErr_(err);
}
} // CMailFlexTable::AddSelectionToDrag
//----------------------------------------------------------------------------------------
void CMailFlexTable::AddRowToDrag(
TableIndexT inRow,
DragReference inDragRef,
RgnHandle inDragRgn)
// 98/04/03 added to support dragging of an unselected item.
// Adds a single drag item, which is an array of ONE row index, probably not currently
// selected!
// Throws drag manager errors.
//----------------------------------------------------------------------------------------
{
if (inRow == LArray::index_Bad)
return;
Inherited::AddRowToDrag(inRow, inDragRef, inDragRgn);
// Our drag data is just a pointer to a pseudo selection
// Danger: the list changes when the selection changes,
// so this pointer's lifetime is limited.
CMailSelection selection;
// Subtract 1 to make a MSG_ViewIndex (0-based) from the TableIndexT (1-based)
selection.xpPane = mMsgPane;
selection.SetSingleSelection(inRow - 1);
mDragFlavor = kMailNewsSelectionDragFlavor;
OSErr err = ::AddDragItemFlavor(inDragRef, eMailNewsSelectionDragItemRefNum,
mDragFlavor, &selection, sizeof(selection), flavorSenderOnly);
ThrowIfOSErr_(err);
} // CMailFlexTable::AddSelectionToDrag
//----------------------------------------------------------------------------------------
Boolean CMailFlexTable::GetSelectionFromDrag(
DragReference inDragRef,
CMailSelection& outSelection)
// Get the selection back out from the drag data.
// NOTE: this is called by the DESTINATION pane of the drop.
// The only flavor we need is kMailNewsSelectionDragFlavor
//----------------------------------------------------------------------------------------
{
Size dataSize;
dataSize = sizeof(CMailSelection);
if (noErr != ::GetFlavorData(
inDragRef,
eMailNewsSelectionDragItemRefNum,
kMailNewsSelectionDragFlavor,
&outSelection,
&dataSize,
0))
return false;
Assert_(dataSize == sizeof(CMailSelection));
outSelection.Normalize();
Assert_(outSelection.GetSelectionList() != NULL);
return true;
} // CMailFlexTable::GetSelectionFromDrag
//-----------------------------------
void CMailFlexTable::ToggleExpandAction(TableIndexT row)
//-----------------------------------
{
// rowDelta tells us how many items are added or removed. We don't
// need it, because we call ChangeFinished in the FE_LIstChangeFinished
// callback.
SInt32 rowDelta;
MSG_ToggleExpansion(mMsgPane, row - 1, &rowDelta);
} // CMailFlexTable::ToggleExpansion
//-----------------------------------
void CMailFlexTable::ChangeStarting(
MSG_Pane* /* inPane */,
MSG_NOTIFY_CODE /* inChangeCode */,
TableIndexT /* inStartRow */,
SInt32 /* inRowCount */)
//-----------------------------------
{
++mMysticPlane;
} // CMailFlexTable::ChangeStarting
//-----------------------------------
void CMailFlexTable::RowsChanged(TableIndexT inFirst, TableIndexT inCount)
// Accumulate a range of rows to update. We use this to delay refreshing until
// mMysticPlane has reached zero (outer call).
//-----------------------------------
{
if (inCount == 0 || inFirst == 0)
return;
if (inFirst > mRows)
return;
if (mFirstRowToRefresh == 0 || inFirst < mFirstRowToRefresh)
mFirstRowToRefresh = inFirst;
TableIndexT maxCount = mRows - inFirst + 1;
if (inCount > maxCount)
mLastRowToRefresh = ULONG_MAX;
else
{
TableIndexT last = inFirst + inCount - 1;
if (last > mLastRowToRefresh)
mLastRowToRefresh = last;
}
} // CMailFlexTable::RowsChanged
//-----------------------------------
void CMailFlexTable::ChangeFinished(
MSG_Pane* /* inPane */,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount)
//-----------------------------------
{
if (mMysticPlane > 0)
--mMysticPlane;
if (mMsgPane && (mMysticPlane <= (kMysticUpdateThreshHold+1))) switch (inChangeCode)
{
case MSG_NotifyInsertOrDelete:
{
if (inRowCount > 0)
{
if (mRows + inRowCount > ::MSG_GetNumLines(mMsgPane))
{
// Undo bug. Undo inserts extra rows.
Assert_(FALSE); // congrats! The backend "extra ghost row on undo" bug.
}
else
{
// InsertRows has an "inAfterRow" parameter, but the meaning of
// inStartRow as received from libmsg is that it is the index of
// the first INSERTED row!
InsertRows(inRowCount, inStartRow - 1, NULL, 0, false); // line order...
RowsChanged(inStartRow, ULONG_MAX); // ...does matter
}
}
else if (inRowCount < 0 && mRows > 0)
{
if (inStartRow - inRowCount - 1 <= mRows)
{
RowsChanged(inStartRow, ULONG_MAX); // line order...
RemoveRows(-inRowCount, inStartRow, false); // ...does matter
}
}
break;
}
case MSG_NotifyChanged:
{
RowsChanged(inStartRow, inRowCount);
break;
}
case MSG_NotifyScramble:
case MSG_NotifyAll:
SetRowCount();
// TableIndexT rows, cols;
// GetTableSize(rows, cols);
mFirstRowToRefresh =1 ;
mLastRowToRefresh = ULONG_MAX;
break;
default:
case MSG_NotifyNone:
break;
} // switch
if (mMysticPlane == 0 && mFirstRowToRefresh != 0)
{
const STableCell topLeftCell(mFirstRowToRefresh, 1);
const STableCell botRightCell(
mLastRowToRefresh > mRows ? mRows : mLastRowToRefresh, mCols);
if (mLastRowToRefresh > mRows)
{
// (note that we're refreshing all the way to the bottom here).
// Because of the complication of "reconcile
// overhang", we really need to refresh all --- but only if part of the
// range is visible. To do this, we need only check if the top of the top cell
// is above the bottom of the frame.
Int32 cellLeft, cellTop, cellRight, cellBottom;
mTableGeometry->GetImageCellBounds(topLeftCell, cellLeft, cellTop,
cellRight, cellBottom);
// Convert from image coordinates to port coordinates
cellTop += mImageLocation.v;
Int32 frameBottom = mFrameLocation.v + mFrameSize.height;
if (cellTop <= frameBottom) // Note the "=", edge case for deleting the last row.
Refresh();
}
else
RefreshCellRange(topLeftCell, botRightCell);
mFirstRowToRefresh = 0;
mLastRowToRefresh = 0;
}
} // CMailFlexTable::ChangeFinished
//-----------------------------------
void CMailFlexTable::PaneChanged(
MSG_Pane* /* inPane */,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 /* value */)
//-----------------------------------
{
switch (inNotifyCode)
{
case MSG_PanePastPasswordCheck:
//EnableStopButton(true);
break;
}
} // CMailFlexTable::PaneChanged
//-----------------------------------
Boolean CMailFlexTable::FindMessageLibraryCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
// returns false if not a msglib command.
//-----------------------------------
{
CMailSelection selection;
GetSelection(selection);
return UMessageLibrary::FindMessageLibraryCommandStatus(
GetMessagePane(),
(MSG_ViewIndex*)selection.GetSelectionList(),
selection.selectionSize,
inCommand,
outEnabled,
outUsesMark,
outMark,
outName);
}
//-----------------------------------
void CMailFlexTable::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
//-----------------------------------
{
if (mClosing) // don't respond to BE callbacks when being destroyed
return;
if (inCommand == cmd_Stop && mStillLoading)
{
outEnabled = true; // stop button on, nothing else.
return;
// ... otherwise, fall through and pass it up to the window
}
if (!mMsgPane)
{
LCommander::GetTopCommander()->FindCommandStatus(
inCommand, outEnabled, outUsesMark, outMark, outName);
return;
}
switch (inCommand)
{
case cmd_AddToBookmarks:
{
outEnabled = mContext && SHIST_GetCurrent(&((MWContext*)*mContext)->hist);
return;
}
}
if (!FindMessageLibraryCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName)
|| !outEnabled)
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
} // CMailFlexTable::FindCommandStatus
//-----------------------------------
Boolean CMailFlexTable::ObeyMessageLibraryCommand(
CommandT inCommand,
void * /* ioParam*/)
// Commands handled here are enabled/disabled in
// UMessageLibrary::FindMessageLibraryCommandStatus.
//-----------------------------------
{
CStr255 commandName;
MSG_CommandType cmd;
switch (inCommand)
{
case cmd_CompressAllFolders:
inCommand = cmd_CompressFolder;
cmd = MSG_CompressFolder; // see hack below.
break;
default:
// Callers rely on this to check if it really is a msglib command.
// Do that first.
cmd = UMessageLibrary::GetMSGCommand(inCommand);
break;
}
if (!UMessageLibrary::IsValidCommand(cmd))
return false;
// For msglib commands, we have to be careful to check whether the command
// can be handled for THIS pane, because (in the case of a thread pane)
// the message pane might have enabled the menu item. Failing to check
// again here leads to a nasty crash.
Boolean enabled; Boolean usesMark; Char16 mark;
if (inCommand == cmd_Undo)
{
inCommand = mUndoCommand;
// set it for next time
mUndoCommand = (inCommand == cmd_Undo) ? cmd_Redo : cmd_Undo;
}
else
mUndoCommand = cmd_Undo;
if (!FindMessageLibraryCommandStatus(inCommand, enabled, usesMark, mark, commandName)
|| !enabled)
{
if (inCommand == cmd_CompressFolder)
{
// Hack.
// The logic is: if the selection permits MSG_CompressFolder, then do that.
// Otherwise, try for MSG_CompressAllFolders. We can't change the resources
// now (localization freeze). So the menu may have either of these commands
// in it.
// I don't think that we will ever get here since FindCommand status does a
// a conversion between CompressFolder and CompressALLFolders --djm
inCommand = cmd_CompressAllFolders;
cmd = MSG_CompressAllFolders;
if (!FindMessageLibraryCommandStatus(inCommand, enabled, usesMark, mark, commandName)
|| !enabled)
return false;
}
else
return false;
}
// YAH (Yet another Hack) FindMessageLibraryCommandStatus is going to return true since it internally
// does a conversion between cmd_CompressAllFolders and cmd_CompressFolder. The command then never
// gets switched
if ( inCommand == cmd_CompressFolder )
{
CMailSelection selection;
GetSelection(selection);
XP_Bool plural;
XP_Bool enabledCommand = false;
MSG_COMMAND_CHECK_STATE checkedState;
const char* display_string = nil;
MSG_CommandStatus( GetMessagePane(), MSG_CompressFolder,
(MSG_ViewIndex*)selection.GetSelectionList(), selection.selectionSize,
&enabledCommand, &checkedState, &display_string, &plural) ;
// If the Compress Folder isn't enabled then Compress all is enabled
if ( !enabledCommand )
{
inCommand = cmd_CompressAllFolders;
cmd = MSG_CompressAllFolders;
}
}
try
{
#define ALLOW_MODELESS_PROGRESS 1
#define ALLOW_MODAL_PROGRESS 1
Boolean cmdHandled = false;
switch (cmd)
{
case MSG_GetNewMail:
case 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 CMessageView.cp.
// - 98/02/10 jrm.
PREF_SetBoolPref("offline.download_discussions", true);
PREF_SetBoolPref("offline.download_mail", true);
PREF_SetBoolPref("offline.download_directories", false);
UOffline::ObeySynchronizeCommand();
cmdHandled = true;
}
else if (ALLOW_MODELESS_PROGRESS)
{
// Modeless window with separate context and pane
CMailProgressWindow::ObeyMessageLibraryCommand(
CMailProgressWindow::res_ID_modeless,
GetMessagePane(), cmd, commandName);
cmdHandled = true;
}
break;
case MSG_MarkAllRead:
// Can't display a dialog with command(s) which apply to
// all the messages at once in the list because we don't
// get the callbacks from the BE which allow to update
// the progress bar and close the Progress window.
break;
case MSG_CompressFolder:
case MSG_CompressAllFolders:
// Bug #90378 (BE problem which is much easier to fix in the FE)
// Make these commands run inside their own separate context.
CMailSelection selection;
GetSelection(selection);
CMailProgressWindow::ObeyMessageLibraryCommand(
CMailProgressWindow::res_ID_modeless,
GetMessagePane(), cmd, commandName,
(MSG_ViewIndex*)selection.GetSelectionList(),
selection.selectionSize);
cmdHandled = true;
break;
default:
if (ALLOW_MODAL_PROGRESS && !NET_IsOffline())
{
// Modal parasite window with same context and pane
CMailProgressWindow::CreateModalParasite(
CMailProgressWindow::res_ID_modal,
GetMessagePane(), commandName);
}
break;
}
if (! cmdHandled)
{
CMailSelection selection;
GetSelection(selection);
MSG_Command(GetMessagePane(), cmd,
(MSG_ViewIndex*)selection.GetSelectionList(),
selection.selectionSize);
}
}
catch(...)
{
}
return true;
} // CMailFlexTable::ObeyMessageLibraryCommand
//-----------------------------------
Boolean CMailFlexTable::ObeyCommand(
CommandT inCommand,
void *ioParam)
//-----------------------------------
{
if (mClosing) // don't respond to BE callbacks when being destroyed
return false;
if (mStillLoading && inCommand != cmd_Stop)
return false;
if (!mMsgPane)
return LCommander::GetTopCommander()->ObeyCommand(inCommand, ioParam);
switch (inCommand)
{
case cmd_Stop:
{
if (mContext)
XP_InterruptContext(*mContext);
EnableStopButton(false);
return true;
}
case cmd_AddToBookmarks:
{
// MSG_GetFolderInfoFromURL() does not work for URLs pointing to Mail & News messages.
// SHIST_GetCurrent(&((MWContext*)*mContext)->hist)
// );
// Nova: BM_Entry *entry = SHIST_CreateHotlistStructFromHistoryEntry(
// SHIST_GetCurrent(&((MWContext*)*mContext)->hist) );
History_entry *entry = mContext->GetCurrentHistoryEntry(); // Mozilla
if (entry)
CBookmarksAttachment::AddToBookmarks(entry->address, entry->title);
else
SysBeep(1);
break;
}
case cmd_Preferences:
CPrefsDialog::EditPrefs(CPrefsDialog::eExpandMailNews);
return true;
default:
return ObeyMessageLibraryCommand(inCommand, ioParam)
|| Inherited::ObeyCommand(inCommand, ioParam);
}
return false;
} // CMailFlexTable::ObeyCommand
//-----------------------------------
void CMailFlexTable::EnableStopButton(Boolean inBusy)
//-----------------------------------
{
if (inBusy == mStillLoading)
return;
mStillLoading = inBusy;
(CFrontApp::GetApplication())->UpdateMenus();
// done in CFrontApp::UpdateMenus() already. CPaneEnabler::UpdatePanes();
}
//-----------------------------------
void CMailFlexTable::DrawCountCell(
Int32 inCount,
const Rect& inLocalRect)
// inCount < 0 indicates unknown value
//-----------------------------------
{
char sizeString[32];
if (inCount >= 0)
sprintf(sizeString, "%d", inCount);
else
sprintf(sizeString, "?");
DrawTextString(sizeString, &mTextFontInfo, 2, inLocalRect, true, truncEnd);
} // CMessageFolderView::DrawCountCell
//-----------------------------------
void CMailFlexTable::ListenToMessage(MessageT inMessage, void* ioParam)
//-----------------------------------
{
switch (inMessage)
{
case CMailCallbackManager::msg_PaneChanged:
case CMailCallbackManager::msg_ChangeStarting:
case CMailCallbackManager::msg_ChangeFinished:
if (IsMyPane(ioParam))
CMailCallbackListener::ListenToMessage(inMessage, ioParam);
break;
case msg_NSCStartLoadURL:
case msg_NSCProgressBegin:
EnableStopButton(true);
break;
case msg_NSCAllConnectionsComplete:
EnableStopButton(false);
break;
default:
if (!IsOnDuty() || !ObeyCommand(inMessage, ioParam))
ListenToHeaderMessage(inMessage, ioParam);
}
} // CMailFlexTable::ListenToMessage
//---------------------------------------------------------------------
char* CMailFlexTable::GetTextFromDrag(
DragReference inDragRef,
ItemReference inItemRef)
// Check if this drag is a URL and returns the URL if it is.
// *** It is the responsibility of the client to delete the returned
// result by calling XP_FREEIF()
//---------------------------------------------------------------------
{
// get the drag data size
Size dataSize = 0;
OSErr err = ::GetFlavorDataSize(inDragRef, inItemRef, 'TEXT', &dataSize);
if (err)
return nil; // we can't throw during a drag! Inconvenient in MWDebug.
char* result = (char*)XP_ALLOC(1 + dataSize);
if (!result)
return nil;
unsigned long offset = 0;
// get the data out of the drag and put it into the buffer
err = ::GetFlavorData(inDragRef, inItemRef, 'TEXT', result, &dataSize, offset);
if (!err)
{
// terminate the string with a null char
result[dataSize] = '\0';
return result;
}
XP_FREEIF(result);
return nil;
} // CMailFlexTable::GetTextFromDrag
//---------------------------------------------------------------------
MessageKey CMailFlexTable::MessageKeyFromURLDrag(
DragReference inDragRef,
ItemReference inItemRef)
// Check if this drag is the URL of a message and returns the message key if it is.
//---------------------------------------------------------------------
{
MessageKey result = MSG_MESSAGEKEYNONE;
char* url = GetTextFromDrag(inDragRef, inItemRef);
if (!url)
return MSG_MESSAGEKEYNONE;
MSG_MessageLine messageLine;
int status = MSG_GetMessageLineForURL( CMailNewsContext::GetMailMaster(), url, &messageLine );
if (status >= 0)
result = messageLine.messageKey;
XP_FREEIF(url);
return result;
} // CMailFlexTable::MessageKeyFromURLDrag
//---------------------------------------------------------------------
MSG_FolderInfo* CMailFlexTable::GetFolderInfoFromURLDrag(
DragReference inDragRef,
ItemReference inItemRef)
// Check if this drag is the URL of a folder and returns the folderInfo if it is.
//---------------------------------------------------------------------
{
char* url = GetTextFromDrag(inDragRef, inItemRef);
if (!url)
return nil;
MSG_FolderInfo* result = MSG_GetFolderInfoFromURL(CMailNewsContext::GetMailMaster(), url, false);
XP_FREEIF(url);
return result;
} // CMailFlexTable::GetFolderInfoFromURLDrag

View File

@ -0,0 +1,195 @@
/* -*- 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.
*/
#pragma once
#include "msgcom.h"
#include "CStandardFlexTable.h"
#include "MailNewsCallbacks.h"
const kMysticUpdateThreshHold = 10;
class CMailNewsContext;
class CMailProgressWindow;
class CMailSelection;
//========================================================================================
class CMailFlexTable
: public CStandardFlexTable
, public CMailCallbackListener
// Like CStandardFlexTable, an abstract class.
//========================================================================================
{
private:
typedef CStandardFlexTable Inherited;
public:
enum
{ class_ID = 'mfTb'
};
enum
{
eMailNewsSelectionDragItemRefNum = 0
};
CMailFlexTable(LStream *inStream);
virtual ~CMailFlexTable();
virtual void SetRowCount();
Boolean IsStillLoading() const { return mStillLoading; }
//-----------------------------------
// Drawing
//-----------------------------------
virtual void DrawSelf();
//-----------------------------------
// Selection
//-----------------------------------
virtual Boolean GetSelection(CMailSelection&);
// CStandardFlexTable has one-based lists which are lists of TableIndexT.
// CMailSelection requires zero-based lists which are lists of MSG_ViewIndex
// This routine clones and converts.
virtual void OpenSelection();
//-----------------------------------
// Drag/drop
//-----------------------------------
FlavorType GetMessageFlavor(TableIndexT /*inMessageRow*/) const
{ return mDragFlavor; }
virtual void AddSelectionToDrag(
DragReference inDragRef, RgnHandle inDragRgn);
virtual void AddRowToDrag(
TableIndexT inRow,
DragReference inDragRef,
RgnHandle inDragRgn);
Boolean GetSelectionFromDrag(
DragReference inDragRef,
CMailSelection& outSelection);
CNSContext* GetContext() const { return mContext; }
//-----------------------------------
// CMailCallbackListener overrides
//-----------------------------------
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
MSG_Pane* GetMessagePane(void) const
{ return mMsgPane; }
virtual void DestroyMessagePane( MSG_Pane* inPane );
void ListenToMessage(MessageT inMessage, void* ioParam);
protected:
void SetMessagePane(MSG_Pane* inPane);
static char* GetTextFromDrag(
DragReference inDragRef,
ItemReference inItemRef);
// Caller must XP_FREE the result.
static MSG_FolderInfo* GetFolderInfoFromURLDrag(
DragReference inDragRef,
ItemReference inItemRef);
// Check if this drag is the URL of a folder
// and returns the folderInfo if it is.
static MessageKey MessageKeyFromURLDrag(
DragReference inDragRef,
ItemReference inItemRef);
// Check if this drag is the URL of a message
// and returns the message key if it is.
//-----------------------------------
// Commands
//-----------------------------------
protected:
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
Boolean FindMessageLibraryCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
// returns false if not a msglib command.
Boolean ObeyMessageLibraryCommand(
CommandT inCommand,
void *ioParam);
void NotifySelfAll() { // Manual notification for BE bugs!
ChangeStarting(mMsgPane, MSG_NotifyAll, 0, 0);
ChangeFinished(mMsgPane, MSG_NotifyAll, 0, 0);
}
public:
void EnableStopButton(Boolean inBusy);
//-----------------------------------
// Internal helpers
//-----------------------------------
protected:
void DrawCountCell(
Int32 inCount,
const Rect& inLocalRect);
void RowsChanged(TableIndexT inFirst, TableIndexT inCount);
//-----------------------------------
// Window Saving
//-----------------------------------
private:
virtual const TableIndexT* GetUpdatedSelectionList(TableIndexT& outSelectionSize);
// This does an assert: the idea is to use only GetSelection, above.
protected:
//-----------------------------------
// Discloser support
//-----------------------------------
void ToggleExpandAction(TableIndexT row);
protected:
CNSContext* mContext; // Belongs to the window, not us.
SInt32 mMysticPlane; // for keeping track of callback level
FlavorType mDragFlavor;
Boolean mStillLoading;
TableIndexT mFirstRowToRefresh;
TableIndexT mLastRowToRefresh;
Boolean mClosing;
CommandT mUndoCommand; // cmd_Undo or cmd_Redo
private:
MSG_Pane* mMsgPane; // MUST be private. Must call Get/Set.
}; // class CMailFlexTable

View File

@ -0,0 +1,503 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMailFolderButtonPopup.cp
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "CMailFolderButtonPopup.h"
#include "StSetBroadcasting.h"
#include "MailNewsgroupWindow_Defines.h"
#include "CDrawingState.h"
#include "CMessageFolder.h"
#pragma mark -
/*======================================================================================
Call UpdateMailFolderMixins() to initialize the menu.
======================================================================================*/
void CMailFolderButtonPopup::FinishCreateSelf(void) {
CPatternButtonPopup::FinishCreateSelf();
CMailFolderMixin::UpdateMailFolderMixinsNow(this);
}
/*======================================================================================
Instead of broadcasting the actual value, broadcast the new folder string.
======================================================================================*/
void CMailFolderButtonPopup::BroadcastValueMessage(void) {
if ( mValueMessage != msg_Nothing )
{
BroadcastMessage(mValueMessage, MGetSelectedFolder().GetFolderInfo());
}
}
/*======================================================================================
When the user selects a new item, we don't really want to change the currently
selected item in the menu, just broadcast the item that the user selected and
reset the currently selected item.
======================================================================================*/
Boolean CMailFolderButtonPopup::TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers) {
// Store the current value
Int32 oldValue = mValue;
OSErr thrownErr = noErr;
Boolean result;
Try_ {
result = CPatternButtonPopup::TrackHotSpot(inHotSpot, inPoint, inModifiers);
}
Catch_(inErr) {
thrownErr = inErr;
}
EndCatch_
// Reset the old value
StSetBroadcasting setBroadcasting(this, false); // Don't broadcast anything here
SetValue(oldValue);
FailOSErr_(thrownErr);
return result;
}
/*======================================================================================
Get a handle to the Mac menu associated with this object.
======================================================================================*/
MenuHandle CMailFolderButtonPopup::MGetSystemMenuHandle(void)
{
MenuHandle menuH = nil;
if (GetMenu())
{
menuH = GetMenu()->GetMacMenuH();
}
return menuH;
}
/*======================================================================================
Refresh the menu display.
======================================================================================*/
void CMailFolderButtonPopup::MRefreshMenu(void) {
// Nothing, no user menu displayed unless clicked
}
#pragma mark -
//-----------------------------------
CMailFolderPatternTextPopup::CMailFolderPatternTextPopup(LStream *inStream)
: CPatternButtonPopupText(inStream)
//-----------------------------------
{
mUseFolderIcons = eUseFolderIcons;
// This is for the relocation menu, so add newsgroups.
CMailFolderMixin::mDesiredFolderFlags =
(FolderChoices)(int(mDesiredFolderFlags) | int(eWantNews));
}
/*======================================================================================
Call UpdateMailFolderMixins() to initialize the menu.
======================================================================================*/
void CMailFolderPatternTextPopup::FinishCreateSelf(void)
{
Inherited::FinishCreateSelf();
CMailFolderMixin::UpdateMailFolderMixinsNow(this);
}
/*======================================================================================
Instead of broadcasting the actual value, broadcast the new folder string.
======================================================================================*/
void CMailFolderPatternTextPopup::BroadcastValueMessage(void) {
if ( mValueMessage != msg_Nothing ) {
BroadcastMessage(mValueMessage, MGetSelectedFolder().GetFolderInfo());
}
}
/*======================================================================================
Unlike CMailFolderButtonPopup, when the user selects a new item, we DO really want
to change the currently selected item in the menu, not just broadcast the item that
the user selected and reset the currently selected item.
======================================================================================*/
Boolean CMailFolderPatternTextPopup::TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers)
{
return Inherited::TrackHotSpot(inHotSpot, inPoint, inModifiers);
}
void CMailFolderPatternTextPopup::HandlePopupMenuSelect( Point inPopupLoc,
Int16 inCurrentItem,
Int16 &outMenuID,
Int16 &outMenuItem)
{
Int16 saveFont = ::LMGetSysFontFam();
Int16 saveSize = ::LMGetSysFontSize();
StMercutioMDEFTextState theMercutioMDEFTextState;
Inherited::HandlePopupMenuSelect(inPopupLoc, inCurrentItem, outMenuID, outMenuItem);
// Restore the system font
::LMSetSysFontFam(saveFont);
::LMSetSysFontSize(saveSize);
::LMSetLastSPExtra(-1L);
}
/*======================================================================================
Get a handle to the Mac menu associated with this object.
======================================================================================*/
MenuHandle CMailFolderPatternTextPopup::MGetSystemMenuHandle(void) {
if ( GetMenu() )
return GetMenu()->GetMacMenuH();
return NULL;
}
/*======================================================================================
Refresh the menu display.
======================================================================================*/
void CMailFolderPatternTextPopup::MRefreshMenu(void) {
// Nothing, no user menu displayed unless clicked
}
#pragma mark -
//-----------------------------------
CMailFolderGAPopup::CMailFolderGAPopup(LStream *inStream)
: LGAPopup(inStream)
//-----------------------------------
{
mUseFolderIcons = eUseFolderIcons;
// This is for the relocation menu, so add newsgroups.
CMailFolderMixin::mDesiredFolderFlags =
(FolderChoices)(int(mDesiredFolderFlags) | int(eWantNews));
}
/*======================================================================================
Call UpdateMailFolderMixins() to initialize the menu.
======================================================================================*/
void CMailFolderGAPopup::FinishCreateSelf(void)
{
LGAPopup::FinishCreateSelf();
CMailFolderMixin::UpdateMailFolderMixinsNow(this);
}
/*======================================================================================
Instead of broadcasting the actual value, broadcast the new folder string.
======================================================================================*/
void CMailFolderGAPopup::BroadcastValueMessage(void) {
if ( mValueMessage != msg_Nothing ) {
BroadcastMessage(mValueMessage, MGetSelectedFolder().GetFolderInfo());
}
}
/*======================================================================================
Unlike CMailFolderButtonPopup, when the user selects a new item, we DO really want
to change the currently selected item in the menu, not just broadcast the item that
the user selected and reset the currently selected item.
======================================================================================*/
Boolean CMailFolderGAPopup::TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers)
{
return LGAPopup::TrackHotSpot(inHotSpot, inPoint, inModifiers);
}
void CMailFolderGAPopup::HandlePopupMenuSelect( Point inPopupLoc,
Int16 inCurrentItem,
Int16 &outMenuID,
Int16 &outMenuItem)
{
Int16 saveFont = ::LMGetSysFontFam();
Int16 saveSize = ::LMGetSysFontSize();
StMercutioMDEFTextState theMercutioMDEFTextState;
LGAPopup::HandlePopupMenuSelect(inPopupLoc, inCurrentItem, outMenuID, outMenuItem);
// Restore the system font
::LMSetSysFontFam(saveFont);
::LMSetSysFontSize(saveSize);
::LMSetLastSPExtra(-1L);
}
/*======================================================================================
Get a handle to the Mac menu associated with this object.
======================================================================================*/
MenuHandle CMailFolderGAPopup::MGetSystemMenuHandle(void) {
return GetMacMenuH();
}
/*======================================================================================
Refresh the menu display.
======================================================================================*/
void CMailFolderGAPopup::MRefreshMenu(void) {
// Nothing, no user menu displayed unless clicked
}
#pragma mark -
//-----------------------------------
CFolderScopeGAPopup::CFolderScopeGAPopup(LStream* inStream)
//-----------------------------------
: CMailFolderGAPopup(inStream)
{
// This is for the scope menu in the message search window.
mUseFolderIcons = eUseFolderIcons;
CMailFolderMixin::mDesiredFolderFlags =
(FolderChoices)(int(mDesiredFolderFlags) | int(eWantNews) | int(eWantHosts));
}
#pragma mark -
// Class static members
CMailFolderSubmenu *CMailFolderSubmenu::sMoveMessageMenu = nil;
CMailFolderSubmenu *CMailFolderSubmenu::sCopyMessageMenu = nil;
// Helper functions
static void CreateMailFolderSubmenu(Int16 inMENUid, CMailFolderSubmenu **outMenu) {
if ( *outMenu == nil ) {
Try_ {
*outMenu = new CMailFolderSubmenu(inMENUid);
if ( *outMenu ) {
CMailFolderMixin::UpdateMailFolderMixinsNow(*outMenu);
}
}
Catch_(inErr) {
if ( *outMenu ) {
delete *outMenu;
*outMenu = nil;
}
}
EndCatch_
}
}
static void InstallMailFolderSubmenu(CommandT inCommand, CMailFolderSubmenu *inMenu) {
if ( inMenu && !inMenu->IsInstalled() ) {
ResIDT menuID;
MenuHandle menuHandle;
Int16 menuItem;
LMenuBar::GetCurrentMenuBar()->FindMenuItem(inCommand, menuID,
menuHandle, menuItem);
if ( menuHandle != nil ) {
LMenuBar::GetCurrentMenuBar()->InstallMenu(inMenu, hierMenu);
// Install the submenu (hierarchical menu)
::SetItemCmd(menuHandle, menuItem, hMenuCmd);
::SetItemMark(menuHandle, menuItem, inMenu->GetMenuID());
}
}
}
static void RemoveMailFolderSubmenu(CMailFolderSubmenu *inMenu) {
if ( inMenu && inMenu->IsInstalled() ) {
LMenuBar::GetCurrentMenuBar()->RemoveMenu(inMenu);
}
}
/*======================================================================================
Install the mail folder submenus (file, copy) into the current menu bar. If the
menu bar already contains the submenus, do nothing. This method should be called
when a window using the menus becomes active.
This method can be called at any time.
======================================================================================*/
void CMailFolderSubmenu::InstallMailFolderSubmenus(void) {
// Create and initialize the menus if they don't exist yet
CreateMenus();
// Install the menus
InstallMailFolderSubmenu(cmd_MoveMailMessages, sMoveMessageMenu);
InstallMailFolderSubmenu(cmd_CopyMailMessages, sCopyMessageMenu);
}
/*======================================================================================
Remove the mail folder submenus (file, copy) from the current menu bar. If the
menu bar doesn't contain the submenus, do nothing. This method should be called
when a window using the menus becomes inactive or a new menu bar is installed.
This method can be called at any time.
======================================================================================*/
void CMailFolderSubmenu::RemoveMailFolderSubmenus(void) {
// Remove the menus
RemoveMailFolderSubmenu(sMoveMessageMenu);
RemoveMailFolderSubmenu(sCopyMessageMenu);
}
//-----------------------------------
void CMailFolderSubmenu::SetSelectedFolder(const MSG_FolderInfo* inInfo)
// Set the currently selected folder item in the hierarchical menus. If inInfo is nil
// or empty, all items are unselected.
//
// This method can be called at any time.
//-----------------------------------
{
// Create and initialize the menus if they don't exist yet
CreateMenus();
if ( sMoveMessageMenu != nil )
sMoveMessageMenu->MSetSelectedFolder(inInfo);
if ( sCopyMessageMenu != nil )
sCopyMessageMenu->MSetSelectedFolder(inInfo);
}
//-----------------------------------
Boolean CMailFolderSubmenu::IsMailFolderCommand(CommandT *ioMenuCommand, const char** outName)
// Determine if the specified synthetic menu command passed to ObeyCommand() is from
// a mail folder menu. If it is, reassign ioMenuCommand to represent the actual mail
// folder command ID and set outName to the name of the selected mail folder and return
// true. Otherwise, return false and do nothing. outName can be nil, in which case no
// name is assigned.
//
// This method can be called at any time.
//-----------------------------------
{
ResIDT menuID;
Int16 menuItem;
if ( LCommander::IsSyntheticCommand(*ioMenuCommand, menuID, menuItem) )
{
if ( menuID == menuID_MoveMessage )
{
if ( sMoveMessageMenu != nil )
{
*ioMenuCommand = cmd_MoveMailMessages;
if ( outName != nil )
*outName = sMoveMessageMenu->MGetFolderName(menuItem);
return true;
}
}
else if ( menuID == menuID_CopyMessage )
{
if ( sCopyMessageMenu != nil )
{
*ioMenuCommand = cmd_CopyMailMessages;
if ( outName != nil )
*outName = sCopyMessageMenu->MGetFolderName(menuItem);
return true;
}
}
}
return false;
}
/*======================================================================================
Create the hierarchical menus if they don't already exist.
This method can be called at any time.
======================================================================================*/
void CMailFolderSubmenu::CreateMenus(void) {
// Create and initialize the menus if they don't exist yet
CreateMailFolderSubmenu(CMailFolderSubmenu::menuID_MoveMessage, &sMoveMessageMenu);
CreateMailFolderSubmenu(CMailFolderSubmenu::menuID_CopyMessage, &sCopyMessageMenu);
}
#pragma mark -
/*======================================================================================
======================================================================================*/
CFolderMoveGAPopup::CFolderMoveGAPopup(LStream *inStream) :
CMailFolderGAPopup( inStream )
{
}
CFolderMoveGAPopup::~CFolderMoveGAPopup()
{
}
// reset the default menu item to the original value
Boolean
CFolderMoveGAPopup::TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers)
{
Int32 oldValue = GetValue();
bool result = false;
result = LGAPopup::TrackHotSpot(inHotSpot, inPoint, inModifiers);
if (oldValue != GetValue())
{
BroadcastMessage(mValueMessage, MGetSelectedFolder().GetFolderInfo());
}
else
{
// we want to prevent a broadcast because we have already
// sent one out when we set the value of the control
StSetBroadcasting broacast(this, false);
SetValue(oldValue);
}
return result;
}

View File

@ -0,0 +1,198 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMailFolderButtonPopup.h
#pragma once
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "CPatternButtonPopup.h"
#include "CPatternButtonPopupText.h"
#include "UMailFolderMenus.h"
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
#pragma mark - CMailFolderButtonPopup
//======================================
class CMailFolderButtonPopup : public CPatternButtonPopup,
public CMailFolderPopupMixin
// Class for the button popup
//======================================
{
public:
enum { class_ID = 'MfPu' };
CMailFolderButtonPopup(LStream *inStream) :
CPatternButtonPopup(inStream) {
}
protected:
virtual void FinishCreateSelf(void);
virtual void BroadcastValueMessage(void);
virtual Boolean TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers);
virtual MenuHandle MGetSystemMenuHandle(void);
virtual void MRefreshMenu(void);
};
#pragma mark - CMailFolderPatternTextPopup
//======================================
class CMailFolderPatternTextPopup : public CPatternButtonPopupText,
public CGAPopupFolderMixin
// Class for the relocation popup menu in the thread pane
//======================================
{
private:
typedef CPatternButtonPopupText Inherited;
public:
enum { class_ID = 'MfPT' };
CMailFolderPatternTextPopup(LStream *inStream);
protected:
virtual void FinishCreateSelf(void);
virtual void BroadcastValueMessage(void);
virtual Boolean TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers);
virtual void HandlePopupMenuSelect( Point inPopupLoc,
Int16 inCurrentItem,
Int16 &outMenuID,
Int16 &outMenuItem);
virtual MenuHandle MGetSystemMenuHandle(void);
virtual void MRefreshMenu(void);
}; // class CMailFolderPatternTextPopup
#pragma mark - CMailFolderGAPopup
//======================================
class CMailFolderGAPopup : public LGAPopup,
public CGAPopupFolderMixin
// Class for the relocation popup menu in the thread pane
//======================================
{
public:
enum { class_ID = 'MfPM' };
CMailFolderGAPopup(LStream *inStream);
protected:
virtual void FinishCreateSelf(void);
virtual void BroadcastValueMessage(void);
virtual Boolean TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers);
virtual void HandlePopupMenuSelect( Point inPopupLoc,
Int16 inCurrentItem,
Int16 &outMenuID,
Int16 &outMenuItem);
virtual MenuHandle MGetSystemMenuHandle(void);
virtual void MRefreshMenu(void);
}; // class CMailFolderGAPopup
#pragma mark - CFolderScopeGAPopup
//======================================
class CFolderScopeGAPopup : public CMailFolderGAPopup
// differs from CMailFolderGAPopup only in the setting of mDesiredFolderFlags
//======================================
{
public:
enum { class_ID = 'SsPM' };
CFolderScopeGAPopup(LStream *inStream);
}; // class CFolderScopeGAPopup
#pragma mark - CFolderMoveGAPopup
//======================================
class CFolderMoveGAPopup : public CMailFolderGAPopup
//======================================
{
typedef CMailFolderGAPopup Inherited;
public:
enum { class_ID = 'SsFM' };
CFolderMoveGAPopup(LStream *inStream);
virtual ~CFolderMoveGAPopup();
protected:
virtual Boolean TrackHotSpot(
Int16 inHotSpot,
Point inPoint,
Int16 inModifiers);
}; // class CFolderScopeGAPopup
#pragma mark - CMailFolderSubmenu
//======================================
class CMailFolderSubmenu : public LMenu,
public CMenuMailFolderMixin
// Class for the hierarchical menu
//======================================
{
public:
static void InstallMailFolderSubmenus(void);
static void RemoveMailFolderSubmenus(void);
static void SetSelectedFolder(const MSG_FolderInfo* inInfo);
static Boolean IsMailFolderCommand(CommandT *ioMenuCommand, const char** outName = nil);
CMailFolderSubmenu(Int16 inMENUid,
CommandT inMenuCommand = cmd_UseMenuItem) :
LMenu(inMENUid),
CMenuMailFolderMixin(inMenuCommand) {
}
protected:
enum {
menuID_MoveMessage = 44
, menuID_CopyMessage = 46
};
static void CreateMenus(void);
// Instance variables
// Class variables
static CMailFolderSubmenu *sMoveMessageMenu;
static CMailFolderSubmenu *sCopyMessageMenu;
};

View File

@ -0,0 +1,426 @@
/* -*- 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.
*/
// CMailNewsContext.cp
#include "CMailNewsContext.h"
#include "ufilemgr.h"
#include "CCheckMailContext.h"
#include "UStdDialogs.h"
#include "CMessageFolderView.h"
// Command numbers
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
#include "uprefd.h"
#include "prefapi.h"
#include "shist.h"
#include "macutil.h"
#include "macgui.h"
#include "uerrmgr.h"
// get string constants
#define WANT_ENUM_STRING_IDS
#include "allxpstr.h"
#undef WANT_ENUM_STRING_IDS
#include "mimages.h"
#include "layers.h"
#include "CDrawable.h"
#include "CBrowserContext.h"
#include "CNSContextCallbacks.h"
#include "CMailProgressWindow.h"
// The message master from which all life springs...
MSG_Master* CMailNewsContext::sMailMaster = NULL;
Int32 CMailNewsContext::sMailMasterRefCount = 0;
MSG_Prefs* CMailNewsContext::sMailPrefs = NULL;
//----------------------------------------------------------------------------------------
CMailNewsContext::CMailNewsContext(MWContextType inContextType)
//----------------------------------------------------------------------------------------
: Inherited(inContextType)
, mWasPromptOkay( false )
{
ThrowUnlessPrefsSet(inContextType);
GetMailMaster(); // make sure it's there.
sMailMasterRefCount++;
SHIST_InitSession(&mContext);
#if 0
// Bug: hang when replying to a thread with attachment icons
// from the collapsed thread window.
// The following is left here as a caution to young programmers who might need a lesson
// learned the hard way by a foolish forerunner - me. The easy solution
// is to set the output_function pointer in mimemoz.c to a stub, so that no
// HTML is generated.
// Adding an image context avoids the hang by handling the attachment icon images.
CreateImageContext( &mContext );
// Adding a compositor to avoid the HTML dialog complaining about window.document.layers
// having "no properties" mime converter was adding javascript that referred to them.
CRouterDrawable* onscreenDrawable = new CRouterDrawable();
CL_Drawable * theDrawable = CL_NewDrawable(100, 100, CL_WINDOW,
&mfe_drawable_vtable, (void *) onscreenDrawable);
CL_Compositor* c = CL_NewCompositor(theDrawable, nil, 0, 0, 100, 100, 10);
CSharableCompositor* compositor = new CSharableCompositor(c);
compositor->AddUser(this); // shared by context and view. - NEVER REMOVED/ TEST/
mContext.compositor = *compositor;
CL_SetCompositorEnabled(*compositor, PR_TRUE);
#endif
} // CMailNewsContext::CMailNewsContext
//----------------------------------------------------------------------------------------
CMailNewsContext::~CMailNewsContext()
//----------------------------------------------------------------------------------------
{
XP_InterruptContext(*this); // This must happen before the master is deleted!
#if 1 //CNSContext::NoMoreUsers is responsible for disposing the history sessions
// yes, but 97/05/22 CNSContext::NoMoreUsers now has "NoMoreUsers".
LO_DiscardDocument(&mContext);
SHIST_EndSession(&mContext);
MimeDestroyContextData(&mContext);
// No java
// No layers
// No mocha
#endif //0
if (sMailMasterRefCount == 1)
{
// If we are about to delete the last mail-news context...
// (WARNING: there's a backend bug: MSG_CleanupNeeded will continue to return
// true even after the cleanup is finished. So be sure not to get into an
// infinite loop.)
if (mContext.type != MWContextMailNewsProgress && MSG_CleanupNeeded(sMailMaster))
{
try
{
CMailProgressWindow::CleanUpFolders();
}
catch(...)
{
// Don't throw here, we're trying to quit.
}
}
}
Assert_(sMailMaster);
Assert_(sMailMasterRefCount);
sMailMasterRefCount--;
if (sMailMasterRefCount == 0)
{
MSG_DestroyMaster(sMailMaster);
sMailMaster = NULL;
}
} // CMailNewsContext::~CMailNewsContext
//----------------------------------------------------------------------------------------
Boolean CMailNewsContext::IsPrefSet(const char* inPrefKey)
//----------------------------------------------------------------------------------------
{
char buffer[512]; int bufferLength = sizeof(buffer);
PREF_GetCharPref(inPrefKey, buffer, &bufferLength);
if (*buffer)
return true;
return false;
} // CMailNewsContext::IsPrefSet
//----------------------------------------------------------------------------------------
Boolean CMailNewsContext::ThrowUnlessPrefSet(
const char* inPrefKey,
PREF_Enum inPrefPaneSelector)
//----------------------------------------------------------------------------------------
{
if (IsPrefSet(inPrefKey))
return true;
AlertPrefAndThrow(inPrefPaneSelector);
return false; // dead, but the compiler needs this, see?
} // CMailNewsContext::ThrowUnlessPrefSet
//----------------------------------------------------------------------------------------
void CMailNewsContext::AlertPrefAndThrow(PREF_Enum inPrefPaneSelector)
//----------------------------------------------------------------------------------------
{
// OK. We're going to throw, but first, we prompt and send them to the prefs pane.
// Ask "Would you like to set the preference?"
short strID;
switch (inPrefPaneSelector)
{
case PREF_EmailAddress: strID = 23; break; // I don't know why but all string IDs from
case PREF_Pop3ID: strID = 21; break; // STR# 7099 are hard-coded in other parts
case PREF_SMTPHost: strID = 21; break; // of the code: let's continue!
case PREF_PopHost: strID = 21; break;
case PREF_NewsHost: strID = 22; break;
default: strID = 24; break;
}
CStr255 whereString;
::GetIndString(whereString, 7099, strID);
CStr255 alertString;
::GetIndString(alertString, 7099, 7);
::StringParamText(alertString, (char*)whereString, nil, nil, nil);
if (UStdDialogs::AskOkCancel(alertString, nil, nil)) // if "ok"
FE_EditPreference(inPrefPaneSelector);
throw (OSErr)userCanceledErr; // we already presented the alert. This avoids another.
} // CMailNewsContext::AlertPrefAndThrow
//----------------------------------------------------------------------------------------
/* static */ Boolean CMailNewsContext::UserHasNoLocalInbox()
//----------------------------------------------------------------------------------------
{
// Check whether there is an inbox in their local mail tree. If not, assume
// first time setup.
FSSpec inboxSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
// *(CStr63*)(inboxSpec.name) = XP_GetString(MK_MSG_INBOX_L10N_NAME);
// if (FSMakeFSSpec(inboxSpec.vRefNum, inboxSpec.parID, inboxSpec.name, &spec2) == fnfErr)
// return true;
FSSpec spec2;
*(CStr63*)(inboxSpec.name) = XP_GetString(MK_MSG_TRASH_L10N_NAME);
if (FSMakeFSSpec(inboxSpec.vRefNum, inboxSpec.parID, inboxSpec.name, &spec2) == fnfErr)
return true;
return false;
} // CMailNewsContext::UserHasNoLocalInbox
//----------------------------------------------------------------------------------------
/* static */ void CMailNewsContext::ThrowIfNoLocalInbox()
//----------------------------------------------------------------------------------------
{
if (UserHasNoLocalInbox())
AlertPrefAndThrow(PREF_PopHost);
} // CMailNewsContext::ThrowIfNoLocalInbox
//----------------------------------------------------------------------------------------
void CMailNewsContext::ThrowUnlessPrefsSet(MWContextType inContextType)
//----------------------------------------------------------------------------------------
{
if (inContextType == MWContextBiff
|| inContextType == MWContextSearch
|| inContextType == MWContextAddressBook
|| inContextType == MWContextMailFilters)
return; // no prefs required for biff.
#ifdef HAVE_SEPARATE_SMTP_USERNAME_PREF
//if (we are using POP)
// ThrowUnlessPrefSet("mail.pop_name",PREF_Pop3ID);
ThrowUnlessPrefSet("mail.smtp_name", PREF_Pop3ID);
#else
// temporary code while the backend is still using pop_name for smtp_name
if ( !IsPrefSet("mail.pop_name") )
{
char *smtpName = NULL;
if (PREF_CopyCharPref("mail.smtp_name", &smtpName) == PREF_NOERROR)
{
int prefError = PREF_SetCharPref("mail.pop_name", smtpName);
Assert_(prefError == PREF_NOERROR || prefError == PREF_VALUECHANGED);
}
XP_FREEIF(smtpName);
}
#endif
if (!IsPrefSet("network.hosts.pop_server") && !IsPrefSet("network.hosts.imap_servers"))
AlertPrefAndThrow(PREF_PopHost);
// OK, she has the basic stuff. Now for the fancy stuff. I know it's plain wrong
// to have a switch like this in an object-oriented world, but time is of the essence.
switch (inContextType)
{
case MWContextNews: // A news reader window
case MWContextNewsMsg: // A window to display a news msg
ThrowUnlessPrefSet(
"network.hosts.nntp_server",
PREF_NewsHost);
break;
case MWContextMessageComposition: // A news-or-mail message editing window
ThrowUnlessPrefSet(
"network.hosts.smtp_server",
PREF_SMTPHost);
ThrowUnlessPrefSet(
"mail.identity.useremail",
PREF_EmailAddress);
break;
}
} // CMailNewsContext::ThrowUnlessPrefsSet
//----------------------------------------------------------------------------------------
/* static */ MSG_Master* CMailNewsContext::GetMailMaster()
//----------------------------------------------------------------------------------------
{
if (!sMailMaster)
{
sMailMaster = MSG_InitializeMail(GetMailPrefs());
ThrowIfNULL_(sMailMaster);
}
return sMailMaster;
}
/*
//----------------------------------------------------------------------------------------
void CMailNewsContext::DoProgress(const char* message, int level)
//----------------------------------------------------------------------------------------
{
StatusInfo info; // constructor zeroes fields
info.message = message;
info.level = level;
BroadcastMessage(CProgressBroadcaster::msg_StatusText, &info);
}
//----------------------------------------------------------------------------------------
void CMailNewsContext::DoSetProgressBarPercent(int32 percent)
//----------------------------------------------------------------------------------------
{
StatusInfo info; // constructor zeroes fields
info.percent = percent;
BroadcastMessage(CProgressBroadcaster::msg_StatusPercent, &info);
}
//----------------------------------------------------------------------------------------
void CMailNewsContext::AllConnectionsComplete()
//----------------------------------------------------------------------------------------
{
CNSContext::AllConnectionsComplete();
StatusInfo info; // constructor zeroes fields
BroadcastMessage(CProgressBroadcaster::msg_StatusText, &info);
BroadcastMessage(CProgressBroadcaster::msg_StatusPercent, &info);
BroadcastMessage(CProgressBroadcaster::msg_StatusComplete, &info);
}
*/
//----------------------------------------------------------------------------------------
/* static */ MSG_Prefs* CMailNewsContext::GetMailPrefs()
//----------------------------------------------------------------------------------------
{
if (!sMailPrefs)
{
sMailPrefs = MSG_CreatePrefs();
ThrowIfNULL_(sMailPrefs);
FSSpec mailFolder = CPrefs::GetFolderSpec(CPrefs::MailFolder);
char* mailFolderPath = CFileMgr::EncodedPathNameFromFSSpec(mailFolder, true);
MSG_SetFolderDirectory(sMailPrefs, mailFolderPath);
XP_FREE(mailFolderPath);
}
return sMailPrefs;
}
//----------------------------------------------------------------------------------------
char* CMailNewsContext::PromptWithCaption(
const char* inTitleBarText,
const char* inMessage,
const char* inDefaultText)
//----------------------------------------------------------------------------------------
{
char* result = NULL;
CStr255 mesg(inMessage), ioString(inDefaultText);
mesg = NET_UnEscape(mesg);
uint8 maxLength;
switch (GetCurrentCommand())
{
case cmd_RenameFolder:
case cmd_NewFolder:
maxLength = 27;
break;
default:
maxLength = 255;
break;
}
mWasPromptOkay = UStdDialogs::AskStandardTextPrompt(
inTitleBarText, mesg, ioString, NULL, NULL, maxLength );
if ( mWasPromptOkay )
{
if (ioString.Length() > 0)
{
if ( GetCurrentCommand() == cmd_NewFolder ||
GetCurrentCommand() == cmd_RenameFolder )
{
ioString = NET_UnEscape(ioString); // make sure the path...
char * temp = NET_Escape(ioString, URL_PATH); // ...is fully escaped
if (temp)
{
ioString = temp;
XP_FREE(temp);
}
}
result = (char*)XP_STRDUP((const char*)ioString);
}
}
// If result is null then set as canceled
if ( !result )
{
mWasPromptOkay = false;
SetCurrentCommand(cmd_Nothing);
}
return result;
}
//----------------------------------------------------------------------------------------
void CMailNewsContext::NoMoreUsers()
//----------------------------------------------------------------------------------------
{
Inherited::NoMoreUsers();
#if 0
// CNSContext::NoMoreUsers has so much unnecessary stuff in it now, that
// we have to AVOID calling it. We don't have mocha, images, layers, or any of that
// stuff. All we have is session history.
MWContext* cx = (MWContext*)*this;
LSharable::NoMoreUsers(); // which says "delete this".
cx->fe.newContext = nil; // prevent callbacks (and crashes).
//#if DEBUG
// Make sure we assert instead of crashing.
CNSContextCallbacks* theCallbacks = CNSContextCallbacks::GetContextCallbacks();
Assert_(theCallbacks != NULL);
cx->funcs = &(theCallbacks->GetInternalCallbacks());
//#endif
#endif // 0
}
//----------------------------------------------------------------------------------------
void CMailNewsContext::SwitchLoadURL(
URL_Struct* inURL,
FO_Present_Types inOutputFormat)
//----------------------------------------------------------------------------------------
{
Inherited::SwitchLoadURL(inURL, inOutputFormat);
}
//----------------------------------------------------------------------------------------
void CMailNewsContext::AllConnectionsComplete()
//----------------------------------------------------------------------------------------
{
// Note: since this might lead to deletion of our host window (eg, a progress context),
// we might lose all our users after broadcasting here. On the other hand, we may be
// called from our destructor, in which case making a StSharer here led to
// double deletion on exit (when StSharer goes out of scope).
// The solution? Don't do anything if we know we are in a destruction sequence.
if (GetUseCount() <= 0)
return;
StSharer theShareLock(this);
Inherited::AllConnectionsComplete();
} // CMailNewsContext::AllConnectionsComplete

View File

@ -0,0 +1,90 @@
/* -*- 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.
*/
// CMailNewsContext.h
#pragma once
// XP
#include "msgcom.h"
// MacFE
#include "CNSContext.h"
//======================================
class CMailNewsContext
//======================================
: public CNSContext
{
private:
typedef CNSContext Inherited;
public:
CMailNewsContext(MWContextType inContextType = MWContextMail);
virtual ~CMailNewsContext();
// Overrides
public:
// virtual void DoProgress(const char* message, int level); // 1 called by netlib
// virtual void DoSetProgressBarPercent(int32 percent);
// Safe and guaranteed access
protected:
static MSG_Prefs* GetMailPrefs();
public:
static MSG_Master* GetMailMaster();
// This is for offline/online support.
// If mail/news isn't up and running, we shouldn't call GetMailMaster.
// This allows us to determine if we've already allocated the MSG_Master
static Boolean HaveMailMaster()
{ return sMailMaster != NULL; }
static Boolean UserHasNoLocalInbox();
// Prompt callback support
virtual char* PromptWithCaption(
const char* inTitleBarText,
const char* inMessage,
const char* inDefaultText);
virtual void SwitchLoadURL(
URL_Struct* inURL,
FO_Present_Types inOutputFormat);
virtual void AllConnectionsComplete();
Boolean GetWasPromptOkay() { return mWasPromptOkay; }
// LSharable
virtual void NoMoreUsers();
static void ThrowUnlessPrefsSet(MWContextType inContextType);
static void AlertPrefAndThrow(PREF_Enum inPrefPaneSelector);
static void ThrowIfNoLocalInbox();
protected:
static Boolean IsPrefSet(const char* inPrefKey);
static Boolean ThrowUnlessPrefSet(
const char* inPrefKey,
PREF_Enum inPrefPaneSelector);
// Data
private:
static MSG_Prefs* sMailPrefs;
static MSG_Master* sMailMaster;
static Int32 sMailMasterRefCount;
Boolean mWasPromptOkay;
}; // class CMailNewsContext

View File

@ -0,0 +1,449 @@
/* -*- 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.
*/
// CMailNewsWindow.cp
#include "CMailNewsWindow.h"
#include "MailNewsgroupWindow_Defines.h"
#include "CGrayBevelView.h"
#include "CProgressListener.h"
#include "CMailNewsContext.h"
#include "LTableViewHeader.h"
#include "CMailFlexTable.h"
#include "CMessageFolderView.h"
#include "CPrefsDialog.h"
#include "CPatternButton.h"
#include "URobustCreateWindow.h"
#include "CSpinningN.h"
#include "CProxyPane.h"
#include "CDragBarContainer.h"
#include "UDeferredTask.h"
#include "CWindowMenu.h"
#include "resgui.h"
#include "macutil.h"
// helper function used by CThreadWindow and CMessageWindow to set the default action of
// the folder button.
#include "prefapi.h"
#pragma mark -
//======================================
// class CMailNewsWindow
//======================================
const char* Pref_MailShowToolbar = "mailnews.chrome.show_toolbar";
const char* Pref_MailShowLocationBar = "mailnews.chrome.show_url_bar";
//----------------------------------------------------------------------------------------
CMailNewsWindow::CMailNewsWindow(LStream *inStream, DataIDT inWindowType)
//----------------------------------------------------------------------------------------
: Inherited(inStream, inWindowType)
, CSaveWindowStatus(this)
, mProgressListener(NULL)
, mMailNewsContext(NULL)
{
mToolbarShown[LOCATION_TOOLBAR] = false; // set to true in base class
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::DoDefaultPrefs()
//----------------------------------------------------------------------------------------
{
CPrefsDialog::EditPrefs(CPrefsDialog::eExpandMailNews);
}
//----------------------------------------------------------------------------------------
CMailNewsWindow::~CMailNewsWindow()
//----------------------------------------------------------------------------------------
{
if (mMailNewsContext)
mMailNewsContext->RemoveUser(this);
delete mProgressListener;
}
//----------------------------------------------------------------------------------------
const char* CMailNewsWindow::GetLocationBarPrefName() const
//----------------------------------------------------------------------------------------
{
return Pref_MailShowLocationBar;
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::ReadGlobalDragbarStatus()
// Unfortunately, the visibility of the drag bars is determined in several ways, all
// of which must be kept in synch. These ways include, but are not limited to,
// the PPob resource (through the visible flag), the saved window status (through
// Read/WriteWindowStatus and Save/RestorePlace etc) and the preferences, which are
// used to save the values of mToolbarShown.
//----------------------------------------------------------------------------------------
{
XP_Bool value;
if (PREF_GetBoolPref(Pref_MailShowToolbar, &value) == PREF_NOERROR)
mToolbarShown[MESSAGE_TOOLBAR] = value;
if (PREF_GetBoolPref(GetLocationBarPrefName(), &value) == PREF_NOERROR)
mToolbarShown[LOCATION_TOOLBAR] = value;
} // CMailNewsWindow::ReadGlobalDragbarStatus
//----------------------------------------------------------------------------------------
void CMailNewsWindow::WriteGlobalDragbarStatus()
//----------------------------------------------------------------------------------------
{
PREF_SetBoolPref(Pref_MailShowToolbar, mToolbarShown[MESSAGE_TOOLBAR]);
PREF_SetBoolPref(GetLocationBarPrefName(), mToolbarShown[LOCATION_TOOLBAR]);
} // CMailNewsWindow::WriteGlobalDragbarStatus
//----------------------------------------------------------------------------------------
void CMailNewsWindow::FinishCreateSelf()
//----------------------------------------------------------------------------------------
{
Inherited::FinishCreateSelf();
SetAttribute(windAttr_DelaySelect);
// should be in resource, but there's a resource freeze.
try
{
//================================================================================
// WARNING! WARNING! WARNING!
// CThreadWindow::FinishCreateSelf() does not call CMailNewsWindow::FinishCreateSelf.
// So if you add any new stuff here, you have to add it there, too.
//================================================================================
ReadGlobalDragbarStatus();
// Let there be a mail-news context
mMailNewsContext = CreateContext();
StSharer theLock(mMailNewsContext);
// Let there be a progress listener, placed in my firmament,
// which shall listen to the mail-news context
if (mProgressListener)
mMailNewsContext->AddListener(mProgressListener);
else
mProgressListener = new CProgressListener(this, mMailNewsContext);
ThrowIfNULL_(mProgressListener);
// The progress listener should be "just a bit" lazy during network activity
// and "not at all" at idle time to display the URLs pointed by the mouse cursor.
mProgressListener->SetLaziness(CProgressListener::lazy_NotAtAll);
mMailNewsContext->AddListener(mProgressListener);
mMailNewsContext->AddUser(this);
CMailFlexTable* table = GetActiveTable();
if (table)
{
SetLatentSub(table);
mMailNewsContext->AddListener(table); // listen for all connections complete.
}
CSpinningN* theN = dynamic_cast<CSpinningN*>(FindPaneByID(CSpinningN::class_ID));
if (theN)
mMailNewsContext->AddListener(theN);
}
catch (...) {
throw;
}
// And behold, he saw that it was good.
CSaveWindowStatus::FinishCreateWindow();
} // CMailNewsWindow::FinishCreateSelf
//----------------------------------------------------------------------------------------
CNSContext* CMailNewsWindow::CreateContext() const
//----------------------------------------------------------------------------------------
{
CMailNewsContext* result = new CMailNewsContext();
FailNIL_(result);
return result;
} //CMailNewsWindow::CreateContext
//----------------------------------------------------------------------------------------
void CMailNewsWindow::AboutToClose()
//----------------------------------------------------------------------------------------
{
//================================================================================
// WARNING! WARNING! WARNING!
// CThreadWindow::AboutToClose() does not call CMailNewsWindow::AboutToClose.
// So if you add any new stuff here, you have to add it there, too.
//================================================================================
CSaveWindowStatus::AttemptCloseWindow(); // Do this first: uses table
WriteGlobalDragbarStatus();
// Bug fix: must delete the pane before killing the context, because
// the destructor of the pane references the context when it cleans up.
CMailFlexTable* t = GetActiveTable();
if (t)
{
if (mMailNewsContext)
mMailNewsContext->RemoveListener(t); // bad time to listen for all connections complete.
delete t;
}
} // CMailNewsWindow::AboutToClose
//----------------------------------------------------------------------------------------
void CMailNewsWindow::AttemptClose()
//----------------------------------------------------------------------------------------
{
CDeferredCloseTask::DeferredClose(this);
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::DoClose()
//----------------------------------------------------------------------------------------
{
AboutToClose();
Inherited::DoClose();
}
//----------------------------------------------------------------------------------------
Boolean CMailNewsWindow::AttemptQuitSelf(Int32 /* inSaveOption */)
// Derived classes should be careful to call DeferredClose if they override this fn.
//----------------------------------------------------------------------------------------
{
CDeferredCloseTask::DeferredClose(this);
return true;
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::ReadWindowStatus(LStream *inStatusData)
//----------------------------------------------------------------------------------------
{
CSaveWindowStatus::ReadWindowStatus(inStatusData);
CDragBarContainer* dragContainer = (CDragBarContainer*)FindPaneByID('DbCt');
if (dragContainer && inStatusData)
dragContainer->RestorePlace(inStatusData);
// CThreadWindow does this now
//CMailFlexTable* table = GetActiveTable();
//if (table && inStatusData)
// table->GetTableHeader()->ReadColumnState(inStatusData);
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::WriteWindowStatus(LStream *outStatusData)
//----------------------------------------------------------------------------------------
{
CSaveWindowStatus::WriteWindowStatus(outStatusData);
CDragBarContainer* dragContainer = (CDragBarContainer*)FindPaneByID('DbCt');
if (dragContainer && outStatusData)
dragContainer->SavePlace(outStatusData);
// CThreadWindow does this now
//CMailFlexTable* table = GetActiveTable();
//if (table && outStatusData)
// table->GetTableHeader()->WriteColumnState(outStatusData);
}
//----------------------------------------------------------------------------------------
void CMailNewsWindow::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
//----------------------------------------------------------------------------------------
{
outUsesMark = false;
switch (inCommand) {
case cmd_ToggleToolbar:
outEnabled = true;
if (mToolbarShown[MESSAGE_TOOLBAR])
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, HIDE_MESSAGE_TOOLBAR_STRING);
else
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, SHOW_MESSAGE_TOOLBAR_STRING);
break;
case cmd_ToggleLocationBar:
outEnabled = true;
if (mToolbarShown[LOCATION_TOOLBAR])
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, HIDE_LOCATION_TOOLBAR_STRING);
else
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, SHOW_LOCATION_TOOLBAR_STRING);
break;
case cmd_ShowLocationBar:
outEnabled = !mToolbarShown[LOCATION_TOOLBAR];
break;
case cmd_HideLocationBar:
outEnabled = mToolbarShown[LOCATION_TOOLBAR];
break;
default:
CNetscapeWindow::FindCommandStatus(
inCommand, outEnabled, outUsesMark, outMark, outName);
}
} // CMailNewsWindow::FindCommandStatus
//----------------------------------------------------------------------------------------
Boolean CMailNewsWindow::ObeyCommand(
CommandT inCommand,
void *ioParam)
//----------------------------------------------------------------------------------------
{
Boolean cmdHandled = false;
switch (inCommand) {
case cmd_ToggleToolbar:
ToggleDragBar(cMessageToolbar, MESSAGE_TOOLBAR, Pref_MailShowToolbar);
cmdHandled = true;
break;
case cmd_ShowLocationBar:
case cmd_HideLocationBar:
if (mToolbarShown[LOCATION_TOOLBAR] != (inCommand == cmd_ShowLocationBar))
ToggleDragBar(cMailNewsLocationToolbar, LOCATION_TOOLBAR, GetLocationBarPrefName());
cmdHandled = true;
break;
case cmd_ToggleLocationBar:
ToggleDragBar(cMailNewsLocationToolbar, LOCATION_TOOLBAR, GetLocationBarPrefName());
cmdHandled = true;
break;
default:
cmdHandled = CNetscapeWindow::ObeyCommand(inCommand, ioParam);
}
return cmdHandled;
} // CMailNewsWindow::ObeyCommand
#pragma mark -
//======================================
// class CMailNewsFolderWindow
//======================================
//----------------------------------------------------------------------------------------
/* static */ CMailNewsFolderWindow* CMailNewsFolderWindow::FindAndShow(
Boolean inMakeNew,
CommandT inCommand)
// Handle the menu command that creates/shows/selects the MailNews window.
// Currently there can only be one of these.
//----------------------------------------------------------------------------------------
{
CMailNewsFolderWindow* result = NULL;
try
{
CMailNewsContext::ThrowUnlessPrefsSet(MWContextMail);
if (inCommand == cmd_NewsGroups)
CMailNewsContext::ThrowUnlessPrefsSet(MWContextNews);
CWindowIterator iter(WindowType_MailNews);
iter.Next(result);
if (!result && inMakeNew)
{
result = dynamic_cast<CMailNewsFolderWindow*>(
URobustCreateWindow::CreateWindow(res_ID, LCommander::GetTopCommander())
);
ThrowIfNULL_(result);
}
if (result)
{
result->Show();
result->Select();
}
if (inCommand)
{
CMessageFolderView* folderView = (CMessageFolderView*)result->GetActiveTable();
if (folderView)
{
switch (inCommand)
{
case cmd_NewsGroups: // Select first news host
case cmd_MailNewsFolderWindow: // Select first mail host
folderView->SelectFirstFolderWithFlags(
inCommand == cmd_NewsGroups
? MSG_FOLDER_FLAG_NEWS_HOST
: MSG_FOLDER_FLAG_MAIL);
break;
default:
folderView->ObeyCommand(inCommand, nil);
}
}
}
}
catch( ... )
{
}
return result;
}
//----------------------------------------------------------------------------------------
CMailNewsFolderWindow::CMailNewsFolderWindow(LStream *inStream)
//----------------------------------------------------------------------------------------
: CMailNewsWindow(inStream, WindowType_MailNews)
{
}
//----------------------------------------------------------------------------------------
CMailNewsFolderWindow::~CMailNewsFolderWindow()
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
void CMailNewsFolderWindow::FinishCreateSelf()
//----------------------------------------------------------------------------------------
{
Inherited::FinishCreateSelf();
CMessageFolderView* list = (CMessageFolderView*)GetActiveTable();
Assert_(list);
LCaption* locationCaption = (LCaption*)FindPaneByID('LCap');
if (locationCaption && list)
{
CStr255 tempString;
list->GetLongWindowDescription(tempString);
locationCaption->SetDescriptor(tempString);
CProxyPane* proxy = dynamic_cast<CProxyPane*>(FindPaneByID(CProxyPane::class_ID));
if (proxy)
{
proxy->ListenToMessage(msg_NSCDocTitleChanged, (char*)tempString);
proxy->SetIconIDs(15393, 15393);
}
}
list->LoadFolderList(mMailNewsContext);
UReanimator::LinkListenerToControls((CMailFlexTable*)list, this, res_ID);
} // CMailNewsWindow::FinishCreateSelf
//----------------------------------------------------------------------------------------
void CMailNewsFolderWindow::CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const
//----------------------------------------------------------------------------------------
{
LWindow::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
Rect contRect = UWindows::GetWindowContentRect(mMacWindowP);
outStdBounds.left = contRect.left;
outStdBounds.right = contRect.right;
}
//----------------------------------------------------------------------------------------
UInt16 CMailNewsFolderWindow::GetValidStatusVersion(void) const
//----------------------------------------------------------------------------------------
{
return 0x0113;
}
//----------------------------------------------------------------------------------------
CMailFlexTable* CMailNewsFolderWindow::GetActiveTable()
// Get the currently active table in the window. The active table is the table in
// the window that the user considers to be receiving input.
//----------------------------------------------------------------------------------------
{
return dynamic_cast<CMessageFolderView*>(FindPaneByID('Flst'));
}

View File

@ -0,0 +1,125 @@
/* -*- 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.
*/
// CMailNewsWindow.h
#pragma once
// Mac UI Lib
#include "CNetscapeWindow.h"
#include "CSaveWindowStatus.h"
class CProgressListener;
class CMailNewsContext;
class CMailNewsFolderContext;
class CMailFlexTable;
const PaneIDT cMessageToolbar = 'BBar';
const PaneIDT cMailNewsLocationToolbar = 'BnBr';
//======================================
class CMailNewsWindow : public CNetscapeWindow, public CSaveWindowStatus
// Base class for all content windows in mail.
// implements the progress bar and the status line etc.
//======================================
{
private:
typedef CNetscapeWindow Inherited; // trick suggested by the ANSI committee.
protected:
// Indices into mToolbarShown for tracking visibility of toolbars
enum { MESSAGE_TOOLBAR, LOCATION_TOOLBAR };
CMailNewsWindow(LStream *inStream, DataIDT inWindowType);
public:
virtual ~CMailNewsWindow();
virtual CNSContext* CreateContext() const; // allow each window to create its own
virtual void FinishCreateSelf();
virtual CNSContext* GetWindowContext() const { return (CNSContext*)mMailNewsContext; }
// Return the currently active table in the window, nil if none.
// Can't be const, because derived classes need to call FindPaneByID(), which isn't.
virtual CMailFlexTable* GetActiveTable() { return nil; }
virtual CMailFlexTable* GetSearchTable() { return GetActiveTable(); }
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam = nil);
//-----------------------------------
// Window closing and saving - overrides for CSaveWindowStatus
//-----------------------------------
public:
virtual void AttemptClose();
virtual Boolean AttemptQuitSelf(Int32 /* inSaveOption */);
virtual void DoClose();
CProgressListener* GetProgressListener() {return mProgressListener;}
protected:
virtual void AboutToClose(); // place to put common code from [Attempt|Do]Close()
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
virtual void ReadGlobalDragbarStatus();
virtual void WriteGlobalDragbarStatus();
virtual const char* GetLocationBarPrefName() const;
//-----------------------------------
// Preferences
//-----------------------------------
virtual void DoDefaultPrefs();
//-----------------------------------
//data
//-----------------------------------
protected:
CProgressListener* mProgressListener;
CNSContext* mMailNewsContext;
};
//======================================
class CMailNewsFolderWindow : public CMailNewsWindow
//======================================
{
private:
typedef CMailNewsWindow Inherited;
public:
enum { class_ID = 'mnWN', res_ID = 10507};
virtual ~CMailNewsFolderWindow();
CMailNewsFolderWindow(LStream *inStream);
virtual ResIDT GetStatusResID(void) const { return res_ID; }
virtual UInt16 GetValidStatusVersion(void) const;
virtual void FinishCreateSelf();
virtual void CalcStandardBoundsForScreen(const Rect &inScreenBounds,
Rect &outStdBounds) const;
// Return the currently active table in the window, nil if none
static CMailNewsFolderWindow* FindAndShow(Boolean inMakeNew, CommandT inCommand = 0);
virtual CMailFlexTable* GetActiveTable();
};

View File

@ -0,0 +1,513 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMailProgressWindow.cp
#include "CMailProgressWindow.h"
#include "MailNewsCallbacks.h"
#include "URobustCreateWindow.h"
#include "CMailNewsContext.h"
#include "PascalString.h"
#include "CProgressBar.h"
#include "COffscreenCaption.h"
#include "uapp.h" // to check if we're quitting.
#include "CWindowMenu.h"
#include "prefapi.h"
#include "CNetscapeWindow.h"
#include "UOffline.h"
#include "StSetBroadcasting.h"
const ResIDT cOfflineListID = 16010;
const Int16 cOfflineStrIndex = 3;
//======================================
class CDownloadListener : public CMailCallbackListener
// All Connections Complete is not always sent by operations within msglib. Therefore,
// we must listen for the MSG_PaneProgressDone message via the pane-changed mechanism, too.
// So the progress window "has a" CDownloadListener, which has authority to force the
// progress window to close itself.
//======================================
{
public:
CDownloadListener(
CMailProgressWindow* inWindow, MSG_Pane* inPane);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value); // must always be supported.
CMailProgressWindow* mProgressWindow;
}; // class CDownloadListener
//-----------------------------------
CDownloadListener::CDownloadListener(CMailProgressWindow* inWindow, MSG_Pane* inPane)
//-----------------------------------
: mProgressWindow(inWindow)
{
SetPane(inPane);
}
//-----------------------------------
void CDownloadListener::PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value)
//-----------------------------------
{
#pragma unused (inPane)
#pragma unused (value)
if (inNotifyCode == MSG_PaneProgressDone
|| inNotifyCode == MSG_PaneNotifySelectNewFolder // Bug #106165
|| inNotifyCode == MSG_PaneNotifyNewFolderFailed // ''
|| inNotifyCode == MSG_PaneNotifyCopyFinished) // Bug #113142 and #113860
{
mProgressWindow->ListenToMessage(msg_NSCAllConnectionsComplete, nil);
}
}
//======================================
// class CMailProgressWindow
//======================================
CMailProgressWindow* CMailProgressWindow::sModalMailProgressWindow = nil;
// if you initiate a get mail command, you can't start getting mail again before the
// first CMailProgressWindow closes
Boolean CMailProgressWindow::sGettingMail = false;
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::CreateWindow(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName)
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
try
{
MSG_SetFEData(inPane, CMailCallbackManager::Get());
progressWindow = dynamic_cast<CMailProgressWindow*>(
URobustCreateWindow::CreateWindow(inResID, LCommander::GetTopCommander()));
ThrowIfNULL_(progressWindow);
progressWindow->SetWindowContext(ExtractNSContext(MSG_GetContext(inPane)));
// the window will be shown after a decent interval.
if (inCommandName.Length() > 0)
progressWindow->SetDescriptor(inCommandName);
progressWindow->ListenToPane(inPane);
}
catch (...)
{
delete progressWindow;
throw;
}
return progressWindow;
} // CMailProgressWindow::CreateWindow
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::CreateIndependentWindow(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName,
UInt16 inDelay)
// This is private to the class. The pane passed in must have been made by this class.
//-----------------------------------
{
CMailProgressWindow* progressWindow = CreateWindow(inResID, inPane, inCommandName);
progressWindow->mPane = inPane; // This is the sign that we made it.
progressWindow->SetDelay(inDelay);
if (inDelay == 0)
progressWindow->Show();
return progressWindow;
} // CMailProgressWindow::CreateModelessWindow
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::CreateModalParasite(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName)
//-----------------------------------
{
sModalMailProgressWindow = CreateWindow(inResID, inPane, inCommandName);
return sModalMailProgressWindow;
} // CMailProgressWindow::CreateModalParasite
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::ObeyMessageLibraryCommand(
ResIDT inResID,
MSG_Pane* inPane,
MSG_CommandType inCommand,
const CStr255& inCommandName,
MSG_ViewIndex* inSelectedIndices,
int32 inNumIndices)
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
try
{
CMailNewsContext* context = new CMailNewsContext(MWContextMailNewsProgress);
MSG_Pane* pane = MSG_CreateProgressPane(*context, CMailNewsContext::GetMailMaster(), inPane);
ThrowIfNULL_(pane);
progressWindow = CreateIndependentWindow(inResID, pane, inCommandName);
progressWindow->mParentPane = inPane;
// remember if we're getting mail or news...
progressWindow->mCommandBeingServiced = inCommand;
// only allowed to get mail one dialog at a time... (in other words, you can't
// have two of these dialogs open at the same time both of them getting mail)
if (inCommand == MSG_GetNewMail)
{
sGettingMail = true;
// Note: for MSG_GetNewMail, we get the pane notification CopyFinished when
// messages are filtered, and later we get allconnectionscomplete from the
// context. So avoid closing the window too early by turning off pane
// notifications.
progressWindow->ListenToPane(nil);
// This is getting messy. I think CDownloadListener should have a new built-in
// data member, which stores the notify code which it will use to destroy the window.
// eg, for a file copy, set this to MSG_PaneNotifyCopyFinished, etc etc. The problem
// now is that some operations, like GetNewMail, send one of these AS WELL AS all
// connections complete. Whereas some operations send only one or the other of these.
}
::MSG_Command(pane, inCommand, inSelectedIndices, inNumIndices);
}
catch (...)
{
delete progressWindow;
throw;
}
return progressWindow;
} // CMailProgressWindow::ObeyMessageLibraryCommand
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::CleanUpFolders()
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
try
{
CMailNewsContext* context = new CMailNewsContext(MWContextMailNewsProgress);
MSG_Pane* pane = MSG_CreateFolderPane(*context, CMailNewsContext::GetMailMaster());
ThrowIfNULL_(pane);
progressWindow = CreateIndependentWindow(res_ID_modeless, pane, "");
progressWindow->mCommandBeingServiced = (MSG_CommandType)'ClnF';
MSG_CleanupFolders(pane);
// Of course, that should be "CleanUpFolders"
// Sigh. It's asynchronous. It works in the background. But we may be trying to quit.
Boolean quitting = (CFrontApp::GetApplication()->GetState() == programState_Quitting);
if (quitting)
{
do
{
// progress call will hide wind when done.
// Or user will cancel (and close and delete). This will set mPane to nil.
CFrontApp::GetApplication()->ProcessNextEvent();
} while (progressWindow->IsVisible() && progressWindow->mPane == pane);
if (progressWindow->mPane == pane)
progressWindow->DoClose(); // close it if it's not closed already
}
}
catch (...)
{
delete progressWindow;
throw;
}
return progressWindow;
} // CMailProgressWindow::CleanUpFolders
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::SynchronizeForOffline(
const CStr255& inCommandName,
ResIDT inResID)
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
try
{
// Read the prefs
XP_Bool getNews, getMail, sendMail, getDirectories, goOffline;
PREF_GetBoolPref("offline.download_discussions", &getNews);
PREF_GetBoolPref("offline.download_mail", &getMail);
PREF_GetBoolPref("offline.download_messages", &sendMail);
PREF_GetBoolPref("offline.download_directories", &getDirectories);
PREF_GetBoolPref("offline.offline_after_sync", &goOffline);
// Synchronize
CMailNewsContext* context = new CMailNewsContext(MWContextMailNewsProgress);
MSG_Pane* pane = MSG_CreateFolderPane(*context, CMailNewsContext::GetMailMaster());
ThrowIfNULL_(pane);
progressWindow = CreateIndependentWindow(inResID, pane, inCommandName);
::MSG_SynchronizeOffline(CMailNewsContext::GetMailMaster(), pane,
getNews, getMail, sendMail, getDirectories, goOffline);
}
catch (...)
{
delete progressWindow;
throw;
}
return progressWindow;
} // CMailProgressWindow::SynchronizeForOffline
//-----------------------------------
/*static*/ CMailProgressWindow* CMailProgressWindow::ToggleOffline(
ResIDT inResID)
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
try
{
CMailNewsContext* context = new CMailNewsContext(MWContextMailNewsProgress);
MSG_Pane* pane = MSG_CreateFolderPane(*context, CMailNewsContext::GetMailMaster());
ThrowIfNULL_(pane);
progressWindow = CreateIndependentWindow(inResID, pane, "\p", 60);
::MSG_GoOffline(CMailNewsContext::GetMailMaster(), pane, false, false, false, false);
// force a menu update to toggle the menu command name
LCommander::SetUpdateCommandStatus(true);
// display a status msg in all windows
LStr255 offlineString("");
if (!UOffline::AreCurrentlyOnline())
offlineString = LStr255(cOfflineListID, cOfflineStrIndex);
CNetscapeWindow::DisplayStatusMessageInAllWindows(offlineString);
}
catch (...)
{
delete progressWindow;
throw;
}
return progressWindow;
} // CMailProgressWindow::ToggleOffline
//-----------------------------------
/*static*/ MSG_Pane* CMailProgressWindow::JustGiveMeAPane(
const CStr255& inCommandName,
MSG_Pane* inParentPane)
//-----------------------------------
{
CMailProgressWindow* progressWindow = nil;
MSG_Pane* pane = nil;
try
{
CMailNewsContext* context = new CMailNewsContext(MWContextMailNewsProgress);
pane = ::MSG_CreateProgressPane(
*context, CMailNewsContext::GetMailMaster(), inParentPane);
ThrowIfNULL_(pane);
progressWindow = CreateIndependentWindow(res_ID_modeless, pane, inCommandName);
}
catch (...)
{
delete progressWindow;
throw;
}
return pane;
} // CMailProgressWindow::GoOffline
//-----------------------------------
CMailProgressWindow::CMailProgressWindow(LStream* inStream)
//-----------------------------------
: CDownloadProgressWindow(inStream)
, mStartTime(::TickCount())
, mCallbackListener(nil)
, mLastCall(0)
, mPane(nil)
, mParentPane(nil)
, mCancelCallback(nil)
{
*inStream >> mDelay;
// Don't list these windows in the window menu (unfortunately, the constructor
// of CMediatedWindow has already added us at this point). So tell Mr. WindowMenu
// that we're dead, dead, dead. Do this by calling Hide(), which has the side-effect
// of causing a broadcast that we've disappeared. The window is currently invisible
// anyway.
Hide();
//CWindowMenu::sWindowMenu->ListenToMessage(msg_WindowDisposed, this);
// Watch out for commands that never call us back: we won't have cleaned up
// the previous window until now...
delete sModalMailProgressWindow;
// this static is reassigned in the routine that makes modal ones.
} // CMailProgressWindow::CMailProgressWindow
//-----------------------------------
CMailProgressWindow::~CMailProgressWindow()
//-----------------------------------
{
if (sModalMailProgressWindow == this)
sModalMailProgressWindow = nil;
// if we're the window servicing the get mail request then after we're destroyed,
// someone else can get issue a get mail command too
if ((mCommandBeingServiced == MSG_GetNewMail) && sGettingMail)
sGettingMail = false;
delete mCallbackListener;
mCallbackListener = nil;
if (mPane) // ie, I made it...
{
// clear mPane so e won't come into this block again.
MSG_Pane* temp = mPane;
mPane = nil;
// Now let the back end run its course
CNSContext* context = GetWindowContext();
if (context)
XP_InterruptContext((MWContext*)*context);
::MSG_DestroyPane(temp);
// When we delete a progress pane it can affect CommandStatus for commands like GetMail
// since the window has already been activated, FindCommandStatus needs to be called
SetUpdateCommandStatus( true );
}
} // CMailProgressWindow::~CMailProgressWindow
//-----------------------------------
ResIDT CMailProgressWindow::GetStatusResID() const
//-----------------------------------
{
return res_ID_modal;
} // client must provide!
//-----------------------------------
UInt16 CMailProgressWindow::GetValidStatusVersion() const
//-----------------------------------
{
return 0x0001;
} // CDownloadProgressWindow::GetValidStatusVersion
//-----------------------------------
void CMailProgressWindow::FinishCreateSelf()
//-----------------------------------
{
Inherited::FinishCreateSelf();
if (HasAttribute(windAttr_Modal))
{
Assert_(!sModalMailProgressWindow);
sModalMailProgressWindow = this;
}
StartIdling();
} // CMailProgressWindow::FinishCreateSelf
//-----------------------------------
void CMailProgressWindow::ListenToPane(MSG_Pane* inPane)
//-----------------------------------
{
if (!mCallbackListener)
mCallbackListener = new CDownloadListener(this, inPane);
else
mCallbackListener->SetPane(inPane);
}
//-----------------------------------
void CMailProgressWindow::SpendTime(const EventRecord&)
//-----------------------------------
{
UInt32 time = ::TickCount();
// First time, set the time called.
if (mLastCall == 0)
{
mLastCall = time;
return;
}
// If this is not the first call, but we're not getting tickled, close.
if (time > mStartTime + mDelay * 2 && !IsVisible())
{
// prevent re-entrancy (DoClose can take time, because of callbacks
// from interrupt context.)
StopRepeating();
DoClose();
return;
}
// Normal case. Make sure the barber-pole spins.
if (mBar->GetValue() == CProgressBar::eIndefinite)
mBar->Refresh();
} // CMailProgressWindow::SpendTime
//-----------------------------------
void CMailProgressWindow::Show()
//-----------------------------------
{
// Keep it out of the window menu!
StSetBroadcasting saver(CWindowMediator::GetWindowMediator(), false);
Inherited::Show();
}
//-----------------------------------
void CMailProgressWindow::ListenToMessage(
MessageT inMessage,
void* ioParam)
//-----------------------------------
{
const UInt32 kMinTimeBetweenUpdates = 20;
UInt32 time = ::TickCount();
if (!IsVisible() // ooh, it's been comfy here, invisible, but maybe there's work...
&& inMessage != msg_NSCAllConnectionsComplete // heck, I'm not showing up for this...
&& time > mStartTime + mDelay) // I only show up for LONG processes.
Show();
mLastCall = time;
switch (inMessage)
{
case msg_NSCProgressUpdate:
// Ignore that message in mail/news windows (it's ignored on
// Windows too). Otherwise, the progress bar alternates between
// a percent value and a barber pole.
return;
case msg_NSCAllConnectionsComplete:
if (mParentPane)
{
// send a fake progress-done call to parent pane. This helps with "get new mail"
// because the inbox has to scroll to display it.
FE_PaneChanged(
mParentPane,
PR_TRUE, // async
MSG_PaneProgressDone,
msg_NSCAllConnectionsComplete);
}
Hide(); // So that on idle we'll close.
// This avoids the base class behavior (calling DoClose()) immediately,
// and instead waits till idle time to close.
mDelay = 0 ; // Don't want to wait a long time to destroy the window
StopListening(); // Don't show ourselves on subsequent messages.
ListenToPane(nil);
return;
case msg_Cancel:
if (mCancelCallback && !mCancelCallback()) // result true means "execute default"
return;
break;
}
Inherited::ListenToMessage(inMessage, ioParam);
} // CMailProgressWindow::ListenToMessage
//-----------------------------------
void CMailProgressWindow::NoteProgressBegin(const CContextProgress& inProgress)
//-----------------------------------
{
// Base class will clobber the window title with a null string. Don't do that!
if (inProgress.mAction.length())
SetDescriptor(CStr255(inProgress.mAction));
mMessage->SetDescriptor(inProgress.mMessage);
mComment->SetDescriptor(inProgress.mComment);
} // CMailProgressWindow::NoteProgressBegin

View File

@ -0,0 +1,120 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMailProgressWindow.h
#include "CDownloadProgressWindow.h"
#include "msgcom.h"
class CMailCallbackListener;
class CMailNewsContext;
class CStr255;
class CContextProgress;
//-----------------------------------
class CMailProgressWindow : public CDownloadProgressWindow, public LPeriodical
// This class exists because mail stuff does not get the "progress begin/end/update" calls.
// Also, it has a timer, and shows itself automatically after a short delay. It also
// takes itself down if nobody told it to come down after some time.
//-----------------------------------
{
private:
typedef CDownloadProgressWindow Inherited;
public:
enum { class_ID = 'MPWd', res_ID_modal = 10526, res_ID_modeless = 10527 };
//--------
// static
//--------
static CMailProgressWindow* CreateModalParasite(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName);
static void RemoveModalParasite() { delete sModalMailProgressWindow; }
static CMailProgressWindow* GetModal() { return sModalMailProgressWindow; }
static CMailProgressWindow* ObeyMessageLibraryCommand(
ResIDT inResID,
MSG_Pane* inPane,
MSG_CommandType inCommand,
const CStr255& inCommandName,
MSG_ViewIndex* inSelectedIndices = nil,
int32 inNumIndices = 0);
static CMailProgressWindow* ToggleOffline(
ResIDT inResID = res_ID_modeless);
static CMailProgressWindow* SynchronizeForOffline(
const CStr255& inCommandName,
ResIDT inResID = res_ID_modeless);
static CMailProgressWindow* CleanUpFolders();
static Boolean GettingMail () { return sGettingMail; }
static MSG_Pane* JustGiveMeAPane(
const CStr255& inCommandName,
MSG_Pane* inParentPane = nil);
// creates a MSG_Pane attached to
// a modeless progress window.
//--------
// non-static
//--------
CMailProgressWindow(LStream* inStream);
virtual ~CMailProgressWindow();
virtual ResIDT GetStatusResID() const; // client must provide!
virtual UInt16 GetValidStatusVersion() const; // client must provide!
virtual void Show();
virtual void ListenToMessage(
MessageT inMessage,
void* ioParam);
virtual void NoteProgressBegin(const CContextProgress& inProgress);
void ListenToPane(MSG_Pane* inPane);
virtual void SpendTime(const EventRecord&);
void SetDelay(UInt16 delay) { mDelay = delay; }
void SetCancelCallback(Boolean (*f)()) { mCancelCallback = f; }
MSG_CommandType GetCommandBeingServiced() const { return mCommandBeingServiced; }
protected:
static CMailProgressWindow* CreateWindow(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName);
static CMailProgressWindow* CreateIndependentWindow(
ResIDT inResID,
MSG_Pane* inPane,
const CStr255& inCommandName,
UInt16 inDelay = 0);
virtual void FinishCreateSelf();
//-------
// data
//-------
protected:
UInt32 mStartTime; // in ticks;
UInt16 mDelay; // ditto
CMailCallbackListener* mCallbackListener;
UInt32 mLastCall; // ticks
MSG_Pane* mPane; // only used for the modeless window.
MSG_Pane* mParentPane; // ditto.
Boolean (*mCancelCallback)();
MSG_CommandType mCommandBeingServiced; // the command we're handling
static Boolean sGettingMail; // true if an instance of us is getting mail
static CMailProgressWindow* sModalMailProgressWindow;
}; // CMailProgressWindow

View File

@ -0,0 +1,621 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMessageAttachmentView.cp
#include "CMessageAttachmentView.h"
#include "UDebugging.h"
#include "PascalString.h"
#include "UGraphicGizmos.h"
#include "xp_str.h"
#define WANT_ENUM_STRING_IDS // why don't we just have a header that does this?
#include "allxpstr.h"
#undef WANT_ENUM_STRING_IDS
#include "UDrawingUtils.h"
#include "CMessageView.h"
#include <LTableMonoGeometry.h>
#include <LTableMultiselector.h>
#include "CSwatchBrokerView.h"
#include "CURLDispatcher.h"
#include "cstring.h"
#include "CBrowserContext.h"
#include "uerrmgr.h"
#include "resgui.h"
#include "cstring.h"
#include <LDragTask.h>
#include "macutil.h"
#include "ufilemgr.h"
#include "MoreDesktopMgr.h"
#include "CDeviceLoop.h"
#include "CContextMenuAttachment.h"
#include "CBevelView.h"
#include "macutil.h"
#include "miconutils.h"
const Uint16 kColWidth = 100;
const Uint16 kRowHeight = 50;
const Uint16 kExpandedHeight = 56;
CMessageAttachmentView::CMessageAttachmentView(LStream* inStream):
Inherited(inStream), LDragAndDrop(GetMacPort(), this),
mAttachmentList(NULL),
mMSGPane(NULL),
mExpandedHeight(kExpandedHeight),
mNumberAttachments(0),
mClickCountToOpen(2),
mAttachmentIconList(nil)
{
SetUseDragSelect( false );
mSendDataUPP = NewDragSendDataProc(LDropArea::HandleDragSendData);
Assert_(mSendDataUPP != NULL);
SetUpTableHelpers();
LWindow* window = LWindow::FetchWindowObject( GetMacPort() );
if( window )
mBrokeredView = dynamic_cast<CBrokeredView*>(window->FindPaneByID( 'MAtV' ) );
} // CMessageAttachmentView::CMessageAttachmentView
CMessageAttachmentView::~CMessageAttachmentView()
{
if ( mSendDataUPP != NULL )
DisposeRoutineDescriptor(mSendDataUPP);
ClearMessageAttachmentView();
} // CMessageAttachmentView::~CMessageAttachmentView()
void CMessageAttachmentView::FinishCreateSelf()
{
} // CMessageAttachmentView::FinishCreateSelf
void CMessageAttachmentView::SetUpTableHelpers()
{
SetTableGeometry(new LTableMonoGeometry(this, kColWidth, kRowHeight) );
SetTableSelector(new LTableMultiSelector(this));
} // CMessageAttachmentView::SetUpTableHelpers
void CMessageAttachmentView::SetMessageAttachmentList( MSG_Pane* pane, int32 numberAttachments )
{
ClearMessageAttachmentView();
mMSGPane = pane;
if (numberAttachments <= 0)
{
Hide();
return;
}
mNumberAttachments = numberAttachments;
Assert_( mMSGPane != NULL );
MWContext* context = MSG_GetContext( mMSGPane );
mMessageView = dynamic_cast<CMessageView*>( context->fe.newView );
Assert_( mMessageView != NULL );
XP_Bool isAllAttachments;
MSG_GetViewedAttachments( mMSGPane, &mAttachmentList, &isAllAttachments);
if (mAttachmentList == nil)
{
ClearMessageAttachmentView();
return;
}
CalculateRowsColumns();
mAttachmentIconList = new CAttachmentIcon*[mNumberAttachments]; //careful!
MSG_AttachmentData* attachment = &mAttachmentList[0];
for (int i = 0; i < mNumberAttachments; i++, attachment++)
{
CAttachmentIcon *attachIcon = NULL;
if (attachment->x_mac_creator && attachment->x_mac_type)
{
OSType fileCreator;
OSType fileType;
// creator and type are 8-byte hex representations...
sscanf(attachment->x_mac_creator, "%X", &fileCreator);
sscanf(attachment->x_mac_type, "%X", &fileType);
attachIcon = new CAttachmentIcon(fileCreator, fileType);
}
else
{
attachIcon = new CAttachmentIcon(attachment->real_type);
}
mAttachmentIconList[i] = attachIcon;
}
} // CMessageAttachmentView::SetMessageAttachmentList
void CMessageAttachmentView::ClearMessageAttachmentView()
{
if (mAttachmentIconList)
{
for (int i = 0; i < mNumberAttachments; i++)
{
CAttachmentIcon *thisAttachmentIcon = mAttachmentIconList[i];
delete thisAttachmentIcon;
}
delete mAttachmentIconList;
mAttachmentIconList = NULL;
}
if (mMSGPane && mAttachmentList)
{
MSG_FreeAttachmentList( mMSGPane, mAttachmentList);
}
mAttachmentList = NULL;
mMSGPane = NULL;
mNumberAttachments = 0;
} // CMessageAttachmentView::ClearMessageAttachmentView
void CMessageAttachmentView::OpenSelection( Int32 action)
{
STableCell selectedCell( 0,0);
while ( GetNextSelectedCell(selectedCell) )
{
Int32 attachmentIndex = CalculateAttachmentIndex (selectedCell );
const char* url = mAttachmentList[ attachmentIndex ].url;
URL_Struct* theURL = NET_CreateURLStruct( url, NET_DONT_RELOAD);
ThrowIfNULL_(theURL);
HandleURL(theURL, action );
}
} // CMessageAttachmentView::OpenSelection()
void CMessageAttachmentView::HandleURL( URL_Struct* inURL, int32 action )
{
CBrowserContext* browserContext = mMessageView->GetContext();
if( browserContext )
{
cstring theReferer = browserContext->GetCurrentURL();
if (theReferer.length() > 0)
inURL->referer = XP_STRDUP(theReferer);
inURL->window_target = NULL;
if( action == FO_SAVE_AS )
{
CStr31 fileName;
fe_FileNameFromContext(*browserContext, inURL->address, fileName);
StandardFileReply reply;
::StandardPutFile(GetPString(SAVE_AS_RESID), fileName, &reply);
if (reply.sfGood)
{
CURLDispatcher::DispatchToStorage( inURL, reply.sfFile, FO_SAVE_AS, false);
}
}
else
mMessageView->DispatchURL( inURL, browserContext, false, false, action);
}
} // CMessageAttachmentView::HandleURL
void CMessageAttachmentView::ResizeFrameBy(
Int16 inWidthDelta,
Int16 inHeightDelta,
Boolean inRefresh)
{
LTableView::ResizeFrameBy( inWidthDelta, inHeightDelta, inRefresh);
CalculateRowsColumns();
} // CMessageAttachmentView::ResizeFrameBy
void CMessageAttachmentView::ToggleVisibility()
{
if ( IsVisible() )
Hide();
else
Show();
} // CMessageAttachmentView::ToggleVisibility
void CMessageAttachmentView::Hide()
{
if( mBrokeredView )
{
if( mBrokeredView->IsVisible() )
Remove();
}
} // CMessageAttachmentView::Hide
void CMessageAttachmentView::Show()
{
if ( mBrokeredView )
{
if( !mBrokeredView->IsVisible() && mNumberAttachments )
{
mBrokeredView->Show();
mBrokeredView->MoveBy( 0, -mExpandedHeight, true );
mBrokeredView->ResizeFrameBy(0, mExpandedHeight, true );
CBevelView::SubPanesChanged(this, true);
Rect portRect;
if ( CalcPortFrameRect( portRect ) )
::EraseRect( &portRect );
}
}
} // CMessageAttachmentView::Show()
void CMessageAttachmentView::Remove()
{
if ( mBrokeredView )
{
if ( mBrokeredView->IsVisible() )
{
mBrokeredView->ResizeFrameBy(0, -mExpandedHeight, true);
mBrokeredView->MoveBy( 0, mExpandedHeight, false );
mBrokeredView->Hide();
}
}
} // CMessageAttachmentView::Remove
void CMessageAttachmentView::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
{
switch (inCommand)
{
//case cmd_GetInfo:
// outEnabled = GetSelectedRowCount() == 1;
// break;
case cmd_SaveAs:
STableCell dummyCell( 0,0 );
outEnabled = GetNextSelectedCell( dummyCell);
break;
case cmd_SelectAll:
outEnabled = true;
break;
default:
LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
break;
}
} // CCMessageAttachmentView::FindCommandStatus
Boolean CMessageAttachmentView::ObeyCommand(
CommandT inCommand,
void *ioParam)
{
Boolean result = false;
switch(inCommand)
{
case cmd_SaveAs:
OpenSelection( FO_SAVE_AS );
return true;
case cmd_Open:
OpenSelection( FO_CACHE_AND_PRESENT );
return true;
default:
return mMessageView->ObeyCommand( inCommand, ioParam );
}
} // CMessageAttachmentView::ObeyCommand
void CMessageAttachmentView::HiliteCell(
const STableCell &inCell,
Boolean /* inHilite */ )
{
Rect cellRect;
if ( GetLocalCellRect( inCell, cellRect) )
{
FocusDraw();
DrawCell( inCell, cellRect );
}
} // CMessageAttachmentView::HiliteCell
void CMessageAttachmentView::HiliteSelection(
Boolean /* inActively */,
Boolean inHilite )
{
STableCell theCell;
while (GetNextSelectedCell(theCell))
{
if( !inHilite )
UnselectCell( theCell );
HiliteCell( theCell, inHilite );
}
}
Boolean CMessageAttachmentView::ClickSelect(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown)
{
// select the cell
if (LTableView::ClickSelect(inCell, inMouseDown))
{
// Handle it ourselves if the popup attachment doesn't want it.
CContextMenuAttachment::SExecuteParams params;
params.inMouseDown = &inMouseDown;
if (ExecuteAttachments(CContextMenuAttachment::msg_ContextMenu, (void*)&params))
{
// drag ? - don't become target
if ( ::WaitMouseMoved(inMouseDown.macEvent.where))
DragSelection(inCell, inMouseDown);
else
{
// become target
if (!IsTarget())
SwitchTarget(this);
// open selection if we've got the right click count
if (GetClickCount() == mClickCountToOpen)
OpenSelection( FO_CACHE_AND_PRESENT );
}
}
return true;
}
return false;
} // CMessageAttachmentView::ClickSelect
void CMessageAttachmentView::DragSelection(
const STableCell& /*inCell*/,
const SMouseDownEvent& inMouseDown )
{
DragReference dragRef = 0;
if (!FocusDraw()) return;
try
{
//StRegion dragRgn;
OSErr err;
CBrowserDragTask attachmentDrag( inMouseDown.macEvent );
AddSelectionToDrag( attachmentDrag.GetDragReference() , attachmentDrag.GetDragRegion() );
err = ::SetDragSendProc( attachmentDrag.GetDragReference() , mSendDataUPP, (LDragAndDrop*)this);
attachmentDrag.DoDrag();
}
catch( ... ) {}
} //CMessageAttachmentView::DragSelection
void CMessageAttachmentView::AddSelectionToDrag(DragReference /* inDragRef */, RgnHandle inDragRgn)
{
StRegion tempRgn;
STableCell cell;
Rect cellRect;
::SetEmptyRgn(inDragRgn);
cell.col = 1;
cell.row = 0;
while (GetNextSelectedCell(cell))
{
if (GetLocalCellRect(cell, cellRect))
{
Int32 attachmentIndex = CalculateAttachmentIndex( cell );
/*
::LocalToGlobal(&(topLeft(cellRect)));
::LocalToGlobal(&(botRight(cellRect)));
::RectRgn(tempRgn, &cellRect);
::UnionRgn(tempRgn, inDragRgn, inDragRgn);
*/
CAttachmentIcon *attachmentIcon = mAttachmentIconList[attachmentIndex];
if (attachmentIcon)
{
::SetEmptyRgn(tempRgn);
attachmentIcon->AddIconOutlineToRegion(tempRgn, CAttachmentIcon::kIconSizeLarge);
int16 horizontalOffset = ( cellRect.right - cellRect.left - 32 ) / 2;
Rect localRect = cellRect;
::LocalToGlobal(&(topLeft(cellRect)));
OffsetRgn(tempRgn, horizontalOffset + localRect.left + cellRect.left - localRect.left, localRect.top + (cellRect.top - localRect.top));
::UnionRgn(tempRgn, inDragRgn, inDragRgn);
}
}
}
::CopyRgn(inDragRgn, tempRgn);
::InsetRgn(tempRgn, 1, 1);
::DiffRgn(inDragRgn, tempRgn, inDragRgn);
}
void CMessageAttachmentView::DoDragSendData(FlavorType inFlavor,
ItemReference inItemRef,
DragReference inDragRef)
{
OSErr theErr;
cstring theUrl;
STableCell selectedCell( 0,0);
switch( inFlavor )
{
case 'TEXT':
while ( GetNextSelectedCell(selectedCell) )
{
Int32 attachmentIndex = CalculateAttachmentIndex (selectedCell );
const char* url = mAttachmentList[ attachmentIndex ].url;
theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, url, strlen(url), 0);
ThrowIfOSErr_ (theErr);
}
break;
case emBookmarkFileDrag:
// Get the target drop location
AEDesc dropLocation;
theErr = ::GetDropLocation(inDragRef, &dropLocation);
if (theErr != noErr)
return;
// Get the directory ID and volume reference number from the drop location
SInt16 volume;
SInt32 directory;
theErr = GetDropLocationDirectory(&dropLocation, &directory, &volume);
// Ok, this is a hack, and here's why: This flavor type is sent with the FlavorFlag 'flavorSenderTranslated' which
// means that this send data routine will get called whenever someone accepts this flavor. The problem is that
// it is also called whenever someone calls GetFlavorDataSize(). This routine assumes that the drop location is
// something HFS related, but it's perfectly valid for something to query the data size, and not be a HFS
// derrivative (like the text widget for example).
// So, if the coercion to HFS thingy fails, then we just punt to the textual representation.
if (theErr == errAECoercionFail)
{
theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, theUrl, strlen(theUrl), 0);
return;
}
if (theErr != noErr)
return;
// Combine with the unique name to make an FSSpec to the new file
FSSpec prototypeFilespec;
FSSpec locationSpec;
prototypeFilespec.vRefNum = volume;
prototypeFilespec.parID = directory;
// Save the selection
while ( GetNextSelectedCell( selectedCell ) )
{
MSG_AttachmentData* attachment = &mAttachmentList[ CalculateAttachmentIndex( selectedCell ) ];
char* fileName = CFileMgr::MacPathFromUnixPath(attachment->real_name );
if ( fileName )
{
theErr = CFileMgr::UniqueFileSpec( prototypeFilespec, fileName , locationSpec );
if (theErr && theErr != fnfErr) // need a unique name, so we want fnfErr!
ThrowIfOSErr_(theErr);
Int32 attachmentIndex = CalculateAttachmentIndex (selectedCell );
const char* url = mAttachmentList[ attachmentIndex ].url;
URL_Struct* theURL = NET_CreateURLStruct( url, NET_DONT_RELOAD );
theErr = ::SetDragItemFlavorData( inDragRef, inItemRef, inFlavor, &locationSpec, sizeof(FSSpec), 0 );
ThrowIfOSErr_(theErr);
ThrowIfNULL_(theURL);
CURLDispatcher::DispatchToStorage( theURL, locationSpec, FO_SAVE_AS, true );
XP_FREE( fileName );
}
}
break;
}
} //CMessageAttachmentView::AddSelectionToDrag
void CMessageAttachmentView::DrawSelf()
{
// This function is similar to what we had when the "Erase On Update"
// LWindow attribute was set in Constructor. This flag has been removed
// because it created a lot of flickers when browsing mails.
// The other objects in the Thread window continued to behave correctly
// but the CThreadView showed some update problems. Instead of fixing
// them as we are supposed to (ie. by invalidating and erasing only what
// needs to be redrawn), I prefered to emulate the way it used to work
// when "Erase On Update" was set. My apologies for this easy solution
// but we have something to ship next week.
// erase everything
ApplyForeAndBackColors();
Rect frame;
CalcLocalFrameRect(frame);
::EraseRect(&frame);
// redraw everything
Inherited::DrawSelf();
}// CMessageAttachmentView::DrawSelf()
void CMessageAttachmentView::DrawCell( const STableCell &inCell, const Rect &inLocalRect )
{
const Int32 kIconSize = 32;
Int32 attachmentIndex = CalculateAttachmentIndex( inCell );
if( attachmentIndex < 0 || attachmentIndex >= mNumberAttachments )
return ;
MSG_AttachmentData& attachment = mAttachmentList[attachmentIndex];
char* attachmentName = NULL;
if (attachment.real_name != NULL)
attachmentName = CFileMgr::MacPathFromUnixPath(attachment.real_name );
else
attachmentName = XP_STRDUP( XP_GetString(XP_MSG_NONE));
Uint32 nameLength;
if( attachmentName )
nameLength= XP_STRLEN(attachmentName);
// file icon
Rect iconRect;
int16 horizontalOffset = ( inLocalRect.right - inLocalRect.left - kIconSize )/2;
iconRect.left = inLocalRect.left + horizontalOffset;
iconRect.right = iconRect.left + kIconSize;
iconRect.top = inLocalRect.top + 2;
iconRect.bottom = iconRect.top + kIconSize;
IconTransformType transformType = CellIsSelected(inCell) ? kTransformSelected : kTransformNone;
CAttachmentIcon *attachmentIcon = mAttachmentIconList[attachmentIndex];
if (attachmentIcon != NULL)
attachmentIcon->PlotIcon(iconRect, kAlignNone, transformType);
// file name and yes, you can have attachments without names
if( attachmentName != NULL )
{
Rect textRect = inLocalRect;
textRect.left+=4;
textRect.top = iconRect.bottom;
FontInfo fontInfo;
UTextTraits::SetPortTextTraits( 130 );
::GetFontInfo(&fontInfo);
UGraphicGizmos::PlaceTextInRect(
attachmentName, nameLength, textRect, teCenter, teCenter, &fontInfo, true, truncMiddle);
XP_FREE( attachmentName );
}
} // CMessageAttachmentView::DrawCell
void CMessageAttachmentView::CalculateRowsColumns()
{
SDimension16 frameSize;
GetFrameSize(frameSize);
if( mNumberAttachments <= 0 )
return;
int16 numCols = frameSize.width / kColWidth;
if ( numCols == 0 )
numCols = 1; // if the only cell is a fractionally visible cell, use it
if ( numCols > mNumberAttachments )
numCols = mNumberAttachments;
int16 numRows = mNumberAttachments / numCols;
if ( mNumberAttachments % numCols )
numRows ++;
// Remove old table geometry
RemoveRows( mRows,0, false );
RemoveCols (mCols, 0, false );
// Insert the new geometry
InsertCols( numCols, 1, NULL, 0, false);
InsertRows( numRows, 1, NULL, 0, true );
} // CMessageAttachmentView::CalculateRowsColumns()
Int32 CMessageAttachmentView::CalculateAttachmentIndex( STableCell inCell)
{
Int32 attachmentIndex = ( (inCell.row-1)*(mCols) + inCell.col -1 ); // Attachment Lists are zero based
Assert_( attachmentIndex >= 0 );
return attachmentIndex;
} // CMessageAttachmentView::CalculateAttachmentIndex

View File

@ -0,0 +1,106 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMessageAttachmentView.h
#pragma once
#include "LTableView.h"
#include "msgcom.h"
#include <LDragAndDrop.h>
class CMessageView;
class CBrokeredView;
class CAttachmentIcon;
class CMessageAttachmentView: public LTableView, public LCommander, public LDragAndDrop
{
private:
typedef LTableView Inherited;
public:
enum { class_ID = 'MATv' };
CMessageAttachmentView(LStream* inStream);
virtual ~CMessageAttachmentView();
virtual void FinishCreateSelf();
virtual void SetUpTableHelpers();
void SetMessageAttachmentList( MSG_Pane* pane, int32 numberAttachments );
void ClearMessageAttachmentView();
virtual void OpenSelection( int32 action );
virtual void HandleURL( URL_Struct* inURL, int32 action );
// LPane
virtual void ResizeFrameBy(
Int16 inWidthDelta,
Int16 inHeightDelta,
Boolean inRefresh);
void ToggleVisibility();
virtual void Hide();
virtual void Show();
void Remove();
// LCommander
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand( CommandT inCommand, void *ioParam );
// LTableView
virtual void HiliteSelection(
Boolean inActively,
Boolean inHilite);
virtual void HiliteCell(
const STableCell &inCell,
Boolean inHilite);
virtual Boolean ClickSelect(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
// LDragandDrop
// ------------------------------------------------------------
virtual void DragSelection(const STableCell& /*inCell*/, const SMouseDownEvent &inMouseDown);
virtual void AddSelectionToDrag(DragReference inDragRef, RgnHandle inDragRgn);
virtual void DoDragSendData(FlavorType inFlavor,
ItemReference inItemRef,
DragReference inDragRef);
protected:
virtual void DrawSelf();
virtual void DrawCell( const STableCell &inCell, const Rect &inLocalRect );
void CalculateRowsColumns();
Int32 CalculateAttachmentIndex( STableCell inCell);
CBrokeredView* mBrokeredView;
MSG_Pane *mMSGPane;
CMessageView *mMessageView;
Int16 mExpandedHeight;
Int16 mClickCountToOpen;
MSG_AttachmentData *mAttachmentList;
Int32 mNumberAttachments;
CAttachmentIcon **mAttachmentIconList;
DragSendDataUPP mSendDataUPP;
};

View File

@ -0,0 +1,469 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CMessageFolder.cp
#include "CMessageFolder.h"
#include "MailNewsCallbacks.h"
#include "CMailNewsContext.h"
//======================================
#pragma mark --- CCachedFolderLine
//======================================
#if 0
//======================================
class CMessageFolderListener : public CMailCallbackListener
//======================================
{
public:
CMessageFolderListener() { sMessageFolderListener = this; }
~CMessageFolderListener() { sMessageFolderListener = nil; }
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value); // must always be supported.
static CMessageFolderListener* sMessageFolderListener;
};
#endif // 0
//======================================
class CFolderLineComparator : public LComparator
//======================================
{
virtual Int32 Compare(
const void* inItemOne,
const void* inItemTwo,
Uint32 inSizeOne,
Uint32 inSizeTwo) const;
virtual Int32 CompareToKey(
const void* inItem,
Uint32 /* inSize */,
const void* inKey) const;
}; // class CFolderLineComparator
LArray* CCachedFolderLine::sLineList = nil;
//----------------------------------------------------------------------------------------
Int32 CFolderLineComparator::Compare(
const void* inItemOne,
const void* inItemTwo,
Uint32 /*inSizeOne*/,
Uint32 /*inSizeTwo*/) const
//----------------------------------------------------------------------------------------
{
return (Int32)(*(const CCachedFolderLine**)inItemOne)->mFolderLine.id
- (Int32)(*(const CCachedFolderLine**)inItemTwo)->mFolderLine.id;
}
//----------------------------------------------------------------------------------------
Int32 CFolderLineComparator::CompareToKey(
const void* inItem,
Uint32 /* inSize */,
const void* inKey) const
//----------------------------------------------------------------------------------------
{
return (Int32)(*(CCachedFolderLine**)inItem)->mFolderLine.id
- (Int32)(const MSG_FolderInfo*)inKey;
}
//----------------------------------------------------------------------------------------
CCachedFolderLine::CCachedFolderLine(MSG_Pane* inFolderPane, MSG_FolderInfo* inID)
//----------------------------------------------------------------------------------------
: mRefCount(0)
{
mFolderLine.id = inID; // set this up for the FolderInfoChanged() call.
FolderInfoChanged(inFolderPane);
// Listen for changes to the folder info.
// if (!CMessageFolderListener::sMessageFolderListener)
// new CMessageFolderListener;
if (!sLineList)
{
// Initialize the sorted array
sLineList = new LArray(sizeof(CCachedFolderLine*), new CFolderLineComparator, true);
sLineList->AdjustAllocation(50); // Allow for 50 items initially
}
sLineList->InsertItemsAt(1, 0/*ignored*/, &this);
} // CCachedFolderLine::CCachedFolderLine
//----------------------------------------------------------------------------------------
CCachedFolderLine::~CCachedFolderLine()
//----------------------------------------------------------------------------------------
{
if (sLineList)
{
sLineList->Remove(&this);
// When the last cached folderline goes, no need to have a listener.
if (sLineList->GetCount() == 0)
{
delete sLineList;
sLineList = nil;
// delete CMessageFolderListener::sMessageFolderListener;
}
}
} // CCachedFolderLine::~CCachedFolderLine
//----------------------------------------------------------------------------------------
void CCachedFolderLine::FolderInfoChanged(MSG_Pane* inFolderPane)
//----------------------------------------------------------------------------------------
{
MSG_FolderInfo* id = mFolderLine.id; // this is non-volatile
if (id)
{
MSG_ViewIndex index = MSG_VIEWINDEXNONE;
if (inFolderPane && ::MSG_GetPaneType(inFolderPane) == MSG_FOLDERPANE)
{
// Only relative to a pane can we get the "elided" bit right, to tell
// whether or not the twistie is open.
index = ::MSG_GetFolderIndex(inFolderPane, id);
}
if (index != MSG_VIEWINDEXNONE)
::MSG_GetFolderLineByIndex(inFolderPane, index, 1, &mFolderLine);
else
::MSG_GetFolderLineById(CMailNewsContext::GetMailMaster(), id, &mFolderLine);
}
else
{
// There is a hack in which we add a NULL MSG_FolderInfo* to the cache.
// Rather than call msglib to initialize the folder line (which will cause
// an assert) just zero out the folderline ourselves.
memset(&mFolderLine, 0, sizeof(MSG_FolderLine));
}
Assert_(id==mFolderLine.id);
}
//----------------------------------------------------------------------------------------
void CMessageFolder::FolderLevelChanged(MSG_Pane* inFolderPane)
// Calls FolderInfoChanged on this and all its descendents.
//----------------------------------------------------------------------------------------
{
FolderInfoChanged(inFolderPane);
UInt32 childCount = CountSubFolders();
if (childCount)
{
typedef MSG_FolderInfo* mfip;
try
{
MSG_FolderInfo** childList = new mfip[childCount]; // throws...
::MSG_GetFolderChildren(
CMailNewsContext::GetMailMaster(),
GetFolderInfo(),
childList,
childCount);
MSG_FolderInfo** child = &childList[0];
for (SInt32 j = 0; j < childCount; j++, child++)
{
CMessageFolder childFolder(*child, inFolderPane);
childFolder.FolderLevelChanged(inFolderPane);
}
delete [] childList;
}
catch(...)
{
}
}
} // CMessageFolder::FolderLevelChanged
//----------------------------------------------------------------------------------------
void CCachedFolderLine::FolderInfoChanged(MSG_Pane* inFolderPane, MSG_FolderInfo* inID)
//----------------------------------------------------------------------------------------
{
CCachedFolderLine* folder = FindFolderFor(inID);
if (folder)
folder->FolderInfoChanged(inFolderPane);
}
//----------------------------------------------------------------------------------------
CCachedFolderLine* CCachedFolderLine::FindFolderFor(MSG_FolderInfo* inID)
//----------------------------------------------------------------------------------------
{
if (!sLineList)
return nil;
CCachedFolderLine* result = nil;
ArrayIndexT arrayIndex = sLineList->FetchIndexOfKey(inID);
if (arrayIndex != LArray::index_Bad)
{
sLineList->FetchItemAt(arrayIndex, &result);
}
return result;
}
//----------------------------------------------------------------------------------------
CCachedFolderLine* CCachedFolderLine::GetFolderFor(MSG_Pane* inFolderPane, MSG_FolderInfo* inID)
//----------------------------------------------------------------------------------------
{
CCachedFolderLine* folderLine = FindFolderFor(inID);
if (!folderLine)
folderLine = new CCachedFolderLine(inFolderPane, inID);
return folderLine;
}
//----------------------------------------------------------------------------------------
CCachedFolderLine* CCachedFolderLine::GetFolderFor(MSG_Pane* inFolderPane, MSG_ViewIndex inIndex)
//----------------------------------------------------------------------------------------
{
MSG_FolderInfo* id = ::MSG_GetFolderInfo(inFolderPane, inIndex);
CCachedFolderLine* folderLine = FindFolderFor(id);
if (!folderLine)
folderLine = new CCachedFolderLine(inFolderPane, id);
return folderLine;
}
#if 0
//======================================
#pragma mark --- CMessageFolderListener
//======================================
CMessageFolderListener* CMessageFolderListener::sMessageFolderListener = nil;
//----------------------------------------------------------------------------------------
void CMessageFolderListener::PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value)
//----------------------------------------------------------------------------------------
{
if (inNotifyCode == MSG_PaneNotifyFolderInfoChanged)
CCachedFolderLine::FolderInfoChanged((MSG_FolderInfo*)value);
}
#endif // 0
//======================================
#pragma mark --- CMessageFolder
//======================================
//----------------------------------------------------------------------------------------
CMessageFolder::CMessageFolder(TableIndexT inRow, MSG_Pane* inFolderList)
//----------------------------------------------------------------------------------------
{
mCachedFolderLine = CCachedFolderLine::GetFolderFor(inFolderList, inRow - 1);
mCachedFolderLine->AddUser(this);
}
//----------------------------------------------------------------------------------------
CMessageFolder::CMessageFolder(const MSG_FolderInfo* id, MSG_Pane* inFolderPane)
//----------------------------------------------------------------------------------------
{
mCachedFolderLine = CCachedFolderLine::GetFolderFor(inFolderPane, (MSG_FolderInfo*)id);
mCachedFolderLine->AddUser(this);
}
//----------------------------------------------------------------------------------------
CMessageFolder::CMessageFolder(const CMessageFolder& inFolder)
//----------------------------------------------------------------------------------------
{
mCachedFolderLine = inFolder.mCachedFolderLine;
mCachedFolderLine->AddUser(this);
}
//----------------------------------------------------------------------------------------
CMessageFolder::~CMessageFolder()
//----------------------------------------------------------------------------------------
{
mCachedFolderLine->RemoveUser(this);
}
//----------------------------------------------------------------------------------------
void CMessageFolder::operator=(const CMessageFolder& other)
//----------------------------------------------------------------------------------------
{
if (!(*this == other)) // uses operator ==
{
mCachedFolderLine->RemoveUser(this);
mCachedFolderLine = other.mCachedFolderLine;
mCachedFolderLine->AddUser(this);
}
}
//----------------------------------------------------------------------------------------
MSG_FolderInfo* CMessageFolder::GetFolderInfo() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.id;
}
//----------------------------------------------------------------------------------------
void CMessageFolder::SetFolderInfo(const MSG_FolderInfo* id, MSG_Pane* inFolderPane)
//----------------------------------------------------------------------------------------
{
if (id != GetFolderInfo())
{
mCachedFolderLine->RemoveUser(this);
mCachedFolderLine = CCachedFolderLine::GetFolderFor(inFolderPane, (MSG_FolderInfo*)id);
mCachedFolderLine->AddUser(this);
}
}
//----------------------------------------------------------------------------------------
MSG_Pane* CMessageFolder::GetThreadPane() const
//----------------------------------------------------------------------------------------
{
return ::MSG_FindPaneOfType(
CMailNewsContext::GetMailMaster(),
GetFolderInfo(),
MSG_THREADPANE);
}
//----------------------------------------------------------------------------------------
MSG_Pane* CMessageFolder::GetFolderPane()
//----------------------------------------------------------------------------------------
{
return ::MSG_FindPane(
nil, // Don't care about context matching
MSG_FOLDERPANE);
}
//----------------------------------------------------------------------------------------
void CMessageFolder::FolderInfoChanged(MSG_Pane* inFolderPane)
//----------------------------------------------------------------------------------------
{
mCachedFolderLine->FolderInfoChanged(inFolderPane);
}
//----------------------------------------------------------------------------------------
Int32 CMessageFolder::CountMessages() const
//----------------------------------------------------------------------------------------
{
if (mCachedFolderLine->mFolderLine.unseen < 0)
return -1; // hack: this indicates unknown.
return mCachedFolderLine->mFolderLine.total;
}
//----------------------------------------------------------------------------------------
UInt32 CMessageFolder::GetDeletedBytes() const
//----------------------------------------------------------------------------------------
{
if (mCachedFolderLine->mFolderLine.deletedBytes < 0)
return -1; // hack: this indicates unknown.
return mCachedFolderLine->mFolderLine.deletedBytes;
}
//
// Icon suite IDs
//
enum
{
kNormalMessageFolderIconID = 15238
, kInboxMessageFolderIconID = 15240
, kInboxWithNewMailMessageFolderIconID = 15242
, kOutboxMessageFolderIconID = 15244
, kSentMailMessageFolderIconID = 15246
, kDraftsMessageFolderIconID = 15248
, kRemoteMessageFolderIconID = 15250
, kEmptyTrashMessageFolderIcon = 270
, kNonEmptyTrashMessageFolderIcon = 270
// Icons for message folders. These need to be in a menu, so their numbers are 256+
// Add 1 for the "open" state (except for trash)
, kMailServerFolderIconID = 15225
// Icons for news groups/hosts
, kNewsHostFolderIconID = 15227
, kNewsGroupFolderIconID = 15227
};
static ResIDT gIconIDTable[] = {
//----------------------------------------------------------------------------------------
//NAME READ UNREAD
// LOCAL ONLINE LOCAL ONLINE
// DEFAULT SPECIAL DEFAULT SPECIAL DEFAULT SPECIAL DEFAULT SPECIAL
//----------------------------------------------------------------------------------------
/* Folder*/ 15238 , 15238 , 15250 , 15250 , 15238 , 15394 , 15250 , 15394 ,
/* Inbox */ 15240 , 15240 , 15240 , 15240 , 15242 , 15242 , 15242 , 15242 ,
/* Outbox*/ 15244 , 15244 , 15244 , 15244 , 15244 , 15244 , 15244 , 15244 ,
/* Sent */ 15246 , 15246 , 15246 , 15246 , 15246 , 15246 , 15246 , 15246 ,
/* Drafts*/ 15248 , 15248 , 15248 , 15248 , 15248 , 15248 , 15248 , 15248 ,
/* Trash */ 15252 , 15252 , 15252 , 15252 , 15252 , 15252 , 15252 , 15252 ,
/* Newsgrp*/ 0 , 0 , 15231 , 15233 , 0 , 0 , 15231 , 15232
};
enum {
kSpecial = 1 // offset
, kOnline = 2 // offset
, kNewMessages = 4 // offset
, kKindsPerRow = 8
, kIconBaseIx = 0 // SPECIAL = Got new
, kInboxIx = 1 * kKindsPerRow // SPECIAL = Got new
, kOutboxIx = 2 * kKindsPerRow // SPECIAL = OCCUPIED
, kSentIx = 3 * kKindsPerRow
, kDraftsIx = 4 * kKindsPerRow
, kTrashIx = 5 * kKindsPerRow // SPECIAL = OCCUPIED
, kNewsGroupIx = 6 * kKindsPerRow // SPECIAL = SUBSCRIBED
};
//----------------------------------------------------------------------------------------
ResIDT CMessageFolder::GetIconID() const
// To do: deal with the "Open" state, the "read" state, etc.
//----------------------------------------------------------------------------------------
{
UInt32 folderFlags = this->GetFolderType();
if (GetLevel() == kRootLevel)
{
if ((folderFlags & MSG_FOLDER_FLAG_NEWS_HOST))
return kNewsHostFolderIconID; // li'l computer
return kMailServerFolderIconID; // li'l computer
}
short iconIndex = kIconBaseIx;
switch (folderFlags & ~(MSG_FOLDER_FLAG_MAIL | MSG_FOLDER_FLAG_IMAPBOX))
{
case MSG_FOLDER_FLAG_NEWSGROUP:
iconIndex = kNewsGroupIx + kOnline; // always online!
if (this->IsSubscribedNewsgroup())
iconIndex += kSpecial; // special = subscribed
break;
case MSG_FOLDER_FLAG_TRASH:
iconIndex = kTrashIx;
if (this->CountMessages() != 0)
iconIndex += kSpecial; // special = nonempty
break;
case MSG_FOLDER_FLAG_SENTMAIL:
iconIndex = kSentIx;
break;
case MSG_FOLDER_FLAG_TEMPLATES:
case MSG_FOLDER_FLAG_DRAFTS:
iconIndex = kDraftsIx;
break;
case MSG_FOLDER_FLAG_QUEUE:
iconIndex = kOutboxIx;
if (this->CountMessages() != 0)
iconIndex += kSpecial; // special = nonempty
break;
case MSG_FOLDER_FLAG_INBOX:
iconIndex = kInboxIx;
if (this->HasNewMessages())
iconIndex += kSpecial; // special = got new messages
break;
default:
iconIndex = kIconBaseIx;
if (this->HasNewMessages())
iconIndex += kSpecial; // special = got new messages
}
if (this->HasNewMessages() )
iconIndex += kNewMessages;
if ((folderFlags & MSG_FOLDER_FLAG_IMAPBOX) != 0)
iconIndex += kOnline;
return gIconIDTable[iconIndex];
} // CMessageFolder::GetIconID

View File

@ -0,0 +1,322 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
#pragma once
enum
{ kRootLevel = 1 // news host, local mail etc.
, kSpecialFolderLevel = 2 // inbox, sent, drafts...
};
#include <LTableView.h> // for TableIndexT
#include "msgcom.h"
struct CCachedFolderLine; // forward
//========================================================================================
class CMessageFolder
//========================================================================================
{
public:
CMessageFolder(TableIndexT inRow, MSG_Pane* inFolderPane);
// In the next constructor (and similar functions that
// take a MSG_FolderInfo*, there is a MSG_Pane* param
// which is optional. Supplying the pane will allow
// the ELIDED flag to work properly, because it is
// a property of the "view" and not an intrinsic property
// of the folder itself.
CMessageFolder(
const MSG_FolderInfo* id = nil,
MSG_Pane* inFolderPane = nil);
// inFolderPane can be nil, as can id.
CMessageFolder(const CMessageFolder& inFolder);
~CMessageFolder();
void operator=(const CMessageFolder& other);
Boolean operator==(const CMessageFolder& other) const;
operator MSG_FolderInfo*() const { return GetFolderInfo(); }
void SetFolderInfo(const MSG_FolderInfo* id, MSG_Pane* inFolderPane = nil);
// inFolderPane can be nil, as can id.
void FolderInfoChanged(MSG_Pane* inFolderPane = nil);
void FolderLevelChanged(MSG_Pane* inFolderPane = nil);
// calls FolderInfoChanged on children, too.
// inFolderPane can be nil.
UInt32 GetFolderType() const;
const char* GetName() const;
const char* GetPrettyName() const;
UInt32 GetLevel() const;
SInt32 CountMessages() const; // neg if unknown
SInt32 CountUnseen() const; // neg if unknown
SInt32 CountDeepUnseen() const; // neg if unknown
UInt32 CountSubFolders() const;
UInt32 GetDeletedBytes() const;
Boolean IsOpen() const;
MSG_ViewIndex GetIndex() const;
MSG_FolderInfo* GetFolderInfo() const;
const MSG_FolderLine* GetFolderLine() const;
MSG_Pane* GetThreadPane() const; // Returns a threadpane viewing this.
static MSG_Pane* GetFolderPane();
// Flag property accessors:
UInt32 GetFolderFlags() const;
UInt32 GetFolderPrefFlags() const;
Boolean HasNewMessages() const;
Boolean ContainsCategories() const;
Boolean IsInbox() const;
Boolean IsTrash() const;
Boolean IsMailServer() const;
Boolean IsMailFolder() const;
Boolean IsLocalMailFolder() const;
Boolean IsIMAPMailFolder() const;
Boolean IsNewsgroup() const;
Boolean IsNewsHost() const;
Boolean CanContainThreads() const;
Boolean IsSubscribedNewsgroup() const;
ResIDT GetIconID() const;
// Data
// NOTE WELL: This class is currently 4 bytes. Many users rely on its being light weight,
// and it is passed around by value, not by reference. Note that the copy
// constructor does the right thing with reference counting.
// So BE VERY RELUCTANT TO ADD NEW DATA MEMBERS!
protected:
CCachedFolderLine* mCachedFolderLine;
}; // class CMessageFolder
//========================================================================================
class CCachedFolderLine
//========================================================================================
{
private:
CCachedFolderLine(MSG_Pane* inFolderPane, MSG_FolderInfo* id);
// inFolderPane can be nil.
~CCachedFolderLine();
static CCachedFolderLine* FindFolderFor(MSG_FolderInfo* id);
// doesn't create
public:
void AddUser(CMessageFolder*) { mRefCount++; }
void RemoveUser(CMessageFolder*) { if (--mRefCount <= 0) delete this; }
void FolderInfoChanged(MSG_Pane* inFolderPane);
// inFolderPane can be nil.
static void FolderInfoChanged(MSG_Pane* inFolderPane, MSG_FolderInfo* inID);
// inFolderPane can be nil.
static CCachedFolderLine* GetFolderFor(MSG_Pane* inFolderPane, MSG_FolderInfo* id);
// creates if nec. inFolderPane can be nil.
static CCachedFolderLine* GetFolderFor(MSG_Pane* inFolderPane, MSG_ViewIndex inIndex);
// creates if nec.inFolderPane IS REQUIRED.
//-----
// Data
//-----
public:
MSG_FolderLine mFolderLine;
private:
Int32 mRefCount;
static LArray* sLineList;
}; // class CCachedFolderLine
#define kMessageFolderTypeMask ( MSG_FOLDER_FLAG_NEWSGROUP | \
MSG_FOLDER_FLAG_NEWS_HOST | \
MSG_FOLDER_FLAG_MAIL | \
MSG_FOLDER_FLAG_TRASH | MSG_FOLDER_FLAG_SENTMAIL | \
MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE | \
MSG_FOLDER_FLAG_TEMPLATES | MSG_FOLDER_FLAG_PERSONAL_SHARED | \
MSG_FOLDER_FLAG_IMAP_OTHER_USER | MSG_FOLDER_FLAG_IMAP_PUBLIC | \
MSG_FOLDER_FLAG_INBOX | MSG_FOLDER_FLAG_IMAPBOX)
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::operator==(const CMessageFolder& other) const
//----------------------------------------------------------------------------------------
{
return GetFolderInfo() == other.GetFolderInfo();
}
//----------------------------------------------------------------------------------------
inline UInt32 CMessageFolder::GetFolderPrefFlags() const
//----------------------------------------------------------------------------------------
{
return ::MSG_GetFolderPrefFlags(GetFolderInfo());
}
//----------------------------------------------------------------------------------------
inline const MSG_FolderLine* CMessageFolder::GetFolderLine() const
//----------------------------------------------------------------------------------------
{
return &mCachedFolderLine->mFolderLine;
}
//----------------------------------------------------------------------------------------
inline UInt32 CMessageFolder::GetFolderType() const
//----------------------------------------------------------------------------------------
{
return (mCachedFolderLine->mFolderLine.flags & kMessageFolderTypeMask);
}
//----------------------------------------------------------------------------------------
inline const char* CMessageFolder::GetName() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.name;
}
//----------------------------------------------------------------------------------------
inline const char* CMessageFolder::GetPrettyName() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.prettyName;
}
//----------------------------------------------------------------------------------------
inline MSG_ViewIndex CMessageFolder::GetIndex() const
//----------------------------------------------------------------------------------------
{
Assert_(false); // this is probably a bad function, now that multiple f. panes exist.
return MSG_GetFolderIndex(GetFolderPane(), GetFolderInfo());
}
//----------------------------------------------------------------------------------------
inline UInt32 CMessageFolder::GetFolderFlags() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.flags;
}
//----------------------------------------------------------------------------------------
inline UInt32 CMessageFolder::GetLevel() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.level;
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::CanContainThreads() const
//----------------------------------------------------------------------------------------
{
return GetLevel() > kRootLevel;
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsSubscribedNewsgroup() const
//----------------------------------------------------------------------------------------
{
#define SUBSCRIBED_NEWSGROUP (MSG_FOLDER_FLAG_SUBSCRIBED | MSG_FOLDER_FLAG_NEWSGROUP)
return ((GetFolderFlags() & SUBSCRIBED_NEWSGROUP) == SUBSCRIBED_NEWSGROUP );
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::HasNewMessages() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_GOT_NEW) != 0);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsNewsgroup() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_NEWSGROUP) != 0);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsMailServer() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_MAIL) == MSG_FOLDER_FLAG_MAIL
&& GetLevel() == kRootLevel);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsMailFolder() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_MAIL) == MSG_FOLDER_FLAG_MAIL);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsIMAPMailFolder() const
//----------------------------------------------------------------------------------------
{
#define IMAP_FOLDER (MSG_FOLDER_FLAG_IMAPBOX | MSG_FOLDER_FLAG_MAIL)
return ((GetFolderFlags() & IMAP_FOLDER) == IMAP_FOLDER);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsLocalMailFolder() const
//----------------------------------------------------------------------------------------
{
// folder bit set and imap bit clear.
return ((GetFolderFlags() & IMAP_FOLDER) == MSG_FOLDER_FLAG_MAIL);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsNewsHost() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_NEWS_HOST) != 0);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsInbox() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_INBOX) != 0);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsTrash() const
//----------------------------------------------------------------------------------------
{
return ((GetFolderFlags() & MSG_FOLDER_FLAG_TRASH) != 0);
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::ContainsCategories() const
//----------------------------------------------------------------------------------------
{
#define NEWSGROUP_WITH_CATEGORIES (MSG_FOLDER_FLAG_CAT_CONTAINER | MSG_FOLDER_FLAG_NEWSGROUP)
return ((GetFolderFlags() & NEWSGROUP_WITH_CATEGORIES) == NEWSGROUP_WITH_CATEGORIES );
}
//----------------------------------------------------------------------------------------
inline Int32 CMessageFolder::CountUnseen() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.unseen;
}
//----------------------------------------------------------------------------------------
inline Int32 CMessageFolder::CountDeepUnseen() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.deepUnseen;
}
//----------------------------------------------------------------------------------------
inline UInt32 CMessageFolder::CountSubFolders() const
//----------------------------------------------------------------------------------------
{
return mCachedFolderLine->mFolderLine.numChildren;
}
//----------------------------------------------------------------------------------------
inline Boolean CMessageFolder::IsOpen() const
//----------------------------------------------------------------------------------------
{
return ((mCachedFolderLine->mFolderLine.flags & MSG_FOLDER_FLAG_ELIDED) == 0);
} // CMessageFolder::IsOpen

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/* -*- 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.
*/
// CMessageFolderView.h
#pragma once
#include <LTableView.h>
#include <LDragAndDrop.h>
#include "CSimpleFolderView.h"
#include "msgcom.h"
class CThreadView;
class CThreadWindow;
class CStr255;
class CMessageFolder;
class CMailSelection;
//======================================
class CMessageFolderView : public CSimpleFolderView
//======================================
{
private:
typedef CSimpleFolderView Inherited;
public:
enum
{ class_ID = 'msFv'
};
CMessageFolderView(LStream *inStream);
virtual ~CMessageFolderView();
// ------------------------------------------------------------
// Command implementation
// ------------------------------------------------------------
void DoAddNewsGroup();
virtual void DeleteSelection();
void DoDeleteSelection(const CMailSelection& inSelection);
void GetLongWindowDescription(CStr255& outDescription);
virtual void OpenRow(TableIndexT inRow);
virtual void SelectionChanged(); // maintain history
virtual void GetInfo(); // called from the base class.
void DropMessages(
const CMailSelection& inSelection,
const CMessageFolder& inDestFolder,
Boolean doCopy);
protected:
inline void OpenFolder(UInt32 inFolderIndex) { OpenRow(inFolderIndex); }
// ------------------------------------------------------------
// Hierarchy
// ------------------------------------------------------------
virtual Boolean CellInitiatesDrag(const STableCell& inCell) const;
virtual Boolean GetRowDragRgn(TableIndexT inRow, RgnHandle ioHiliteRgn) const;
// ------------------------------------------------------------
// LDragAndDrop overrides
// ------------------------------------------------------------
virtual void AddRowDataToDrag(TableIndexT inRow, DragReference inDragRef);
virtual Boolean ItemIsAcceptable(DragReference inDragRef, ItemReference inItemRef);
virtual void ReceiveDragItem(
DragReference inDragRef,
DragAttributes inDragAttrs,
ItemReference inItemRef,
Rect& inItemBounds);
// Specials from CStandardFlexTable
virtual Boolean CanDoInlineEditing();
virtual void InlineEditorTextChanged();
virtual void InlineEditorDone();
virtual Boolean RowCanAcceptDrop(
DragReference inDragRef,
TableIndexT inDropRow);
virtual Boolean RowCanAcceptDropBetweenAbove(
DragReference inDragRef,
TableIndexT inDropRow);
Boolean GetSelectionAndCopyStatusFromDrag(
DragReference inDragRef,
CMessageFolder& inDestFolder,
CMailSelection& outSelection,
Boolean& outCopy);
//-----------------------------------
// Commands
//-----------------------------------
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
public:
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
protected:
virtual Boolean FindMessageLibraryCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
//-----------------------------------
// Messaging
//-----------------------------------
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
// msg
public:
void WatchFolderForChildren(MSG_FolderInfo* inFolderInfo);
// ------------------------------------------------------------
// QA Partner support
// ------------------------------------------------------------
#if defined(QAP_BUILD)
public:
virtual void GetQapRowText(TableIndexT inRow, char* outText, UInt16 inMaxBufferLength) const;
#endif
// ------------------------------------------------------------
// Data
// ------------------------------------------------------------
Boolean mUpdateMailFolderMenus;
}; // class CMessageFolderView

View File

@ -0,0 +1,328 @@
/* -*- 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.
*/
// CMessageSearchWindow.cp
#define DEBUGGER_ASSERTIONS
#include "CMessageSearchWindow.h"
#include "LGAPushButton.h"
#include "SearchHelpers.h"
#include "CMessageWindow.h"
#include "CMessageView.h"
#include "msgcom.h"
#include "CMailNewsContext.h"
#include "CSearchTableView.h"
#include "CMailFolderButtonPopup.h"
#include "libi18n.h"
#include "nc_exception.h"
#include "UIHelper.h"
#include "UMailSelection.h"
//-----------------------------------
CMessageSearchWindow::CMessageSearchWindow(LStream *inStream) :
CSearchWindowBase(inStream, WindowType_SearchMailNews),
mGoToFolderBtn( nil ), mMsgScopePopup( nil ),
mFileMessagePopup( nil ), scopeInfo( nil )
//-----------------------------------
{
SetPaneID( pane_ID );
mNumBasicScopeMenuItems = 3;
}
//-----------------------------------
CMessageSearchWindow::~CMessageSearchWindow()
//-----------------------------------
{
}
//-----------------------------------
void CMessageSearchWindow::FinishCreateSelf()
//-----------------------------------
{
// get controls
FindUIItemPtr( this, paneID_MsgScopePopup, mMsgScopePopup );
FindUIItemPtr( this, paneID_GoToFolder, mGoToFolderBtn );
FindUIItemPtr( this, paneID_FilePopup, mFileMessagePopup );
// initialize the move popup control
CMailFolderMixin::FolderChoices filePopupChoices
= static_cast<CMailFolderMixin::FolderChoices>(CMailFolderMixin::eWantPOP + CMailFolderMixin::eWantIMAP);
mFileMessagePopup->MSetFolderChoices( filePopupChoices );
CMailFolderMixin::UpdateMailFolderMixinsNow( mFileMessagePopup );
// add listeners
mGoToFolderBtn->AddListener( this );
mFileMessagePopup->AddListener( this );
mMsgScopePopup->AddListener( this );
// disable the selection controls until we get a result
DisableSelectionControls();
Inherited::FinishCreateSelf();
}
//-----------------------------------
void CMessageSearchWindow::SetUpBeforeSelecting()
// Set up the window just before it is selected and brought to the front of other
// windows in the app.
//-----------------------------------
{
// Clear the selected search list
mSearchFolders.RemoveItemsAt(LArray::index_Last, LArray::index_First);
// Determine front window status
CMailFlexTable* frontSearchTable = nil;
CMailNewsWindow* frontMailWindow = nil;
GetDefaultSearchTable(frontMailWindow, frontSearchTable);
//Figure out which folderinfo to use as the scope.
MSG_FolderInfo* msgFolderInfo = nil;
if (frontSearchTable)
{
// Get the xp message pane
MSG_Pane* msgPane = frontSearchTable->GetMessagePane();
// Set up search flags and selected folder list
AssertFail_(msgPane != nil);
MSG_PaneType paneType = MSG_GetPaneType(msgPane);
switch ( paneType )
{
case MSG_FOLDERPANE:
if (!frontSearchTable->IsValidRow(1))
return;
// If there's a single selection, make it the default. Otherwise,
// use the first row.
CMailSelection theSelection;
frontSearchTable->GetSelection(theSelection);
AssertFail_(MSG_GetPaneType(theSelection.xpPane) == MSG_FOLDERPANE);
AssertFail_(theSelection.xpPane == msgPane);
MSG_ViewIndex defaultIndex = 0;
if (theSelection.selectionSize == 1)
defaultIndex = *theSelection.GetSelectionList();
msgFolderInfo = ::MSG_GetFolderInfo(
theSelection.xpPane,
defaultIndex);
break;
case MSG_THREADPANE:
msgFolderInfo = ::MSG_GetCurFolder(msgPane);
AssertFail_(msgFolderInfo);
break;
default:
AssertFail_(false); // No other types accepted now!
break;
} // switch
}
else // message window case
{
CMessageWindow* messageWindow = dynamic_cast<CMessageWindow*>(frontMailWindow);
if (messageWindow)
{
CMessageView* messageView = messageWindow->GetMessageView();
if (messageView)
msgFolderInfo = messageView->GetFolderInfo();
}
}
// As a last resort, use the inbox
if (!msgFolderInfo)
{
::MSG_GetFoldersWithFlag(
CMailNewsContext::GetMailMaster(),
MSG_FOLDER_FLAG_INBOX,
&msgFolderInfo,
1);
}
AssertFail_(msgFolderInfo);
mMsgScopePopup->MSetSelectedFolder(msgFolderInfo, false);
// Get the folder csid and set it
SetWinCSID(INTL_DocToWinCharSetID( MSG_GetFolderCSID( msgFolderInfo ) ));
mSearchFolders.InsertItemsAt(1, LArray::index_Last, &msgFolderInfo);
mSearchManager.SetSearchScope(
(MSG_ScopeAttribute)CSearchManager::cScopeMailSelectedItems,
&mSearchFolders);
} // CMessageSearchWindow::SetUpBeforeSelecting
//-----------------------------------
void CMessageSearchWindow::MessageWindStop(Boolean inUserAborted)
//-----------------------------------
{
if ( mSearchManager.IsSearching() )
{
Inherited::MessageWindStop(inUserAborted);
// enable controls
EnableSelectionControls();
UpdatePort();
}
}
//-----------------------------------
void CMessageSearchWindow::MessageWindSearch()
//-----------------------------------
{
// Disable controls
DisableSelectionControls();
UpdatePort();
Inherited::MessageWindSearch();
} // CMessageSearchWindow::MessageWindSearch()
//-----------------------------------
void CMessageSearchWindow::UpdateTableStatusDisplay()
//-----------------------------------
{
AssertFail_(mResultsTable != nil);
Inherited::UpdateTableStatusDisplay();
XP_Bool enabled = false;
TableIndexT numSelectedItems = mResultsTable->GetSelectedRowCount();
if ( numSelectedItems > 0 )
{
CMailSelection selection;
mResultsTable->GetSelection(selection);
enabled = MSG_GoToFolderStatus(mSearchManager.GetMsgPane(),
(MSG_ViewIndex*)selection.GetSelectionList(),
selection.selectionSize);
}
if (enabled)
EnableSelectionControls();
else
DisableSelectionControls();
} // CMessageSearchWindow::UpdateTableStatusDisplay()
//-----------------------------------
void CMessageSearchWindow::EnableSelectionControls()
//
// Enable selection controls
//-----------------------------------
{
mGoToFolderBtn->Enable();
mFileMessagePopup->Enable();
}
//-----------------------------------
void CMessageSearchWindow::DisableSelectionControls()
//
// Disable selection controls
//-----------------------------------
{
mGoToFolderBtn->Disable();
mFileMessagePopup->Disable();
}
//-----------------------------------
void CMessageSearchWindow::ListenToMessage(MessageT inMessage, void *ioParam)
//-----------------------------------
{
switch (inMessage)
{
case msg_FilePopup:
// make sure we have a result table
AssertFail_(mResultsTable != nil);
// get the selection from the table
CMailSelection moveSelection;
mResultsTable->GetSelection( moveSelection );
// get the destination
MSG_FolderInfo* selectedDestination = ( (MSG_FolderInfo*) ioParam );
// get the search pane
MSG_Pane *searchPane = mSearchManager.GetMsgPane();
// sanity check
#ifdef DEBUG
if( selectedDestination == nil || searchPane == nil )
throw ;
#endif
try
{
// move the selected messages
int status = MSG_MoveMessagesIntoFolder( searchPane, moveSelection.GetSelectionList(),
moveSelection.selectionSize, selectedDestination );
// Currently the enum eSuccess is doubly defined in two different BE headers. So in order
// to prevent possible conflicts I just check for the succes value ( 0 )
if ( status != 0 )
throw mail_exception( eMoveMessageError );
}
catch( mail_exception& error )
{
error.DisplaySimpleAlert();
}
break;
case msg_GoToFolder:
AssertFail_(mResultsTable != nil);
CMailSelection selection;
mResultsTable->GetSelection(selection);
for (MSG_ViewIndex index = 0; index < selection.selectionSize; index ++)
{
mResultsTable->FindOrCreateThreadWindowForMessage(
selection.GetSelectionList()[index]);
}
{
// HACK to support opening of more than one folder
EventRecord ignoredEvent = {0};
LPeriodical::DevoteTimeToIdlers(ignoredEvent);
}
for (MSG_ViewIndex index = 0; index < selection.selectionSize; index ++)
{
mResultsTable->ShowMessage(
selection.GetSelectionList()[index],
CSearchTableView::kAddToThreadWindowSelection);
}
break;
case msg_MsgScope:
// get folder info
scopeInfo = ( ( MSG_FolderInfo*) ioParam );
if (mSearchFolders.GetCount() == 0)
mSearchFolders.InsertItemsAt(1, 1, &scopeInfo);
else
mSearchFolders.AssignItemsAt(1, 1, &scopeInfo);
// set the scope
mSearchManager.SetSearchScope( static_cast<MSG_ScopeAttribute>( CSearchManager::cScopeMailSelectedItems ),
&mSearchFolders );
SetWinCSID(INTL_DocToWinCharSetID(MSG_GetFolderCSID((MSG_FolderInfo *) ioParam)));
break;
default:
Inherited::ListenToMessage(inMessage, ioParam);
break;
}
} // CMessageSearchWindow::ListenToMessage
MSG_ScopeAttribute
CMessageSearchWindow::GetWindowScope() const
{
return static_cast<MSG_ScopeAttribute>( CSearchManager::cScopeMailSelectedItems );
}

View File

@ -0,0 +1,76 @@
/* -*- 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.
*/
// CMessageSearchWindow.h
#pragma once
#include "CSearchWindowBase.h"
class LGAPushButton;
class CFolderScopeGAPopup;
class CFolderMoveGAPopup;
//======================================
class CMessageSearchWindow : public CSearchWindowBase
//======================================
{
private:
typedef CSearchWindowBase Inherited;
public:
enum { class_ID = 'SchW', pane_ID = class_ID, res_ID = 8600 };
enum {
paneID_GoToFolder = 'GOTO'
,paneID_FilePopup = 'FILm'
,paneID_MsgScopePopup = 'SCOP'
};
enum {
msg_FilePopup = 'FILm'
,msg_GoToFolder = 'GOTO'
,msg_MsgScope = 'ScMs'
};
CMessageSearchWindow(LStream *inStream);
virtual ~CMessageSearchWindow();
virtual void SetUpBeforeSelecting();
protected:
virtual MSG_ScopeAttribute GetWindowScope() const;
virtual void FinishCreateSelf();
virtual void ListenToMessage(MessageT inMessage, void *ioParam = nil);
virtual ResIDT GetStatusResID() const { return res_ID; }
virtual void MessageWindStop(Boolean inUserAborted);
virtual void MessageWindSearch();
virtual void UpdateTableStatusDisplay();
private:
void EnableSelectionControls();
void DisableSelectionControls();
CFolderScopeGAPopup *mMsgScopePopup;
LGAPushButton *mGoToFolderBtn;
CFolderMoveGAPopup *mFileMessagePopup;
MSG_FolderInfo *scopeInfo;
}; // class CMessageSearchWindow

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,167 @@
/* -*- 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.h
#pragma once
#define INHERIT_FROM_BROWSERVIEW
#ifdef INHERIT_FROM_BROWSERVIEW
#include "CBrowserView.h"
#else
#include "CHTMLView.h"
#endif
#include "MailNewsCallbacks.h"
typedef struct MSG_ResultElement MSG_ResultElement;
class CMessageAttachmentView;
class CURLDispatchInfo;
class CDeferredCloseTask;
//======================================
class CMessageView
#ifdef INHERIT_FROM_BROWSERVIEW
: public CBrowserView
#else
: public CHTMLView
#endif
, public CMailCallbackListener
//======================================
{
private:
#ifdef INHERIT_FROM_BROWSERVIEW
typedef CBrowserView Inherited;
#else
typedef CHTMLView Inherited;
#endif
public:
enum { class_ID = 'MsVw' };
public:
CMessageView(LStream* inStream);
virtual ~CMessageView();
virtual void FinishCreateSelf(void);
virtual void ClickSelf(const SMouseDownEvent& where);
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
void SetAttachmentView( CMessageAttachmentView* attachmentView)
{ mAttachmentView = attachmentView; }
void SetMasterCommander(LCommander* inCommander)
{ mMasterCommander = inCommander; }
LCommander* GetMasterCommander() const
{ return mMasterCommander; }
virtual void SetContext(
CBrowserContext* inNewContext);
MSG_Pane* GetMessagePane() const { return mMessagePane; }
// Info about the parent folder: must be queried, not cached!
MSG_FolderInfo* GetFolderInfo() const;
uint32 GetFolderFlags() const;
// Info about the message currently displayed.
MSG_ViewIndex GetCurMessageViewIndex() const;
MessageKey GetCurMessageKey() const;
uint32 GetCurMessageFlags() const;
Boolean IsDueToCloseLater() const;
void SetDueToCloseLater();
void ShowMessage(MSG_Master* inMsgMaster,
MSG_FolderInfo* inMsgFolderInfo,
MessageKey inMessageKey,
Boolean inLoadNow = false);
void ClearMessageArea();
void ShowURLMessage(
const char* url,
Boolean inLoadNow = false);
void ShowSearchMessage(
MSG_Master *inMsgMaster,
MSG_ResultElement *inResult,
Boolean inNoFolder = false);
void FileMessageToSelectedPopupFolder(const char *ioFolderName,
Boolean inMoveMessages);//¥¥TSM
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
virtual void FindCommandStatus(
CommandT inCommand,
Boolean& outEnabled, Boolean& outUsesMark,
Char16& outMark,Str255 outName);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam);
Boolean ObeyMotionCommand(MSG_MotionType inCommand);
virtual Boolean HandleKeyPress(const EventRecord& inKeyEvent);
virtual Boolean SetDefaultCSID(Int16 default_csid, Boolean forceRepaginate = false);
virtual void AdaptToSuperFrameSize(
Int32 inSurrWidthDelta,
Int32 inSurrHeightDelta,
Boolean inRefresh);
virtual void AdjustCursorSelf(Point inPortPt, const EventRecord& inMacEvent);
Boolean MaybeCloseLater(CommandT inCommand); // check prefs
protected:
void YieldToMaster();
// An ugly solution, but after trying many, it's the only one that worked.
// This makes sure this view isn't target if there's a thread view in the same
// window.
virtual void InstallBackgroundColor();
// Sets mBackgroundColor. Called from ClearBackground().
// The base class implementation uses the text background
// preference, but derived classes can override this.
virtual void SetBackgroundColor(
Uint8 inRed,
Uint8 inGreen,
Uint8 inBlue);
// Avoids changing the color, cheats and sets it to white, which
// is what we want for mail messages. 98/01/13.
virtual void GetDefaultFileNameForSaveAs(URL_Struct* url, CStr31& defaultName);
// overridden by CMessageView to use subject.
virtual void DispatchURL(
URL_Struct* inURLStruct,
CNSContext* inTargetContext,
Boolean inDelay = false,
Boolean inForceCreate = false,
FO_Present_Types inOutputFormat = FO_CACHE_AND_PRESENT
);
virtual void DispatchURL(CURLDispatchInfo* inDispatchInfo);
void CloseLater(); // Close on next idle
protected:
MSG_Pane* mMessagePane;
LCommander* mMasterCommander; // Not the super commander. See YieldToMaster.
Boolean mLoadingNakedURL;
CMessageAttachmentView* mAttachmentView; // the attachment pane
Boolean mClosing;
MSG_MotionType mMotionPendingCommand;
CDeferredCloseTask* mDeferredCloseTask;
friend class CMessageAttachmentView;
};

View File

@ -0,0 +1,571 @@
/* -*- 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.
*/
// CMessageWindow.cp
#include "CMessageWindow.h"
#include "CMessageAttachmentView.h"
#include "CThreadView.h" // for CMessage
#include "uapp.h"
#include "ntypes.h"
#include "macutil.h"
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
#include "CBrowserContext.h"
#include "CMessageView.h"
#include "CProgressListener.h"
#include "CMailFolderButtonPopup.h"
#include "CThreadWindow.h"
#include "CMailNewsContext.h"
#include "CSpinningN.h"
#include "prefapi.h"
#include "URobustCreateWindow.h"
#include "CApplicationEventAttachment.h"
#include "CProxyPane.h"
#include "CProxyDragTask.h"
#include "UMailSelection.h"
#include "CSearchTableView.h"
#include "libi18n.h"
#include <LIconPane.h>
//----------------------------------------------------------------------------------------
CMessageWindow::CMessageWindow(LStream* inStream)
//----------------------------------------------------------------------------------------
: CMailNewsWindow(inStream, WindowType_Message)
, mContext(NULL)
{
}
//----------------------------------------------------------------------------------------
CMessageWindow::~CMessageWindow()
//----------------------------------------------------------------------------------------
{
SetWindowContext(nil);
}
//----------------------------------------------------------------------------------------
void CMessageWindow::FinishCreateSelf()
//----------------------------------------------------------------------------------------
{
UReanimator::LinkListenerToControls(this, this, res_ID);
Inherited::FinishCreateSelf();
CMessageView* messageView = GetMessageView();
Assert_(messageView);
SetLatentSub(messageView);
CMessageAttachmentView* attachmentView =
dynamic_cast<CMessageAttachmentView*>( FindPaneByID('MATv') );
if( attachmentView )
{
messageView->SetAttachmentView( attachmentView );
attachmentView->ClearMessageAttachmentView();
attachmentView->Hide();
}
// the location toolbar is a waste of space and should be hidden by default
LPane *locationBar = FindPaneByID(cMailNewsLocationToolbar);
if (mToolbarShown[CMailNewsWindow::LOCATION_TOOLBAR])
ToggleDragBar(cMailNewsLocationToolbar, CMailNewsWindow::LOCATION_TOOLBAR);
USecurityIconHelpers::AddListenerToSmallButton(
this /*LWindow**/,
(CHTMLView*)messageView /*LListener**/);
}
//----------------------------------------------------------------------------------------
CMessageView* CMessageWindow::GetMessageView()
//----------------------------------------------------------------------------------------
{
return dynamic_cast<CMessageView*>(FindPaneByID(CMessageView::class_ID));
}
//----------------------------------------------------------------------------------------
void CMessageWindow::SetWindowContext(CBrowserContext* inContext)
//----------------------------------------------------------------------------------------
{
CBrowserContext* oldContext = mContext; // save for below.
CSpinningN* theN = dynamic_cast<CSpinningN*>(FindPaneByID(CSpinningN::class_ID));
mContext = inContext;
if (mContext != NULL)
{
mContext->AddListener(this);
mContext->AddUser(this);
Assert_(mProgressListener != NULL);
mContext->AddListener(mProgressListener);
mContext->AddListener( &mSecurityListener);
if (theN)
mContext->AddListener(theN);
}
CMessageView* theMessageView = GetMessageView();
Assert_(theMessageView); // Can happen in lowmem, if creation fails
if (theMessageView)
{
theMessageView->SetContext(mContext);
mSecurityListener.SetMessageView( theMessageView );
// This call links up the model object hierarchy for any potential
// sub model that gets created within the scope of the html view.
theMessageView->SetFormElemBaseModel(this);
}
// Now it's safe to delete the old context, because the view's done with it.
if (oldContext)
{
oldContext->RemoveListener( &mSecurityListener );
mSecurityListener.SetMessageView( NULL );
oldContext->RemoveListener(this);
if (theN)
oldContext->RemoveListener(theN);
oldContext->RemoveUser(this); // and delete, probably.
}
} // CMessageWindow::SetWindowContext
//----------------------------------------------------------------------------------------
cstring CMessageWindow::GetCurrentURL()
//----------------------------------------------------------------------------------------
{
if (mContext)
return mContext->GetCurrentURL();
else
return cstring("");
}
//----------------------------------------------------------------------------------------
Int16 CMessageWindow::DefaultCSIDForNewWindow()
//----------------------------------------------------------------------------------------
{
Int16 csid = 0;
if (mContext != NULL)
csid = mContext->GetDefaultCSID();
if(0 == csid)
{
CMessageView* theMessageView = GetMessageView();
Assert_(theMessageView != NULL);
csid = theMessageView->DefaultCSIDForNewWindow();
}
return csid;
} // CMessageWindow::DefaultCSIDForNewWindow
//----------------------------------------------------------------------------------------
void CMessageWindow::ListenToMessage(MessageT inMessage, void* ioParam)
//----------------------------------------------------------------------------------------
{
switch (inMessage)
{
case msg_NSCDocTitleChanged:
{
CStr255 theTitle((const char*)ioParam);
// if we have a message view use the subject as the title
CMessageView* messageView = GetMessageView();
if (messageView)
{
MessageKey id = messageView->GetCurMessageKey();
if (id != MSG_MESSAGEKEYNONE )
{
MSG_MessageLine messageLine;
::MSG_GetThreadLineById(messageView->GetMessagePane(), id, &messageLine);
char buffer[256];
const char* raw = CMessage::GetSubject(&messageLine, buffer, sizeof(buffer)-1);
char* conv = IntlDecodeMimePartIIStr(raw, GetWindowContext()->GetWinCSID(), FALSE);
theTitle = CStr255((conv != NULL) ? conv : raw);
if (conv)
XP_FREE(conv);
}
}
SetDescriptor(theTitle);
CProxyPane* proxy = dynamic_cast<CProxyPane*>(FindPaneByID(CProxyPane::class_ID));
if (proxy)
proxy->ListenToMessage(inMessage, (char*)theTitle);
break;
}
case msg_NSCLayoutNewDocument:
//NoteBeginLayout();
break;
case msg_NSCFinishedLayout:
//NoteFinishedLayout();
break;
case msg_NSCAllConnectionsComplete:
//NoteAllConnectionsComplete();
CSpinningN* theN = dynamic_cast<CSpinningN*>(FindPaneByID(CSpinningN::class_ID));
if (theN)
theN->StopSpinningNow();
break;
case CMailCallbackManager::msg_ChangeStarting:
case CMailCallbackManager::msg_ChangeFinished:
case CMailCallbackManager::msg_PaneChanged:
CMailCallbackListener::SetPane(GetMessageView()->GetMessagePane());
if (IsMyPane(ioParam))
CMailCallbackListener::ListenToMessage(inMessage, ioParam);
break;
default:
// assume it's a button message.
GetMessageView()->ObeyCommand(inMessage, ioParam);
}
} // CMessageWindow::ListenToMessage
//----------------------------------------------------------------------------------------
void CMessageWindow::ChangeStarting(
MSG_Pane* /*inPane*/,
MSG_NOTIFY_CODE /*inChangeCode*/,
TableIndexT /*inStartRow*/,
SInt32 /*inRowCount*/)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
void CMessageWindow::ChangeFinished(
MSG_Pane* /*inPane*/,
MSG_NOTIFY_CODE /*inChangeCode*/,
TableIndexT /*inStartRow*/,
SInt32 /*inRowCount*/)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
void CMessageWindow::PaneChanged(
MSG_Pane* /*inPane*/,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value)
//----------------------------------------------------------------------------------------
{
switch (inNotifyCode)
{
case MSG_PaneNotifyMessageLoaded:
AdaptToolbarToMessage();
if (!GetMessageView()->IsDueToCloseLater())
Show();
break;
case MSG_PaneNotifyLastMessageDeleted:
// AttemptClose() here leads to nasty re-entrant interrrupt-context.
// What to do? Should close the window, but how?
break;
case MSG_PaneNotifyFolderDeleted:
if ((MSG_FolderInfo*)value != GetMessageView()->GetFolderInfo())
break;
// ELSE FALL THROUGH...
case MSG_PaneNotifyMessageDeleted:
AttemptClose(); // Causes reentrant InterruptContext call.
break;
}
} // CMessageWindow::PaneChanged
//----------------------------------------------------------------------------------------
CMessageWindow* CMessageWindow::FindAndShow(MessageKey inMessageKey)
//----------------------------------------------------------------------------------------
{
CWindowIterator iter(WindowType_Message, false);
CMessageWindow* window;
for (iter.Next(window); window; iter.Next(window))
{
window = dynamic_cast<CMessageWindow*>(window);
ThrowIfNULL_(window);
CMessageView* messageView = window->GetMessageView();
// inMessageKey zero means return the first message window of any kind
if (!inMessageKey || (messageView && messageView->GetCurMessageKey() == inMessageKey))
return window;
}
return nil;
} // CMessageWindow::FindAndShow
//----------------------------------------------------------------------------------------
void CMessageWindow::OpenFromURL(const char* url)
//----------------------------------------------------------------------------------------
{
MSG_MessageLine msgLine;
MSG_GetMessageLineForURL(CMailNewsContext::GetMailMaster(), url, &msgLine);
CMessageWindow* messageWindow = CMessageWindow::FindAndShow(msgLine.messageKey);
if (messageWindow)
{
// Found it. Bring it to the front.
messageWindow->Select();
return;
}
XP_Bool prefReuseWindow = 0; // recycle any message window
PREF_GetBoolPref("mailnews.reuse_message_window", &prefReuseWindow);
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) ^ prefReuseWindow)
{
messageWindow = CMessageWindow::FindAndShow(0);
}
// If we couldn't (or shouldn't) recycle one, make a new one.
if (!messageWindow)
{
try
{
messageWindow =
(CMessageWindow*)URobustCreateWindow::CreateWindow(
CMessageWindow::res_ID,
LCommander::GetTopCommander());
CBrowserContext* theContext = new CBrowserContext(MWContextMailMsg);
StSharer theShareLock(theContext); // if we throw, theContext will have no users & die
messageWindow->SetWindowContext(theContext);
}
catch(...)
{
delete messageWindow;
messageWindow = NULL;
throw;
}
}
// Whether it's a new one or an old one, load the message now.
if (messageWindow)
{
try
{
CMessageView* messageView = messageWindow->GetMessageView();
ThrowIfNULL_(messageView);
messageView->ShowURLMessage(url, false);
messageWindow->Select();
messageWindow->Show();
}
catch(...)
{
delete messageWindow;
messageWindow = NULL;
throw;
}
}
} // CMessageWindow::OpenFromURL
//----------------------------------------------------------------------------------------
/* static */ void CMessageWindow::CloseAll(MessageKey inMessageKey)
//----------------------------------------------------------------------------------------
{
CMessageWindow* win;
do {
win = CMessageWindow::FindAndShow(inMessageKey);
if (win )
win->AttemptClose();
} while (win);
} // CMessageWindow::CloseAll
//----------------------------------------------------------------------------------------
/* static */ void CMessageWindow::NoteSelectionFiledOrDeleted(const CMailSelection& inSelection)
// Tell every relevant message window that its message has been moved, so that it
// can, according to the preferences, close itself.
//----------------------------------------------------------------------------------------
{
const MSG_ViewIndex* index = inSelection.GetSelectionList();
MSG_PaneType paneType = ::MSG_GetPaneType(inSelection.xpPane);
for (int count = 0; count < inSelection.selectionSize; count++, index++)
{
MessageKey key;
switch (paneType)
{
case MSG_THREADPANE:
// These are the list panes:
key = ::MSG_GetMessageKey(inSelection.xpPane, *index);
break;
case MSG_SEARCHPANE:
// These are the list panes:
MSG_ResultElement* ignoredElement;
MSG_FolderInfo* ignoredFolder;
if (!CSearchTableView::GetMessageResultInfo(
inSelection.xpPane,
*index,
ignoredElement,
ignoredFolder,
key))
continue;
break;
case MSG_MESSAGEPANE:
// The message pane itself is running the copy. It will be notified
// on completion and close itself. Fall through and return.
default:
return; // no messages involved! Zero loop iterations.
}
CWindowIterator iter(WindowType_Message, false);
CMessageWindow* window;
for (iter.Next(window); window; iter.Next(window))
{
window = dynamic_cast<CMessageWindow*>(window);
Assert_(window);
CMessageView* messageView = window->GetMessageView();
if (messageView->GetCurMessageKey() == key)
messageView->MaybeCloseLater(cmd_MoveMailMessages);
} // for iter
} // for count
} // CMessageWindow::CloseAll
//----------------------------------------------------------------------------------------
void CMessageWindow::ActivateSelf()
//----------------------------------------------------------------------------------------
{
CMailNewsWindow::ActivateSelf();
}
//----------------------------------------------------------------------------------------
void CMessageWindow::AdaptToolbarToMessage()
//----------------------------------------------------------------------------------------
{
const PaneIDT paneID_MessageFileButton = 'Bfil';
const PaneIDT paneID_MessageReplyButton = 'Brep';
const PaneIDT paneID_MessageGetMailButton = 'Bget'; // mail
const PaneIDT paneID_MessageGetNewsButton = 'Bmor'; // news
const PaneIDT paneID_MessageComposeButton = 'Bcmp'; // mail
const PaneIDT paneID_MessagePostNewButton = 'Bpst'; // news
const PaneIDT paneID_MessagePrintButton = 'Bprn'; // mail
const PaneIDT paneID_MessageBackButton = 'Bbck'; // news
const PaneIDT paneID_MessageDeleteButton = 'Bdel'; // mail
const PaneIDT paneID_MessageMarkButton = 'Bmrk'; // news
CMessageView* messageView = GetMessageView();
Assert_(messageView != NULL);
uint32 folderFlags = messageView->GetFolderFlags();
// Set the window title to the subject of the message.
MessageKey id = messageView->GetCurMessageKey();
if (id != MSG_MESSAGEKEYNONE)
{
MSG_MessageLine messageLine;
::MSG_GetThreadLineById(messageView->GetMessagePane(), id, &messageLine);
char buffer[256];
const char* raw = CMessage::GetSubject(&messageLine, buffer, sizeof(buffer)-1);
char* conv = IntlDecodeMimePartIIStr(raw, GetWindowContext()->GetWinCSID(), FALSE);
SetDescriptor(CStr255((conv != NULL) ? conv : raw));
if (conv)
XP_FREE(conv);
}
// show/hide buttons depending on the window type (News vs Mail)
LControl * aControl;
Boolean isNewsWindow = ((folderFlags & MSG_FOLDER_FLAG_NEWSGROUP) != 0);
const short kBtnCount = 3;
PaneIDT mailBtn[kBtnCount] =
{
paneID_MessageGetMailButton,
paneID_MessageComposeButton,
paneID_MessageDeleteButton // update kBtnCount if you add a btn
};
PaneIDT newsBtn[kBtnCount] =
{
paneID_MessageGetNewsButton,
paneID_MessagePostNewButton,
paneID_MessageMarkButton // update kBtnCount if you add a btn
};
for (short btnIndex = 0; btnIndex < kBtnCount; btnIndex ++)
{
if (isNewsWindow)
{
aControl = dynamic_cast<LControl *>(FindPaneByID(mailBtn[btnIndex]));
if (aControl != nil) aControl->Hide();
aControl = dynamic_cast<LControl *>(FindPaneByID(newsBtn[btnIndex]));
if (aControl != nil) aControl->Show();
}
else
{
aControl = dynamic_cast<LControl *>(FindPaneByID(newsBtn[btnIndex]));
if (aControl != nil) aControl->Hide();
aControl = dynamic_cast<LControl *>(FindPaneByID(mailBtn[btnIndex]));
if (aControl != nil) aControl->Show();
}
}
// other changes depending on the window type
if (isNewsWindow)
{
aControl = dynamic_cast<LControl *>(FindPaneByID(paneID_MessageReplyButton));
if (aControl != nil) aControl->SetValueMessage(cmd_PostReply); // quick-click default
}
else
{
aControl = dynamic_cast<LControl *>(FindPaneByID(paneID_MessageReplyButton));
if (aControl != nil) aControl->SetValueMessage(cmd_ReplyToSender); // quick-click default
}
UInt32 messageFlags = messageView->GetCurMessageFlags();
ResIDT iconID = (id == MSG_MESSAGEKEYNONE)
? CProxyPane::kProxyIconNormalID
: CMessage::GetIconID(folderFlags, messageFlags);
LIconPane* proxyIcon = dynamic_cast<LIconPane*>(FindPaneByID('poxy'));
if (proxyIcon)
{
proxyIcon->SetIconID(iconID);
}
CProxyPane* newProxy = dynamic_cast<CProxyPane*>(FindPaneByID(CProxyPane::class_ID));
if (newProxy)
{
newProxy->SetIconIDs(iconID, iconID);
}
} // CMessageWindow::AdaptToolbarToMessage
//----------------------------------------------------------------------------------------
CExtraFlavorAdder* CMessageWindow::CreateExtraFlavorAdder() const
//----------------------------------------------------------------------------------------
{
class MessageWindowFlavorAdder : public CExtraFlavorAdder
{
public:
MessageWindowFlavorAdder(CMessageView* inMessageView)
: mMessageView(inMessageView)
{
}
virtual void AddExtraFlavorData(DragReference inDragRef, ItemReference inItemRef)
{
#if 1
// Pass a selection using the message view. Not sure if this will work with the BE
mSelection.xpPane = mMessageView->GetMessagePane();
if (!mSelection.xpPane)
return;
MSG_ViewIndex viewIndex = mMessageView->GetCurMessageViewIndex();
#else
// Pass a selection, as if this is done from a thread view.
mSelection.xpPane = ::MSG_FindPaneOfType(
CMailNewsContext::GetMailMaster(),
mMessageView->GetFolderInfo(),
MSG_THREADPANE);
if (!mSelection.xpPane)
return; // drat. This is a real drag.
MSG_ViewIndex viewIndex = mMessageView->GetCurMessageKey();
MSG_ViewIndex viewIndex = MSG_GetIndexForKey(mSelection.xpPane, key, true);
#endif
if (viewIndex == MSG_VIEWINDEXNONE)
return;
mSelection.SetSingleSelection(viewIndex);
::AddDragItemFlavor(
inDragRef,
inItemRef,
kMailNewsSelectionDragFlavor,
&mSelection,
sizeof(mSelection),
0);
}
private:
CMessageView* mMessageView;
CMailSelection mSelection;
};
return new MessageWindowFlavorAdder(const_cast<CMessageWindow*>(this)->GetMessageView());
} // CMessageWindow::CreateExtraFlavorAdder

View File

@ -0,0 +1,119 @@
/* -*- 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.
*/
// CMessageWindow.h
#pragma once
#include "CMailNewsWindow.h"
#include <LListener.h>
#include "CSaveWindowStatus.h"
#include "MailNewsCallbacks.h"
#include "CSecurityButton.h"
#include "cstring.h"
const ResIDT cMessageWindowPPobID = 10667;
class CBrowserContext;
class CNSContext;
class CMessageView;
class CMailSelection;
struct SPaneChangeInfo;
//======================================
class CMessageWindow
: public CMailNewsWindow
, public CMailCallbackListener
//======================================
{
private:
typedef CMailNewsWindow Inherited; // trick suggested by the ANSI committee.
public:
enum { class_ID = 'MsgW', res_ID = cMessageWindowPPobID };
CMessageWindow(LStream* inStream);
virtual ~CMessageWindow();
virtual void FinishCreateSelf();
// MY VERSION
virtual void SetWindowContext(CBrowserContext* inContext);
virtual CNSContext* GetWindowContext() const { return (CNSContext*)mContext; }
public:
CMessageView* GetMessageView();
static CMessageWindow* FindAndShow(MessageKey inMessageKey);
static void OpenFromURL(const char* url);
static void CloseAll(MessageKey inMessageKey);
static void NoteSelectionFiledOrDeleted(const CMailSelection& inSelection);
virtual void ActivateSelf(void);
cstring GetCurrentURL();
// CMailCallbackListener overrides:
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
virtual void ListenToMessage(MessageT inMessage,void *ioParam);
/*
virtual void SetWindowContext(CBrowserContext* inContext);
// Info about the parent folder: must be queried, not cached!
MessageKey GetMessageKey() const;
MSG_FolderInfo* GetFolderInfo() const;
MSG_ViewIndex GetViewIndex() const;
uint16 GetFolderFlags() const;
void ShowMessage(MSG_Master* inMsgMaster,
MSG_FolderInfo* inMsgFolderInfo,
MessageKey inMessageKey);
void ShowSearchMessage(MSG_Master *inMsgMaster,
MSG_ResultElement *inResult);
*/
// I18N stuff
virtual Int16 DefaultCSIDForNewWindow(void);
// CNetscapeWindow overrides
virtual CExtraFlavorAdder* CreateExtraFlavorAdder() const;
//-----------------------------------
// Window Saving - overrides for CSaveWindowStatus.
//-----------------------------------
protected:
virtual ResIDT GetStatusResID(void) const { return res_ID; }
virtual UInt16 GetValidStatusVersion(void) const { return 0x0113; }
virtual void AdaptToolbarToMessage(void);
protected:
CBrowserContext* mContext;
CMailSecurityListener mSecurityListener;
};

View File

@ -0,0 +1,305 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CNewsSubscriber.cp
#include "CNewsSubscriber.h"
#include "CMailNewsContext.h"
#include "CSubscribeWindow.h"
#include "UModalDialogs.h"
#include "LGAEditField.h"
#include "LGACheckbox.h"
#include "LGARadioButton.h"
#include "prefapi.h"
#include "msgcom.h"
#include "uprefd.h"
#include "uerrmgr.h"
extern "C"
{
extern int MK_NNTP_SERVER_NOT_CONFIGURED;
}
MSG_Host* CNewsSubscriber::mHost = nil;
//-----------------------------------
Boolean CNewsSubscriber::DoSubscribeNewsGroup(MSG_Host* host, Boolean inModal)
//-----------------------------------
{
Boolean result = false;
// When no host is specified, we try to use the previously
// accessed host or the default host. If there isn't any,
// we display an alert and ask the user to configure one.
if (host == nil)
host = GetHost();
if (host == nil)
host = (MSG_Host*)MSG_GetDefaultNewsHost(CMailNewsContext::GetMailMaster());
if (host == nil)
{
FE_Alert(nil, XP_GetString(MK_NNTP_SERVER_NOT_CONFIGURED));
FE_EditPreference(PREF_NewsHost);
}
else
{
SetHost(host);
if (inModal)
{
result = CSubscribeWindow::DisplayDialog();
}
else
{
CSubscribeWindow::FindAndShow(true);
result = true;
}
}
return result;
} // CMessageFolderView::DoSubscribeNewsGroup
//-----------------------------------
Boolean CNewsSubscriber::DoAddNewsHost()
//-----------------------------------
{
// Put up dialog
StDialogHandler handler(14000, NULL);
// Select the "Host" edit field
LWindow* dialog = handler.GetDialog();
LGAEditField *hostfield = (LGAEditField*)dialog->FindPaneByID('Host');
SignalIf_(!hostfield);
LGAEditField* portfield = (LGAEditField*)dialog->FindPaneByID('Port');
SignalIf_(!portfield);
LGACheckbox* securebox = (LGACheckbox*)dialog->FindPaneByID('Secu');
SignalIf_(!securebox);
if (!hostfield || ! portfield || !securebox)
return false;
dialog->SetLatentSub(hostfield);
// Run the dialog
MessageT message = 'Secu'; // so that the port is initialized correctly.
CStr255 porttext;
Int32 port = 0;
Boolean userChangedPort = false;
LControl* okButton = dynamic_cast<LControl*>(dialog->FindPaneByID ('Add_') );
XP_ASSERT( okButton );
do {
if (message == 'Secu' && !userChangedPort)
{
port = securebox->GetValue() ? 563 : 119;
NumToString(port, porttext);
portfield->SetDescriptor(porttext);
}
message = handler.DoDialog();
portfield->GetDescriptor(porttext);
Int32 newport;
StringToNum(porttext, &newport);
userChangedPort = (newport != port);
port = newport;
CStr255 hosttext;
hostfield->GetDescriptor(hosttext);
if( hosttext.Length() > 0 )
okButton->Enable();
else
okButton->Disable();
} while (message != msg_OK && message != msg_Cancel);
// Use the result.
if (message == msg_OK)
{
CStr255 hosttext;
hostfield->GetDescriptor(hosttext);
MSG_NewsHost* newHost = MSG_CreateNewsHost(CMailNewsContext::GetMailMaster(),
hosttext, securebox->GetValue(), port);
CNewsSubscriber::SetHost(MSG_GetMSGHostFromNewsHost(newHost)); // make it the default host
// Be kind to the user: if there was no News server configured yet,
// then use this one (otherwise, we'll throw the Prefs dialog
// on the next common MSG_ call, such as MSG_SubscribeSetNewsHost())
if (MSG_GetDefaultNewsHost(CMailNewsContext::GetMailMaster()) == NULL)
(void)CPrefs::SetString(hosttext, CPrefs::NewsHost);
}
return (message == msg_OK);
} // CNewsSubscriber::DoAddNewsHost()
//======================================
// FE_NewsDownloadPrompt
//======================================
// From listngst.cpp
extern "C" XP_Bool FE_NewsDownloadPrompt(
MWContext *context,
int32 numMessagesToDownload,
XP_Bool *downloadAll);
//-----------------------------------
class StDownloadDialogHandler: public StDialogHandler
//-----------------------------------
{
public:
StDownloadDialogHandler(
MWContext* context,
int32 numMessagesToDownload,
XP_Bool& downloadAll);
Boolean InitFields();
void ReadFields();
UInt32 mNumberOfMessages;
XP_Bool mDownloadSome;
Int32 mDownloadMax;
XP_Bool mMarkRead;
LGAEditField* mMaxHeadersField;
LGACheckbox* mMarkReadCheckbox;
LGARadioButton* mDownloadSomeRadio;
}; // class StDownloadDialogHandler
//-----------------------------------
StDownloadDialogHandler::StDownloadDialogHandler(
MWContext* context,
int32 numMessages,
XP_Bool& downloadAll)
//-----------------------------------
: StDialogHandler(14001, NULL)
, mNumberOfMessages(numMessages)
, mDownloadMax(0)
, mDownloadSome(false)
, mMarkRead(false)
, mMaxHeadersField(NULL)
, mMarkReadCheckbox(NULL)
, mDownloadSomeRadio(NULL)
{
#pragma unused (context)
#pragma unused (downloadAll)
}
//-----------------------------------
void StDownloadDialogHandler::ReadFields()
//-----------------------------------
{
mDownloadSome = mDownloadSomeRadio->GetValue();
mMarkRead = mMarkReadCheckbox->GetValue();
CStr255 headersText;
mMaxHeadersField->GetDescriptor(headersText);
StringToNum(headersText, &mDownloadMax);
if (mDownloadSome)
{
PREF_SetBoolPref("news.mark_old_read", mMarkRead);
PREF_SetIntPref("news.max_articles", mDownloadMax);
}
}
//-----------------------------------
Boolean StDownloadDialogHandler::InitFields()
//-----------------------------------
{
// Select the "Host" edit field
LWindow* dialog = GetDialog();
mMaxHeadersField = (LGAEditField*)dialog->FindPaneByID('maxH');
SignalIf_(!mMaxHeadersField);
mMarkReadCheckbox = (LGACheckbox*)dialog->FindPaneByID('MkUn');
SignalIf_(!mMarkReadCheckbox);
mDownloadSomeRadio = (LGARadioButton*)dialog->FindPaneByID('DnSm');
SignalIf_(!mDownloadSomeRadio);
LCaption* messagefield = (LCaption*)dialog->FindPaneByID('Mesg');
SignalIf_(!messagefield);
if (!messagefield || !mMaxHeadersField || !mMarkReadCheckbox || !mDownloadSomeRadio)
return false;
// The caption has the message format string with %d in it...
CStr255 messageText;
messagefield->GetDescriptor(messageText);
char messageString[255];
sprintf(messageString, messageText, mNumberOfMessages);
messageText = messageString;
messagefield->SetDescriptor(messageText);
PREF_GetBoolPref( "news.mark_old_read", &mMarkRead );
mMarkReadCheckbox->SetValue(mMarkRead);
PREF_GetIntPref("news.max_articles", &mDownloadMax);
CStr255 downloadString;
NumToString(mDownloadMax, downloadString);
mMaxHeadersField->SetDescriptor(downloadString);
return true;
}
//-----------------------------------
XP_Bool FE_NewsDownloadPrompt(
MWContext* context,
int32 numMessagesToDownload,
XP_Bool* downloadAll)
//-----------------------------------
{
// Put up dialog
StDownloadDialogHandler handler(context, numMessagesToDownload, *downloadAll);
// Set up the dialog
if (!handler.InitFields())
return false;
// Run the dialog
MessageT message = msg_Nothing;
do {
message = handler.DoDialog();
} while (message != msg_Cancel && message != msg_OK);
// Use the result.
if (message == msg_OK)
{
handler.ReadFields();
*downloadAll = !handler.mDownloadSome;
return true;
}
return false;
} // FE_NewsDownloadPrompt
//-----------------------------------
XP_Bool FE_CreateSubscribePaneOnHost(
MSG_Master* master,
MWContext* parentContext,
MSG_Host* host)
//-----------------------------------
{
#pragma unused (master)
#pragma unused (parentContext)
XP_Bool result;
result = CNewsSubscriber::DoSubscribeNewsGroup(host, false);
// modeless, as required by API spec for this call.
return result;
}

View File

@ -0,0 +1,42 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CNewsSubscriber.h
#pragma once
#include "msgcom.h"
//======================================
class CNewsSubscriber
//======================================
{
public:
static Boolean DoAddNewsHost();
static Boolean DoSubscribeNewsGroup(MSG_Host* host = nil, Boolean inModal = false);
static void SetHost(MSG_Host* host) { mHost = host; };
static MSG_Host* GetHost() { return mHost; };
private:
static MSG_Host* mHost;
}; // class CNewsSubscriber

View File

@ -0,0 +1,925 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// COfflinePicker.cp
#include "COfflinePicker.h"
#include "CMessageFolder.h"
#include "MailNewsAddressBook.h"
#include "URobustCreateWindow.h"
#include "UModalDialogs.h"
#include "cstring.h"
#include "macutil.h"
#include "MailNewsgroupWindow_Defines.h"
#include "LGAPushButton.h"
#include "dirprefs.h"
enum
{
kCheckedIconID = 15237
, kUncheckedIconID = 15235
, kLDAPHdrIconID = 15258 //15226
, kLDAPIconID = 15258
};
//------------------------------------------------------------------------------
// ¥ COfflineItem
//------------------------------------------------------------------------------
//
class COfflineItem
{
public:
COfflineItem(const TableIndexT inRow, const COfflinePickerView* inPickerView);
~COfflineItem();
UInt32 GetLevel() const;
ResIDT GetIconID() const;
const char* GetName() const;
UInt32 GetFolderPrefFlags() const;
void SetFolderPrefFlags(const UInt32) const;
Boolean IsOpen() const;
Boolean IsNewsgroup() const;
Boolean IsLocalMailFolder() const;
Boolean IsIMAPMailFolder() const;
Boolean IsLDAPDirectory() const;
Boolean HasNewMessages() const;
UInt32 CountSubFolders() const;
TableIndexT GetRow() const {return mRow;};
COfflinePickerView::RowType GetRowType() const {return mRowType;};
void * GetInfo() const {return (mMessageFolder ? (void*)mMessageFolder->GetFolderInfo() : (void*)mDirServer);};
protected:
const COfflinePickerView * mPickerView;
const TableIndexT mRow;
COfflinePickerView::RowType mRowType;
CMessageFolder * mMessageFolder;
DIR_Server * mDirServer;
};
// ¥ COfflineItem
COfflineItem::COfflineItem(const TableIndexT inRow, const COfflinePickerView* inPickerView)
: mPickerView(inPickerView)
, mRow(inRow)
, mMessageFolder(nil)
, mDirServer(nil)
{
mRowType = mPickerView->GetRowType(inRow);
if (mRowType == COfflinePickerView::kRowMailNews)
mMessageFolder = new CMessageFolder(inRow, inPickerView->GetMessagePane());
else
if (mRowType == COfflinePickerView::kRowLDAP)
{
TableIndexT outRows, outCols;
mPickerView->GetTableSize(outRows, outCols);
mDirServer = (DIR_Server *)XP_ListGetObjectNum(mPickerView->mLDAPList, outRows - mRow + 1);
}
}
// ¥ ~COfflineItem
COfflineItem::~COfflineItem()
{
delete mMessageFolder;
}
// ¥ GetLevel
UInt32 COfflineItem::GetLevel() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->GetLevel();
case COfflinePickerView::kRowLDAPHdr: return kRootLevel;
case COfflinePickerView::kRowLDAP: return kRootLevel + 1;
}
return kRootLevel;
}
// ¥ GetIconID
ResIDT COfflineItem::GetIconID() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->GetIconID();
case COfflinePickerView::kRowLDAPHdr: return kLDAPHdrIconID;
case COfflinePickerView::kRowLDAP: return kLDAPIconID;
}
return 0;
}
// ¥ GetName
const char* COfflineItem::GetName() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->GetName();
case COfflinePickerView::kRowLDAPHdr: return (char*)&mPickerView->mLDAPHdrStr[1];
case COfflinePickerView::kRowLDAP: return mDirServer->description;
}
return nil;
}
// ¥ GetFolderPrefFlags
UInt32 COfflineItem::GetFolderPrefFlags() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->GetFolderPrefFlags();
case COfflinePickerView::kRowLDAPHdr: return 0;
case COfflinePickerView::kRowLDAP: return (DIR_TestFlag(mDirServer, DIR_REPLICATION_ENABLED) ? MSG_FOLDER_PREF_OFFLINE : 0);
}
return 0;
}
// ¥ SetFolderPrefFlags
void COfflineItem::SetFolderPrefFlags(const UInt32 inPrefFlags) const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews:
::MSG_SetFolderPrefFlags(mMessageFolder->GetFolderInfo(), inPrefFlags);
break;
case COfflinePickerView::kRowLDAPHdr:
// nothing
break;
case COfflinePickerView::kRowLDAP:
DIR_ForceFlag(mDirServer, DIR_REPLICATION_ENABLED, ((inPrefFlags & MSG_FOLDER_PREF_OFFLINE) != 0));
break;
}
}
// ¥ IsOpen
Boolean COfflineItem::IsOpen() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->IsOpen();
case COfflinePickerView::kRowLDAPHdr: return mPickerView->IsLDAPExpanded();
case COfflinePickerView::kRowLDAP: return false;
}
return false;
}
// ¥ IsNewsgroup
Boolean COfflineItem::IsNewsgroup() const
{
return (mMessageFolder ? mMessageFolder->IsNewsgroup() : false);
}
// ¥ IsLocalMailFolder
Boolean COfflineItem::IsLocalMailFolder() const
{
if (mRowType == COfflinePickerView::kRowMailNews)
return mMessageFolder->IsLocalMailFolder();
return false;
}
// ¥ IsIMAPMailFolder
Boolean COfflineItem::IsIMAPMailFolder() const
{
return (mMessageFolder ? mMessageFolder->IsIMAPMailFolder() : false);
}
// ¥ IsLDAPDirectory
Boolean COfflineItem::IsLDAPDirectory() const
{
return (mRowType == COfflinePickerView::kRowLDAP);
}
// ¥ HasNewMessages
Boolean COfflineItem::HasNewMessages() const
{
return (mMessageFolder ? mMessageFolder->HasNewMessages() : false);
}
// ¥ CountSubFolders
UInt32 COfflineItem::CountSubFolders() const
{
switch (mRowType)
{
case COfflinePickerView::kRowMailNews: return mMessageFolder->CountSubFolders();
case COfflinePickerView::kRowLDAPHdr: return mPickerView->CountLDAPItems();
case COfflinePickerView::kRowLDAP: return 0;
}
return 0;
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ COfflinePickerView
//------------------------------------------------------------------------------
//
COfflinePickerView::COfflinePickerView(LStream *inStream)
: Inherited(inStream)
, mWantLDAP(true)
, mLDAPList(nil)
, mLDAPCount(0)
, mLDAPExpanded(false)
, mSaveItemArray(sizeof(SSaveItemRec))
{
}
//------------------------------------------------------------------------------
// ¥ ~COfflinePickerView
//------------------------------------------------------------------------------
//
COfflinePickerView::~COfflinePickerView()
{
if (mLDAPList)
XP_ListDestroy(mLDAPList);
}
//------------------------------------------------------------------------------
// ¥ View / GetRowType
//------------------------------------------------------------------------------
//
COfflinePickerView::RowType
COfflinePickerView::GetRowType(TableIndexT inRow) const
{
if (! mWantLDAP)
return kRowMailNews;
TableIndexT outRows, outCols;
GetTableSize(outRows, outCols);
TableIndexT ldapHdrRow;
if (mLDAPExpanded)
ldapHdrRow = outRows - mLDAPCount;
else
ldapHdrRow = outRows;
if (inRow < ldapHdrRow)
return kRowMailNews;
else if (inRow == ldapHdrRow)
return kRowLDAPHdr;
else
return kRowLDAP;
}
//------------------------------------------------------------------------------
// ¥ View / AppendLDAPList
//------------------------------------------------------------------------------
//
void COfflinePickerView::AppendLDAPList()
{
if (!mWantLDAP)
return;
// get list (which also contains Personal ABook + HTML directories)
XP_List *serverList = CAddressBookManager::GetDirServerList();
if (!serverList)
{
mWantLDAP = false;
return;
}
mLDAPList = XP_ListNew();
ThrowIfNULL_(mLDAPList);
// extract LDAP items
int totalCount = XP_ListCount(serverList);
for (Int32 i = 1; i <= totalCount ; i++)
{
DIR_Server *server = (DIR_Server *) XP_ListGetObjectNum(serverList, i);
if (server->dirType == LDAPDirectory)
XP_ListAddObject(mLDAPList, server);
}
mLDAPCount = XP_ListCount(mLDAPList);
if (mLDAPCount == 0)
{
XP_ListDestroy(mLDAPList);
mLDAPList = nil;
mWantLDAP = false;
return;
}
// get the LDAP header string and insert a row at the end of the list
::GetIndString(mLDAPHdrStr, 7099, 26);
mLDAPHdrStr[mLDAPHdrStr[0]+1] = '\0';
TableIndexT outRows, outCols;
GetTableSize(outRows, outCols);
InsertRows(1, outRows, nil, 0, true);
}
//----------------------------------------------------------------------------
// ¥ View / SaveItemPrefFlags
//----------------------------------------------------------------------------
//
void COfflinePickerView::SaveItemPrefFlags(const COfflineItem * inOfflineItem, UInt32 inPrefsFlags)
{
// prepare new item to save
SSaveItemRec newItemRec;
newItemRec.itemType = inOfflineItem->GetRowType();
newItemRec.itemInfo = inOfflineItem->GetInfo();
newItemRec.originalPrefsFlags = inPrefsFlags;
// check if item has already been saved
LArrayIterator iterator(mSaveItemArray, LArrayIterator::from_Start);
SSaveItemRec itemRec;
while (iterator.Next(&itemRec))
{
if ((itemRec.itemType == newItemRec.itemType)
&& (itemRec.itemInfo == newItemRec.itemInfo))
return; // item already saved
}
// save new item
mSaveItemArray.InsertItemsAt(1, LArray::index_Last, (void*)&newItemRec, sizeof(newItemRec));
}
//----------------------------------------------------------------------------
// ¥ View / CancelSelection
//----------------------------------------------------------------------------
//
void COfflinePickerView::CancelSelection()
{
LArrayIterator iterator(mSaveItemArray, LArrayIterator::from_Start);
SSaveItemRec itemRec;
while (iterator.Next(&itemRec))
{
switch (itemRec.itemType)
{
case COfflinePickerView::kRowMailNews:
::MSG_SetFolderPrefFlags((MSG_FolderInfo *)itemRec.itemInfo, itemRec.originalPrefsFlags);
break;
case COfflinePickerView::kRowLDAP:
DIR_ForceFlag((DIR_Server *)itemRec.itemInfo, DIR_REPLICATION_ENABLED, ((itemRec.originalPrefsFlags & MSG_FOLDER_PREF_OFFLINE) != 0));
DIR_SaveServerPreferences(CAddressBookManager::GetDirServerList());
break;
}
}
mSaveItemArray.RemoveItemsAt(1, mSaveItemArray.GetCount());
}
//----------------------------------------------------------------------------
// ¥ View / CommitSelection
//----------------------------------------------------------------------------
//
void COfflinePickerView::CommitSelection()
{
if (mLDAPList)
DIR_SaveServerPreferences(CAddressBookManager::GetDirServerList());
}
//----------------------------------------------------------------------------
// ¥ View / DrawCell
//----------------------------------------------------------------------------
//
void COfflinePickerView::DrawCell(const STableCell& inCell, const Rect& inLocalRect)
{
PaneIDT cellType = GetCellDataType(inCell);
switch (cellType)
{
case kFolderNameColumn:
Inherited::DrawCell(inCell, inLocalRect);
break;
case kSelectFolderColumn:
COfflineItem item(inCell.row, this);
if (item.GetLevel() > kRootLevel)
{
short iconID, transformType;
if (item.IsLocalMailFolder())
{
iconID = kCheckedIconID;
transformType = ttDisabled;
}
else
{
UInt32 folderPrefFlags = item.GetFolderPrefFlags();
if (folderPrefFlags & MSG_FOLDER_PREF_OFFLINE)
iconID = kCheckedIconID;
else
iconID = kUncheckedIconID;
transformType = ttNone;
}
DrawIconFamily(iconID, 16, 16, transformType, inLocalRect);
}
break;
}
}
//----------------------------------------------------------------------------
// ¥ View / ClickSelect
//----------------------------------------------------------------------------
// We don't want any fancy behavior on mouse clicks: no cell selection,
// no Finder selection, nothing. Just toggle the check-box.
//
Boolean COfflinePickerView::ClickSelect(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown)
{
#pragma unused (inCell)
#pragma unused (inMouseDown)
return true;
}
//----------------------------------------------------------------------------
// ¥ View / ClickCell
//----------------------------------------------------------------------------
// We don't want any fancy behavior on mouse clicks: no cell selection,
// no Finder selection, nothing. Just toggle the check-box.
//
void COfflinePickerView::ClickCell(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown)
{
SPoint32 currentPoint;
STableCell hitCell = inCell;
currentPoint.h = inMouseDown.whereLocal.h;
currentPoint.v = inMouseDown.whereLocal.v;
COfflineItem item(hitCell.row, this);
if (item.GetLevel() > kRootLevel)
{
if (item.IsNewsgroup() || item.IsIMAPMailFolder() || item.IsLDAPDirectory())
{
UInt32 folderPrefFlags = item.GetFolderPrefFlags();
SaveItemPrefFlags(&item, folderPrefFlags);
folderPrefFlags ^= MSG_FOLDER_PREF_OFFLINE;
item.SetFolderPrefFlags(folderPrefFlags);
for (int i = 1; i <= mTableHeader->CountVisibleColumns(); i++)
{
hitCell.col = i;
RefreshCell(hitCell);
}
}
}
}
// ---------------------------------------------------------------------------
// ¥ View / HandleKeyPress
// ---------------------------------------------------------------------------
// Overide CStandardFlexTable: Return and Enter don't open the selection.
//
Boolean
COfflinePickerView::HandleKeyPress(
const EventRecord &inKeyEvent)
{
Boolean keyHandled = false;
LControl *keyButton = nil;
switch (inKeyEvent.message & charCodeMask)
{
case char_Enter:
case char_Return:
LCommander::HandleKeyPress(inKeyEvent);
return true;
}
return Inherited::HandleKeyPress(inKeyEvent);
}
//----------------------------------------------------------------------------
// ¥ View / GetQapRowText
//----------------------------------------------------------------------------
// Return info for QA Partner
//
#if defined(QAP_BUILD)
void COfflinePickerView::GetQapRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const
{
if (!outText || inMaxBufferLength == 0)
return;
cstring rowText("");
short colCount = mTableHeader->CountVisibleColumns();
COfflineItem item(inRow, this);
CMailNewsWindow * myWindow = dynamic_cast<CMailNewsWindow*>(LWindow::FetchWindowObject(GetMacPort()));
if (!myWindow) return;
for (short col = 1; col <= colCount; col ++)
{
STableCell aCell(inRow, col);
LTableHeader::SColumnData * colData = mTableHeader->GetColumnData(col);
if (!colData) break;
LPane * colPane = myWindow->FindPaneByID(colData->paneID);
if (!colPane) break;
// get column name
CStr255 descriptor;
colPane->GetDescriptor(descriptor);
rowText += descriptor;
rowText += "=\042";
// add cell text
switch (PaneIDT dataType = GetCellDataType(aCell))
{
case kFolderNameColumn:
Boolean isExpanded;
if (CellHasDropFlag(aCell, isExpanded))
{
if (isExpanded)
rowText += "-";
else
rowText += "+";
}
else
rowText += " ";
rowText += item.GetName();
break;
case kSelectFolderColumn:
if (item.GetLevel() > kRootLevel)
{
UInt32 folderPrefFlags = item.GetFolderPrefFlags();
if (folderPrefFlags & MSG_FOLDER_PREF_OFFLINE)
rowText += "+";
}
break;
}
if (col < colCount)
rowText += "\042 | ";
else
rowText += "\042\r";
}
strncpy(outText, (char*)rowText, inMaxBufferLength);
outText[inMaxBufferLength - 1] = '\0';
}
#endif //QAP_BUILD
#pragma mark --
//------------------------------------------------------------------------------
// ¥ View / GetIconID
//------------------------------------------------------------------------------
//
ResIDT COfflinePickerView::GetIconID(TableIndexT inRow) const
{
COfflineItem item(inRow, this);
return item.GetIconID();
}
//------------------------------------------------------------------------------
// ¥ View / GetNestedLevel
//------------------------------------------------------------------------------
//
UInt16 COfflinePickerView::GetNestedLevel(TableIndexT inRow) const
{
COfflineItem item(inRow, this);
return item.GetLevel() - 1;
}
//------------------------------------------------------------------------------
// ¥ View / ApplyTextStyle
//------------------------------------------------------------------------------
//
void COfflinePickerView::ApplyTextStyle(TableIndexT inRow) const
{
COfflineItem item(inRow, this);
::TextFace(item.HasNewMessages() ? bold : normal);
}
//------------------------------------------------------------------------------
// ¥ View / CellHasDropFlag
//------------------------------------------------------------------------------
// Check if a cell has a twistee icon and if the twistee is open.
//
Boolean COfflinePickerView::CellHasDropFlag(
const STableCell& inCell,
Boolean& outIsExpanded) const
{
COfflineItem item(inCell.row, this);
if (GetCellDataType(inCell) == kFolderNameColumn && item.CountSubFolders() != 0)
{
outIsExpanded = item.IsOpen();
return true;
}
return false;
}
//------------------------------------------------------------------------------
// ¥ View / SetCellExpansion
//------------------------------------------------------------------------------
//
void COfflinePickerView::SetCellExpansion(
const STableCell& inCell,
Boolean inExpand)
{
switch (GetRowType(inCell.row))
{
case kRowMailNews:
Inherited::SetCellExpansion(inCell, inExpand);
break;
case kRowLDAPHdr:
mLDAPExpanded = inExpand;
TableIndexT outRows, outCols;
GetTableSize(outRows, outCols);
if (inExpand)
InsertRows(mLDAPCount, outRows, nil, 0, true);
else
RemoveRows(mLDAPCount, outRows - mLDAPCount, true);
break;
case kRowLDAP:
break;
}
}
//------------------------------------------------------------------------------
// ¥ View / GetMainRowText
//------------------------------------------------------------------------------
//
void COfflinePickerView::GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const
{
switch (GetRowType(inRow))
{
case kRowMailNews:
Inherited::GetMainRowText(inRow, outText, inMaxBufferLength);
break;
case kRowLDAPHdr:
case kRowLDAP:
if (outText)
{
COfflineItem item(inRow, this);
::strncpy(outText, item.GetName(), inMaxBufferLength);
}
break;
}
}
//------------------------------------------------------------------------------
// ¥ View / ChangeFinished
//------------------------------------------------------------------------------
//
void COfflinePickerView::ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount)
{
// call the inherited method, restoring the original BE row count
// to work around a check in CMailFlexTable::ChangeFinished()
// on MSG_NotifyInsertOrDelete
if ((mLDAPCount > 0) && (inChangeCode == MSG_NotifyInsertOrDelete))
{
mRows -= (mLDAPExpanded ? mLDAPCount + 1 : 1);
Inherited::ChangeFinished(inPane, inChangeCode, inStartRow, inRowCount);
mRows += (mLDAPExpanded ? mLDAPCount + 1 : 1);
}
else
Inherited::ChangeFinished(inPane, inChangeCode, inStartRow, inRowCount);
switch (inChangeCode)
{
case MSG_NotifyScramble:
case MSG_NotifyAll:
if (mWantLDAP)
{
COfflineItem item(1, this);
if (item.IsLocalMailFolder() && item.IsOpen())
{
STableCell aCell(1, 1);
SetCellExpansion(aCell, false);
}
AppendLDAPList();
}
break;
}
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ COfflinePickerWindow
//------------------------------------------------------------------------------
//
COfflinePickerWindow::COfflinePickerWindow(LStream *inStream)
: CMailNewsWindow(inStream, WindowType_OfflinePicker)
, mList(nil)
{
}
//------------------------------------------------------------------------------
// ¥ ~COfflinePickerWindow
//------------------------------------------------------------------------------
//
COfflinePickerWindow::~COfflinePickerWindow()
{
}
//------------------------------------------------------------------------------
// ¥ Window / FinishCreateSelf
//------------------------------------------------------------------------------
//
void COfflinePickerWindow::FinishCreateSelf()
{
Inherited::FinishCreateSelf();
mList = (COfflinePickerView*)GetActiveTable();
Assert_(mList);
mList->LoadFolderList(mMailNewsContext);
UReanimator::LinkListenerToControls(this, this, GetPaneID());
LGAPushButton * okBtn = dynamic_cast<LGAPushButton*>(FindPaneByID(paneID_OkButton));
if (okBtn) okBtn->SetDefaultButton(true, true);
Show();
Select();
}
//------------------------------------------------------------------------------
// ¥ Window / CalcStandardBoundsForScreen
//------------------------------------------------------------------------------
// Zoom in the vertical direction only.
//
void COfflinePickerWindow::CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const
{
LWindow::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
Rect contRect = UWindows::GetWindowContentRect(mMacWindowP);
outStdBounds.left = contRect.left;
outStdBounds.right = contRect.right;
}
//----------------------------------------------------------------------------
// ¥ Window / ListenToMessage
//----------------------------------------------------------------------------
void COfflinePickerWindow::ListenToMessage(MessageT inMessage, void* ioParam)
{
#pragma unused (ioParam)
switch (inMessage)
{
case msg_Cancel:
if (mList)
mList->CancelSelection();
Inherited::DoClose();
break;
case msg_OK:
if (mList)
mList->CommitSelection();
Inherited::DoClose();
break;
}
}
// ---------------------------------------------------------------------------
// ¥ Window / HandleKeyPress
// ---------------------------------------------------------------------------
// As usual, copied and adapted from LDialogBox.
// Can't we do an attachment with that?
//
Boolean
COfflinePickerWindow::HandleKeyPress(
const EventRecord &inKeyEvent)
{
Boolean keyHandled = false;
LControl *keyButton = nil;
switch (inKeyEvent.message & charCodeMask) {
case char_Enter:
case char_Return:
keyButton = (LControl*) FindPaneByID(paneID_OkButton);
break;
case char_Escape:
if ((inKeyEvent.message & keyCodeMask) == vkey_Escape) {
keyButton = (LControl*) FindPaneByID(paneID_CancelButton);
}
break;
default:
if (UKeyFilters::IsCmdPeriod(inKeyEvent)) {
keyButton = (LControl*) FindPaneByID(paneID_CancelButton);
} else {
keyHandled = LWindow::HandleKeyPress(inKeyEvent);
}
break;
}
if (keyButton != nil) {
keyButton->SimulateHotSpotClick(kControlButtonPart);
keyHandled = true;
}
return keyHandled;
}
//------------------------------------------------------------------------------
// ¥ Window / GetActiveTable
//------------------------------------------------------------------------------
// From CMailNewsWindow. Get the currently active table in the window.
// The active table is the one that the user considers to be receiving input.
//
CMailFlexTable* COfflinePickerWindow::GetActiveTable()
{
return dynamic_cast<COfflinePickerView*>(FindPaneByID('Flst'));
}
//------------------------------------------------------------------------------
// ¥ Window / FindAndShow [static]
//------------------------------------------------------------------------------
// Creates/shows/selects the Offline Picker window. There can only be one of these.
// Use COfflinePickerWindow::DisplayDialog() for a modal dialog.
//
COfflinePickerWindow* COfflinePickerWindow::FindAndShow(Boolean inMakeNew)
{
COfflinePickerWindow* result = NULL;
try
{
CWindowIterator iter(WindowType_OfflinePicker);
iter.Next(result);
if (!result && inMakeNew)
{
result = dynamic_cast<COfflinePickerWindow*>(
URobustCreateWindow::CreateWindow(
res_ID, LCommander::GetTopCommander()));
ThrowIfNULL_(result);
}
}
catch (...)
{
}
return result;
}
//------------------------------------------------------------------------------
// ¥ Window / DisplayDialog [static]
//------------------------------------------------------------------------------
// Creates/shows/selects the Offline Picker window. There can only be one of these.
// Use COfflinePickerWindow::FindAndShow() for a non-modal window.
//
Boolean COfflinePickerWindow::DisplayDialog()
{
StDialogHandler handler(res_ID, NULL);
MessageT message;
do
{
message = handler.DoDialog();
} while (message != msg_OK && message != msg_Cancel);
return (message == msg_OK);
}

View File

@ -0,0 +1,172 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// COfflinePicker.h
#pragma once
#include "CMailNewsWindow.h"
#include "CSimpleFolderView.h"
//------------------------------------------------------------------------------
// ¥ COfflinePickerView
//------------------------------------------------------------------------------
//
class COfflinePickerView : public CSimpleFolderView
{
friend class COfflineItem;
private:
typedef CSimpleFolderView Inherited;
public:
enum { class_ID = 'ofVW' };
COfflinePickerView(LStream *inStream);
virtual ~COfflinePickerView();
//-----------------------------------
// LDAP folders
//-----------------------------------
protected:
typedef enum { kRowMailNews = 1, kRowLDAPHdr, kRowLDAP} RowType;
typedef struct SSaveItemRec
{
RowType itemType;
void * itemInfo;
UInt32 originalPrefsFlags;
} SSaveItemRec;
virtual RowType GetRowType(TableIndexT inRow) const;
virtual UInt16 CountLDAPItems() const {return mLDAPCount;};
virtual Boolean IsLDAPExpanded() const {return mLDAPExpanded;};
virtual void AppendLDAPList();
virtual void SaveItemPrefFlags(const COfflineItem * inOfflineItem, UInt32 inPrefsFlags);
public:
virtual void CancelSelection();
virtual void CommitSelection();
//-----------------------------------
// Command implementation
//-----------------------------------
public:
virtual void DrawCell(
const STableCell &inCell,
const Rect &inLocalRect);
virtual Boolean ClickSelect(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
virtual void ClickCell(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
//-----------------------------------
// Commands
//-----------------------------------
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
//-----------------------------------
// Drawing (Overrides of CSimpleFolderView)
//-----------------------------------
virtual Boolean TableDesiresSelectionTracking ( ) { return false; }
virtual ResIDT GetIconID(TableIndexT inRow) const;
virtual UInt16 GetNestedLevel(TableIndexT inRow) const;
virtual void ApplyTextStyle(TableIndexT inRow) const;
virtual Boolean CellHasDropFlag(const STableCell& inCell, Boolean& outIsExpanded) const;
virtual void SetCellExpansion(const STableCell& inCell, Boolean inExpand);
virtual void GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const;
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
// ------------------------------------------------------------
// QA Partner support
// ------------------------------------------------------------
#if defined(QAP_BUILD)
public:
virtual void GetQapRowText(TableIndexT inRow, char* outText, UInt16 inMaxBufferLength) const;
#endif
//-----------------------------------
// Data
//-----------------------------------
protected:
Boolean mWantLDAP;
XP_List * mLDAPList;
UInt16 mLDAPCount;
Boolean mLDAPExpanded;
Str63 mLDAPHdrStr;
LArray mSaveItemArray;
};
//------------------------------------------------------------------------------
// ¥ COfflinePickerWindow
//------------------------------------------------------------------------------
//
class COfflinePickerWindow : public CMailNewsWindow,
public LListener
{
private:
typedef CMailNewsWindow Inherited;
public:
enum { class_ID = 'ofWN', res_ID = 20003};
enum {
paneID_OkButton = 'BtOk',
paneID_CancelButton = 'Canc'
};
protected:
virtual ResIDT GetStatusResID(void) const { return res_ID; }
virtual UInt16 GetValidStatusVersion(void) const { return 0x0112; }
public:
COfflinePickerWindow(LStream *inStream);
virtual ~COfflinePickerWindow();
virtual void FinishCreateSelf();
virtual void CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const;
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
virtual CMailFlexTable * GetActiveTable();
static COfflinePickerWindow * FindAndShow(Boolean inMakeNew);
static Boolean DisplayDialog();
protected:
COfflinePickerView * mList;
};

View File

@ -0,0 +1,49 @@
/* -*- 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.
*/
// CProgressBroadcaster.h
#pragma once
#include <LBroadcaster.h>
//======================================
class CProgressBroadcaster : public LBroadcaster
//======================================
{
public:
enum { msg_StatusText = 'StRp',
msg_StatusPercent = 'StPc',
msg_StatusComplete = 'StCt'
};
struct StatusInfo
{
const char* message;
Int32 percent;
int level;
StatusInfo () : message(NULL), percent(0), level(0) {}
};
CProgressBroadcaster() {}
virtual ~CProgressBroadcaster() {}
};

View File

@ -0,0 +1,122 @@
/* -*- 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.
*/
// CProgressListener.cp
#include "CProgressListener.h"
#include "CPatternProgressBar.h"
#include "CNSContext.h" // for progress messages
#include "xp.h"
#include "MailNewsgroupWindow_Defines.h"
#include <LCaption.h>
#define MIN_TICKS (60/4) // Don't refresh the progress bar more than 4x /sec.
//-----------------------------------
CProgressListener::CProgressListener(LView* super, LBroadcaster* context)
//-----------------------------------
{
Assert_(super);
Assert_(context);
mProgressCaption = dynamic_cast<CPatternProgressCaption*>(super->FindPaneByID(kMailNewsStatusPaneID));
mProgressLastTicks = 0;
mMessageLastTicks = 0;
mPercentLastTicks = 0;
mLaziness = mPreviousLaziness = lazy_NotAtAll;
Assert_(mProgressCaption);
context->AddListener(this);
} // CProgressListener::CProgressListener
//-----------------------------------
CProgressListener::~CProgressListener()
//-----------------------------------
{
} // CProgressListener::~CProgressListener()
//-----------------------------------
void CProgressListener::SetLaziness(ProgressBarLaziness inLaziness)
//-----------------------------------
{
mPreviousLaziness = mLaziness;
mLaziness = inLaziness;
}
//-----------------------------------
void CProgressListener::ListenToMessage(MessageT inMessage, void *ioParam)
//-----------------------------------
{
if (!mProgressCaption)
return;
switch (inMessage)
{
// case msg_NSCStartLoadURL:
// case msg_NSCProgressBegin:
// // context is busy
// break;
case msg_NSCProgressEnd:
case msg_NSCAllConnectionsComplete:
if (mLaziness == lazy_VeryButForThisCommandOnly)
mLaziness = mPreviousLaziness;
mProgressCaption->SetValue(CPatternProgressCaption::eSeamless);
mProgressCaption->SetDescriptor("\p");
break;
case msg_NSCProgressUpdate:
if (mLaziness != lazy_VeryButForThisCommandOnly)
{
if (::TickCount() - mProgressLastTicks >= MIN_TICKS)
{
mProgressLastTicks = ::TickCount();
CContextProgress* progress = (CContextProgress*)ioParam;
mProgressCaption->SetDescriptor(progress->mMessage);
// mProgressCaption->SetValue(progress->mPercent);
}
}
break;
case msg_NSCProgressMessageChanged:
Boolean displayIt = true;
if (mLaziness == lazy_JustABit || mLaziness == lazy_VeryButForThisCommandOnly)
{
if (::TickCount() - mMessageLastTicks < MIN_TICKS)
displayIt = false;
}
if (displayIt)
{
mMessageLastTicks = ::TickCount();
if (ioParam)
mProgressCaption->SetDescriptor(TString<Str255>((const char*)ioParam));
else
mProgressCaption->SetDescriptor("\p");
}
break;
case msg_NSCProgressPercentChanged:
if (::TickCount() - mPercentLastTicks >= MIN_TICKS)
{
mPercentLastTicks = ::TickCount();
mProgressCaption->SetValue(*(Int32*)ioParam);
}
break;
}
} // CProgressListener::ListenToMessage

View File

@ -0,0 +1,82 @@
/* -*- 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.
*/
// CProgressListener.h
#pragma once
#include <LListener.h>
class LCaption;
class CPatternProgressCaption;
class LBroadcaster;
//======================================
class CProgressListener : public LListener
//======================================
{
public:
// We have three kinds of information displayed by the Progress Bar:
// - graphical status level showing a percent value (msg_NSCProgressPercentChanged)
// - text message showing a percent value (msg_NSCProgressUpdate)
// - general purpose text message (msg_NSCProgressMessageChanged)
//
// The first two messages (those about the percent value) are always filtered
// in order to avoid flickers generated by frequent updates.
//
// The last one is not filtered by default: it allows for instance
// to keep track of the mouse cursor over an HTML page and display as fast
// as possible the URLs corresponding to the links pointed by the cursor.
//
// The first level of laziness (lazy_JustABit) filters frequent updates of
// the text messages and allows to go much faster when loading a mail.
//
// The second level of laziness (lazy_VeryButForThisCommandOnly) filters
// the normal text messages and completely ignores the text messages showing
// a percent value. It allows to go much faster when downloading news articles.
// This mode is automatically reset to the previous one when the command has completed.
//
enum ProgressBarLaziness
{
lazy_NotAtAll = 1,
// display all messages, still filter frequent refresh of the progress bar
lazy_JustABit,
// filter
lazy_VeryButForThisCommandOnly
};
CProgressListener(CPatternProgressCaption* progressCaption)
: mProgressCaption(progressCaption) {}
CProgressListener(LView* superview, LBroadcaster* broadcaster);
// The broadcaster is the one to listen to.
~CProgressListener();
void ListenToMessage(MessageT inMessage, void *ioParam);
void SetLaziness(ProgressBarLaziness inLaziness);
protected:
// LCaption* mCaption;
// CProgressBar* mProgressBar;
CPatternProgressCaption* mProgressCaption;
unsigned long mProgressLastTicks;
unsigned long mMessageLastTicks;
unsigned long mPercentLastTicks;
ProgressBarLaziness mLaziness;
ProgressBarLaziness mPreviousLaziness;
}; // class ProgressListener

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,342 @@
/* -*- 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.
*/
// CSearchManager.h
#pragma once
/*======================================================================================
DESCRIPTION: Handles interaction with BE and management of search window.
All calls to the BE search engine bottleneak through this class.
======================================================================================*/
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
// BE stuff
#include "msg_srch.h"
// Other files
//"search.cpp"
class CSearchPopupMenu;
class CSearchEditField;
class CSearchDateField;
class CSearchTabGroup;
class CStr255;
class LGAPushButton;
class LGAPopup;
class LGARadioButton;
class CSingleTextColumn;
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
// Information about a given search level
typedef struct {
// CListenerCaption *booleanOperator; no longer used: we have a global AND/OR now (the code was removed, it was not very clean anyway)
CSearchPopupMenu *attributesPopup;
CSearchPopupMenu *operatorsPopup;
CSearchPopupMenu *valuePopup;
CSearchEditField *valueText;
CSearchEditField *valueInt;
CSearchDateField *valueDate;
LPane *lastVisibleValue;
} SearchLevelInfoT;
typedef struct {
char text[128];
} SearchTextValueT;
typedef struct {
MSG_SearchValue val;
MSG_SearchOperator op;
XP_Bool boolOp; // we have a global AND/OR now but we continue to use
// that flag for compatibility with existing rules
long customHeaderPos;
} SearchLevelParamT;
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
class CSearchManager : public LListener,
public LBroadcaster {
public:
CSearchManager();
virtual ~CSearchManager();
void AboutToClose();
Boolean GetBooleanOperator() const;
// IDs for panes in associated view, also messages that are broadcast to this object
enum {
paneID_Attributes = 'ATTR' // CSearchPopupMenu *, attributes popup
, paneID_Operators = 'OPER' // CSearchPopupMenu *, operators popup
, paneID_TextValue = 'TXVL' // nil, text value
, paneID_IntValue = 'ioNT' // nil, integer value
, paneID_PopupValue = 'POVL' // nil, popup value
, paneID_DateValue = 'DTVL' // nil, date value
, paneID_More = 'MORE' // nil, more button
, paneID_Fewer = 'FEWR' // nil, fewer button
, paneID_Clear = 'CLER' // nil, clear button
, paneID_ParamEncl = 'PENC' // nil, parameter enclosure
, paneID_ParamSubEncl = 'SENC' // nil, subview parameter enclosure
, paneID_MatchAllRadio = 'MAND' // AND radio
, paneID_MatchAnyRadio = 'MOR ' // OR radio
};
// Messages that this object broadcasts
enum {
msg_SearchParametersResized = paneID_ParamEncl // Int16 *, search parameters enclosure was resized
, msg_SearchParametersCleared = paneID_Clear // nil, search parameters were cleared
, msg_UserChangedSearchParameters = 'UCHG' // nil, search parameters were changed, broadcast
// on ANY change of the parameters by the user
, msg_AND_OR_Toggle = 'ANOR'
};
// Other constants
enum {
cMaxNumSearchLevels = 5
, cMaxNumSearchMenuItems = 20
, cScopeMailFolderNewsgroup = 20
, cScopeMailSelectedItems = 21
, cScopeNewsSelectedItems = 22
, cPriorityScope = 30
, cStatusScope = 31
};
// this constants are used for the search dialogs
enum {
eAND_STR = 1, // location of the AND string in macfe.r
eOR_STR = 2, // location of the OR string in macfe.r
eEditMenuItem = 3, // location of the Customize string in macfe.r
eSTRINGS_RES_ID = 901, // string resource number
eCustomizeSearchItem = -3 // command number for the customize menu item
};
OSErr InitSearchManager(LView *inContainer, CSearchTabGroup *inTabGroup,
MSG_ScopeAttribute inScope, LArray *inFolderScopeList = nil );
Boolean CanSearch() const;
void SetIsSearching( Boolean inValue ) { mIsSearching = inValue; }
Boolean IsSearching() const {
return mIsSearching;
}
MSG_Pane *GetMsgPane() const {
return mMsgPane;
}
Int16 GetNumVisibleLevels() const {
return mNumVisLevels;
}
Int16 GetNumDefaultLevels() const {
return 1;
}
Int16 GetNumLevels() const {
return mNumLevels;
}
Int32 GetNumResultRows() const {
return (mMsgPane == nil) ? 0 : MSG_GetNumLines(mMsgPane);
}
void SetSearchScope(MSG_ScopeAttribute inScope, LArray *inFolderScopeList = nil);
void SetNumVisibleLevels(Int32 inNumLevels);
void StopSearch(MWContext *inContext = nil);
void StartSearch()
{
// Don't switch target when disabling
StValueChanger<Boolean> change(mCanRotateTarget, false);
mParamEnclosure->Disable();
}
/* void SaveSearchResults(); Not implemented -- 10/30/97 */
void ReadSavedSearchStatus(LStream *inStatusData);
void WriteSavedSearchStatus(LStream *outStatusData);
void GetSearchParameters(SearchLevelParamT *outSearchParams);
void SetSearchParameters(Int16 inNumVisLevels, const SearchLevelParamT *inSearchParams);
// For accessing result data
// MWContext *IsResultElementOpen(MSG_ViewIndex inIndex, MWContextType *outType);
void PopulateAttributesMenus(MSG_ScopeAttribute inScope);
void PopulatePriorityMenu(CSearchPopupMenu *inMenu);
void PopulateStatusMenu(CSearchPopupMenu *inMenu);
static void FailSearchError(MSG_SearchError inError);
void SetWinCSID(int16 wincsid);
////////////////////////////////////////////////////////////////////////////////////////
// Custom headers
virtual char* GetSelectedCustomHeader( const SearchLevelParamT* curLevel ) const;
virtual UInt16 GetNumberOfAttributes( MSG_ScopeAttribute& scope, void* scopeItem );
virtual const char* GetCustomHeadersFromTable( CSingleTextColumn* table );
virtual const MSG_SearchMenuItem* GetSearchMenuItems() const { return mAttributeItems; }
virtual const UInt16& GetLastNumOfAttributes() const { return mLastNumOfAttributes; };
void AddScopesToSearch(MSG_Master *inMaster);
void AddParametersToSearch();
void SetMSGPane( MSG_Pane* inPane) { mMsgPane = inPane ;}
protected:
void MessageAttributes( SearchLevelInfoT& searchLevel );
virtual void ListenToMessage(MessageT inMessage, void *ioParam = nil);
// Utility methods
MSG_ScopeAttribute GetBEScope(MSG_ScopeAttribute inScope) const;
void PopulateOperatorsMenus(MSG_ScopeAttribute inScope);
enum ECheckDirection { eCheckForward = 1, eCheckBackward = 2, eCheckNothing = 3 };
void SelectSearchLevel(Int16 inBeginLevel, ECheckDirection inCheckDirection);
Int32 GetSelectedSearchLevel();
// void MessageAttributes(CSearchPopupMenu *inAttributesMenu);
void MessageOperators(CSearchPopupMenu *inOperatorsMenu);
void MessageSave();
void MessageMoreFewer(Boolean inMore);
void MessageClear();
void ClearSearchParams(Int16 inStartLevel, Int16 inEndLevel);
//void UpdateMsgResult(MSG_ViewIndex inIndex);
void UserChangedParameters() {
if ( mBroadcastUserChanges ) BroadcastMessage(msg_UserChangedSearchParameters);
}
////////////////////////////////////////////////////////////////////////////////////////
// Custom headers
virtual void EditCustomHeaders();
virtual void FillUpCustomHeaderTable( const char buffer[], CSingleTextColumn* table );
virtual void FinishCreateAttributeMenu( MSG_SearchMenuItem* inMenuItems, UInt16& inNumItems );
virtual bool InputCustomHeader( const StringPtr ioHeader, bool newHeader );
enum {
eCustomHeaderSeparator = ' '
};
// Instance variables
Int32 mNumLevels; // Number of possible search levels
Int32 mNumVisLevels; // Number of currently visible search levels
Int32 mLevelResizeV; // Visible margin between levels
SearchLevelInfoT mLevelFields[cMaxNumSearchLevels];
LGAPushButton *mMoreButton;
LGAPushButton *mFewerButton;
LGARadioButton *mMatchAllRadio;
LGARadioButton *mMatchAnyRadio;
LView *mParamEnclosure;
Boolean mCanRotateTarget;
Boolean mIsSearching;
// BE related
MSG_SearchMenuItem mSearchMenuItems[cMaxNumSearchMenuItems];
// *** Attributes menu support
MSG_SearchMenuItem *mAttributeItems; // menu items array for attributes
UInt16 mLastNumOfAttributes; // last number of attributes
MSG_ScopeAttribute mLastMenuItemsScope;
MSG_SearchAttribute mLastMenuItemsAttribute;
UInt16 mNumLastMenuItems;
MSG_ScopeAttribute mCurrentScope;
LArray *mFolderScopeList; // List of MSG_FolderInfo * for current scope
MSG_Pane *mMsgPane; // Search message pane during an actual search
Boolean mBroadcastUserChanges;
Boolean mBoolOperator;
};
// StSearchDataBlock
class StSearchDataBlock {
public:
enum { eAllocateStrings = true, eDontAllocateStrings = false };
StSearchDataBlock() :
mData(nil) {
}
StSearchDataBlock(Int16 inNumSearchLevels, Boolean inAllocateStrings = true) :
mData(nil) {
Allocate(inNumSearchLevels, inAllocateStrings);
}
~StSearchDataBlock() {
Dispose();
}
void Allocate(Int16 inNumSearchLevels, Boolean inAllocateStrings = true) {
Int32 size = inAllocateStrings ? ((sizeof(SearchLevelParamT) + sizeof(SearchTextValueT)) * inNumSearchLevels) :
(sizeof(SearchLevelParamT) * inNumSearchLevels);
delete mData;
mData = (SearchLevelParamT *) new char[size];
FailNIL_(mData);
SearchLevelParamT *data = mData;
SearchTextValueT *text = (SearchTextValueT *) &data[inNumSearchLevels];
for (Int16 i = 0; i < inNumSearchLevels; ++i) data[i].val.u.string = inAllocateStrings ? text[i].text : nil;
}
void Dispose() {
delete mData;
mData = nil;
}
SearchLevelParamT *GetData() {
return mData;
}
private:
SearchLevelParamT *mData;
};

View File

@ -0,0 +1,809 @@
/* -*- 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.
*/
#define DEBUGGER_ASSERTIONS
#include "CSearchTableView.h"
#include "CApplicationEventAttachment.h"
#include "CSearchWindowBase.h"
#include "CMessageSearchWindow.h"
#include "LFlexTableGeometry.h"
#include "CTableKeyAttachment.h"
#include "CThreadWindow.h"
#include "CThreadView.h"
#include "CMessageWindow.h"
#include "CMessageView.h"
#include "UMessageLibrary.h"
#include "UMailSelection.h"
#include "UMailFolderMenus.h"
#include "UGraphicGizmos.h"
#include "UException.h"
#include "UIHelper.h"
#include "CBrowserContext.h"
#include "LSharable.h"
#include "CComposeAddressTableView.h"
#include "libi18n.h"
#include "LCommander.h"
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
#include "ntypes.h"
//-----------------------------------
CSearchTableView::~CSearchTableView()
//-----------------------------------
{
SetMessagePane( NULL );
}
void CSearchTableView::SetSearchManager(CSearchManager *inSearchManager)
{
mSearchManager = inSearchManager;
SetMessagePane( inSearchManager->GetMsgPane() );
}
//-----------------------------------
void CSearchTableView::DrawCellContents( const STableCell& inCell, const Rect& inLocalRect)
//-----------------------------------
{
// Get the text to display
CStr255 displayText;
MSG_SearchAttribute inAttribute = CSearchWindowBase::AttributeFromDataType(GetCellDataType(inCell));
if ( !GetDisplayText(inCell.row - 1, inAttribute, displayText) )
return; // Error occurred getting the text
// Display the text
Boolean cellIsSelected = CellIsSelected(inCell);
Rect cellDrawFrame = inLocalRect;
::InsetRect(&cellDrawFrame, 2, 0); // For a nicer look between cells
StSectClipRgnState saveSetClip(&cellDrawFrame);
displayText = NET_UnEscape(displayText);
if ( cellIsSelected )
{
UGraphicGizmos::PlaceTextInRect((char *) &displayText[1], displayText[0], cellDrawFrame, teFlushLeft, teCenter,
&mTextFontInfo, true, truncMiddle);
// PlaceHilitedTextInRect((char *) &displayText[1], displayText[0], cellDrawFrame, teFlushLeft, teCenter,
// &mTextFontInfo, true, truncMiddle);
}
else
UGraphicGizmos::PlaceTextInRect((char *) &displayText[1], displayText[0], cellDrawFrame, teFlushLeft, teCenter,
&mTextFontInfo, true, truncMiddle);
}
/*======================================================================================
Set up helpers for the table.
======================================================================================*/
//-----------------------------------
void CSearchTableView::SetUpTableHelpers()
//-----------------------------------
{
SetTableGeometry( new LFlexTableGeometry(this, mTableHeader) );
SetTableSelector( new LTableRowSelector(this) );
// standard keyboard navigation.
AddAttachment( new CTableKeyAttachment(this) );
}
//-----------------------------------
void CSearchTableView::ListenToMessage(
MessageT inCommand,
void *ioParam)
//-----------------------------------
{
if (!ObeyCommand((CommandT)inCommand, ioParam))
CMailFlexTable::ListenToMessage(inCommand, ioParam);
}
//-----------------------------------
Boolean
CSearchTableView::ObeyCommand( CommandT inCommand, void* ioParam )
//-----------------------------------
{
Boolean commandObeyed = false;
switch( inCommand )
{
case msg_TabSelect:
break;
default:
commandObeyed = Inherited::ObeyCommand( inCommand, ioParam );
break;
}
return commandObeyed;
}
//-----------------------------------
// Delete selected messages either via menu command or
// key.
//
//-----------------------------------
void CSearchTableView::DeleteSelection()
//-----------------------------------
{
// see if you got a selection
CMailSelection selection;
if ( GetSelection( selection ) )
{
const MSG_ViewIndex *indices = selection.GetSelectionList();
MSG_ViewIndex numIndices = selection.selectionSize;
MSG_Pane* searchPane = GetMessagePane();
// try closing all the open message windows
MSG_ResultElement* outElement;
MSG_FolderInfo* outFolder;
MessageKey outKey;
const MSG_ViewIndex *indexCounter = indices;
for ( int i = 0; i < numIndices; i++, indexCounter++ )
{
if( GetMessageResultInfo( *indexCounter, outElement, outFolder, outKey ) )
CMessageWindow::CloseAll( outKey );
}
// Get correct BE message. It can either be for mail or news messages, but not for both
CMessageFolder messageFolder( outFolder );
UInt32 folderFlags = messageFolder.GetFolderFlags();
MSG_CommandType cmd = MSG_CancelMessage; // news posting - cancel command
if ( (folderFlags & MSG_FOLDER_FLAG_NEWSGROUP) == 0 )
cmd = UMessageLibrary::GetMSGCommand( cmd_Clear ); // mail message - delete command
// send command to the BE. Copy the index list, because it gets clobbered by
// RemoveRows().
MSG_ViewIndex* copyOfIndices = new MSG_ViewIndex[numIndices];
const MSG_ViewIndex* src = &indices[0];
MSG_ViewIndex* dst = &copyOfIndices[0];
for (int i = 0; i < numIndices; i++, src++, dst++)
*dst = *src;
// BE delete command
MSG_Command( searchPane, cmd, copyOfIndices, numIndices );
// delete the list
delete [] copyOfIndices;
SelectionChanged();
}
}
//-----------------------------------
void CSearchTableView::OpenRow(TableIndexT inRow)
//-----------------------------------
{
MSG_ViewIndex index = inRow - 1;
ShowMessage(index, kInMessageWindow);
}
//-----------------------------------
void CSearchTableView::FindOrCreateThreadWindowForMessage(MSG_ViewIndex inMsgIndex)
//-----------------------------------
{
AssertFail_(mSearchManager != nil);
Try_
{
MSG_ResultElement *elem = NULL;
MSG_GetResultElement(GetMessagePane(), inMsgIndex, &elem);
if (!elem)
return;
MWContextType cxType = MSG_GetResultElementType(elem);
if (! (cxType == MWContextMail || cxType == MWContextMailMsg
|| cxType == MWContextNews || cxType == MWContextNewsMsg))
return;
// Get info about the message
MSG_SearchValue *value;
MSG_GetResultAttribute(elem, attribFolderInfo, &value);
MSG_FolderInfo *folderInfo = value->u.folder;
if (!folderInfo)
return;
// Create the thread window if it doesn't exist
CThreadWindow *threadWindow = CThreadWindow::FindOrCreate( folderInfo, CThreadView::cmd_UnselectAllCells);
}
Catch_(inErr)
{
Throw_(inErr);
}
EndCatch_
} // CSearchTableView::FindOrCreateThreadWindowForMessage
//-----------------------------------
void CSearchTableView::FindCommandStatus(CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark, Str255 outName)
//-----------------------------------
{
ResIDT menuID;
Int16 menuItem;
// Check for synthetic commands
if( IsSyntheticCommand( inCommand, menuID, menuItem ) )
{
switch( menuID )
{
case menu_Navigator: // enable menus
outEnabled = true;
break;
case menu_Go: // disable menus
case menu_View:
outEnabled = false;
break;
}
}
else // check for regular commands
{
switch (inCommand)
{
case cmd_AboutPlugins: // always enabled
case cmd_About:
case cmd_Quit:
case cmd_Close:
case cmd_Preferences:
outEnabled = true;
break;
case cmd_SelectAll: // need at least one result
if( IsValidRow( 1 ) )
outEnabled = true;
else
outEnabled = false;
break;
case cmd_Clear: // need at least one result and one selection
// Only support deleting of Mail Messages not news.
CMailSelection selection;
if ( GetSelection( selection ) )
{
const MSG_ViewIndex *indices = selection.GetSelectionList();
MSG_ResultElement* outElement;
MSG_FolderInfo* outFolder;
MessageKey outKey;
GetMessageResultInfo( *indices, outElement, outFolder, outKey );
CMessageFolder messageFolder( outFolder );
UInt32 folderFlags = messageFolder.GetFolderFlags();
if ( (folderFlags & MSG_FOLDER_FLAG_NEWSGROUP) == 0 )
outEnabled = true; // mail message - delete command
}
break;
default:
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
break;
}
}
}
//-----------------------------------
Boolean CSearchTableView::GetMessageResultInfo(
MSG_ViewIndex inMsgIndex,
MSG_ResultElement*& outElement,
MSG_FolderInfo*& outFolder,
MessageKey& outKey)
//-----------------------------------
{
return GetMessageResultInfo(
GetMessagePane(), inMsgIndex, outElement, outFolder, outKey);
} // SearchTableView::GetMessageResultInfo
//-----------------------------------
Boolean CSearchTableView::GetMessageResultInfo(
MSG_Pane* inPane,
MSG_ViewIndex inMsgIndex,
MSG_ResultElement*& outElement,
MSG_FolderInfo*& outFolder,
MessageKey& outKey)
//-----------------------------------
{
MSG_SearchError err;
err = ::MSG_GetResultElement(inPane, inMsgIndex, &outElement);
if (err != SearchError_Success || outElement == nil)
return false;
MWContextType cxType = ::MSG_GetResultElementType(outElement);
if (! (cxType == MWContextMail || cxType == MWContextMailMsg
|| cxType == MWContextNews || cxType == MWContextNewsMsg))
return false;
// Get info about the message
MSG_SearchValue *value;
err = ::MSG_GetResultAttribute(outElement, attribMessageKey, &value);
if (err != SearchError_Success || value == nil)
return false;
outKey = value->u.key;
if (outKey == MSG_MESSAGEKEYNONE)
return false;
// Get info about the folder the message is in
err = ::MSG_GetResultAttribute(outElement, attribFolderInfo, &value);
if (err == SearchError_Success && value != nil)
outFolder = value->u.folder;
return true;
} // SearchTableView::GetMessageResultInfo
//-----------------------------------
void CSearchTableView::AddRowDataToDrag(TableIndexT inRow, DragReference inDragRef)
// Base class implementation is for a message search. Return the URL.
//-----------------------------------
{
MSG_ResultElement *elem = NULL;
MSG_FolderInfo *folderInfo = nil;
MessageKey key;
// get key and folder info
if (!GetMessageResultInfo(inRow - 1, elem, folderInfo, key))
return;
if (folderInfo == nil)
return;
// MSG_Pane* pane = ::MSG_FindPaneOfType(
// CMailNewsContext::GetMailMaster(), folderInfo, MSG_THREADPANE);
MSG_Pane* pane = GetMessagePane(); // get search pane from the search manager
if (!pane) // fails unless there is a threadpane open to this folder. Too bad.
return; // That's why I turned off dragging.
// create URL
URL_Struct* url = ::MSG_ConstructUrlForMessage( pane, key );
if (!url)
return; // we always return here, as far as I can see
// add the drag item
OSErr err = ::AddDragItemFlavor( inDragRef, inRow, 'TEXT', url->address, XP_STRLEN(url->address), flavorSenderOnly);
NET_FreeURLStruct(url);
}
//-----------------------------------
void CSearchTableView::ShowMessage(MSG_ViewIndex inMsgIndex, SearchWindowOpener inWindow)
//-----------------------------------
{
AssertFail_(mSearchManager != nil);
Try_
{
MSG_ResultElement *elem = NULL;
MSG_FolderInfo *folderInfo = nil;
MessageKey key;
if (!GetMessageResultInfo(inMsgIndex, elem, folderInfo, key))
return;
if (folderInfo == nil && inWindow != kInMessageWindow)
return;
// Got the info we wanted: we can display now...
if (inWindow == kInMessageWindow)
{
// Check if there's an open window with this message.
CMessageWindow *messageWindow = CMessageWindow::FindAndShow(key);
if (messageWindow)
{
messageWindow->Select();
return;
}
// If option key down, try to reuse a window
if ( CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) )
{
messageWindow = CMessageWindow::FindAndShow(0);
messageWindow->Select();
}
// Create the window
if (messageWindow == nil)
{
// We should probably create a generic utility function to generate
// windows that contain a CHTMLView
CBrowserContext *theContext = new CBrowserContext(MWContextMailMsg);
FailNIL_(theContext);
StSharer theShareLock(theContext);
// Create a message window with this view as its super commander.
LWindow *theWindow = LWindow::CreateWindow(cMessageWindowPPobID, LCommander::GetTopCommander());
FailNIL_(theWindow);
messageWindow = dynamic_cast<CMessageWindow*>(theWindow);
FailNIL_(messageWindow);
messageWindow->SetWindowContext(theContext);
}
// Show the message
messageWindow->GetMessageView()->ShowSearchMessage(
CMailNewsContext::GetMailMaster(),
elem,
folderInfo == nil);
}
else
{
CommandT command;
switch (inWindow)
{
case kInThreadWindow: command = CThreadView::cmd_UnselectAllCells; break;
case kAddToThreadWindowSelection: command = cmd_Nothing; break;
default: return;
}
// Check if there's an open window with this folder, and open one if needed
CThreadWindow *threadWindow = CThreadWindow::FindAndShow(folderInfo, true, command);
if (threadWindow)
{
// Show the message
threadWindow->ShowMessageKey(key);
}
}
}
Catch_(inErr)
{
Throw_(inErr);
}
EndCatch_
} // CSearchTableView::ShowMessage
//-----------------------------------
Boolean CSearchTableView::IsValidRow(TableIndexT inRow) const
// *** WARNING ***
// USING mRows is WRONG WHEN DELETING ROWS, it's possibly changed already!
// Use the Table Selector's value instead. That's why this override is here!
//-----------------------------------
{
if (inRow < 1)
return false;
if (inRow > mRows ) /* ((LTableRowSelector*)mTableSelector)->GetRowCount()) */
return false;
return true;
}
//-----------------------------------
MessageKey CSearchTableView::GetRowMessageKey(TableIndexT inRow)
// Get the message key for the specified row. Return MSG_MESSAGEKEYNONE if the
// specified inRow is invalid.
//-----------------------------------
{
AssertFail_(mSearchManager != nil);
if ( !IsValidRow(inRow) ) return MSG_MESSAGEKEYNONE;
MSG_ViewIndex inIndex = inRow - 1;
UpdateMsgResult(inIndex);
MSG_SearchValue *value = nil;
MSG_SearchAttribute attribute = attribMessageKey;
CSearchManager::FailSearchError(MSG_GetResultAttribute(mResultElement, attribute, &value));
MessageKey key = value->u.key;
MSG_SearchError error = MSG_DestroySearchValue(value);
AssertFail_(error == SearchError_Success); // What to do with an error?
return key;
}
//-----------------------------------
MSG_ResultElement* CSearchTableView::GetCurrentResultElement(TableIndexT inRow)
//-----------------------------------
{
AssertFail_(mSearchManager != nil);
if ( !IsValidRow(inRow) ) return nil;
MSG_ResultElement *result;
CSearchManager::FailSearchError(MSG_GetResultElement(GetMessagePane(), inRow-1, &result));
return result;
}
/*======================================================================================
Get the current sort params for the result data.
======================================================================================*/
void CSearchTableView::GetSortParams(MSG_SearchAttribute *outSortKey, Boolean *outSortBackwards)
{
AssertFail_(mTableHeader != nil);
AssertFail_(mSearchManager != nil);
PaneIDT sortColumnID;
mTableHeader->GetSortedColumn(sortColumnID);
*outSortKey = CSearchWindowBase::AttributeFromDataType(sortColumnID);
AssertFail_(*outSortKey != kNumAttributes);
*outSortBackwards = mTableHeader->IsSortedBackwards();
}
/*======================================================================================
Force a sort to occur based upon the current sort column.
======================================================================================*/
void CSearchTableView::ForceCurrentSort()
{
MSG_SearchAttribute sortKey;
Boolean sortBackwards;
GetSortParams(&sortKey, &sortBackwards);
CSearchManager::FailSearchError(MSG_SortResultList(GetMessagePane(), sortKey, sortBackwards));
}
//-----------------------------------
void CSearchTableView::ChangeSort(const LTableHeader::SortChange *inSortChange)
// Notification to sort the table.
//-----------------------------------
{
AssertFail_(mSearchManager != nil);
Inherited::ChangeSort(inSortChange);
MSG_SearchAttribute sortKey = CSearchWindowBase::AttributeFromDataType(inSortChange->sortColumnID);
if ( sortKey != kNumAttributes ) {
::SetCursor(*::GetCursor(watchCursor));
// Call BE to sort the table
AssertFail_(GetMessagePane() != nil);
CSearchManager::FailSearchError(MSG_SortResultList(GetMessagePane(), sortKey, inSortChange->reverseSort));
}
}
//-----------------------------------
void CSearchTableView::SetWinCSID(Int16 wincsid)
// Set the font for the view
//-----------------------------------
{
if (wincsid == INTL_CharSetNameToID(INTL_ResourceCharSet()))
this->SetTextTraits( 8603 );
else
this->SetTextTraits(CPrefs::GetTextFieldTextResIDs(wincsid));
Refresh();
}
//-----------------------------------
//void CSearchTableView::AddSelectionToDrag(
// DragReference inDragRef,
// RgnHandle inDragRgn )
//-----------------------------------
//{
// Since we inherit from CMailFlexTable, we want to avoid it and just call the
// CStandardFlexTable method, thereby avoiding the CMailFlexTable behavior
// CStandardFlexTable::AddSelectionToDrag(inDragRef, inDragRgn);
//} // CAddressSearchTableView::AddSelectionToDrag
//-----------------------------------
void CSearchTableView::SelectionChanged()
// adjust the 'Move Message To' popup accordingly to the current selection
//-----------------------------------
{
Inherited::SelectionChanged();
// Set the 'Move Message' popup to the folder of the first selected item
CMailSelection selection;
if (GetSelection(selection))
{
CMessageSearchWindow* myWindow = dynamic_cast<CMessageSearchWindow*>
(LWindow::FetchWindowObject(GetMacPort()));
if (myWindow)
{
CMailFolderPopupMixin* fileMessagePopup;
FindUIItemPtr(myWindow, CMessageSearchWindow::paneID_FilePopup, fileMessagePopup);
const MSG_ViewIndex *indices = selection.GetSelectionList();
MSG_ViewIndex numIndices = selection.selectionSize;
MSG_ResultElement* outElement;
MSG_FolderInfo* outFolder;
MessageKey outKey;
if (GetMessageResultInfo(*indices, outElement, outFolder, outKey))
fileMessagePopup->MSetSelectedFolder(outFolder, false);
}
}
}
//
/*======================================================================================
Get the display text for the specified attribute and table row index. Return
true if the text could be gotten.
======================================================================================*/
Boolean CSearchTableView::GetDisplayText(MSG_ViewIndex inIndex, MSG_SearchAttribute inAttribute,
CStr255& outString)
{
AssertFail_(GetMessagePane() != nil);
UpdateMsgResult(inIndex);
MSG_SearchValue *value = nil;
MSG_SearchError error = MSG_GetResultAttribute(mResultElement, inAttribute, &value);
//Assert_(error == SearchError_Success);
if ( error != SearchError_Success ) return false;
Int16 wincsid = 0;
MSG_SearchValue *folderinfoValue = nil;
error = MSG_GetResultAttribute(mResultElement, attribFolderInfo, &folderinfoValue);
if( ( error == SearchError_Success ) && folderinfoValue && folderinfoValue->u.folder)
{
folderinfoValue->attribute = attribFolderInfo;
wincsid = INTL_DocToWinCharSetID(MSG_GetFolderCSID(folderinfoValue->u.folder));
error = MSG_DestroySearchValue(folderinfoValue);
Assert_(error == SearchError_Success);
}
switch ( inAttribute ) {
case attribSender:
case attribSubject:
outString = "";
char *buf = IntlDecodeMimePartIIStr(value->u.string,
wincsid,
FALSE);
if (buf) {
outString = buf;
XP_FREE(buf);
break;
}
outString = value->u.string;
break;
case attribLocation:
case attribCommonName:
case attrib822Address:
case attribOrganization:
case attribLocality:
case attribPhoneNumber:
outString = value->u.string;
break;
case attribDate:
outString = MSG_FormatDate(GetMessagePane(), value->u.date);
break;
case attribMsgStatus:
case attribPriority:
{
char name[32];
if ( inAttribute == attribMsgStatus ) {
MSG_GetStatusName(value->u.msgStatus, name, sizeof(name));
} else {
MSG_GetPriorityName(value->u.priority, name, sizeof(name));
}
outString = name;
}
break;
default:
AssertFail_(false);
break;
}
error = MSG_DestroySearchValue(value);
Assert_(error == SearchError_Success);
return true;
}
/*======================================================================================
Call this method whenever the indexes in the message pane change.
======================================================================================*/
void CSearchTableView::UpdateMsgResult(MSG_ViewIndex inIndex) {
AssertFail_(GetMessagePane() != nil);
if ( (mResultElement == nil) || (mResultIndex != inIndex) ) {
mResultElement = nil;
CSearchManager::FailSearchError(MSG_GetResultElement(GetMessagePane(), inIndex, &mResultElement));
mResultIndex = inIndex;
}
}
/*======================================================================================
React to search message.
======================================================================================*/
void CSearchTableView::StartSearch(MWContext *inContext, MSG_Master *inMaster, MSG_SearchAttribute inSortKey,
Boolean inSortBackwards) {
if ( !mSearchManager->CanSearch() || mSearchManager->IsSearching() ) return;
MsgPaneChanged(); // For results
// Prepare for a new search session
NewSearchSession(inContext, inMaster, inSortKey, inSortBackwards);
mSearchManager->SetMSGPane( GetMessagePane() );
// Add scopes to search
mSearchManager->AddScopesToSearch(inMaster);
// Add search parameters
mSearchManager->AddParametersToSearch();
CSearchManager::FailSearchError(MSG_Search(GetMessagePane()));
mSearchManager->StartSearch();
mSearchManager->SetIsSearching( true );
}
/*======================================================================================
Prepare for a new search session.
======================================================================================*/
void CSearchTableView::NewSearchSession(MWContext *inContext, MSG_Master *inMaster, MSG_SearchAttribute inSortKey,
Boolean inSortBackwards)
{
AssertFail_(inContext != nil);
AssertFail_(inMaster != nil);
if ( GetMessagePane() == nil )
{
// Create the search pane and store related date
MSG_Pane* msgPane = MSG_CreateSearchPane(inContext, inMaster);
FailNIL_(msgPane);
SetMessagePane( msgPane );
MSG_SetFEData( GetMessagePane(), CMailCallbackManager::Get() );
} else
{
// Free any previously allocated search memory
CSearchManager::FailSearchError(MSG_SearchFree(GetMessagePane()));
}
// Alloc mem for new search parameters
CSearchManager::FailSearchError(MSG_SearchAlloc(GetMessagePane()));
// Setup the sort order
CSearchManager::FailSearchError(
MSG_SortResultList(GetMessagePane(), inSortKey, inSortBackwards) );
}
void CSearchTableView::ChangeFinished(MSG_Pane * inPane, MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow, SInt32 inRowCount)
{
MsgPaneChanged();
CMailFlexTable::ChangeFinished( inPane, inChangeCode, inStartRow, inRowCount );
}

View File

@ -0,0 +1,141 @@
/* -*- 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.
*/
// CSearchTableView.h
#pragma once
#include "SearchHelpers.h"
#include "CSearchManager.h"
#include "CDateView.h"
#include "NetscapeDragFlavors.h"
///////////////////////////////////////////////////////////////////////////////////
// CSearchTableView
class CSearchTableView : public CMailFlexTable
{
private:
typedef CMailFlexTable Inherited;
public:
enum { class_ID = 'SrTb' };
enum {
menu_Navigator = 305,
menu_View = 502,
menu_Go = 503
};
typedef enum {
kInMessageWindow,
kInThreadWindow,
kAddToThreadWindowSelection
} SearchWindowOpener;
CSearchTableView(LStream *inStream);
virtual ~CSearchTableView();
void SetSearchManager(CSearchManager *inSearchManager);
void ForceCurrentSort();
void GetSortParams(MSG_SearchAttribute *outSortKey, Boolean *outSortBackwards);
virtual void ChangeSort(const LTableHeader::SortChange *inSortChange);
virtual void OpenRow(TableIndexT inRow);
virtual void ShowMessage(MSG_ViewIndex inMsgIndex, SearchWindowOpener inWindow);
virtual void FindOrCreateThreadWindowForMessage(MSG_ViewIndex inMsgIndex);
virtual void FindCommandStatus( CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark, Str255 outName);
MessageKey GetRowMessageKey(TableIndexT inRow);
MSG_ResultElement* GetCurrentResultElement(TableIndexT inRow);
virtual void SetWinCSID(Int16 wincsid);
virtual void ListenToMessage( MessageT inCommand, void *ioParam);
virtual Boolean ObeyCommand( CommandT inCommand, void* ioParam );
void StartSearch(MWContext *inContext, MSG_Master *inMaster,
MSG_SearchAttribute inSortKey, Boolean inSortBackwards);
static Boolean GetMessageResultInfo(
MSG_Pane* inPane,
MSG_ViewIndex inMsgIndex, MSG_ResultElement*& outElement,
MSG_FolderInfo*& outFolder, MessageKey& outKey);
protected:
Boolean GetDisplayText(MSG_ViewIndex inIndex, MSG_SearchAttribute inAttribute,
CStr255& outString);
void UpdateMsgResult(MSG_ViewIndex inIndex);
void NewSearchSession(MWContext *inContext, MSG_Master *inMaster, MSG_SearchAttribute inSortKey,
Boolean inSortBackwards);
virtual Boolean IsValidRow(TableIndexT inRow) const;
virtual void SetUpTableHelpers();
virtual void DeleteSelection();
virtual void DrawCellContents(const STableCell &inCell, const Rect &inLocalRect);
virtual void MsgPaneChanged();
virtual Int32 GetBENumRows();
Boolean GetMessageResultInfo( MSG_ViewIndex inMsgIndex, MSG_ResultElement*& outElement,
MSG_FolderInfo*& outFolder, MessageKey& outKey);
// drag support
virtual Boolean CellInitiatesDrag(const STableCell&) const { return true; }
// uncomment the line above to turn on drag from the message search
// results window. Problem is, URL not obtainable for message search
// unless the enclosing folder is open in a thread window. SO it's
// turned off for now.
// virtual void AddSelectionToDrag( DragReference inDragRef, RgnHandle inDragRgn );
virtual void AddRowDataToDrag(TableIndexT inRow, DragReference inDragRef);
virtual void SelectionChanged();
virtual void ChangeFinished(MSG_Pane */*inPane*/, MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow, SInt32 inRowCount);
// Instance variables ==========================================================
enum { eInvalidResultIndex = -1 };
CSearchManager *mSearchManager; // Belongs to the window, not us.
MSG_ResultElement *mResultElement;
MSG_ViewIndex mResultIndex;
};
///////////////////////////////////////////////////////////////////////////////////
// inlines
inline
CSearchTableView::CSearchTableView(LStream *inStream)
: CMailFlexTable(inStream), mSearchManager(nil), mResultElement( nil ), mResultIndex (eInvalidResultIndex )
{
mDragFlavor = kMailNewsSelectionDragFlavor;
SetRefreshAllWhenResized(false);
}
inline void
CSearchTableView::MsgPaneChanged()
{
mResultElement = nil;
}
inline Int32
CSearchTableView::GetBENumRows()
{
return (GetMessagePane() == nil) ? 0 : MSG_GetNumLines(GetMessagePane());
}

View File

@ -0,0 +1,931 @@
/* -*- 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.
*/
// CSearchWindowBase.cp
#define DEBUGGER_ASSERTIONS
#include "CSearchWindowBase.h"
#include "SearchHelpers.h"
#include "CMailNewsContext.h"
#include "CSearchTableView.h"
#include "libi18n.h"
#include "LGAPushButton.h"
#include "CPatternProgressBar.h"
#include "MailNewsgroupWindow_Defines.h"
#include "resgui.h"
#include <UModalDialogs.h>
#include "prefapi.h"
#include "LGARadioButton.h"
#include "UStClasses.h"
#include "CThreadWindow.h"
#include "CMessageWindow.h"
#include "CProgressListener.h"
const UInt16 resIDT_SearchOptionsDialog = 8851;
const char* const searchSubfolderPrefName = "mailnews.searchSubFolders";
const char* const searchServerPrefName = "mailnews.searchServer";
//-----------------------------------
CSearchWindowBase::CSearchWindowBase(LStream *inStream, DataIDT inWindowType) :
CMailNewsWindow(inStream, inWindowType),
LListener(),
LPeriodical(),
mSearchManager(),
mResultsEnclosure(nil),
mResultsTable(nil),
mResultsVertWindExtension(0),
mResultsTableVisible(true),
mSearchFolders(),
mProgressBar(nil),
mSearchButton(nil),
mSearchOptionsButton(nil)
//-----------------------------------
{
SetRefreshAllWhenResized(false);
}
CSearchWindowBase::~CSearchWindowBase()
// Stop any current search.
//-----------------------------------
{
Boolean canRotate = false;
if ( IsVisible() )
USearchHelper::FindWindowTabGroup(&mSubCommanders)->SetRotateWatchValue(&canRotate);
} // CSearchWindowBase::~CSearchWindowBase
// --------------------------------------------------------------------------
UInt16
CSearchWindowBase::GetValidStatusVersion() const
//
// -- 10/30/97 ---------------------------------------------------------
//
// This is the proper place for this method, because
// every time the two subclasses of this class stream out they stream out a member of
// this class ( CSearchManager). Therefore when the search manager parameters for stream out
// are changed both subclasses are affected.
//
// Copied the following comments from the CAddressSearchWindow implementation, now defunct.
//
// ---------------------------------------------------------------------------
// So here's the skinny on the directory (aka address) search window.
// You see, when we shipped version 4.01, there were three "levels" of criteria,
// and the version we shipped with was:
//
// static const UInt16 cAddressSearchSaveWindowStatusVersion = 0x0203;
//
// Then on 97/06/30, the number of levels has changed from 3 to 5 in MailNewsSearch.cnst,
// in the enclosures include view. That meant that builds from 7/1 - 7/30 were writing
// out saved window status records containing five levels of criteria.
// Unfortunately, the data is written out as:
//
// bounds/vertextension/levelsdata/tableheaderdata
//
// so that the extra data was written out in the middle. In version 4.01, the routine
// CSearchManager::ReadSavedSearchStatus was not skipping the extra fields, so a crash
// occurred when reading in the table header stuff. This happened when the search window
// was used in 4.01 after running it in 4.02 (7/30 build).
//
// This is bug #78713. There are two parts of the fix. (1) start with a version number
// of zero. Then, version 4.01 will ignore the resource as being "too old", and write
// out a resource with version 0x203. This will be handled OK by version 4.02.
//
// The other part of the fix is that CSearchManager::ReadSavedSearchStatus will now skip
// extra fields, so that this crash won't happen if somebody further increases the number
// of levels.
//
// FINAL NOTE (97/10/13) Because of this same problem, I changed CSaveWindowStatus so that
// it always writes out zero in the first field, which will be interpreted as a zero version
// by Communicator 4.0x, and ignored. So now it's OK to increment this as originally
// intended.
{
return eValidStreamVersion;
}
//-----------------------------------
void CSearchWindowBase::AboutToClose()
//-----------------------------------
{
// Not re-entrant! Don't call this twice.
CSearchWindowBase::MessageWindStop(true);
Inherited::AttemptCloseWindow(); // Do this first: uses table
// Bug fix: Do these things in the right order here
if (mMailNewsContext)
mMailNewsContext->RemoveUser(this);
mMailNewsContext = nil;
mSearchManager.AboutToClose();
if (mResultsTable)
{
if (mMailNewsContext)
mMailNewsContext->RemoveListener(mResultsTable); // bad time to listen for all connections complete.
delete mResultsTable;
mResultsTable = nil;
}
}
//-----------------------------------
void CSearchWindowBase::FinishCreateSelf()
//-----------------------------------
{
// Create context and and progress listener
mMailNewsContext = new CMailNewsContext(MWContextSearch);
FailNIL_(mMailNewsContext);
mMailNewsContext->AddUser(this);
mMailNewsContext->AddListener(this);
CMediatedWindow::FinishCreateSelf(); // Call CMediatedWindow for now since we need to
// create a different context than CMailNewsWindow
if (mProgressListener)
mMailNewsContext->AddListener(mProgressListener);
else
mProgressListener = new CProgressListener(this, mMailNewsContext);
// SetAttribute(windAttr_DelaySelect); put in resource
// should be in resource, but there's a resource freeze.
mMailNewsContext->SetWinCSID(INTL_DocToWinCharSetID(mMailNewsContext->GetDefaultCSID()));
USearchHelper::FindWindowTabGroup(&mSubCommanders)->SetRotateWatchValue(&mCanRotateTarget);
// Populate scope window
mResultsEnclosure = USearchHelper::FindViewSubview(this, paneID_ResultsEnclosure);
FailNILRes_(mResultsEnclosure);
mResultsTable = dynamic_cast<CSearchTableView *>(USearchHelper::FindViewSubview(this, paneID_ResultsTable));
FailNILRes_(mResultsTable);
mSearchButton = dynamic_cast<LGAPushButton *>(USearchHelper::FindViewControl(this, paneID_Search));
FailNILRes_(mSearchButton);
mProgressBar = dynamic_cast<CPatternProgressCaption *>(USearchHelper::FindViewSubpane(this, paneID_ProgressBar));
FailNILRes_(mProgressBar);
mResultsTable->AddListener(this);
mSearchButton->SetDefaultButton(true, false);
mResultsEnclosure->SetRefreshAllWhenResized(false);
Rect windowBounds;
this->CalcPortFrameRect(windowBounds);
mMinVResultsSize = windowBounds.bottom - windowBounds.top;
UReanimator::LinkListenerToControls(this, this, GetStatusResID());
ShowHideSearchResults(false);
// Initialize the search manager
mSearchManager.AddListener(this);
mSearchManager.InitSearchManager(
this, USearchHelper::FindWindowTabGroup(&mSubCommanders),
GetWindowScope(),
&mSearchFolders );
mResultsTable->SetSearchManager(&mSearchManager);
// Call inherited method
FinishCreateWindow();
}
//-----------------------------------
Boolean CSearchWindowBase::ObeyCommand(CommandT inCommand, void *ioParam)
//-----------------------------------
{
if ( IsResultsTableVisible() )
{
switch ( inCommand )
{
case cmd_PreviousMessage:
case cmd_NextMessage:
case cmd_NextUnreadMessage:
return true;
case cmd_SortBySubject:
case cmd_SortBySender:
case cmd_SortByDate:
case cmd_SortByLocation:
case cmd_SortByPriority:
case cmd_SortByStatus:
{
LTableHeader *theHeader = mResultsTable->GetTableHeader();
PaneIDT dataType = DataTypeFromSortCommand(inCommand);
if ( theHeader != nil )
{
theHeader->SetSortedColumn(theHeader->ColumnFromID(dataType),
mResultsTable->IsSortedBackwards(), true);
}
}
return true;
case cmd_SortAscending:
case cmd_SortDescending:
LTableHeader *theHeader = mResultsTable->GetTableHeader();
if ( theHeader != nil )
{
theHeader->SetSortedColumn(theHeader->ColumnFromID(mResultsTable->GetSortedColumn()),
inCommand == cmd_SortDescending, true);
}
return true;
case msg_TabSelect:
break;
}
}
switch ( inCommand ) {
default:
return Inherited::ObeyCommand(inCommand, ioParam);
}
}
//-----------------------------------
void CSearchWindowBase::FindCommandStatus(CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark,
Str255 outName)
//-----------------------------------
{
// Boolean isLineSelected = (GetSelectedRowCount() > 0);
if ( IsResultsTableVisible() )
{
switch ( inCommand )
{
case cmd_PreviousMessage:
case cmd_NextMessage:
case cmd_NextUnreadMessage:
outEnabled = true;
outUsesMark = false;
return;
case cmd_SortBySubject:
case cmd_SortBySender:
case cmd_SortByDate:
case cmd_SortByLocation:
case cmd_SortByPriority:
case cmd_SortByStatus:
{
PaneIDT dataType = DataTypeFromSortCommand(inCommand);
PaneIDT paneID = mResultsTable->GetSortedColumn();
outUsesMark = true;
outEnabled = true;
outMark = ((dataType == paneID) ? checkMark : noMark);
}
return;
case cmd_SortAscending:
case cmd_SortDescending:
outMark =
((inCommand == cmd_SortDescending) == mResultsTable->IsSortedBackwards()) ?
checkMark : 0;
outUsesMark = true;
outEnabled = true;
return;
}
}
switch ( inCommand ) {
default:
if (inCommand == cmd_OpenSelection) // enabled in base class
::GetIndString(outName, kMailNewsMenuStrings, kOpenMessageStrID);
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark,
outName);
break;
}
}
//-----------------------------------
void CSearchWindowBase::ListenToMessage(MessageT inMessage, void *ioParam)
//-----------------------------------
{
switch ( inMessage )
{
case paneID_Search:
if (mProgressBar) mProgressBar->SetDescriptor("\p");
MessageWindSearch();
break;
case paneID_SearchOptions:
SearchOptions();
break;
case paneID_Stop:
MessageWindStop(true);
UpdateTableStatusDisplay();
break;
case CStandardFlexTable::msg_SelectionChanged:
UpdateTableStatusDisplay();
break;
case CSearchManager::msg_SearchParametersCleared:
ShowHideSearchResults(false);
break;
case CSearchManager::msg_SearchParametersResized:
MessageSearchParamsResized(*((Int16 *) ioParam));
break;
// Status messages
case msg_NSCAllConnectionsComplete:
MessageWindStop(false);
UpdateTableStatusDisplay();
// no break here
default:
// No superclass method
break;
}
} // CSearchWindowBase::ListenToMessage
//-----------------------------------
void CSearchWindowBase::SearchOptions()
// This function allows the user to set the following prefs:
// - search in subfolders [yes / no]
// - search locally / on server
// After changing these prefs, it is necessary to reconstruct the attributes menu
// because a search on server usually doesn't offer as many criteria as a local search.
// So we call PopulateAttributesMenus() which will do a MSG_GetAttributesForSearchScopes().
//-----------------------------------
{
StDialogHandler theOptionsDialogHandler( resIDT_SearchOptionsDialog, dynamic_cast<LCommander*>(this) );
// get the options dialog
LWindow* theOptionsDialog = theOptionsDialogHandler.GetDialog();
AssertFail_( theOptionsDialog != nil );
int prefResult;
XP_Bool searchSubFolderPref = false;
XP_Bool searchServerPref = false;
// set the default value for the subfolder search from the preferences
LGACheckbox* searchSubChkb
= dynamic_cast<LGACheckbox*>( theOptionsDialog->FindPaneByID( 'SUBF' ) );
AssertFail_( searchSubChkb != nil );
prefResult = PREF_GetBoolPref( searchSubfolderPrefName, &searchSubFolderPref );
if ( prefResult == PREF_ERROR ) searchSubFolderPref = true; // default from spec.
searchSubFolderPref ? searchSubChkb->SetValue( Button_On ) : searchSubChkb->SetValue( Button_Off );
// set the default value for the local/server search from the preferences
LGARadioButton* searchServerBtn
= dynamic_cast<LGARadioButton*>( theOptionsDialog->FindPaneByID( 'SRCS' ) );
LGARadioButton* searchLocalBtn
= dynamic_cast<LGARadioButton*>( theOptionsDialog->FindPaneByID( 'SRCL' ) );
AssertFail_( searchServerBtn != nil );
prefResult = PREF_GetBoolPref( searchServerPrefName, &searchServerPref );
if ( prefResult == PREF_ERROR ) searchServerPref = true; // default from spec.
if( searchServerPref )
{
searchServerBtn->SetValue( Button_On ); // Other radio will be turned off via LTabGroup
}
else
{
searchLocalBtn->SetValue( Button_On ); // ditto
}
MessageT theMessage;
while( true )
{
theMessage = theOptionsDialogHandler.DoDialog();
if( theMessage == msg_OK )
{
Boolean choice;
if( ( choice = searchSubChkb->IsSelected() ) != searchSubFolderPref )
PREF_SetBoolPref( searchSubfolderPrefName, choice );
if( ( choice = searchServerBtn->IsSelected() ) != searchServerPref )
PREF_SetBoolPref( searchServerPrefName, choice );
// See the comment in the function header
mSearchManager.PopulateAttributesMenus(GetWindowScope());
break;
}
else
if( theMessage == msg_Cancel )
break;
}
}
//-----------------------------------
Boolean CSearchWindowBase::HandleKeyPress(const EventRecord &inKeyEvent)
//-----------------------------------
{
Int16 theKey = inKeyEvent.message & charCodeMask;
if ( ((theKey == char_Enter) || (theKey == char_Return)) && !mSearchManager.IsSearching() )
{
mSearchButton->SimulateHotSpotClick(kControlButtonPart);
return true;
}
else if ( (((theKey == char_Escape) && ((inKeyEvent.message & keyCodeMask) == vkey_Escape)) ||
UKeyFilters::IsCmdPeriod(inKeyEvent)) && mSearchManager.IsSearching() )
{
USearchHelper::FindViewControl(this, paneID_Stop)->SimulateHotSpotClick(kControlButtonPart);
return true;
}
return Inherited::HandleKeyPress(inKeyEvent);
}
//-----------------------------------
void CSearchWindowBase::SpendTime(const EventRecord &/*inMacEvent*/)
//-----------------------------------
{
USearchHelper::EnableDisablePane(mSearchButton, mSearchManager.CanSearch());
}
//-----------------------------------
void CSearchWindowBase::Activate()
// Start repeating.
//-----------------------------------
{
StopIdling();
StartRepeating();
// CSearchTabGroup *theTabGroup = USearchHelper::FindWindowTabGroup(&mSubCommanders);
// Boolean couldRotate = theTabGroup->SetCanRotate(false); // Don't rotate when activating
Inherited::Activate();
// theTabGroup->SetCanRotate(couldRotate);
}
//-----------------------------------
void CSearchWindowBase::DeactivateSelf()
//-----------------------------------
{
StopRepeating();
StartIdling();
Inherited::DeactivateSelf();
}
//-----------------------------------
void CSearchWindowBase::DrawSelf()
//-----------------------------------
{
Boolean doResultsTable = IsResultsTableVisible();
Rect frame;
if ( doResultsTable && mResultsTable->CalcPortFrameRect(frame) &&
::RectInRgn(&frame, mUpdateRgnH) )
{
{
StExcludeVisibleRgn excludeRgn(mResultsTable);
Inherited::DrawSelf();
}
StColorPenState::Normalize();
::EraseRect(&frame);
}
else
{
Inherited::DrawSelf();
}
USearchHelper::RemoveSizeBoxFromVisRgn(this);
}
//-----------------------------------
void CSearchWindowBase::SetDescriptor(ConstStr255Param inDescriptor)
//-----------------------------------
{
if ( !::EqualString(inDescriptor, *((WindowPeek) GetMacPort())->titleHandle, true, true) )
{
Inherited::SetDescriptor(inDescriptor);
}
}
//-----------------------------------
void CSearchWindowBase::MessageSearchParamsResized(Int16 inResizeAmount)
// React to more message.
//-----------------------------------
{
LPane *resultsView = USearchHelper::FindViewSubpane(this, paneID_ResultsEnclosure);
if ( inResizeAmount > 0 ) { // Make refresh look good!
resultsView->ResizeFrameBy(0, -inResizeAmount, true);
resultsView->MoveBy(0, inResizeAmount, true);
}
else
{
resultsView->MoveBy(0, inResizeAmount, true);
resultsView->ResizeFrameBy(0, -inResizeAmount, true);
}
if ( !IsResultsTableVisible() )
{
Rect bounds;
CSaveWindowStatus::GetPaneGlobalBounds(this, &bounds);
bounds.bottom += inResizeAmount;
this->DoSetBounds(bounds); // Update window size
}
RecalcMinMaxStdSizes();
}
//-----------------------------------
void CSearchWindowBase::MessageWindSearch()
//-----------------------------------
{
AssertFail_(mSearchManager.CanSearch());
MSG_SearchAttribute attrib;
Boolean sortBackwards;
mResultsTable->GetSortParams(&attrib, &sortBackwards);
mResultsTable->StartSearch(*mMailNewsContext, CMailNewsContext::GetMailMaster(),
attrib, sortBackwards);
mSearchButton->Hide();
USearchHelper::FindViewSubpane(this, paneID_Stop)->Show();
USearchHelper::FindViewSubpane(this, paneID_ScopeEnclosure)->Disable();
ShowHideSearchResults(true);
UpdatePort();
} // CSearchWindowBase::MessageWindSearch()
//-----------------------------------
void CSearchWindowBase::RecalcMinMaxStdSizes()
// Recalculate the window's min/max and std sizes based on the current window state.
//-----------------------------------
{
if ( IsResultsTableVisible() )
{
mMinMaxSize.top = mMinVResultsSize;
mMinMaxSize.bottom = 16000;
mStandardSize.height = max_Int16;
}
else
{
Rect bounds;
CSaveWindowStatus::GetPaneGlobalBounds(this, &bounds);
mMinMaxSize.top = mMinMaxSize.bottom = mStandardSize.height = (bounds.bottom - bounds.top);
}
}
//-----------------------------------
void CSearchWindowBase::ShowHideSearchResults(Boolean inDoShow)
// Show or hide the search results in this window by resizing the window vertically.
// If the results are being hidden, the last window vertical extension is stored in
// mResultsVertWindExtension, otherwise mResultsVertWindExtension is used for determining
// the amount to resize the window.
//
// If search results are hidden, all current results are deleted from the result table.
//-----------------------------------
{
if ( IsResultsTableVisible() )
return;
Rect curBounds;
CSaveWindowStatus::GetPaneGlobalBounds(this, &curBounds);
Rect newBounds = curBounds;
if ( inDoShow )
{
if ( mResultsVertWindExtension < 0 ) mResultsVertWindExtension = -mResultsVertWindExtension; // Undo initialization
newBounds.bottom += mResultsVertWindExtension;
mResultsEnclosure->Show();
if ( (newBounds.bottom - newBounds.top) < mMinVResultsSize )
{
newBounds.bottom = newBounds.top + mMinVResultsSize;
}
}
else
{
Rect bounds2;
CSaveWindowStatus::GetPaneGlobalBounds(USearchHelper::FindViewSubpane(this, CSearchManager::paneID_ParamEncl),
&bounds2);
Int16 newBottom = (bounds2.left - newBounds.left) + bounds2.bottom;
if ( mResultsVertWindExtension >= 0 ) mResultsVertWindExtension = newBounds.bottom - newBottom;
newBounds.bottom = newBottom;
mResultsEnclosure->Hide();
}
mResultsTableVisible = inDoShow;
mMinMaxSize.bottom = max_Int16; // Set so that VerifyWindowBounds() can do its work correctly!
mMinMaxSize.top = 100; // Set so that VerifyWindowBounds() can do its work correctly!
CSaveWindowStatus::VerifyWindowBounds(this, &newBounds);
if ( !::EqualRect(&newBounds, &curBounds) )
{
this->DoSetBounds(newBounds);
}
RecalcMinMaxStdSizes();
}
//-----------------------------------
void CSearchWindowBase::UpdateResultsVertWindExtension()
// Update the vertical window extension variable.
//-----------------------------------
{
if ( IsResultsTableVisible() && (mResultsVertWindExtension >= 0) )
{
Rect windBounds, enclBounds;
CSaveWindowStatus::GetPaneGlobalBounds(this, &windBounds);
CSaveWindowStatus::GetPaneGlobalBounds(USearchHelper::FindViewSubpane(
this, CSearchManager::paneID_ParamEncl), &enclBounds);
Int16 enclBottom = (enclBounds.left - windBounds.left) + enclBounds.bottom;
mResultsVertWindExtension = windBounds.bottom - enclBottom;
}
}
//-----------------------------------
void CSearchWindowBase::ReadWindowStatus(LStream *inStatusData)
//-----------------------------------
{
if ( inStatusData != nil )
{
Rect bounds;
*inStatusData >> bounds;
CSaveWindowStatus::MoveWindowTo(this, topLeft(bounds));
Int16 resultsVertWindExtension;
*inStatusData >> resultsVertWindExtension;
if ( resultsVertWindExtension > 0 )
{
mResultsVertWindExtension = -resultsVertWindExtension; // See the ShowHideSearchResults(), set to negative
// to mean initialization
}
}
else
{
CSaveWindowStatus::MoveWindowToAlertPosition(this);
}
mSearchManager.ReadSavedSearchStatus(inStatusData);
if( inStatusData )
mResultsTable->GetTableHeader()->ReadColumnState(inStatusData);
}
//-----------------------------------
void CSearchWindowBase::WriteWindowStatus(LStream *outStatusData)
//-----------------------------------
{
CSaveWindowStatus::WriteWindowStatus(outStatusData);
UpdateResultsVertWindExtension();
*outStatusData << ((Int16) ((mResultsVertWindExtension > 0) ? mResultsVertWindExtension :
(-mResultsVertWindExtension)));
mSearchManager.WriteSavedSearchStatus(outStatusData);
mResultsTable->GetTableHeader()->WriteColumnState(outStatusData);
}
//-----------------------------------
void CSearchWindowBase::UpdateTableStatusDisplay()
//-----------------------------------
{
if ( !IsResultsTableVisible() ) return;
AssertFail_(mResultsTable != nil);
TableIndexT numItems, numSelectedItems;
mResultsTable->GetTableSize(numItems, numSelectedItems);
numSelectedItems = mResultsTable->GetSelectedRowCount();
CStr255 messageString;
if ( numItems > 0 )
{
CStr31 numString, selectedString;
::NumToString(numItems, numString);
if ( numSelectedItems > 0 )
{
::NumToString(numSelectedItems, selectedString);
USearchHelper::AssignUString(
(numItems == 1) ?
USearchHelper::USearchHelper::uStr_OneMessageFoundSelected :
USearchHelper::uStr_MultipleMessagesSelected,
messageString);
}
else
USearchHelper::AssignUString((numItems == 1) ? USearchHelper::uStr_OneMessageFound : USearchHelper::uStr_MultipleMessagesFound,
messageString);
::StringParamText(messageString, numString, selectedString);
}
else
USearchHelper::AssignUString(USearchHelper::uStr_NoMessagesFound, messageString);
mProgressBar->SetDescriptor(messageString);
}
//-----------------------------------
Boolean CSearchWindowBase::GetDefaultSearchTable(
CMailNewsWindow*& outMailNewsWindow,
CMailFlexTable*& outMailFlexTable)
// Using the current PP window hierarchy, determine if the current top regular window is
// a window that we can use to associate with our search window. This method is
// called just before the search window is brought to the front of the regular window
// hierarchy. If the method returns false, no window was found that could be associated
// with our search window and the output parameters are set to nil. If the method returns
// true, a window was found that has an active flex table, and both objects are returned
// in the output parameters.
//-----------------------------------
{
outMailNewsWindow = nil;
outMailFlexTable = nil;
// Get the current top regular window of the type we need
CMediatedWindow *theFoundWindow = nil;
CWindowIterator theIterator(WindowType_Any);
do
{
if (theIterator.Next(theFoundWindow))
{
DataIDT windowType = theFoundWindow->GetWindowType();
switch (windowType)
{
case WindowType_SearchMailNews:
continue; // Found ourselves.
case WindowType_MailNews:
outMailNewsWindow = dynamic_cast<CMailNewsFolderWindow *>(theFoundWindow);
break;
case WindowType_MailThread:
case WindowType_Newsgroup:
outMailNewsWindow = dynamic_cast<CThreadWindow *>(theFoundWindow);
break;
case WindowType_Message:
outMailNewsWindow = dynamic_cast<CMessageWindow *>(theFoundWindow);
break;
}
if (outMailNewsWindow)
break; // Found a MailNews window that can return a "search table"
}
else
theFoundWindow = nil;
}
while (theFoundWindow != nil);
if (outMailNewsWindow)
{
// Is there an active target table?
outMailFlexTable = outMailNewsWindow->GetSearchTable();
if (outMailFlexTable == nil)
outMailNewsWindow = nil;
}
return (outMailFlexTable != nil);
}
//-----------------------------------
void CSearchWindowBase::MessageWindStop(Boolean inUserAborted)
//-----------------------------------
{
if ( mSearchManager.IsSearching() )
{
mSearchManager.StopSearch(inUserAborted ? ((MWContext *) *mMailNewsContext) : nil);
mSearchButton->Show();
USearchHelper::FindViewSubpane(this, paneID_Stop)->Hide();
USearchHelper::FindViewSubpane(this, paneID_ScopeEnclosure)->Enable();
// This call fixes a bug in the BE search row insertion
mResultsTable->ForceCurrentSort();
}
}
/*======================================================================================
Return a display name for the specified folder name.
======================================================================================*/
CStr255& CSearchWindowBase::GetFolderDisplayName(const char *inFolderName, CStr255& outFolderName)
{
outFolderName = inFolderName;
char* temp = (char*)outFolderName;
NET_UnEscape(temp);
outFolderName = temp;
return outFolderName;
}
/*======================================================================================
Get the display text for the specified attribute and table row index. Return
kNumAttributes if the inCellDataType is invalid.
======================================================================================*/
MSG_SearchAttribute CSearchWindowBase::AttributeFromDataType(PaneIDT inCellDataType)
{
MSG_SearchAttribute rtnVal;
switch ( inCellDataType )
{
// Message search columns
case kSubjectMessageColumn: rtnVal = attribSubject; break;
case kSenderMessageColumn: rtnVal = attribSender; break;
case kDateMessageColumn: rtnVal = attribDate; break;
case kStatusMessageLocation: rtnVal = attribLocation; break;
case kPriorityMessageColumn: rtnVal = attribPriority; break;
case kStatusMessageColumn: rtnVal = attribMsgStatus; break;
default: rtnVal = kNumAttributes; break;
}
return rtnVal;
}
/*======================================================================================
Return a sort data type from the specified sort command. Return 0L if the
inSortCommand is invalid.
======================================================================================*/
PaneIDT CSearchWindowBase::DataTypeFromSortCommand(CommandT inSortCommand)
{
PaneIDT rtnVal;
switch ( inSortCommand )
{
case cmd_SortBySubject: rtnVal = kSubjectMessageColumn; break;
case cmd_SortBySender: rtnVal = kSenderMessageColumn; break;
case cmd_SortByDate: rtnVal = kDateMessageColumn; break;
case cmd_SortByLocation: rtnVal = kStatusMessageLocation; break;
case cmd_SortByPriority: rtnVal = kPriorityMessageColumn; break;
case cmd_SortByStatus: rtnVal = kStatusMessageColumn; break;
// Do we need these commands for column sorting in the LDAP search result pane?
default: rtnVal = cmd_Nothing; break;
}
return rtnVal;
}
//-----------------------------------
void CSearchWindowBase::AddOneScopeMenuItem(
Int16 inStringIndex,
Int16 inAttrib
)
//-----------------------------------
{
CStr255 string;
USearchHelper::AssignUString(inStringIndex, string);
AddOneScopeMenuItem(string, inAttrib);
}
//-----------------------------------
void CSearchWindowBase::AddOneScopeMenuItem(
const CStr255& inString,
Int16 inAttrib
)
//-----------------------------------
{
Assert_(mNumBasicScopeMenuItems < MAX_SEARCH_MENU_ITEMS);
if (mNumBasicScopeMenuItems < MAX_SEARCH_MENU_ITEMS)
{
MSG_SearchMenuItem& curItem = mSearchMenuItems[mNumBasicScopeMenuItems];
LString::CopyPStr(inString, (UInt8*)curItem.name, sizeof(curItem.name));
curItem.attrib = inAttrib;
curItem.isEnabled = true;
++mNumBasicScopeMenuItems;
}
}
//-----------------------------------
void CSearchWindowBase::SetWinCSID(Int16 wincsid)
//-----------------------------------
{
if(mMailNewsContext)
mMailNewsContext->SetWinCSID(wincsid);
if(mResultsTable)
mResultsTable->SetWinCSID(wincsid);
mSearchManager.SetWinCSID(wincsid);
}

View File

@ -0,0 +1,147 @@
/* -*- 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.
*/
// CSearchWindowBase.h
#pragma once
#include "CMailNewsWindow.h"
#include "LPeriodical.h"
#include "LListener.h"
#include "msg_srch.h"
#include "PascalString.h"
#include "CSearchManager.h"
#include "MailNewsgroupWindow_Defines.h"
class LGAPushButton;
class CPatternProgressCaption;
class CSearchTableView;
const long MAX_SEARCH_MENU_ITEMS = 16;
//======================================
class CSearchWindowBase : public CMailNewsWindow,
public LPeriodical,
public LListener
//======================================
{
typedef CMailNewsWindow Inherited;
public:
// IDs for panes in associated view, also messages that are broadcast to this object
enum
{
paneID_Search = 'SRCH' // MSG_Pane *, search button
, paneID_Stop = 'STOP' // nil, stop button
, paneID_ResultsEnclosure = 'RENC' // Results enclosure
, paneID_ScopeEnclosure = 'SENC' // Scope enclosure
, paneID_ResultsTable = 'Tabl' // Results table
, paneID_ProgressBar = kMailNewsStatusPaneID // Progress bar
, paneID_SearchOptions = 'SOPT' // Search options dialog
};
// Stream version number
// This must be changed every time you change the streamed parameters
enum { eValidStreamVersion = 0x000b };
CSearchWindowBase(LStream *inStream, DataIDT inWindowType);
virtual ~CSearchWindowBase();
virtual void SetUpBeforeSelecting() = 0;
static MSG_SearchAttribute AttributeFromDataType(PaneIDT inCellDataType);
static PaneIDT DataTypeFromSortCommand(CommandT inSortCommand);
protected:
// Overriden methods
virtual MSG_ScopeAttribute GetWindowScope() const = 0;
virtual void FinishCreateSelf();
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam = nil);
virtual void FindCommandStatus(CommandT inCommand, Boolean &outEnabled,
Boolean &outUsesMark, Char16 &outMark,
Str255 outName);
virtual void ListenToMessage(MessageT inMessage, void *ioParam = nil);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
virtual void SpendTime(const EventRecord &inMacEvent);
virtual void DrawSelf();
virtual void SetDescriptor(ConstStr255Param inDescriptor);
virtual void Activate();
virtual void DeactivateSelf();
virtual void AboutToClose();
virtual void SearchOptions() ;
// Utility methods
void RecalcMinMaxStdSizes();
void ShowHideSearchResults(Boolean inDoShow);
void UpdateResultsVertWindExtension();
Boolean IsResultsTableVisible()
{
return mResultsTableVisible;
}
Boolean GetDefaultSearchTable( CMailNewsWindow*& outWindow, CMailFlexTable*& outMailFlexTable);
CStr255& GetFolderDisplayName(const char *inFolderName, CStr255& outFolderName);
void MessageSearchParamsResized(Int16 inResizeAmount);
virtual void MessageWindSearch();
virtual void MessageWindStop(Boolean inUserAborted);
void AddOneScopeMenuItem(
Int16 inStringIndex,
Int16 inAttrib);
void AddOneScopeMenuItem(
const CStr255& inString,
Int16 inAttrib);
virtual void ReadWindowStatus(LStream *inStatusData);
virtual void WriteWindowStatus(LStream *outStatusData);
virtual void UpdateTableStatusDisplay();
virtual void SetWinCSID(Int16 wincsid);
virtual UInt16 GetValidStatusVersion() const;
// Instance variables
Int16 mMinVResultsSize;
Int16 mResultsVertWindExtension;
Boolean mResultsTableVisible;
LPane *mResultsEnclosure;
CSearchTableView *mResultsTable;
LGAPushButton *mSearchButton;
Boolean mCanRotateTarget;
CSearchManager mSearchManager;
LArray mSearchFolders;
CPatternProgressCaption *mProgressBar;
Int16 mNumBasicScopeMenuItems;
Int16 mNumMenuItems;
MSG_SearchMenuItem mSearchMenuItems[MAX_SEARCH_MENU_ITEMS];
private:
LGAPushButton *mSearchOptionsButton;
}; // class CSearchWindowBase

View File

@ -0,0 +1,145 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSecurityButton.cp
#include "CSecurityButton.h"
/* #include "CMailComposeWindow.h" */
/* #include "msgcom.h" */
#include "CComposeSession.h"
/* #include "CBrowserContext.h" */
#include "CButton.h"
#include "LGAIconSuiteControl.h"
#include "CMessageView.h"
#include "ssl.h"
void USecurityIconHelpers::UpdateMailWindow( CMessageView *messageView )
{
if ( messageView )
{
CMailNewsWindow* window = dynamic_cast<CMailNewsWindow*>(LWindow::FetchWindowObject(
messageView->GetMacPort()));
if ( !window )
return;
MWContext* context = NULL;
context = (MWContext*)*messageView->GetContext();
uint32 folderFlags = messageView->GetFolderFlags();
XP_Bool isEncrypted = 0;
XP_Bool isSigned = 0;
MIME_GetMessageCryptoState( context , 0 ,0, &isSigned, &isEncrypted );
Boolean isNewsGroup = ((folderFlags & MSG_FOLDER_FLAG_NEWSGROUP)!=0) ;
if ( isNewsGroup )
{
// news message encryption depends if the News group is secure
int secLevel = XP_GetSecurityStatus( context );
isEncrypted = (secLevel != SSL_SECURITY_STATUS_OFF);
}
if ( isSigned >1 || isSigned<0)
isSigned = 0;
if ( isEncrypted>1 || isEncrypted<0 )
isEncrypted = 0;
USecurityIconHelpers::ChangeToSecurityState( window, isEncrypted, isSigned );
}
}
void USecurityIconHelpers::UpdateComposeButton( CMailComposeWindow *window )
{
Assert_( window !=NULL );
CComposeSession * session = window->GetComposeSession();
XP_Bool isEncrypted = 0;
XP_Bool isSigned = 0;
isEncrypted = session->GetCompBoolHeader( MSG_ENCRYPTED_BOOL_HEADER_MASK );
isSigned = session->GetCompBoolHeader( MSG_SIGNED_BOOL_HEADER_MASK );
USecurityIconHelpers::ChangeToSecurityState( window, isEncrypted, isSigned );
}
void USecurityIconHelpers::SetNoMessageLoadedSecurityState( LWindow * window )
{
Assert_( window != NULL );
USecurityIconHelpers::ChangeToSecurityState( window, false, false );
}
void USecurityIconHelpers::AddListenerToSmallButton(LWindow* inWindow, LListener* inListener)
{
LGAIconSuiteControl* button = dynamic_cast<LGAIconSuiteControl*>(inWindow->FindPaneByID( eSmallEncryptedButton ));
if (button)
button->AddListener(inListener);
button = dynamic_cast<LGAIconSuiteControl*>(inWindow->FindPaneByID( eSmallSignedButton ));
if (button)
button->AddListener(inListener);
}
void USecurityIconHelpers::ChangeToSecurityState(
LWindow* inWindow,
Boolean inEncrypted,
Boolean inSigned )
{
if (!inWindow)
return;
CButton* button = dynamic_cast<CButton*>(inWindow->FindPaneByID( eBigSecurityButton ));
if (button)
{
static const ResIDT bigSecurityIcons[4]={ 15439, 15435, 15447, 15443 };
ResIDT newIconID = bigSecurityIcons[ inSigned + 2*inEncrypted ];
if (button->GetGraphicID() != newIconID )
{
button->SetGraphicID( newIconID);
button->Refresh();
}
}
LGAIconSuiteControl* smallButton
= dynamic_cast<LGAIconSuiteControl*>(inWindow->FindPaneByID( eSmallEncryptedButton ));
if (smallButton)
{
ResIDT newIconID = inEncrypted ? 15336 : 15335;
if (smallButton->GetIconResourceID() != newIconID )
{
smallButton->SetIconResourceID( newIconID);
smallButton->Refresh();
}
}
smallButton
= dynamic_cast<LGAIconSuiteControl*>(inWindow->FindPaneByID( eSmallSignedButton ));
if (smallButton)
{
if (inSigned)
smallButton->Show();
else
smallButton->Hide();
}
}
void CMailSecurityListener::ListenToMessage(MessageT inMessage, void* ioParam)
{
#pragma unused (ioParam)
switch( inMessage )
{
case msg_NSCAllConnectionsComplete:
USecurityIconHelpers::UpdateMailWindow( mMessageView);
break;
default:
break;
}
}

View File

@ -0,0 +1,59 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSecurityButton.h
#pragma once
#include <LListener.h>
class CMailComposeWindow;
class CMailNewsWindow;
class CMessageView;
class LWindow;
// Modifies the Security button to reflect wether the message is
// signed/encrypted
class CMailSecurityListener : public LListener
{
public:
CMailSecurityListener() : mMessageView(NULL) {};
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
void SetMessageView( CMessageView* view) { mMessageView = view;}
private:
CMessageView *mMessageView;
};
class USecurityIconHelpers
{
public:
enum State { eNone, eSigned, eEncrypted, eSignedEncrypted};
enum { eBigSecurityButton = 'Bsec',
eSmallEncryptedButton = 'SBsc',
eSmallSignedButton = 'SBsg' };
// Large security buttons must be 'Bsec'
// Small security buttons must be 'SBsc' (encryption) or 'SBsg' (signed)
static void UpdateComposeButton( CMailComposeWindow *window );
static void UpdateMailWindow( CMessageView *messageView);
static void SetNoMessageLoadedSecurityState( LWindow * window );
static void AddListenerToSmallButton(LWindow* inWindow, LListener* inListener);
private:
static void ChangeToSecurityState(
LWindow* window,
Boolean inEncrypted,
Boolean inSigned );
};

View File

@ -0,0 +1,565 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSimpleFolderView.cp
/*
This class allows to get a list of containers:
- Mail servers & folders
- News servers & groups
It was originally developed as part of CMessageFolderView
which implements the Message Center. Having a separate class
allows to implement folder lists in other places (Offline Picker).
It inherits from CMailFlexTable and CStandardFlexTable.
It handles the selection and clicks on the twistee icons but
it doesn't handle any command, except for the Stop button.
Mail and News folders are obtained from the Back-End by creating
a Folder Pane.
History:
¥ In version 1.1 of this file, there was a mechanism to save/restore
the selection in case of MSG_NotifyScramble or MSG_NotifyAll (like
in CThreadView). This mechanism was removed because the folder view
does not support sort commands.
*/
#include "CSimpleFolderView.h"
// Netscape Mac Libs
#include "resgui.h"
// Mail/News Specific
#include "CMailNewsWindow.h"
#include "MailNewsgroupWindow_Defines.h"
#include "CProgressListener.h"
#include "CMessageFolder.h"
#include "CMailNewsContext.h"
#include "UMailFolderMenus.h"
#define cmd_ExpandCellKludge 'Expd' // fake command number used in a
// kludge to avoid multiple redraws
//------------------------------------------------------------------------------
// ¥ CSimpleFolderView
//------------------------------------------------------------------------------
//
CSimpleFolderView::CSimpleFolderView(LStream *inStream)
: Inherited(inStream)
, mUpdateMailFolderMenusWhenComplete(false)
, mUpdateMailFolderMenusOnNextUpdate(false)
, mSelectHilitesWholeRow(false)
{
}
//------------------------------------------------------------------------------
// ¥ ~CSimpleFolderView
//------------------------------------------------------------------------------
//
CSimpleFolderView::~CSimpleFolderView()
{
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ LoadFolderList
//------------------------------------------------------------------------------
// Given a context, starts getting the list. Typically called in the
// FinishCreateSelf() of the parent window which is the one which creates the context.
//
void CSimpleFolderView::LoadFolderList(CNSContext* inContext)
{
Assert_(inContext != NULL);
mContext = inContext;
if (GetMessagePane() == NULL)
{
SetMessagePane(MSG_CreateFolderPane(*inContext, CMailNewsContext::GetMailMaster()));
ThrowIfNULL_(GetMessagePane());
MSG_SetFEData(GetMessagePane(), CMailCallbackManager::Get());
}
NotifySelfAll(); // notify ourselves that everything has changed
}
//------------------------------------------------------------------------------
// ¥ GetSelectedFolder
//------------------------------------------------------------------------------
// Public utility: return the ID of the selected folder.
//
MSG_FolderInfo* CSimpleFolderView::GetSelectedFolder() const
{
TableIndexT row = 0;
if (GetMessagePane() && GetNextSelectedRow(row))
return MSG_GetFolderInfo(GetMessagePane(), row - 1);
return NULL;
}
//------------------------------------------------------------------------------
// ¥ SelectFirstFolderWithFlags
//------------------------------------------------------------------------------
// Public utility: used to select the Inbox on "Window | Message Center"
// or the first news server on "Prefs | Launch Collabra Discussions".
//
void CSimpleFolderView::SelectFirstFolderWithFlags(uint32 inFlags)
{
MSG_FolderInfo* folderInfo;
::MSG_GetFoldersWithFlag(CMailNewsContext::GetMailMaster(), inFlags, &folderInfo, 1);
SelectFolder(folderInfo);
}
//------------------------------------------------------------------------------
// ¥ SelectFolder
//------------------------------------------------------------------------------
// Public utility: can be used to select the parent folder of a Thread window.
//
void CSimpleFolderView::SelectFolder(const MSG_FolderInfo* inFolderInfo)
{
if (inFolderInfo)
{
MSG_ViewIndex index = ::MSG_GetFolderIndexForInfo(
GetMessagePane(), (MSG_FolderInfo*)inFolderInfo, true);
ArrayIndexT lineNumber = 1 + index;
STableCell cellToSelect(lineNumber, 1);
SetNotifyOnSelectionChange(false);
UnselectAllCells();
SetNotifyOnSelectionChange(true);
ScrollCellIntoFrame(cellToSelect); // show folder before selecting it
SelectCell(cellToSelect);
}
else
UnselectAllCells();
}
//------------------------------------------------------------------------------
// ¥ DeleteSelection
//------------------------------------------------------------------------------
// Required by CStandardFlexTable. We don't want to implement that here:
// the Message Center will certainly stay the only place where a folder can be
// deleted. If this were to change, move the code from CMessageFolderView back
// to here along with the 'mWatchedFolder' hack.
//
void CSimpleFolderView::DeleteSelection()
{
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ GetIconID
//------------------------------------------------------------------------------
// From CStandardFlexTable. Return the folder icon for that row.
//
ResIDT CSimpleFolderView::GetIconID(TableIndexT inRow) const
{
CMessageFolder folder(inRow, GetMessagePane());
return folder.GetIconID();
}
//------------------------------------------------------------------------------
// ¥ GetNestedLevel
//------------------------------------------------------------------------------
// From CStandardFlexTable. Return the ident for that row.
// This method goes together with GetHiliteTextRect().
//
UInt16 CSimpleFolderView::GetNestedLevel(TableIndexT inRow) const
{
CMessageFolder folder(inRow, GetMessagePane());
return folder.GetLevel() - 1;
}
//------------------------------------------------------------------------------
// ¥ GetHiliteColumn
//------------------------------------------------------------------------------
// From CStandardFlexTable. When a row is selected, we can hilite the
// whole row (default behavior of the base class) or just the folder name.
// This method goes together with GetHiliteTextRect().
//
TableIndexT CSimpleFolderView::GetHiliteColumn() const
{
if (mSelectHilitesWholeRow)
return Inherited::GetHiliteColumn();
return mTableHeader->ColumnFromID(kFolderNameColumn);
}
//------------------------------------------------------------------------------
// ¥ GetHiliteTextRect
//------------------------------------------------------------------------------
// From CStandardFlexTable. Pass back the rect to hilite for that row (either
// the whole row, either just the folder name). Return true if rect is not empty.
// This method goes together with GetHiliteColumn() and GetNestedLevel().
//
Boolean CSimpleFolderView::GetHiliteTextRect(
const TableIndexT inRow,
Rect& outRect) const
{
if (mSelectHilitesWholeRow)
return Inherited::GetHiliteTextRect(inRow, outRect);
STableCell cell(inRow, GetHiliteColumn());
if (!GetLocalCellRect(cell, outRect))
return false;
Rect iconRect;
GetIconRect(cell, outRect, iconRect);
outRect.left = iconRect.right;
char folderName[cMaxMailFolderNameLength + 1];
GetHiliteText(inRow, folderName, sizeof(folderName), &outRect);
return true;
}
//------------------------------------------------------------------------------
// ¥ ApplyTextStyle
//------------------------------------------------------------------------------
// From CStandardFlexTable. Set the text style for that row.
//
void CSimpleFolderView::ApplyTextStyle(TableIndexT inRow) const
{
CMessageFolder folder(inRow, GetMessagePane());
// According to the latest UI spec (4/16/98), bold is used for folders with unread messages
int32 textStyle = normal;
if( folder.IsOpen() )
{
if ( folder.CountUnseen()> 0 )
textStyle = bold;
}
else
{
// if the folder is closed we want to bold the folder if any subfolder has unread messages
if ( folder.CountDeepUnseen()> 0 )
textStyle = bold;
}
::TextFace( textStyle );
}
//------------------------------------------------------------------------------
// ¥ DrawCellContents
//------------------------------------------------------------------------------
// From CStandardFlexTable. Pass a cell and a rect: it draws it.
// It knows how to draw the name column (with a twistee if necessary +
// the icon corresponding to the item) and the 'Unread' and 'Total'
// columns. If you have additional columns, overide this method.
//
void CSimpleFolderView::DrawCellContents(
const STableCell& inCell,
const Rect& inLocalRect)
{
PaneIDT cellType = GetCellDataType(inCell);
switch (cellType)
{
case kFolderNameColumn:
{
// Draw icons (item icon + twistee)
SInt16 iconRight = DrawIcons(inCell, inLocalRect);
if (mRowBeingEdited != inCell.row || !mNameEditor)
{
// Draw folder name
Rect textRect = inLocalRect;
textRect.left = iconRight;
char folderName[cMaxMailFolderNameLength + 1];
if (GetHiliteText(inCell.row, folderName, sizeof(folderName), &textRect))
{
DrawTextString(folderName, &mTextFontInfo, 0, textRect);
if (inCell.row == mDropRow)
::InvertRect(&textRect);
}
}
break;
}
case kFolderNumUnreadColumn:
{
CMessageFolder folder(inCell.row, GetMessagePane());
if (folder.CanContainThreads())
if (folder.CountMessages() != 0)
DrawCountCell(folder.CountUnseen(), inLocalRect);
break;
}
case kFolderNumTotalColumn:
{
CMessageFolder folder(inCell.row, GetMessagePane());
if (folder.CanContainThreads())
if (folder.CountMessages() != 0)
DrawCountCell(folder.CountMessages(), inLocalRect);
break;
}
}
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ CellHasDropFlag
//------------------------------------------------------------------------------
// Check if a cell has a twistee icon and if the twistee is open.
//
Boolean CSimpleFolderView::CellHasDropFlag(
const STableCell& inCell,
Boolean& outIsExpanded) const
{
CMessageFolder folder(inCell.row, GetMessagePane());
if (GetCellDataType(inCell) == kFolderNameColumn && folder.CountSubFolders() != 0)
{
outIsExpanded = folder.IsOpen();
return true;
}
return false;
}
//------------------------------------------------------------------------------
// ¥ SetCellExpansion
//------------------------------------------------------------------------------
// Open or close the twistee icon of a folder.
//
void CSimpleFolderView::SetCellExpansion(
const STableCell& inCell,
Boolean inExpand)
{
// check current state
CMessageFolder folder(inCell.row, GetMessagePane());
if (inExpand == folder.IsOpen())
return;
// kludge: slow down the status bar refresh rate
// to reduce flickers and improve performance
if (inExpand)
{
if (folder.IsNewsHost() || folder.IsIMAPMailFolder())
{
CMailNewsWindow * myWindow = dynamic_cast<CMailNewsWindow*>
(LWindow::FetchWindowObject(GetMacPort()));
if (myWindow)
myWindow->GetProgressListener()->SetLaziness(
CProgressListener::lazy_VeryButForThisCommandOnly);
}
}
// kludge to avoid multiple redraws (see ChangeFinished())
mContext->SetCurrentCommand(cmd_ExpandCellKludge);
// toggle twistee
ToggleExpandAction(inCell.row);
folder.FolderInfoChanged();
}
//------------------------------------------------------------------------------
// ¥ GetMainRowText
//------------------------------------------------------------------------------
// From CStandardFlexTable. Return the folder name for that row.
// Implemented here because the folder name is likely to stay
// the main text of the row for the users of the class.
//
void CSimpleFolderView::GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const
{
if (!outText || inMaxBufferLength == 0)
return;
if (inMaxBufferLength < cMaxMailFolderNameLength + 1)
{
*outText = '\0';
return;
}
CMessageFolder folder(inRow, GetMessagePane());
CMailFolderMixin::GetFolderNameForDisplay(outText, folder);
NET_UnEscape(outText);
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ FindCommandStatus
//------------------------------------------------------------------------------
// Enable Stop button when list is loading.
//
void CSimpleFolderView::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
{
if (mStillLoading)
{
if (inCommand == cmd_Stop)
{
outEnabled = true;
return;
}
}
else
{
Inherited::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
}
}
//------------------------------------------------------------------------------
// ¥ ListenToMessage
//------------------------------------------------------------------------------
// When list is complete, update folder menus across the app.
//
void CSimpleFolderView::ListenToMessage(MessageT inMessage, void* ioParam)
{
Inherited::ListenToMessage(inMessage, ioParam);
if (inMessage == msg_NSCAllConnectionsComplete)
{
if (mUpdateMailFolderMenusWhenComplete)
{
mUpdateMailFolderMenusWhenComplete = false;
CMailFolderMixin::UpdateMailFolderMixins();
}
mContext->SetCurrentCommand(cmd_Nothing);
}
}
#pragma mark -
//------------------------------------------------------------------------------
// ¥ ChangeFinished
//------------------------------------------------------------------------------
// A list of hacks to update our list + the folder menus across the app.
// Also restores the selection after a 'sort' command (see ChangeStarting()).
//
void CSimpleFolderView::ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount)
{
//--------
// When opening a News host by toggling the twistee in the Message Center,
// we get one notification for each subscribed newsgroup and it generates
// a lot of flicker.
//
// The following is a kludge which just ignores the notifications because
// a News host info never changes anyway. However we're not guaranteed
// that it will always be the case in the future. A bug report (#79163)
// has been opened asking the Back-End folks to fix the problem and
// reassign the bug to a Mac engineer in order to remove that kludge.
//
if (inChangeCode == MSG_NotifyChanged)
{
if (inRowCount == 1)
{
CMessageFolder folder(inStartRow, GetMessagePane());
folder.FolderInfoChanged();
UInt32 folderFlags = folder.GetFolderFlags();
if (((folderFlags & MSG_FOLDER_FLAG_NEWS_HOST) != 0) &&
((folderFlags & MSG_FOLDER_FLAG_DIRECTORY) != 0))
inChangeCode = MSG_NotifyNone;
}
}
//
//--------
Inherited::ChangeFinished(inPane, inChangeCode, inStartRow, inRowCount);
if (mMysticPlane < kMysticUpdateThreshHold)
{
switch (inChangeCode)
{
case MSG_NotifyScramble:
case MSG_NotifyAll:
UnselectAllCells();
CMailFolderMixin::UpdateMailFolderMixins(); // This should really be somewhere else!
break;
case MSG_NotifyInsertOrDelete:
CMailFolderMixin::UpdateMailFolderMixins();
// When rows are inserted or deleted because the user has moved a folder hierarchy,
// then we have to invalidate the cache for the inserted rows, because
// the folder levels have possibly changed. This also applies to cmd_Clear,
// which (unless the option key is down) is a move in disguise. When expanding
// folders, we need to do this too, just to cover the case when a folder was
// moved into another folder and is now being displayed for the first time.
CommandT currentCommand = mContext->GetCurrentCommand();
if ((currentCommand == cmd_MoveMailMessages
|| currentCommand == cmd_Clear
|| currentCommand == cmd_ExpandCellKludge)
&& inRowCount > 0)
FoldersChanged(inStartRow, inRowCount);
break;
case MSG_NotifyChanged:
if (mContext->GetCurrentCommand() == cmd_ExpandCellKludge)
mUpdateMailFolderMenusWhenComplete = true;
else
if (mUpdateMailFolderMenusOnNextUpdate)
{
mUpdateMailFolderMenusOnNextUpdate = false;
CMailFolderMixin::UpdateMailFolderMixins();
}
else
{
FoldersChanged(inStartRow, inRowCount);
}
break;
}
}
}
//------------------------------------------------------------------------------
// ¥ FoldersChanged
//------------------------------------------------------------------------------
// Mark a range of folders as 'changed': invalidate the cached line for each.
//
void CSimpleFolderView::FoldersChanged(
TableIndexT inStartRow,
SInt32 inRowCount) const
{
if (inRowCount < 0)
inRowCount = -inRowCount;
for (SInt32 i = 0; i < inRowCount; i ++)
{
CMessageFolder folder(inStartRow + i, GetMessagePane());
folder.FolderInfoChanged();
}
}

View File

@ -0,0 +1,137 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSimpleFolderView.h
#pragma once
#include "CMailFlexTable.h"
class CThreadView;
class CThreadWindow;
class CStr255;
class CMessageFolder;
//------------------------------------------------------------------------------
// ¥ CSimpleFolderView
//------------------------------------------------------------------------------
//
class CSimpleFolderView : public CMailFlexTable
{
private:
typedef CMailFlexTable Inherited;
public:
enum
{ class_ID = 'SFVw'
};
CSimpleFolderView(LStream *inStream);
virtual ~CSimpleFolderView();
protected:
//-----------------------------------
// Public folder fun
//-----------------------------------
public:
void LoadFolderList(CNSContext* inContext);
//-----------------------------------
// Command implementation
//-----------------------------------
MSG_FolderInfo* GetSelectedFolder() const;
void SelectFirstFolderWithFlags(uint32 inFlags);
void SelectFolder(const MSG_FolderInfo* inFolderInfo);
void SelectHilitesWholeRow(const Boolean inWholeRow)
{ mSelectHilitesWholeRow = inWholeRow;};
virtual void DeleteSelection();
//-----------------------------------
// Drawing (specials from CStandardFlexTable)
//-----------------------------------
protected:
virtual ResIDT GetIconID(TableIndexT inRow) const;
virtual UInt16 GetNestedLevel(TableIndexT inRow) const;
virtual TableIndexT GetHiliteColumn() const;
virtual Boolean GetHiliteTextRect(
const TableIndexT inRow,
Rect& outRect) const;
virtual void ApplyTextStyle(TableIndexT inRow) const;
virtual void DrawCellContents(
const STableCell &inCell,
const Rect &inLocalRect);
//-----------------------------------
// Hierarchy
//-----------------------------------
virtual Boolean CellHasDropFlag(const STableCell& inCell, Boolean& outIsExpanded) const;
virtual void SetCellExpansion(const STableCell& inCell, Boolean inExpand);
virtual void GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const;
//-----------------------------------
// Commands
//-----------------------------------
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
public:
//-----------------------------------
// Messaging
//-----------------------------------
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
//-----------------------------------
// Data change notification (callbacks from MSGlib)
//-----------------------------------
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
void FoldersChanged(
TableIndexT inStartRow,
SInt32 inRowCount) const;
protected:
void UpdateMailFolderMenusOnNextUpdate()
{ mUpdateMailFolderMenusOnNextUpdate = true; }
//-----------------------------------
// Data
//-----------------------------------
Boolean mSelectHilitesWholeRow; // select whole row vs. just the name
Boolean mUpdateMailFolderMenusWhenComplete;
Boolean mUpdateMailFolderMenusOnNextUpdate;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,228 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSubscribeView.h
#pragma once
// PowerPlant
#include <LTableView.h>
#include <LPeriodical.h>
// Mail/News FE
#include "CMailFlexTable.h"
#include "CProgressListener.h"
#define kRootLevel 1 // news host, local mail etc.
//----------------------------------------------------------------------------
// CNewsgroup
//
//----------------------------------------------------------------------------
class CNewsgroup
{
public:
CNewsgroup(TableIndexT inRow, MSG_Pane* inNewsgroupList);
// Cache management
void InvalidateCache() const;
void UpdateCache() const;
// misc. info accessors
MSG_GroupNameLine* GetNewsgroupLine() const;
char* GetName() const;
char* GetPrettyName() const;
Int32 CountPostings() const; // neg if unknown
UInt32 GetLevel() const;
Boolean CanContainThreads() const;
UInt32 CountChildren() const;
ResIDT GetIconID() const;
// Flag property accessors:
UInt32 GetNewsgroupFlags() const;
Boolean IsOpen() const;
Boolean HasChildren() const;
Boolean IsSubscribed() const;
Boolean IsNew() const;
// Data
public:
MSG_ViewIndex mIndex;
protected:
static MSG_GroupNameLine sNewsgroupData;
static MSG_ViewIndex sCachedIndex;
MSG_Pane* mNewsgroupList;
};
//----------------------------------------------------------------------------
// CSubscribeView
//
//----------------------------------------------------------------------------
class CSubscribeView : public CMailFlexTable,
public LPeriodical
{
private:
typedef CMailFlexTable Inherited;
public:
CSubscribeView(LStream *inStream);
enum { class_ID = 'subV' };
virtual ~CSubscribeView();
//-----------------------------------
// Public folder fun
//-----------------------------------
void SetContext(CNSContext* inContext)
{mContext = inContext;};
void RefreshList(
MSG_Host* newsHost,
MSG_SubscribeMode subscribeMode);
void SearchForString(const StringPtr searchStr);
virtual void SubscribeCancel();
virtual void SubscribeCommit();
//-----------------------------------
// Command implementation
//-----------------------------------
virtual void OpenRow(TableIndexT inRow);
virtual Boolean ProcessKeyPress(
const EventRecord& inKeyEvent);
virtual void DrawCell(
const STableCell &inCell,
const Rect &inLocalRect);
//-----------------------------------
// Hierarchy
//-----------------------------------
virtual Boolean CellHasDropFlag(
const STableCell& inCell,
Boolean& outIsExpanded) const;
virtual void SetCellExpansion(
const STableCell& inCell,
Boolean inExpand);
virtual TableIndexT GetHiliteColumn() const;
virtual UInt16 GetNestedLevel(TableIndexT inRow) const;
virtual Boolean GetHiliteTextRect(
const TableIndexT inRow,
Rect& outRect) const;
virtual void GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const;
virtual ResIDT GetIconID(TableIndexT inRow) const;
virtual void DeleteSelection(void) { /* do nothing */ };
//-----------------------------------
// Commands
//-----------------------------------
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
virtual Boolean ClickSelect(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
virtual void ClickCell(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
//-----------------------------------
// Messaging
//-----------------------------------
protected:
virtual void ListenToMessage(
MessageT inMessage,
void *ioParam);
virtual void FindSubscribeCommandStatus(
CommandT inCommand,
Boolean &outEnabled);
virtual void SpendTime(const EventRecord &);
//-----------------------------------
// Other
//-----------------------------------
virtual void CloseParentWindow();
void SetProgressBarLaziness(
CProgressListener::ProgressBarLaziness inLaziness);
Boolean CanSubscribeToNewsgroup(const CNewsgroup& newsgroup) const
{ return ((newsgroup.CountChildren() == 0) || MSG_IsIMAPHost(mNewsHost));}
//-----------------------------------
// Data change notification
// Callbacks from MSGlib come here.
//-----------------------------------
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
// ------------------------------------------------------------
// QA Partner support
// ------------------------------------------------------------
#if defined(QAP_BUILD)
public:
virtual void GetQapRowText(TableIndexT inRow, char* outText, UInt16 inMaxBufferLength) const;
#endif
//-----------------------------------
// Data
//-----------------------------------
Boolean mStillLoadingFullList;
private:
MSG_Host* mNewsHost;
MSG_SubscribeMode mSubscribeMode;
enum { kIdle, kInterrupting, kCommitting } mCommitState;
};

View File

@ -0,0 +1,871 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSubscribeWindow.cp
#include "CSubscribeWindow.h"
#include "CSubscribeView.h"
#include "CMailNewsContext.h"
#include "CNewsSubscriber.h"
#include "CProgressListener.h"
#include "CPaneEnabler.h"
#include "CTabControl.h"
#include "URobustCreateWindow.h"
#include "UMenuUtils.h"
#include "UMailFolderMenus.h"
#include <LGAPushButton.h>
#include <LGAPopup.h>
#include <UModalDialogs.h>
#include "CLargeEditField.h"
#include "macgui.h"
//#include "newshost.h"
#include "miconutils.h"
#include "MercutioAPI.h"
extern "C" {
#include "asyncCursors.h"
}
// Command Numbers
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
/*
Overview:
---------
CSubscribeWindow:
This window displays the list of newsgroups available on the
different news servers and lets you select the newsgroups you
want to subscribe to. Technically speaking, the CSubscribeWindow
handles the interactions between a CSubscribeView and a small bunch
of buttons and edit fields, plus sother elements listed below.
CSubscribeHostPopup:
Popup menu to select the news server you want to connect to.
CNewsHostIterator:
Simple iterator to access the list of news servers.
Used by the CSubscribeHostPopup.
Hints:
------
The newsgroup list (a CSubscribeView) should not be disposed when switching
panels in order to keep its state (ie. its Context) and not reload it
everytime from the cache file or from the server. The list is originally
attached to the window and when a panel is activated, a CPlaceHolderView
puts it inside the panel. The list is linked where it belongs in the commander
chain after the CTabControl broadcasts the activation of a tab panel.
We have a similar problem with the CSubscribeHostPopup: it must keep its
state when switching panels. This is done by storing the last selected
host in a static variable of the CNewsSubscriber (which has been delegated
this role because it only contains static stuff). The same static variable
is used when bringing up the CSubscribeWindow in order to display the list
corresponding to the host currently selected in the Message Center.
More info about the list in "CSubscribeView.cp".
History:
--------
November 97:
Converted BE calls to the new API in order to support IMAP public folders.
Added Mercutio callback to display imap/news server icons in the popup menu.
March 98:
Disabled "Search" and "New" panels when an IMAP host is selected. It required to
put the host popup menu in a CPlaceHolderView too in order to avoid deleting
and recreating it when a switch from a News host to an IMAP host causes
the tab panel to automatically display "All Groups" (it's bad to delete a
control when it's broadcasting).
*/
static const ResIDT resID_SubscribeTab1 = 14002; // PPob resources
static const ResIDT resID_SubscribeTab2 = 14003;
static const ResIDT resID_SubscribeTab3 = 14004;
static const ResIDT resID_SubscribeWindow = 14006;
static const PaneIDT paneID_OkButton = 'BtOk'; // generic buttons
static const PaneIDT paneID_CancelButton = 'Canc';
static const PaneIDT paneID_EditField = 'NuEd';
static const PaneIDT paneID_FolderList = 'Slst';
static const PaneIDT paneID_FolderView = 'SbVw';
static const PaneIDT paneID_TabSwitcher = 'SbTb';
static const PaneIDT paneID_TabControl = 'TabC';
static const PaneIDT paneID_SubscribeButton = 'Subs';
static const PaneIDT paneID_UnsubscribeButton = 'UnSb';
static const PaneIDT paneID_ServerPopup = 'SPop';
static const PaneIDT paneID_StopButton = 'Stop';
static const PaneIDT paneID_AllTabPanel = 'Sub1'; // tab #1 buttons
static const PaneIDT paneID_ExpandButton = 'Expn';
static const PaneIDT paneID_CollapseButton = 'Coll';
static const PaneIDT paneID_GetGroupsButton = 'GetG';
static const PaneIDT paneID_AddServerButton = 'AddS';
static const PaneIDT paneID_SearchTabPanel = 'Sub2'; // tab #2 buttons
static const PaneIDT paneID_SearchButton = 'Srch';
static const PaneIDT paneID_NewTabPanel = 'Sub3'; // tab #3 buttons
static const PaneIDT paneID_GetNewButton = 'GetN';
static const PaneIDT paneID_ClearNewButton = 'ClrN';
//----------------------------------------------------------------------------
// USubscribeUtilities
//
//----------------------------------------------------------------------------
//#define REGISTER_(letter,root) \
// RegisterClass_(letter##root::class_ID, \
// (ClassCreatorFunc)letter##root::Create##root##Stream);
#define REGISTER_(letter,root) \
RegisterClass_(letter##root);
#define REGISTERC(root) REGISTER_(C,root)
#define REGISTERL(root) REGISTER_(L,root)
void USubscribeUtilities::RegisterSubscribeClasses()
{
REGISTERC(SubscribeWindow)
REGISTERC(SubscribeHostPopup)
REGISTERC(TabContainer) // reusing CTabContainer from CMailComposeWindow.cp
}
#pragma mark -
//----------------------------------------------------------------------------
// CNewsHostIterator
//
//----------------------------------------------------------------------------
MSG_Host* CNewsHostIterator::mHostList[CNewsHostIterator::kMaxNewsHosts];
Int32 CNewsHostIterator::mHostCount = 0;
CNewsHostIterator::CNewsHostIterator(MSG_Master* master)
{
mHostCount = MSG_GetSubscribingHosts(master,
&mHostList[0],
CNewsHostIterator::kMaxNewsHosts);
mIndex = 0;
}
Boolean CNewsHostIterator::Current(MSG_Host*& outNewsHost)
{
outNewsHost = nil;
if (mIndex < mHostCount)
outNewsHost = mHostList[mIndex];
return (outNewsHost != nil);
}
Boolean CNewsHostIterator::Next(MSG_Host*& outNewsHost)
{
Boolean valid = Current(outNewsHost);
ResetTo(GetCurrentIndex() + 1);
return valid;
}
Boolean CNewsHostIterator::FindIndex(const MSG_Host* inNewsHost, Int32& outIndex)
{
Int32 index;
for (index = 0; index < mHostCount; index ++)
{
if (inNewsHost == mHostList[index])
{
outIndex = index;
return true;
}
}
outIndex = 0;
return false;
}
#pragma mark -
//----------------------------------------------------------------------------
// FindAndShow [static]
// Handle the menu command that creates/shows/selects the MailNews window.
// Currently there can only be one of these.
//----------------------------------------------------------------------------
CSubscribeWindow* CSubscribeWindow::FindAndShow(Boolean makeNew)
{
CSubscribeWindow* result = NULL;
try
{
CWindowIterator iter(WindowType_SubscribeNews);
iter.Next(result);
if (!result && makeNew)
{
result = dynamic_cast<CSubscribeWindow*>
(URobustCreateWindow::CreateWindow(
res_ID, LCommander::GetTopCommander()));
ThrowIfNULL_(result);
}
if (result)
{
result->Show();
result->Select();
}
}
catch( ... )
{
}
return result;
}
//------------------------------------------------------------------------------
// DisplayDialog [static]
//------------------------------------------------------------------------------
Boolean CSubscribeWindow::DisplayDialog()
{
StDialogHandler handler(res_ID, NULL);
MessageT message;
do
{
message = handler.DoDialog();
} while (message != paneID_OkButton && message != paneID_CancelButton);
return (message == paneID_OkButton);
}
//----------------------------------------------------------------------------
// CSubscribeWindow Constructor / Destructor
//
//----------------------------------------------------------------------------
CSubscribeWindow::CSubscribeWindow(LStream* inStream) :
CMailNewsWindow(inStream, WindowType_SubscribeNews),
mList(nil)
{
}
CSubscribeWindow::~CSubscribeWindow()
{
stopAsyncCursors();
}
//----------------------------------------------------------------------------
// FinishCreateSelf
//
//----------------------------------------------------------------------------
void CSubscribeWindow::FinishCreateSelf()
{
// Finish create context and other things
Inherited::FinishCreateSelf();
mProgressListener->SetLaziness(CProgressListener::lazy_JustABit);
mList = dynamic_cast<CSubscribeView*>(GetActiveTable());
if (mList) mList->SetContext((CMailNewsContext*)this->GetWindowContext());
// Hook up listeners
UReanimator::LinkListenerToControls(this, this, GetPaneID());
CTabControl* tabControl = dynamic_cast<CTabControl*>(FindPaneByID(paneID_TabControl));
if (tabControl) tabControl->AddListener(this);
// Initialize dialog to display first tab (hack because the CTabControl has
// already broadcasted its value message but nobody was listening at that time)
long msg = resID_SubscribeTab1;
ListenToMessage(msg_TabSwitched, &msg);
// "Search" and "New" are not supported for IMAP
if (MSG_IsIMAPHost(CNewsSubscriber::GetHost()))
{
CTabControl* tabControl = dynamic_cast<CTabControl*>(FindPaneByID(paneID_TabControl));
Assert_(tabControl);
tabControl->SetTabEnable(resID_SubscribeTab2, false);
tabControl->SetTabEnable(resID_SubscribeTab3, false);
}
}
//----------------------------------------------------------------------------
// DoClose
//
//----------------------------------------------------------------------------
void CSubscribeWindow::DoClose()
{
// Update the Mail Folder popup menu
CMailFolderMixin::UpdateMailFolderMixins();
// Update the Message Center
CMailNewsFolderWindow* messageCenter = NULL;
CWindowIterator iter(WindowType_MailNews);
iter.Next(messageCenter);
if (messageCenter)
{
messageCenter->Refresh();
}
// Close window
Inherited::DoClose();
}
//----------------------------------------------------------------------------
// GetActiveTable
//
// Get the currently active table in the window. The active table is
// the table in the window that the user considers to be receiving input.
//----------------------------------------------------------------------------
CMailFlexTable* CSubscribeWindow::GetActiveTable()
{
CMailFlexTable* list = dynamic_cast<CMailFlexTable*>
(FindPaneByID(paneID_FolderList));
Assert_(list);
return list;
}
//----------------------------------------------------------------------------
// CalcStandardBoundsForScreen
//
// Zoom in the vertical direction only.
//----------------------------------------------------------------------------
void CSubscribeWindow::CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const
{
LWindow::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
Rect contRect = UWindows::GetWindowContentRect(mMacWindowP);
outStdBounds.left = contRect.left;
outStdBounds.right = contRect.right;
}
//----------------------------------------------------------------------------
// CommandDelegatesToSubscribeList
//
//----------------------------------------------------------------------------
Boolean CSubscribeWindow::CommandDelegatesToSubscribeList(CommandT inCommand)
{
switch(inCommand)
{
case cmd_Stop:
case cmd_OpenNewsHost:
case cmd_NewsHostChanged:
case cmd_NewsToggleSubscribe:
case cmd_NewsSetSubscribe:
case cmd_NewsClearSubscribe:
case cmd_NewsExpandGroup:
case cmd_NewsExpandAll:
case cmd_NewsCollapseGroup:
case cmd_NewsCollapseAll:
case cmd_NewsGetGroups:
case cmd_NewsSearch:
case cmd_NewsGetNew:
case cmd_NewsClearNew:
return true;
}
return false;
}
//----------------------------------------------------------------------------
// FindCommandStatus
//
// Pass down commands to the list (ie. the CSubscribeView) when another
// object (ie. the edit field) is the target
//----------------------------------------------------------------------------
void CSubscribeWindow::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
{
if (mList == nil)
{
outEnabled = (inCommand == paneID_CancelButton);
}
else
{
if (CommandDelegatesToSubscribeList(inCommand))
{
mList->FindCommandStatus(inCommand, outEnabled, outUsesMark,
outMark, outName);
}
else
{
CMediatedWindow::FindCommandStatus(inCommand, outEnabled, outUsesMark,
outMark, outName);
}
}
}
//----------------------------------------------------------------------------
// ObeyCommand
//
//----------------------------------------------------------------------------
Boolean CSubscribeWindow::ObeyCommand(
CommandT inCommand,
void *ioParam)
{
#pragma unused (ioParam)
if (inCommand == cmd_Stop)
{
if (mList)
{
// Re-enable main controls in case we were committing
mList->Enable();
LButton * btn;
btn = (LButton *)FindPaneByID(paneID_CancelButton);
if (btn) btn->Enable();
btn = (LButton *)FindPaneByID(paneID_OkButton);
if (btn) btn->Enable();
}
}
return false;
}
//----------------------------------------------------------------------------
// ListenToMessage
//
//----------------------------------------------------------------------------
void CSubscribeWindow::ListenToMessage(MessageT inMessage, void* ioParam)
{
#pragma unused (ioParam)
switch (inMessage)
{
// Selecting another host
case cmd_NewsHostChanged:
if (mList)
{
mList->ObeyCommand(cmd_Stop, NULL);
MSG_Host* newsHost = (MSG_Host*)(ioParam);
MSG_SubscribeMode subscribeMode = MSG_SubscribeGetMode(mList->GetMessagePane());
CTabControl* tabControl = dynamic_cast<CTabControl*>(FindPaneByID(paneID_TabControl));
Assert_(tabControl);
if (MSG_IsIMAPHost(newsHost))
{
// "Search" and "New" are not supported for IMAP...
tabControl->SetTabEnable(resID_SubscribeTab2, false);
tabControl->SetTabEnable(resID_SubscribeTab3, false);
// ... so switch back to "All"
if (tabControl->GetValue() != 1)
tabControl->SetValue(1); // will refresh the list too
else
mList->RefreshList(newsHost, subscribeMode);
}
else
{
tabControl->SetTabEnable(resID_SubscribeTab2, true);
tabControl->SetTabEnable(resID_SubscribeTab3, true);
mList->RefreshList(newsHost, subscribeMode);
}
}
break;
// Switching tabs
case msg_TabSwitched:
long paneID = *(long*)ioParam;
switch (paneID)
{
case resID_SubscribeTab1: HandleAllGroupsTabActivate(); break;
case resID_SubscribeTab2: HandleSearchGroupsTabActivate(); break;
case resID_SubscribeTab3: HandleNewGroupsTabActivate(); break;
}
UReanimator::LinkListenerToControls(mList, this, paneID);
break;
// Search: paneID_EditField or paneID_SearchButton
case msg_EditField2:
case cmd_NewsSearch:
HandleSearchInList();
break;
// Add Server button: paneID_AddServerButton
case cmd_OpenNewsHost:
if (CNewsSubscriber::DoAddNewsHost())
{
CSubscribeHostPopup* popup = dynamic_cast<CSubscribeHostPopup*>
(FindPaneByID(paneID_ServerPopup));
Assert_(popup);
if (popup) popup->ReloadMenu();
}
break;
// OK/Cancel buttons
case paneID_CancelButton:
if (mList)
mList->SubscribeCancel();
else
DoClose();
break;
case paneID_OkButton:
if (mList)
{
mList->Disable();
LButton * btn;
btn = (LButton *)FindPaneByID(paneID_CancelButton);
if (btn) btn->Disable();
btn = (LButton *)FindPaneByID(paneID_OkButton);
if (btn) btn->Disable();
startAsyncCursors();
mList->SubscribeCommit();
}
else
DoClose();
break;
}
}
//----------------------------------------------------------------------------
// HandleKeyPress
//
// Handle Escape and Cmd-Period (copied from LDialogBox)
// Handle Enter and Return in the edit fields
//----------------------------------------------------------------------------
Boolean CSubscribeWindow::HandleKeyPress(
const EventRecord &inKeyEvent)
{
Boolean keyHandled = false;
PaneIDT keyButtonID = 0;
switch (inKeyEvent.message & charCodeMask)
{
case char_Enter:
case char_Return:
if (mList == nil)
return false;
switch (MSG_SubscribeGetMode(mList->GetMessagePane()))
{
case MSG_SubscribeAll:
mList->OpenSelection();
keyHandled = true;
break;
case MSG_SubscribeSearch:
keyButtonID = paneID_SearchButton;
break;
}
break;
case char_Escape:
if ((inKeyEvent.message & keyCodeMask) == vkey_Escape)
keyButtonID = paneID_CancelButton;
break;
default:
if (UKeyFilters::IsCmdPeriod(inKeyEvent))
keyButtonID = paneID_CancelButton;
else
keyHandled = LWindow::HandleKeyPress(inKeyEvent);
break;
}
if (keyButtonID != 0)
{
LControl* keyButton = (LControl*)FindPaneByID(keyButtonID);
keyButton->SimulateHotSpotClick(kControlButtonPart);
keyHandled = true;
}
return keyHandled;
}
//----------------------------------------------------------------------------
// HandleAllGroupsTabActivate
//
//----------------------------------------------------------------------------
void CSubscribeWindow::HandleAllGroupsTabActivate()
{
if (! mList)
return;
LControl* addServerBtn = dynamic_cast<LControl*>(FindPaneByID(paneID_AddServerButton));
if (addServerBtn) addServerBtn->AddListener(this);
CSubscribeHostPopup* popup = dynamic_cast<CSubscribeHostPopup*>(FindPaneByID(paneID_ServerPopup));
if (popup) popup->AddListener(this);
CLargeEditFieldBroadcast* groupEdit = dynamic_cast<CLargeEditFieldBroadcast*>
(FindPaneByID(paneID_EditField));
if (groupEdit)
{
groupEdit->AddListener(this);
// put the list in my LTabGroup...
mList->SetSuperCommander(groupEdit->GetSuperCommander());
// ... but make me the target
SwitchTarget(groupEdit);
LCommander::SetUpdateCommandStatus(true);
}
// refresh the list
mList->RefreshList(CNewsSubscriber::GetHost(), MSG_SubscribeAll);
}
//----------------------------------------------------------------------------
// HandleSearchGroupsTabActivate
//
//----------------------------------------------------------------------------
void CSubscribeWindow::HandleSearchGroupsTabActivate()
{
if (! mList)
return;
LControl* searchBtn = dynamic_cast<LControl*>(FindPaneByID(paneID_SearchButton));
if (searchBtn) searchBtn->AddListener(this);
CSubscribeHostPopup* popup = dynamic_cast<CSubscribeHostPopup*>(FindPaneByID(paneID_ServerPopup));
if (popup) popup->AddListener(this);
LEditField* searchEdit = dynamic_cast<LEditField*>(FindPaneByID(paneID_EditField));
if (searchEdit)
{
// put the list in my LTabGroup...
mList->SetSuperCommander(searchEdit->GetSuperCommander());
// ... but make me the target
SwitchTarget(searchEdit);
LCommander::SetUpdateCommandStatus(true);
}
LGAPushButton * defaultBtn = dynamic_cast<LGAPushButton*>(FindPaneByID(paneID_SearchButton));
if (defaultBtn) defaultBtn->SetDefaultButton(true, true);
// refresh the list
mList->RefreshList(CNewsSubscriber::GetHost(), MSG_SubscribeSearch);
}
//----------------------------------------------------------------------------
// HandleNewGroupsTabActivate
//
//----------------------------------------------------------------------------
void CSubscribeWindow::HandleNewGroupsTabActivate()
{
if (! mList)
return;
CSubscribeHostPopup* popup = dynamic_cast<CSubscribeHostPopup*>(FindPaneByID(paneID_ServerPopup));
if (popup) popup->AddListener(this);
SwitchTarget(mList);
LCommander::SetUpdateCommandStatus(true);
// refresh the list
mList->RefreshList(CNewsSubscriber::GetHost(), MSG_SubscribeNew);
}
//----------------------------------------------------------------------------
// HandleSearchInList
//
//----------------------------------------------------------------------------
void CSubscribeWindow::HandleSearchInList()
{
if ((! mList) || (! mList->GetMessagePane()))
return;
Str255 editStr;
LEditField* editField = dynamic_cast<LEditField*>(FindPaneByID(paneID_EditField));
Assert_(editField);
if (editField)
{
editField->GetDescriptor(editStr);
mList->SearchForString(editStr);
}
}
#pragma mark -
//----------------------------------------------------------------------------
// CSubscribeHostPopup
//
//----------------------------------------------------------------------------
void* CSubscribeHostPopup::sMercutioCallback = nil;
static Int16 cIMAPHostIconID = 15226;
static Int16 cNewsHostIconID = 15227;
//-----------------------------------
static pascal void SubscribeMercutioCallback(
Int16 menuID,
Int16 previousModifiers,
RichItemDataYadaYada& inItemData)
//-----------------------------------
{
#pragma unused (menuID)
#pragma unused (previousModifiers)
RichItemData& itemData = (RichItemData&)inItemData;
switch (itemData.cbMsg)
{
case cbBasicDataOnlyMsg:
itemData.flags |=
(ksameAlternateAsLastTime|kIconIsSmall|kHasIcon/*|kChangedByCallback*/|kdontDisposeIcon);
itemData.flags &= ~(kIsDynamic);
return;
case cbIconOnlyMsg:
break; // look out below!
default:
return;
}
MSG_Host * host = CNewsHostIterator::GetHostList()[itemData.itemID - 1];
Int16 iconID = 0;
if (MSG_IsNewsHost(host))
iconID = cNewsHostIconID;
else if (MSG_IsIMAPHost(host))
iconID = cIMAPHostIconID;
itemData.hIcon = CIconList::GetIconSuite(iconID);
itemData.iconType = 'suit';
}
//--------------------------------------
CSubscribeHostPopup::CSubscribeHostPopup(LStream * inStream)
: LGAPopup(inStream),
mNewsHostIterator(nil)
{
}
//-----------------------------------------
CSubscribeHostPopup::~CSubscribeHostPopup()
{
delete mNewsHostIterator;
}
//------------------------------------------
void CSubscribeHostPopup::FinishCreateSelf()
{
LGAPopup::FinishCreateSelf(); // line order...
MenuHandle menuH = GetMacMenuH(); // ...does matter
if (MDEF_IsCustomMenu(menuH))
{
if (!sMercutioCallback)
sMercutioCallback = NewMercutioCallback(SubscribeMercutioCallback);
FailNIL_(sMercutioCallback);
MDEF_SetCallbackProc(menuH, (MercutioCallbackUPP)sMercutioCallback);
// Items with 'condense' style will be drawn by the Mercutio callback
MenuPrefsRec myPrefs;
::memset(&myPrefs, 0, sizeof(myPrefs));
myPrefs.useCallbackFlag.s = condense;
MDEF_SetMenuPrefs(menuH, &myPrefs);
}
ReloadMenu();
}
//------------------------------------
void CSubscribeHostPopup::ReloadMenu()
{
// empty menu
for (Int32 index = 0; index < GetMaxValue(); index ++) {
::DeleteMenuItem(GetMacMenuH(), 1);
}
// reload menu
delete mNewsHostIterator;
mNewsHostIterator = new CNewsHostIterator(CMailNewsContext::GetMailMaster());
MSG_Host* outNewsHost;
MenuHandle menuH = GetMacMenuH();
while (mNewsHostIterator->Next(outNewsHost))
{
// Add the menu item
LStr255 pstr(MSG_GetHostUIName(outNewsHost));
Int16 itemIndex = UMenuUtils::AppendMenuItem(menuH, pstr, true);
// Ask for a callback so we can set the icon
if (MDEF_IsCustomMenu(menuH))
::SetItemStyle(menuH, itemIndex, condense);
}
// select the default host
Int32 hostIndex;
Boolean found = mNewsHostIterator->FindIndex(CNewsSubscriber::GetHost(), hostIndex);
if (! found)
{
mNewsHostIterator->ResetTo(hostIndex = 0);
MSG_Host* outNewsHost;
mNewsHostIterator->Current(outNewsHost);
CNewsSubscriber::SetHost(outNewsHost);
}
SetMaxValue(mNewsHostIterator->GetCount());
mValue = -1; // force BroadcastValueMessage();
SetValue(hostIndex + 1); // iterator is 0-based, menu is 1-based
}
void CSubscribeHostPopup::BroadcastValueMessage()
{
MSG_Host* outNewsHost;
mNewsHostIterator->ResetTo(mValue - 1);
mNewsHostIterator->Current(outNewsHost);
CNewsSubscriber::SetHost(outNewsHost);
if (mValueMessage != msg_Nothing) {
BroadcastMessage(mValueMessage, (void*)outNewsHost);
}
}

View File

@ -0,0 +1,182 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CSubscribeWindow.h
#pragma once
// C/C++ headers
//#include <yvals.h>
// PowerPlant
#include <LListener.h>
#include <LBroadcaster.h>
#include <LEditField.h>
#include <LCommander.h>
#include <LHandleStream.h>
#include <LGAPopup.h>
// Mail/News MacFE stuff
#include "CBrowserContext.h"
#include "CComposeAddressTableView.h"
// UI elements
#include "CMailNewsWindow.h"
#include "CMailComposeWindow.h"
#include "CPatternBevelView.h"
#include "CTabSwitcher.h"
#include "UMailFolderMenus.h"
// Netscape stuff
#include "msgcom.h"
#include "mattach.h"
//#include "MailNewsGUI.h"
class CMailComposeWindow;
class CProgressListener;
class CComposeSession;
class CSubscribeView;
//----------------------------------------------------------------------------
// USubscribeUtilities
//
//----------------------------------------------------------------------------
class USubscribeUtilities
{
public:
static void RegisterSubscribeClasses();
};
//----------------------------------------------------------------------------
// CNewsHostIterator
//
//----------------------------------------------------------------------------
class CNewsHostIterator
{
public:
enum { kMaxNewsHosts = 32 };
CNewsHostIterator(MSG_Master* master);
Boolean Current(MSG_Host*& outNewsHost);
Boolean Next(MSG_Host*& outNewsHost);
Boolean FindIndex(const MSG_Host* inNewsHost, Int32& outIndex);
void ResetTo(Int32 current) {mIndex = current;};
Int32 GetCurrentIndex() {return mIndex;};
static Int32 GetCount() {return mHostCount;};
static MSG_Host** GetHostList() {return mHostList;};
protected:
static MSG_Host* mHostList[kMaxNewsHosts];
static Int32 mHostCount;
Int32 mIndex;
};
//----------------------------------------------------------------------------
// CSubscribeHostPopup
//
//----------------------------------------------------------------------------
class CSubscribeHostPopup : public LGAPopup
{
public:
enum { class_ID = 'SHpp' };
CSubscribeHostPopup(LStream* inStream);
virtual ~CSubscribeHostPopup();
virtual void FinishCreateSelf();
virtual void ReloadMenu();
protected:
virtual void BroadcastValueMessage();
protected:
CNewsHostIterator* mNewsHostIterator;
static void* sMercutioCallback;
};
//----------------------------------------------------------------------------
// CSubscribeWindow
//
//----------------------------------------------------------------------------
class CSubscribeWindow : public CMailNewsWindow,
public LBroadcaster,
public LListener
{
private:
typedef CMailNewsWindow Inherited; // trick suggested by the ANSI committee.
public:
enum { class_ID = 'Subs', res_ID = 14006 };
protected:
virtual ResIDT GetStatusResID(void) const { return res_ID; }
virtual UInt16 GetValidStatusVersion(void) const { return 0x0112; }
public:
static CSubscribeWindow* FindAndShow(Boolean makeNew);
static Boolean DisplayDialog();
CSubscribeWindow(LStream* inStream);
virtual ~CSubscribeWindow();
virtual void FinishCreateSelf();
virtual void DoClose();
CMailFlexTable* GetActiveTable();
virtual void CalcStandardBoundsForScreen(
const Rect &inScreenBounds,
Rect &outStdBounds) const;
virtual void ListenToMessage(MessageT inMessage, void* ioParam);
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
protected:
Boolean CommandDelegatesToSubscribeList(CommandT inCommand);
void HandleAllGroupsTabActivate();
void HandleSearchGroupsTabActivate();
void HandleNewGroupsTabActivate();
void HandleSearchInList();
CSubscribeView* mList;
};

View File

@ -0,0 +1,657 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CThreadMessageController.cp
#include "CThreadMessageController.h"
#include "CMessageView.h"
#include "CMailNewsWindow.h"
#include "CThreadView.h"
#include "CBrowserContext.h"
#include "CProgressListener.h"
#include "UMailSelection.h"
#include "macutil.h"
#include "secnav.h"
#include "prefapi.h"
// Command numbers
#include "resgui.h"
#include "MailNewsgroupWindow_Defines.h"
const Int16 kBottomBevelHeight = 0;
#define THREE_PANE 1
#include "CKeyStealingAttachment.h"
#pragma mark -
//-----------------------------------
void CThreadWindowExpansionData::ReadStatus(LStream* inStream)
//-----------------------------------
{
if (!inStream) return;
// *inStream >> mHeight >> mExpandoHeight;
} // CThreadWindowExpansionData::ReadStatus
//-----------------------------------
void CThreadWindowExpansionData::WriteStatus(LStream* inStream)
//-----------------------------------
{
if (!inStream) return;
// *inStream << mHeight << mExpandoHeight;
} // CThreadWindowExpansionData::WriteStatus
#pragma mark -
//-----------------------------------
CThreadMessageController::CThreadMessageController(
CExpandoDivider* inExpandoDivider
, CThreadView* inThreadView
, CMessageView* inMessageView
, CMessageAttachmentView* inAttachmentView
#if !ONECONTEXTPERWINDOW
, LListener** inMessageContextListeners
// Null-terminated list of pointers, owned by
// this controller henceforth.
#endif
)
//-----------------------------------
: CExpandoListener(&mClosedData, &mOpenData)
, mExpandoDivider(inExpandoDivider)
, mThreadView(inThreadView)
, mMessageView(inMessageView)
, mAttachmentView(inAttachmentView)
, mMessageContext(nil)
, mStoreStatusEnabled(true)
, mThreadKeyStealingAttachment(nil)
#if !ONECONTEXTPERWINDOW
, mMessageContextListeners(inMessageContextListeners)
#endif
{
Assert_(mExpandoDivider);
Assert_(mThreadView);
Assert_(mMessageView);
} // CThreadMessageController::CThreadMessageController
//-----------------------------------
CThreadMessageController::~CThreadMessageController()
//-----------------------------------
{
#if !ONECONTEXTPERWINDOW
delete [] mMessageContextListeners;
#endif
} // CThreadMessageController::~CThreadMessageController
//-----------------------------------
void CThreadMessageController::InitializeDimensions()
//-----------------------------------
{
// In case this is the first instantiation, set up the defaults
StoreCurrentDimensions(); // get the closed state from PPOb
// Set the default open state depending on the initial closed state
*(CThreadWindowExpansionData*)mStates[open_state]
= *(CThreadWindowExpansionData*)mStates[closed_state];
// ExpandoHeight(open_state) -= kBottomBevelHeight;
} // CThreadMessageController::InitializeDimensions
//-----------------------------------
void CThreadMessageController::FinishCreateSelf()
//-----------------------------------
{
mMessageView->SetMasterCommander(mThreadView);
LWindow* win = FindOwningWindow();
LCaption* statisticsCaption = (LCaption*)win->FindPaneByID('Tstt');
// Initialize the format string.
if (statisticsCaption)
{
statisticsCaption->GetDescriptor(mThreadStatisticsFormat);
statisticsCaption->Hide();
}
} // CThreadMessageController::FinishCreateSelf
//-----------------------------------
void CThreadMessageController::ReadStatus(LStream *inStatusData)
//-----------------------------------
{
mExpandoDivider->ReadStatus(inStatusData);
CExpandable::ReadStatus(inStatusData);
} // CThreadMessageController::ReadWindowStatus
//-----------------------------------
void CThreadMessageController::WriteStatus(LStream *inStatusData)
//-----------------------------------
{
mExpandoDivider->WriteStatus(inStatusData);
CExpandable::WriteStatus(inStatusData);
} // CThreadMessageController::WriteWindowStatus
//-----------------------------------
LWindow* CThreadMessageController::FindOwningWindow() const
//-----------------------------------
{
return LWindow::FetchWindowObject(mMessageView->GetMacPort());
}
//-----------------------------------
void CThreadMessageController::SetExpandState(ExpandStateT inExpand)
//-----------------------------------
{
if (!mExpandoDivider) return;
if (mStoreStatusEnabled) // don't do this during the reading-in phase
StoreCurrentDimensions();
mExpandState = inExpand;
Rect myRect;
mExpandoDivider->CalcPortFrameRect(myRect); // relative is fine
::EraseRect(&myRect);
LWindow* win = FindOwningWindow();
win->Refresh();
if (inExpand)
{
// Ordering is important! If we resize the expando pane
// when in the closed position, we change the first frame size. So
// always do the "recall" step when the expando pane has the "open"
// bindings.
mExpandoDivider->SetExpandState(inExpand); // set expando properties
RecallCurrentDimensions(); // resize myself and the expando pane
}
else
{
// Ordering is important!
RecallCurrentDimensions(); // resize myself and the expando pane
mExpandoDivider->SetExpandState(inExpand);
}
InstallMessagePane(inExpand);
if (inExpand)
{
// Since "expanding" means that the threadview gets smaller, it often happens
// that the user's selection is out of the frame after "expansion".
mThreadView->ScrollSelectionIntoFrame();
}
// Set the fancy double-click behavior, which is only needed for the expanded state
mThreadView->SetFancyDoubleClick(inExpand);
// Set the "select after deletion" behavior of the thread view. The correct macui
// behavior is NOT to do this. But when the thread view is controlling the message
// view, it makes sense to go along with the "Netscape" behavior, ie the wintel
// behavior.
Boolean doSelect = inExpand; // (As I just said)
// ... but some big customer may want the Macintosh behavior in both cases, so check
// for the special preference.
XP_Bool noNextRowSelection;
if (PREF_GetBoolPref("mail.no_select_after_delete", &noNextRowSelection) == PREF_NOERROR
&& noNextRowSelection)
doSelect = false; // no matter what.
mThreadView->SetSelectAfterDelete(doSelect);
// The kludge to fix the bottom of the message view has moved to CExpandoDivider.
} // CThreadMessageController::SetExpandState
//-----------------------------------
void CThreadMessageController::StoreDimensions(CExpansionData&)
//-----------------------------------
{
} // CThreadMessageController::StoreDimensions()
//-----------------------------------
void CThreadMessageController::RecallDimensions(const CExpansionData&)
//-----------------------------------
{
} // CThreadMessageController::RecallDimensions()
//-----------------------------------
cstring CThreadMessageController::GetCurrentURL() const
//-----------------------------------
{
if (mMessageContext)
return mMessageContext->GetCurrentURL();
else
return cstring("");
}
//-----------------------------------
void CThreadMessageController::InstallMessagePane(
Boolean inInstall)
//-----------------------------------
{
// Disable the message view to prevent a crash in layout code,
// called from CHTMLView::AdjustCursorSelf()
Assert_(mMessageView);
mMessageView->Disable();
OSErr err = noErr;
CMailNewsWindow* win = dynamic_cast<CMailNewsWindow*>(FindOwningWindow());
ThrowIfNil_(win);
#ifndef THREE_PANE
SwitchTarget(nil); // necessary paranoia if closing window.
// Do before changing the supercommander chain, so that powerplant will correctly
// take the current chain off duty.
#endif
if (inInstall)
{
Try_
{
#if ONECONTEXTPERWINDOW
mMessageContext = dynamic_cast<CBrowserContext*>(win->GetWindowContext());
ThrowIfNil_(mMessageContext);
((MWContext*)*mMessageContext)->type = MWContextMailMsg;
#else
mMessageContext = new CBrowserContext(MWContextMailMsg);
#endif
StSharer theShareLock(mMessageContext);
mMessageContext->AddUser(this);
//mMessageContext->AddListener(this);
mMessageView->SetContext(mMessageContext);
// This call links up the model object hierarchy for any potential
// sub model that gets created within the scope of the html view.
if (win)
mMessageView->SetFormElemBaseModel(win); // ? Probably wrong.
mThreadView->AddListener((CExpandoListener*)this); // for msg_SelectionChanged
// When the message view is installed, we still want the thread view to
// have first crack at all the commands, and then to pass to message view if
// not handled. So we insert the message view between us and the thread view,
// and set the target to the thread view.
#ifndef THREE_PANE
mThreadView->SetSuperCommander(mMessageView);
mMessageView->SetSuperCommander(this);
#endif
CNSContext* context = mThreadView->GetContext();
if (context)
mMessageView->SetDefaultCSID(context->GetDefaultCSID());
// Add the attachment that will divert certain key events to the message pane.
// This is added first so that it is executed first, and can disable normal
// response to keypresses.
mThreadKeyStealingAttachment = new CKeyStealingAttachment(mMessageView);
mThreadView->AddAttachmentFirst(mThreadKeyStealingAttachment);
#ifndef THREE_PANE
mThreadKeyStealingAttachment->StealKey(char_Home);
mThreadKeyStealingAttachment->StealKey(char_End);
mThreadKeyStealingAttachment->StealKey(char_PageUp);
mThreadKeyStealingAttachment->StealKey(char_PageDown);
#endif // THREE_PANE
mThreadKeyStealingAttachment->StealKey(' ');
// Tell message view about its attachment pane and hide it
if (mAttachmentView)
{
mMessageView->SetAttachmentView(mAttachmentView);
//mAttachmentView->Remove();
}
// Tell the thread view its selection changed, so it will broadcast.
// If a message was selected, this will cause it to display in the message pane.
mThreadView->SelectionChanged();
mMessageView->Enable();
#if !ONECONTEXTPERWINDOW
LListener** nextListener = mMessageContextListeners;
while (*nextListener)
mMessageContext->AddListener(*nextListener++);
#endif
mSecurityListener.SetMessageView( mMessageView );
mMessageContext->AddListener( &mSecurityListener);
}
Catch_(localErr)
{
inInstall = false;
}
EndCatch_
}
if (!inInstall) // called with de-install, or threw above...
{
if (mThreadView)
{
mThreadView->RemoveListener((CMailCallbackListener*)mMessageView); // for msg_SelectionChanged
// While the message view is installed, it is inserted in the command chain
// between this and the message view.
#ifndef THREE_PANE
mThreadView->SetSuperCommander(this);
#endif
// If mThreadView is nil, we have deleted it and the attachment will be deleted, too.
delete mThreadKeyStealingAttachment; //... which will remove itself as an attachment
mThreadKeyStealingAttachment = nil;
}
// If a message is loading when we de-install the pane we want to stop the load
if (mMessageContext)
XP_InterruptContext(*mMessageContext);
if (mMessageView)
{
mMessageView->SetFormElemBaseModel(nil); // ? Probably wrong.
mMessageView->SetContext(nil);
}
if (mMessageContext)
{
#if !ONECONTEXTPERWINDOW
LListener** nextListener = mMessageContextListeners;
while (*nextListener)
mMessageContext->RemoveListener(*nextListener++);
#endif
mSecurityListener.SetMessageView( NULL );
mMessageContext->RemoveListener( &mSecurityListener);
USecurityIconHelpers::SetNoMessageLoadedSecurityState( win );
((MWContext*)*mMessageContext)->type = MWContextMail; // see hack in mimemoz.c
mMessageContext->RemoveUser(this); // and delete.
mMessageContext = nil;
}
}
#ifndef THREE_PANE
if (mThreadView)
SwitchTarget(mThreadView);
#endif
} // CThreadMessageController::InstallMessagePane
//-----------------------------------
void CThreadMessageController::ListenToMessage(MessageT inMessage, void *ioParam)
//-----------------------------------
{
switch (inMessage)
{
case CStandardFlexTable::msg_SelectionChanged:
if (!mThreadView)
return;
LWindow* win = FindOwningWindow();
USecurityIconHelpers::SetNoMessageLoadedSecurityState(win);
if (GetExpandState() == open_state)
{
if (mMessageView)
{
CMailSelection selection;
mThreadView->GetSelection(selection);
MSG_FolderInfo* folder = mThreadView->GetOwningFolder();
if (folder && selection.selectionSize == 1)
{
LCommander::SetUpdateCommandStatus(true);
CMessage message(*selection.GetSelectionList() + 1, selection.xpPane);
// (add one to convert MSG_ViewIndex to TableIndexT)
MessageKey id = message.GetMessageKey();
mMessageView->ShowMessage(
CMailNewsContext::GetMailMaster(),
folder,
id,
false); // load on next idle.
if (MSG_GetBacktrackState(mThreadView->GetMessagePane()) == MSG_BacktrackIdle)
MSG_AddBacktrackMessage(mThreadView->GetMessagePane(), folder, id);
else
MSG_SetBacktrackState(mThreadView->GetMessagePane(), MSG_BacktrackIdle);
}
else
{
// blank out the message view.
mMessageView->
ShowMessage(
CMailNewsContext::GetMailMaster(),
folder, MSG_MESSAGEKEYNONE, false); // But on next idle! #107826
}
}
}
#if ONECONTEXTPERWINDOW
else
#endif // with multiple contexts, always do this. If shared, only when message pane not there.
mThreadView->UpdateHistoryEntry();
break;
case CMailCallbackManager::msg_ChangeStarting:
case CMailCallbackManager::msg_ChangeFinished:
case CMailCallbackManager::msg_PaneChanged:
if (mThreadView != nil)
{
// Set the pane in order to receive XP messages.
// Note: SetPane() can't be called in FinishCreateSelf(), instead we
// have to wait until we are notified that a folder is first loaded into
// the mThreadView. Well, we just chose to call it on every notification...
CMailCallbackListener::SetPane(mThreadView->GetMessagePane());
if (IsMyPane(ioParam))
{
// Check if the notification is about _my_ folder
SPaneChangeInfo * callbackInfo = reinterpret_cast<SPaneChangeInfo *>(ioParam);
MSG_FolderInfo * folderInfo = reinterpret_cast<MSG_FolderInfo *>(callbackInfo->value);
if (mThreadView->GetOwningFolder() == folderInfo)
CMailCallbackListener::ListenToMessage(inMessage, ioParam);
}
}
break;
default:
CExpandoListener::ListenToMessage(inMessage, ioParam);
break;
}
} // CThreadMessageController::ListenToMessage
//-----------------------------------
void CThreadMessageController::ChangeStarting(
MSG_Pane* ,
MSG_NOTIFY_CODE ,
TableIndexT ,
SInt32 /*inRowCount*/)
//-----------------------------------
{
}
//-----------------------------------
void CThreadMessageController::ChangeFinished(
MSG_Pane* ,
MSG_NOTIFY_CODE ,
TableIndexT ,
SInt32 /*inRowCount*/)
//-----------------------------------
{
}
//-----------------------------------
void CThreadMessageController::PaneChanged(
MSG_Pane* ,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 /*value*/)
//-----------------------------------
{
switch (inNotifyCode)
{
case MSG_PaneNotifyMessageLoaded:
case MSG_PaneNotifyMessageDeleted:
case MSG_PaneNotifyLastMessageDeleted:
// nothing to do for now
break;
case MSG_PaneNotifyFolderDeleted:
#if !THREE_PANE
LWindow* win = FindOwningWindow();
win->AttemptClose();
#endif // THREE_PANE
return; // duh!
}
if (inNotifyCode != MSG_PaneNotifyMessageDeleted)
{
// Refresh the statistics on the location bar.
LWindow* win = FindOwningWindow();
if (win)
{
LCaption* statisticsCaption = (LCaption*)win->FindPaneByID('Tstt');
if (statisticsCaption && mThreadView)
{
CStr255 tempString = mThreadStatisticsFormat;
CMessageFolder folder(mThreadView->GetOwningFolder());
SInt32 total = folder.CountMessages(), unread = folder.CountUnseen();
if (total >= 0 && unread >= 0)
::StringParamText(tempString, total, unread, 0, 0);
else
::GetIndString(tempString, 7099, 8); // " Message counts unavailable"
statisticsCaption->SetDescriptor(tempString);
statisticsCaption->Show();
}
}
}
} // CThreadMessageController::PaneChanged
//-----------------------------------
Boolean CThreadMessageController::CommandDelegatesToMessagePane(CommandT inCommand)
//-----------------------------------
{
Boolean isOneLineSelected = mThreadView && mThreadView->GetSelectedRowCount() == 1;
if (GetExpandState() == open_state && isOneLineSelected)
switch (inCommand)
{
case cmd_Copy:
case cmd_Print:
case cmd_PrintOne:
case cmd_SecurityInfo:
case cmd_MarkReadByDate:
case cmd_Stop:
case cmd_LoadImages:
case cmd_Reload:
case cmd_ViewSource:
case cmd_DocumentInfo:
case cmd_WrapLongLines:
case cmd_Find:
case cmd_FindAgain:
return true;
// Plus Commands msglib can tell us about.
case cmd_Back:
case cmd_GoForward:
case cmd_NextMessage:
case cmd_NextUnreadMessage:
case cmd_PreviousMessage:
case cmd_PreviousUnreadMessage:
case cmd_NextUnreadThread:
case cmd_NextUnreadGroup:
case cmd_NextFolder:
case cmd_FirstFlagged:
case cmd_PreviousFlagged:
case cmd_NextFlagged:
case cmd_GetMoreMessages:
case cmd_Clear:
case cmd_ReplyToSender:
case cmd_PostReply:
case cmd_PostAndMailReply:
case cmd_PostNew:
case cmd_ReplyToAll:
case cmd_ForwardMessage:
case cmd_ForwardMessageQuoted:
case cmd_ShowMicroMessageHeaders:
case cmd_ShowSomeMessageHeaders:
case cmd_ShowAllMessageHeaders:
case cmd_AttachmentsAsLinks:
case cmd_AttachmentsInline:
return true;
}
return false;
} // CThreadMessageController::CommandDelegatesToMessagePane
//-----------------------------------
void CThreadMessageController::FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName)
// The message pane, if it exists, is never the target (the thread pane is).
// Therefore, some commands must be explicitly passed down to the message pane
// by this, the window object.
//-----------------------------------
{
#if 0
switch (inCommand)
{
case cmd_SelectSelection:
outEnabled = true;
return;
}
#endif // 0
if (CommandDelegatesToMessagePane(inCommand))
{
if (mMessageView)
{
// Set the super commander of the message view to nil, because otherwise
// when it calls the inherited method, we'll get called here again, with
// infinite recursion!
LCommander* savedCommander = mMessageView->GetSuperCommander();
mMessageView->SetSuperCommander(nil);
mMessageView->FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
mMessageView->SetSuperCommander(savedCommander);
}
return;
}
LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
} // CThreadMessageController::FindCommandStatus
//-----------------------------------
Boolean CThreadMessageController::ObeyCommand(
CommandT inCommand,
void *ioParam)
//-----------------------------------
{
#if 0
switch (inCommand)
{
case cmd_RelocateViewToFolder:
// Command was not (could not be) handled by the ThreadView,
// so we leave the window as it is and just update the Location popup.
UpdateFilePopupCurrentItem();
return true;
case cmd_SelectSelection:
// This command comes from the context menu, as the default in the thread view.
LControl* twistie = dynamic_cast<LControl*>(FindPaneByID(kTwistieID));
if (twistie)
twistie->SetValue(true);
// and nature will take its course...
return true;
}
#endif // 0
if (CommandDelegatesToMessagePane(inCommand))
{
if (mMessageView)
{
// Set the super commander of the message view to nil, because otherwise
// when it calls the inherited method, we'll get called here again, with
// infinite recursion!
LCommander* savedCommander = mMessageView->GetSuperCommander();
mMessageView->SetSuperCommander(nil);
LCommander* savedMasterCommander = mMessageView->GetMasterCommander();
mMessageView->SetMasterCommander(nil);
Boolean result = mMessageView->ObeyCommand(inCommand, ioParam);
if (result)
{
// This doesn't work, because the load does not complete.
STableCell cell(mMessageView->GetCurMessageViewIndex() + 1,1);
mThreadView->SetNotifyOnSelectionChange(false);
mThreadView->UnselectAllCells();
mThreadView->SetNotifyOnSelectionChange(true);
mThreadView->SelectCell(cell);
}
mMessageView->SetMasterCommander(savedMasterCommander);
mMessageView->SetSuperCommander(savedCommander);
return result;
}
}
if ( inCommand == cmd_SecurityInfo )
{
// MWContext* context = *GetWindowContext();
MWContext* context = *mThreadView->GetContext();
SECNAV_SecurityAdvisor(context, NULL );
return true;
}
return LCommander::ObeyCommand(inCommand, ioParam);
} // CThreadMessageController::ObeyCommand

View File

@ -0,0 +1,145 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CThreadMessageController.h
#pragma once
#include "CExpandoDivider.h"
#include "MailNewsCallbacks.h"
#include "CSecurityButton.h"
#include "cstring.h"
class CThreadView;
class CMessageView;
class CMessageAttachmentView;
class CExpandoDivider;
class CSpinningN;
class CBrowserContext;
class CProgressListener;
class CKeyStealingAttachment;
//======================================
class CThreadWindowExpansionData : public CExpansionData
//======================================
{
public:
virtual void ReadStatus(LStream* inStream);
virtual void WriteStatus(LStream* inStream);
}; // class CThreadWindowExpansionData
//======================================
class CThreadMessageController
: public CExpandoListener
, public CMailCallbackListener
, public LCommander
// This manages the thread and message panes in the thread window. In 4.0x, this
// was all handled by CThreadWindow. This code moved here on 97/09/30.
//======================================
{
public:
// Construction/Destruction
CThreadMessageController(
CExpandoDivider* inExpandoDivider
, CThreadView* inThreadView
, CMessageView* inMessageView
, CMessageAttachmentView* inAttachmentView
#if !ONECONTEXTPERWINDOW
, LListener** inMessageContextListeners
// Null-terminated list of pointers, owned by
// this controller henceforth.
#endif
);
virtual ~CThreadMessageController();
void ReadStatus(LStream *inStatusData);
void WriteStatus(LStream *inStatusData);
void InitializeDimensions();
void FinishCreateSelf();
void InstallMessagePane(
Boolean inInstall);
LWindow* FindOwningWindow() const;
// Accessors/Mutators
CMessageView* GetMessageView() const { return mMessageView; }
cstring GetCurrentURL() const;
void SetStoreStatusEnabled(Boolean inEnabled)
{ mStoreStatusEnabled = inEnabled; }
void SetThreadView(CThreadView* inThreadView)
{ mThreadView = inThreadView; }
// CMailCallbackListener overrides:
protected:
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
// LCommander Overrides
protected:
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
// command helpers
protected:
Boolean CommandDelegatesToMessagePane(CommandT inCommand);
// CExpandoListener overrides:
protected:
virtual void ListenToMessage(MessageT inMessage, void *ioParam);
// CExpandable overrides:
protected:
virtual void SetExpandState(ExpandStateT inExpanded);
virtual void StoreDimensions(CExpansionData&);
virtual void RecallDimensions(const CExpansionData&);
// Data
protected:
CExpandoDivider* mExpandoDivider;
CThreadView* mThreadView;
CMessageView* mMessageView;
CMessageAttachmentView* mAttachmentView;
#if !ONECONTEXTPERWINDOW
LListener** mMessageContextListeners;
#endif
CThreadWindowExpansionData mClosedData, mOpenData;
Boolean mStoreStatusEnabled;
CBrowserContext* mMessageContext;
CMailSecurityListener mSecurityListener;
CKeyStealingAttachment* mThreadKeyStealingAttachment; // installed when window expanded.
Str255 mThreadStatisticsFormat; // format string
}; // class CThreadMessageController

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,387 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// CThreadView.h
#pragma once
// PowerPlant
#include <LTableView.h>
#include <LListener.h>
#include <LPeriodical.h>
#include "msgcom.h"
// Mac Netscape Lib
#include "CMailFlexTable.h"
#include "LTableHeader.h"
#include "NetscapeDragFlavors.h"
// MacFE
#include "CMailNewsContext.h"
#include "CMessageFolder.h"
class CMessageWindow;
class CDeferredUndoTask;
class CPersistentMessageSelection;
//======================================
class CMessage
//======================================
{
public:
CMessage(TableIndexT inIndex, MSG_Pane* mMessageList);
virtual ~CMessage();
// Sometimes the new mMessageList has the same
// address as the sCacheMessageList. So, when we are
// loading a new message folder, call InvalidateCache
static void InvalidateCache();
MessageId GetThreadID() const;
MessageKey GetMessageKey() const;
Boolean HasBeenRead() const;
Boolean IsFlagged() const;
Boolean HasBeenRepliedTo() const;
const char* GetSubject(char* buffer, UInt16 bufSize) const;
const char* GetSubject() const;
const char* GetSender() const;
const char* GetDateString() const;
const char* GetAddresseeString() const;
const char* GetSizeStr() const;
const char* GetPriorityStr() const;
const char* GetStatusStr() const;
void GetPriorityColor(RGBColor&) const;
static void GetPriorityColor(MSG_PRIORITY inPriority, RGBColor& outColor);
static Int16 PriorityToMenuItem(MSG_PRIORITY inPriority);
static MSG_PRIORITY MenuItemToPriority(Int16 inMenuItem);
static const char* GetSubject(MSG_MessageLine* data, char* buffer, UInt16 bufSize);
inline time_t GetDate() const;
inline UInt32 GetSize() const;
MSG_PRIORITY GetPriority() const;
inline UInt32 GetStatus() const;
int8 GetThreadLevel() const;
uint16 GetNumChildren() const;
uint16 GetNumNewChildren() const;
Boolean HasAttachments() const;
Boolean IsThread() const;
Boolean IsOpenThread() const;
Boolean IsOffline() const; // db has offline news or IMAP msg body
Boolean IsDeleted() const;
Boolean IsTemplate() const;
ResIDT GetIconID(UInt16 inFolderFlags) const;
static ResIDT GetIconID(UInt16 inFolderFlags, UInt32 inMessageFlags);
ResIDT GetThreadIconID() const;
Boolean UpdateMessageCache() const;
protected:
Boolean TestXPFlag(UInt32 inMask) const;
MSG_ViewIndex mIndex;
MSG_Pane* mMessageList;
static MSG_MessageLine sMessageLineData;
static MSG_Pane* sCacheMessageList;
static MSG_ViewIndex sCacheIndex;
}; // class CMessage
//======================================
class CThreadView : public CMailFlexTable
//======================================
{
friend class CThreadMessageController;
friend class CFolderThreadController;
private:
typedef CMailFlexTable Inherited;
public:
enum {class_ID = 'msTb'};
// ------------------------------------------------------------
// Construction
// ------------------------------------------------------------
CThreadView(LStream *inStream);
virtual ~CThreadView();
void LoadMessageFolder(
CNSContext* inContext,
const CMessageFolder& inFolder,
Boolean loadNow = false);
void FileMessagesToSelectedPopupFolder(const char *ioFolderName,
Boolean inMoveMessages);//¥¥TSM
MSG_FolderInfo* GetOwningFolder() const
{
return mXPFolder.GetFolderInfo();
}
uint32 GetFolderFlags() const
{
return mXPFolder.GetFolderFlags();
}
// ------------------------------------------------------------
// Data change notification
// Callbacks from MSGlib come here.
// ------------------------------------------------------------
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount
);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount
);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
protected:
void SetFolder(const CMessageFolder& inFolder);
void SetFolder(const MSG_FolderInfo* inFolderLine);
// ------------------------------------------------------------
// Clicking
// ------------------------------------------------------------
protected:
virtual void ClickCell(
const STableCell &inCell,
const SMouseDownEvent &inMouseDown);
virtual Boolean CellSelects(const STableCell& inCell) const;
virtual Boolean CellWantsClick( const STableCell& inCell ) const;
// ------------------------------------------------------------
// Drawing
// ------------------------------------------------------------
protected:
virtual void DrawCellContents(
const STableCell &inCell,
const Rect &inLocalRect);
void DrawMessageSubject(
TableIndexT inRow,
const Rect& inLocalRect);
void DrawMessageSize(
const CMessage& inMessage,
const Rect& inLocalRect );
void DrawMessagePriority(
const CMessage& inMessage,
const Rect& inLocalRect );
void DrawMessageStatus(
const CMessage& inMessage,
const Rect& inLocalRect );
// Specials from CStandardFlexTable
virtual TableIndexT GetHiliteColumn() const;
virtual ResIDT GetIconID(TableIndexT inRow) const;
virtual UInt16 GetNestedLevel(TableIndexT inRow) const;
virtual void GetDropFlagRect( const Rect& inLocalCellRect,
Rect& outFlagRect) const;
virtual void GetMainRowText(
TableIndexT inRow,
char* outText,
UInt16 inMaxBufferLength) const;
virtual Boolean GetHiliteTextRect(
const TableIndexT inRow,
Rect& outRect) const;
virtual void ApplyTextStyle(TableIndexT inRow) const;
virtual void ApplyTextColor(TableIndexT inRow) const;
virtual void DrawIconsSelf(
const STableCell& inCell,
IconTransformType inTransformType,
const Rect& inIconRect) const;
// ------------------------------------------------------------
// Mail and news
// ------------------------------------------------------------
public:
void ExpectNewMail() { mExpectingNewMail = true; mGotNewMail = false; }
void DontExpectNewMail() { mExpectingNewMail = false; mGotNewMail = false; }
Boolean GotNewMail() { return mExpectingNewMail && mGotNewMail; }
void SaveSelectedMessage();
Boolean RestoreSelectedMessage();
// ------------------------------------------------------------
// Drag and Drop
// ------------------------------------------------------------
public:
URL_Struct* CreateURLForProxyDrag(char* outTitle);
protected:
virtual Boolean ItemIsAcceptable(DragReference inDragRef, ItemReference inItemRef);
//virtual void InsideDropArea(DragReference inDragRef);
virtual void EnterDropArea(DragReference inDragRef, Boolean inDragHasLeftSender);
virtual void LeaveDropArea(DragReference inDragRef);
virtual void ReceiveDragItem(
DragReference inDragRef
, DragAttributes inDragAttrs
, ItemReference inItemRef
, Rect& inItemBounds);
Boolean GetDragCopyStatus(
DragReference inDragRef
, const CMailSelection& inSelection
, Boolean& outCopy);
// ------------------------------------------------------------
// Row Expansion/Collapsing
// ------------------------------------------------------------
protected:
virtual void SetCellExpansion(const STableCell &inCell, Boolean inExpanded);
virtual Boolean CellHasDropFlag(
const STableCell& inCell,
Boolean& outExpanded) const;
virtual Boolean CellInitiatesDrag(const STableCell& inCell) const;
virtual TableIndexT CountExtraRowsControlledByCell(const STableCell& inCell) const;
//-----------------------------------
// Commands
//-----------------------------------
public:
enum {cmd_UnselectAllCells = 'UnSl'};
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
void ObeyCommandWhenReady(CommandT inCommand);
protected:
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
void FindSortCommandStatus(CommandT inCommand, Int16& inOutMark);
Boolean ObeySortCommand(CommandT inCommand);
Boolean ObeyMotionCommand(MSG_MotionType inCommand);
Boolean ObeyMarkReadByDateCommand();
virtual void DeleteSelection();
virtual void ListenToMessage(
MessageT inCommand,
void *ioParam);
// ------------------------------------------------------------
// Miscellany - PP
// ------------------------------------------------------------
public:
virtual void ActivateSelf();
protected:
void NoteSortByThreadColumn(Boolean isThreaded) const;
virtual void OpenRow(TableIndexT inRow);
// ------------------------------------------------------------
// Miscellany - Selection management
// ------------------------------------------------------------
public:
Boolean ScrollToGoodPlace(); // as, to first unread message
virtual void SelectionChanged(); // overridden to scroll into view
void SelectMessageWhenReady(MessageKey inKey);
void SetSelectAfterDelete(Boolean inDoSelect) { mSelectAfterDelete = inDoSelect; }
void SelectAfterDelete(TableIndexT inRow);
protected:
void SelectMessage(MessageKey inKey);
virtual void ResizeFrameBy(
Int16 inWidthDelta,
Int16 inHeightDelta,
Boolean inRefresh);
virtual void SetRowCount();
// ------------------------------------------------------------
// Miscellany - i18n support
// ------------------------------------------------------------
public:
void SetDefaultCSID(Int16 default_csid);
virtual Int16 DefaultCSIDForNewWindow();
// The following two should really go into utility class
static void DrawUTF8TextString( const char* inText,
const FontInfo* inFontInfo,
SInt16 inMargin,
const Rect& inBounds,
SInt16 inJustification = teFlushLeft,
Boolean doTruncate = true,
TruncCode truncWhere = truncMiddle);
static void PlaceUTF8TextInRect(
const char* inText,
Uint32 inTextLength,
const Rect &inRect,
Int16 inHorizJustType = teCenter,
Int16 inVertJustType = teCenter,
const FontInfo* inFontInfo = NULL,
Boolean inDoTruncate = false,
TruncCode inTruncWhere = truncMiddle);
protected:
void ResetTextTraits();
protected:
virtual void ChangeSort(const LTableHeader::SortChange* inSortChange);
void SyncSortToBackend();
void UpdateSortMenuCommands() const;
Boolean RelocateViewToFolder(const CMessageFolder& inFolder);
// Retarget the view to the specified BE folder.
void UpdateHistoryEntry(); // For bookmark support.
void DoSelectThread(TableIndexT inSelectedRow);
void DoSelectFlaggedMessages();
// ------------------------------------------------------------
// QA Partner support
// ------------------------------------------------------------
#if defined(QAP_BUILD)
public:
virtual void GetQapRowText(TableIndexT inRow, char* outText, UInt16 inMaxBufferLength) const;
#endif
// ------------------------------------------------------------
// Data
// ------------------------------------------------------------
protected:
CMessageFolder mXPFolder; // The unique id of the folder we are viewing. Owned by backend.
CPersistentMessageSelection* mSavedSelection; // Used while the window is being rearranged.
Boolean mExpectingNewMail;
Boolean mGotNewMail;
Boolean mIsIdling;
Boolean mSelectAfterDelete; // This was a demand from a big customer
TableIndexT mRowToSelect; // hack to help coordinate thread/message panes.
Boolean mScrollToShowNew;
MSG_MotionType mMotionPendingCommand;
CDeferredUndoTask* mUndoTask;
}; // class CThreadView

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
/* -*- 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.
*/
// CThreadWindow.h
#pragma once
// Mac UI Lib
#include "CMailNewsWindow.h"
#include "msgcom.h"
#include "cstring.h"
class CMessageView;
class CThreadView;
class CMessageFolderView;
class CThreadMessageController;
class CFolderThreadController;
typedef struct MSG_ResultElement MSG_ResultElement;
//======================================
class CThreadWindow
: public CMailNewsWindow
// This window can have up to three contexts (folder, thread, message). The
// one managed by the base class is the THREAD context.
//======================================
{
private:
typedef CMailNewsWindow Inherited;
public:
enum { class_ID = 'thWN', res_ID = 10509, res_ID_Alt = 10508 };
CThreadWindow(LStream *inStream);
virtual ~CThreadWindow();
virtual void FinishCreateSelf();
virtual void AboutToClose(); // place to put common code from [Attempt|Do]Close()
static CThreadWindow* ShowInbox(CommandT inCommand);
enum { kDontMakeNew = false, kMakeNew = true };
static CThreadWindow* FindAndShow(
const MSG_FolderInfo* inFolderInfo,
Boolean makeNew = kDontMakeNew,
CommandT inCommand = cmd_Nothing,
Boolean forceNewWindow = false);
static CThreadWindow* FindOrCreate(
const MSG_FolderInfo* inFolderInfo,
CommandT inCommand = cmd_Nothing);
static CThreadWindow* OpenFromURL(const char* url);
cstring GetCurrentURL() const;
static void CloseAll(const MSG_FolderInfo* inFolderInfo);
virtual CNSContext* CreateContext() const;
virtual void StopAllContexts();
virtual Boolean IsAnyContextBusy();
virtual CMailFlexTable* GetActiveTable();
// Return the currently active table in the window, nil if none
virtual CMailFlexTable* GetSearchTable();
CThreadView* GetThreadView();
CMessageFolderView* GetFolderView();
CMessageView* GetMessageView();
// Return the message view. Note: there may be no MSG_Pane in it!
void SetFolderName(const char* inFolderName, Boolean inIsNewsgroup);
// CSaveWindowStatus Overrides:
virtual void ReadWindowStatus(LStream *inStatusData);
// Overridden to stagger in the default case.
virtual void WriteWindowStatus(LStream *inStatusData);
virtual UInt16 GetValidStatusVersion() const;
virtual ResIDT GetStatusResID() const;
// I18N stuff
virtual Int16 DefaultCSIDForNewWindow(void);
void SetDefaultCSID(Int16 default_csid);
void ShowMessageKey(MessageKey inKey);
protected:
void SetStatusResID(ResIDT id) { mStatusResID = id; }
void UpdateFilePopupCurrentItem();
virtual void ActivateSelf(void);
virtual void AdaptToolbarToFolder(void);
// LCommander overrides
protected:
virtual void FindCommandStatus(
CommandT inCommand,
Boolean &outEnabled,
Boolean &outUsesMark,
Char16 &outMark,
Str255 outName);
virtual Boolean ObeyCommand(
CommandT inCommand,
void *ioParam);
// CNetscapeWindow overrides
protected:
virtual URL_Struct* CreateURLForProxyDrag(char* outTitle = nil);
virtual CExtraFlavorAdder* CreateExtraFlavorAdder() const;
// CMailNewsWindow overrides
protected:
virtual const char* GetLocationBarPrefName() const;
//DATA:
protected:
ResIDT mStatusResID;
CThreadView* mThreadView;
CThreadMessageController* mThreadMessageController;
CMessageFolderView* mFolderView;
CMailNewsContext* mFolderContext;
CFolderThreadController* mFolderThreadController;
}; // class CThreadWindow

View File

@ -0,0 +1,159 @@
/* -*- 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.
*/
// LGABox_fixes.cp
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "LGABox_fixes.h"
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS IMPLEMENTATIONS
/*====================================================================================*/
/*======================================================================================
Turds be gone! Assumes entire frame is visible through superview.
======================================================================================*/
void LGABox_fixes::ResizeFrameBy(Int16 inWidthDelta, Int16 inHeightDelta,
Boolean inRefresh) {
if ( mHasBorder && (mBorderStyle != borderStyleGA_NoBorder) && !mRefreshAllWhenResized ) {
Rect borderRect;
CalcBorderRect(borderRect);
Point beforeBotRight = botRight(borderRect);
Rect invalRect;
CalcPortFrameRect(invalRect);
Point portBeforeBotRight = botRight(invalRect);
inherited::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);
CalcPortFrameRect(invalRect);
CalcBorderRect(borderRect);
Point portAfterBotRight = botRight(invalRect);
if ( inWidthDelta != 0 ) {
if ( beforeBotRight.h < borderRect.right ) {
::SetRect(&invalRect, beforeBotRight.h - mContentOffset.right,
borderRect.top, portBeforeBotRight.h, portBeforeBotRight.v);
} else {
::SetRect(&invalRect, borderRect.right - mContentOffset.right,
borderRect.top, portAfterBotRight.h, portAfterBotRight.v);
}
LocalToPortPoint(topLeft(invalRect));
LocalToPortPoint(botRight(invalRect));
InvalPortRect(&invalRect);
}
if ( inHeightDelta != 0 ) {
if ( beforeBotRight.v < borderRect.bottom ) {
::SetRect(&invalRect, borderRect.left, beforeBotRight.v - mContentOffset.bottom,
portBeforeBotRight.h, portBeforeBotRight.v);
} else {
::SetRect(&invalRect, borderRect.left, borderRect.bottom - mContentOffset.bottom,
portAfterBotRight.h, portAfterBotRight.v);
}
LocalToPortPoint(topLeft(invalRect));
LocalToPortPoint(botRight(invalRect));
InvalPortRect(&invalRect);
}
} else {
inherited::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);
}
}
/*======================================================================================
Fix bug where everything was not refreshed correctly.
======================================================================================*/
void LGABox_fixes::RefreshBoxBorder(void) {
Rect theFrame;
if ( IsVisible() && CalcLocalFrameRect(theFrame) && (mSuperView) ) {
Rect revealed;
mSuperView->GetRevealedRect(revealed);
Point delta = topLeft(revealed);
PortToLocalPoint(topLeft(revealed));
PortToLocalPoint(botRight(revealed));
delta.h -= revealed.left; delta.v -= revealed.top;
if ( ::SectRect(&theFrame, &revealed, &revealed) ) {
RgnHandle borderRgn = GetBoxBorderRegion(revealed);
::OffsetRgn(borderRgn, delta.h, delta.v);
InvalPortRgn(borderRgn);
::DisposeRgn(borderRgn);
}
}
}
/*======================================================================================
Fix bug where everything was not refreshed correctly.
======================================================================================*/
void LGABox_fixes::RefreshBoxTitle(void) {
Rect theFrame;
if ( IsVisible() && CalcPortFrameRect(theFrame) && (mSuperView) ) {
Rect revealed;
mSuperView->GetRevealedRect(revealed);
if ( ::SectRect(&theFrame, &revealed, &theFrame) ) {
Rect titleRect;
CalcTitleRect(titleRect);
LocalToPortPoint(topLeft(titleRect));
LocalToPortPoint(botRight(titleRect));
if ( ::SectRect(&titleRect, &revealed, &titleRect) ) {
InvalPortRect(&titleRect);
}
}
}
}
/*======================================================================================
Fix bug where everything was not refreshed correctly.
======================================================================================*/
void LGABox_fixes::Disable(void) {
LView::Disable();
RefreshBoxBorder();
RefreshBoxTitle();
}
/*======================================================================================
Get rid of the flicker.
======================================================================================*/
void LGABox_fixes::Enable(void) {
LView::Enable();
RefreshBoxBorder();
RefreshBoxTitle();
}

View File

@ -0,0 +1,79 @@
/* -*- 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.
*/
// LGABox_fixes.h
#pragma once
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include <LGABox.h>
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark EXTERNAL FUNCTION PROTOTYPES
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
class LGABox_fixes : public LGABox {
#if !defined(__MWERKS__) || (__MWERKS__ >= 0x2000)
typedef LGABox inherited;
#endif
public:
enum { class_ID = 'Gbo_' };
LGABox_fixes(LStream *inStream) :
LGABox(inStream) {
SetRefreshAllWhenResized(false);
}
virtual void ResizeFrameBy(Int16 inWidthDelta, Int16 inHeightDelta,
Boolean inRefresh);
virtual void RefreshBoxBorder(void);
virtual void RefreshBoxTitle(void);
protected:
virtual void Disable(void);
virtual void Enable(void);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/* -*- 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.
*/
// MailNewsAddressBook.h
#pragma once
//#define MOZ_NEWADDR
#ifdef MOZ_NEWADDR
#include "CAddressBookWindows.h"
#else
class CComposeAddressTableView;
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
typedef struct ABook ABook;
typedef struct DIR_Server DIR_Server;
typedef struct _XP_List XP_List;
typedef UInt32 ABID;
class CNamePropertiesWindow;
class CListPropertiesWindow;
#pragma mark -
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
class CAddressBookWindow;
struct SAddressDragInfo
{
ABID id;
DIR_Server* dir;
};
class CAddressBookManager
{
public:
// Should be called when the application starts up
static void OpenAddressBookManager(void);
// Should be called when the application closes
static void CloseAddressBookManager(void);
static void ImportLDIF(const FSSpec& inSpec);
static CAddressBookWindow* ShowAddressBookWindow(void);
static XP_List *GetDirServerList(void);
static void SetDirServerList(XP_List *inList, Boolean inSavePrefs = true);
static DIR_Server *GetPersonalBook(void);
static ABook *GetAddressBook(void);
static void FailAddressError(Int32 inError);
static CNamePropertiesWindow *FindNamePropertiesWindow(ABID inEntryID);
static CNamePropertiesWindow *GetNamePropertiesWindow(ABID inEntryID, Boolean inOptionKeyDown);
static CListPropertiesWindow *FindListPropertiesWindow(ABID inEntryID);
static CListPropertiesWindow *GetListPropertiesWindow(ABID inEntryID, Boolean inOptionKeyDown);
static void DoPickerDialog( CComposeAddressTableView* initialTable );
private:
static void RegisterAddressBookClasses(void);
static int DirServerListChanged(const char*, void*)
{
sDirServerListChanged = true;
return 0;
}
// Instance variables
static XP_List *sDirServerList;
static Boolean sDirServerListChanged;
static ABook *sAddressBook; // Really, the global address book database
// used in conjunction with all address books
// (local and remote) associated with the
// application. This object is opened at application
// startup and not closed until the application closes.
};
#endif // MOZ_NEWADDR

View File

@ -0,0 +1,333 @@
/* -*- 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.
*/
// MailNewsCallbacks.cp
#include "MailNewsCallbacks.h"
// XP headers
#include "fe_proto.h"
//#include "errcode.h"
//#include "msglpane.h"
#include "addrbook.h"
// FE
#include "CCheckMailContext.h"
#include "uprefd.h"
#include "macutil.h"
#include "CMailFlexTable.h"
#include "CMessageWindow.h"
#include "CThreadWindow.h"
#include "UMailFolderMenus.h"
#include "CMessageFolder.h"
#include "ufilemgr.h"
//======================================
// class CMailCallbackManager
//======================================
CMailCallbackManager* CMailCallbackManager::sMailCallbackManager = nil;
//-----------------------------------
CMailCallbackManager::CMailCallbackManager()
//-----------------------------------
{
sMailCallbackManager = this;
}
//-----------------------------------
CMailCallbackManager::~CMailCallbackManager()
//-----------------------------------
{
sMailCallbackManager = nil;
}
//-----------------------------------
CMailCallbackManager* CMailCallbackManager::Get()
//-----------------------------------
{
if (!sMailCallbackManager)
new CMailCallbackManager;
return sMailCallbackManager;
}
//-----------------------------------
Boolean CMailCallbackManager::ValidData(MSG_Pane *inPane)
//-----------------------------------
{
void* data = MSG_GetFEData(inPane);
//? We WERE getting callbacks before MSG_SetFEData was called. Assert_(data == this);
return (data == this);
}
//-----------------------------------
void CMailCallbackManager::PaneChanged(
MSG_Pane *inPane,
XP_Bool asynchronous,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value)
//-----------------------------------
{
if (inNotifyCode == MSG_PaneNotifyFolderDeleted)
{
// A folder can be deleted even with no active pane (eg, in IMAP synchronization).
// In this case, we get a call with inPane == NULL.
CMailFolderMixin::UpdateMailFolderMixins();
}
if (ValidData(inPane))
{
// the backend can give us a MSG_VIEWINDEXNONE (-1) in value, which we need to change to a 0
if (value == MSG_VIEWINDEXNONE)
value = 0;
// Because of the caching scheme for folders, we must update the caches first:
if (inNotifyCode == MSG_PaneNotifyFolderInfoChanged)
{
CCachedFolderLine::FolderInfoChanged(inPane, (MSG_FolderInfo*)value);
}
SPaneChangeInfo info(inPane, asynchronous, inNotifyCode, value);
BroadcastMessage(msg_PaneChanged, &info);
}
} // CMailCallbackManager::PaneChanged
//-----------------------------------
void CMailCallbackManager::ChangeStarting(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount)
//-----------------------------------
{
if (ValidData(inPane))
{
SLineChangeInfo info(inPane, inAsync, inNotifyCode, inWhere + 1, inCount);
BroadcastMessage(msg_ChangeStarting, &info);
}
} // CMailCallbackManager::ChangeStarting
//-----------------------------------
void CMailCallbackManager::ChangeFinished(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount)
//-----------------------------------
{
if (ValidData(inPane))
{
SLineChangeInfo info(inPane, inAsync, inNotifyCode, inWhere + 1, inCount);
BroadcastMessage(msg_ChangeFinished, &info);
}
} // CMailCallbackManager::ChangeFinished
//======================================
// class CMailCallbackListener
//======================================
//-----------------------------------
CMailCallbackListener::CMailCallbackListener()
//-----------------------------------
: LListener()
, mPane(nil)
{
CMailCallbackManager::Get()->AddUser(this);
CMailCallbackManager::Get()->AddListener(this);
}
//-----------------------------------
CMailCallbackListener::~CMailCallbackListener()
//-----------------------------------
{
mPane = nil; // stop derived classes from listening to callbacks.
CMailCallbackManager::Get()->RemoveListener(this);
CMailCallbackManager::Get()->RemoveUser(this);
}
//-----------------------------------
void CMailCallbackListener::ListenToMessage(MessageT inMessage, void* ioParam)
//-----------------------------------
{
switch (inMessage)
{
case CMailCallbackManager::msg_PaneChanged:
if ( IsMyPane(ioParam) ) {
SPaneChangeInfo* info = reinterpret_cast<SPaneChangeInfo*>(ioParam);
PaneChanged(info->pane, info->notifyCode, info->value);
}
break;
case CMailCallbackManager::msg_ChangeStarting:
if ( IsMyPane(ioParam) ) {
SLineChangeInfo* info = reinterpret_cast<SLineChangeInfo*>(ioParam);
ChangeStarting(info->pane, info->changeCode, info->startRow, info->rowCount);
}
break;
case CMailCallbackManager::msg_ChangeFinished:
if ( IsMyPane(ioParam) ) {
SLineChangeInfo* info = reinterpret_cast<SLineChangeInfo*>(ioParam);
ChangeFinished(info->pane, info->changeCode, info->startRow, info->rowCount);
}
break;
}
} // CMailCallbackListener::ListenToMessage
//-----------------------------------
Boolean CMailCallbackListener::IsMyPane(void* info) const
//-----------------------------------
{
return (mPane == reinterpret_cast<SMailCallbackInfo*>(info)->pane);
}
//-----------------------------------
void CMailCallbackListener::ChangeStarting(
MSG_Pane* /*inPane*/,
MSG_NOTIFY_CODE /*inChangeCode*/,
TableIndexT /*inStartRow*/,
SInt32 /*inRowCount*/)
//-----------------------------------
{
}
//-----------------------------------
void CMailCallbackListener::ChangeFinished(
MSG_Pane* /*inPane*/,
MSG_NOTIFY_CODE /*inChangeCode*/,
TableIndexT /*inStartRow*/,
SInt32 /*inRowCount*/)
//-----------------------------------
{
}
//======================================
//-----------------------------------
void FE_UpdateBiff(MSG_BIFF_STATE inState)
// Called when "check for mail" state changes.
//-----------------------------------
{
CCheckMailContext::Get()->SetState(inState);
}
//
// inDir argument is a Mac path.
uint32 FE_DiskSpaceAvailable( MWContext* inContext, const char* inDir)
//-----------------------------------
{
Boolean isMailContext
= ( inContext->type == MWContextMailMsg
|| inContext->type == MWContextMail
|| inContext->type == MWContextMessageComposition
|| inContext->type == MWContextMailNewsProgress);
if (isMailContext)
{
FSSpec folder = CPrefs::GetFolderSpec( CPrefs::MailFolder );
return GetFreeSpaceInBytes( folder.vRefNum );
}
else
{
FSSpec folder;
Str255 fileName;
OSErr err;
if (inDir)
{
XP_MEMCPY(fileName, inDir, 255);
c2pstr((char*)fileName);
folder.vRefNum = folder.parID = 0;
err = FSMakeFSSpec(folder.vRefNum, folder.parID, fileName, &folder);
}
else
err = fnfErr;
if ( err != noErr)
{
XP_ASSERT(FALSE);
return -1;
}
else
return GetFreeSpaceInBytes( folder.vRefNum );
}
}
//-----------------------------------
void FE_ListChangeStarting(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount)
//-----------------------------------
{
CMailCallbackManager::Get()
->ChangeStarting(inPane, inAsync, inNotifyCode, inWhere, inCount);
} // FE_ListChangeStarting
//-----------------------------------
void FE_ListChangeFinished(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount)
//-----------------------------------
{
CMailCallbackManager::Get()
->ChangeFinished(inPane, inAsync, inNotifyCode, inWhere, inCount);
} // FE_ListChangeFinished
//-----------------------------------
void FE_PaneChanged(
MSG_Pane *inPane,
XP_Bool asynchronous,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value)
//-----------------------------------
{
CMailCallbackManager::Get()->PaneChanged(inPane, asynchronous, inNotifyCode, value);
}
// ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
//
// Awaiting a real composition implementation,
// at which point, these should move there.
//
// ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
extern "C" void FE_InsertMessageCompositionText( MWContext* /*inContext*/, const char* /*text*/, XP_Bool /*leaveCursorAtBeginning*/);
void FE_InsertMessageCompositionText( MWContext* /*inContext*/, const char* /*text*/, XP_Bool /*leaveCursorAtBeginning*/) {}
extern "C" void FE_MsgShowHeaders(MSG_Pane *pPane, MSG_HEADER_SET mhsHeaders);
void FE_MsgShowHeaders (MSG_Pane* /*comppane*/, MSG_HEADER_SET /*headers*/) {}
extern void FE_UpdateCompToolbar(MSG_Pane* /*comppane*/); // in CMailComposeWindow.cp
MSG_Master* FE_GetMaster()
{
// implement get master
return CMailNewsContext::GetMailMaster();
}

View File

@ -0,0 +1,157 @@
/* -*- 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.
*/
// MailNewsCallbacks.h
#pragma once
#include <LBroadcaster.h>
#include <LSharable.h>
#include "msgcom.h"
//======================================
class CMailCallbackManager : public LBroadcaster, public LSharable
//======================================
{
public:
enum
{
msg_PaneChanged = 'PnCh'
, msg_ChangeFinished = 'ChFn'
, msg_ChangeStarting = 'ChSt'
};
CMailCallbackManager();
virtual ~CMailCallbackManager();
static CMailCallbackManager* Get();
public:
void PaneChanged(
MSG_Pane *inPane,
XP_Bool asynchronous,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value);
void ChangeStarting(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount);
void ChangeFinished(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inNotifyCode,
MSG_ViewIndex inWhere,
int32 inCount);
private:
Boolean ValidData(MSG_Pane *inPane);
protected:
static CMailCallbackManager* sMailCallbackManager;
};
//-----------------------------------
struct SMailCallbackInfo
//-----------------------------------
{
MSG_Pane* pane;
XP_Bool async;
SMailCallbackInfo(MSG_Pane* inPane, XP_Bool inAsync) : pane(inPane), async(inAsync){}
};
//-----------------------------------
struct SPaneChangeInfo : public SMailCallbackInfo
//-----------------------------------
{
MSG_PANE_CHANGED_NOTIFY_CODE notifyCode;
int32 value;
SPaneChangeInfo(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 inValue)
: SMailCallbackInfo(inPane, inAsync)
, notifyCode(inNotifyCode)
, value(inValue) {}
};
typedef Uint32 TableIndexT;
//-----------------------------------
struct SLineChangeInfo : public SMailCallbackInfo
//-----------------------------------
{
MSG_NOTIFY_CODE changeCode;
MSG_ViewIndex startRow;
int32 rowCount;
SLineChangeInfo(
MSG_Pane* inPane,
XP_Bool inAsync,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
int32 inCount)
: SMailCallbackInfo(inPane, inAsync)
, changeCode(inChangeCode)
, startRow(inStartRow)
, rowCount(inCount) {}
};
//======================================
class CMailCallbackListener : public LListener
//======================================
{
protected:
CMailCallbackListener();
public:
~CMailCallbackListener();
void SetPane(MSG_Pane* inPane) { mPane = inPane; }
protected:
virtual void ListenToMessage(MessageT message, void* ioParam);
virtual Boolean IsMyPane(void* info) const; // info from a ListenToMessage...
private:
void PaneChanged(void* ioParam);
void ChangeStarting(void* ioParam);
void ChangeFinished(void* ioParam);
virtual void ChangeStarting(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void ChangeFinished(
MSG_Pane* inPane,
MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow,
SInt32 inRowCount);
virtual void PaneChanged(
MSG_Pane* inPane,
MSG_PANE_CHANGED_NOTIFY_CODE inNotifyCode,
int32 value) = 0; // must always be supported.
private:
MSG_Pane* mPane;
};

View File

@ -0,0 +1,108 @@
/* -*- 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.
*/
// MailNewsClasses.cp
#include "MailNewsClasses.h"
//#define REGISTER_(letter,root) \
// RegisterClass_(letter##root::class_ID, \
// (ClassCreatorFunc)letter##root::Create##root##Stream);
#define REGISTER_(letter,root) \
RegisterClass_(letter##root);
#define REGISTERC(root) REGISTER_(C,root)
#define REGISTERL(root) REGISTER_(L,root)
// ### General Purpose UI Classes
#include "CSimpleTextView.h"
// ### MailNews Specific UI Classes
#include "CThreadView.h"
#include "CSimpleFolderView.h"
#include "CMessageFolderView.h"
#include "CMessageWindow.h"
#include "CMailNewsWindow.h"
#include "CSubscribeView.h"
#include "COfflinePicker.h"
#include "CThreadWindow.h"
#include "CMessageWindow.h"
#include "CMessageView.h"
#include "CMailComposeWindow.h"
#include "CBiffButtonAttachment.h"
#include "CSubscribeWindow.h"
#include "CGAStatusBar.h"
#include "LGABox_fixes.h"
#include "SearchHelpers.h"
#include "CSizeBox.h"
#include "CExpandoDivider.h"
#include "MailNewsSearch.h"
#include "MailNewsFilters.h"
#include "CMailFolderButtonPopup.h"
#include "StGetInfoHandler.h"
#include "CMailProgressWindow.h"
#include "CMessageAttachmentView.h"
//-----------------------------------
void RegisterAllMailNewsClasses(void)
//-----------------------------------
{
// ### General Purpose UI Classes
REGISTERC(SimpleTextView)
// stuff that was being registered twice (usually once in address book, the other time
// in a search window). Since the new PP complains when you do this, do it once and for
// all when we init mail/news
RegisterClass_(CGAStatusBar);
RegisterClass_(LGABox_fixes);
RegisterClass_(CSearchEditField);
RegisterClass_(CSizeBox);
RegisterClass_(CSearchCaption);
RegisterClass_(CSearchTabGroup);
// ### MailNews Specific UI Classes
REGISTERC(MailNewsFolderWindow)
REGISTERC(ThreadWindow)
REGISTERC(ThreadView)
REGISTERC(SimpleFolderView)
REGISTERC(MessageFolderView)
REGISTERC(SubscribeView)
REGISTERC(OfflinePickerView)
REGISTERC(OfflinePickerWindow)
REGISTERC(ExpandoDivider)
REGISTERC(MessageWindow)
REGISTERC(MessageView)
REGISTERC(MailFolderButtonPopup)
REGISTERC(MailFolderPatternTextPopup)
REGISTERC(MailFolderGAPopup)
REGISTERC(AttachmentView)
REGISTERC(BiffButtonAttachment);
REGISTERC(MailProgressWindow)
REGISTERC(MessageAttachmentView)
UComposeUtilities::RegisterComposeClasses();
USubscribeUtilities::RegisterSubscribeClasses();
CSearchWindowManager::RegisterSearchClasses();
CFiltersWindowManager::RegisterFiltersClasses();
UGetInfo::RegisterGetInfoClasses();
} // RegisterAllMailNewsClasses

View File

@ -0,0 +1,25 @@
/* -*- 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.
*/
// MailNewsClasses.h
#pragma once
void RegisterAllMailNewsClasses(void);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
/* -*- 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.
*/
// MailNewsFilters.h
#pragma once
/*======================================================================================
DESCRIPTION: Defines classes related to the Mail & News search dialog. The search
dialog is really implemented as a normal window.
======================================================================================*/
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
class CFiltersWindowManager {
public:
static void RegisterFiltersClasses(void);
static void ShowFiltersWindow(void);
private:
};

View File

@ -0,0 +1,96 @@
/* -*- 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.
*/
// MailNewsSearch.cp
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#define DEBUGGER_ASSERTIONS
#include "MailNewsSearch.h"
#include "SearchHelpers.h"
#include "CDateView.h"
#include "CMessageSearchWindow.h"
#include "CSearchTableView.h"
#include "CCaption.h"
#include "CSingleTextColumn.h"
#include "CTSMEditField.h"
#include "URobustCreateWindow.h"
#include "LCommander.h"
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS IMPLEMENTATIONS
/*====================================================================================*/
//-----------------------------------
void CSearchWindowManager::RegisterSearchClasses()
// Register all classes associated with the search window.
//-----------------------------------
{
USearchHelper::RegisterClasses();
CDateView::RegisterDateClasses();
RegisterClass_(CMessageSearchWindow);
RegisterClass_(CSearchTableView);
RegisterClass_(CListenerCaption);
RegisterClass_(LTableView);
RegisterClass_(CSingleTextColumn);
} // CSearchWindowManager::RegisterSearchClasses
//-----------------------------------
void CSearchWindowManager::ShowSearchWindow()
// Show the search dialog by bringing it to the front if it is not already. Create it
// if needed.
//-----------------------------------
{
// Find out if the window is already around
CMessageSearchWindow *searchWindow = dynamic_cast<CMessageSearchWindow *>(
CWindowMediator::GetWindowMediator()->FetchTopWindow(WindowType_SearchMailNews));
if ( searchWindow == nil )
{
// Search dialog has not yet been created, so create it here and display it.
searchWindow = dynamic_cast<CMessageSearchWindow *>(
URobustCreateWindow::CreateWindow(CMessageSearchWindow::res_ID,
LCommander::GetTopCommander()));
}
// Select the window
if (searchWindow)
{
// We set the scope of the search window only when the user issues the
// Search command. Previously, it was done on Activate and ReadWindowStatus.
searchWindow->SetUpBeforeSelecting();
searchWindow->Select();
}
} // CSearchWindowManager::ShowSearchWindow

View File

@ -0,0 +1,39 @@
/* -*- 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.
*/
// MailNewsSearch.h
#pragma once
#define NOLDAPWINDOW
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
class CSearchWindowManager {
public:
static void RegisterSearchClasses(void);
static void ShowSearchWindow(void);
private:
};

View File

@ -0,0 +1,275 @@
/* -*- 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.
*/
// MailNewsgroupWindow_Defines.h
#pragma once
// ID space
//
// All resources and cmd#s should fall within this range
//
// Mail/Newsgroups 10500-10999
// Menu ResIDs
enum
{
kMailNewsViewMenuID = 10500
, kMailNewsMessageMenuID = 10501
, kMailNewsFolderMenuID = 10502
, kMailMenuID = 10503
};
//-----------------------------------
// COMMAND #s
// There are more command numbers in MailNewsGUI.h
//-----------------------------------
enum
{
// these require messages to be selected
// cmd_OpenMailMessage = cmd_Open
cmd_OpenMailMessage = 10500
//, cmd_DeleteMessage = 10500 // NO. Use cmd_Clear
, cmd_ReplyToSender = 10510
, cmd_ReplyToAll = 10511
, cmd_ForwardMessage = 10512
, cmd_ForwardMessageQuoted = 10513
, cmd_AddSenderToAddressBook = 10514
, cmd_AddAllToAddressBook = 10515
, cmd_MarkRead = 10516
, cmd_MarkUnread = 10517
, cmd_ForwardMessageAttachment = 10518
, cmd_ForwardMessageInline = 10519
// these require folders to be selected
//, cmd_DeleteFolder = 10501 // No. Use cmd_Clear
, cmd_RenameFolder = 10520
// these do not require a selection
//, cmd_NewMailMessage = cmd_New
, cmd_NewMailMessage = 10530
, cmd_EmptyTrash = 10531
, cmd_MailFilters = 10532
, cmd_NextMessage = 10534
, cmd_NextUnreadMessage = 10535
, cmd_PreviousMessage = 10536
, cmd_FirstSortCommand = 10537
, cmd_SortByDate = 10537
, cmd_SortBySubject = 10538
, cmd_SortBySender = 10539
, cmd_SortByThread = 10540
, cmd_SortByPriority = 10541
, cmd_SortBySize = 10542
, cmd_SortByStatus = 10543
, cmd_SortByLocation = 10544
, cmd_SortByFlagged = 10545
, cmd_SortByReadness = 10546
, cmd_SortByOrderReceived = 10547 // note new item here, and changed IDs below
, cmd_SortAscending = 10548
, cmd_SortDescending = 10549
, cmd_LastSortCommand = cmd_SortByReadness
, cmd_MarkReadByDate = 10550
, cmd_MarkReadForLater = 10551
, cmd_NewsGroups = 10701 // Show folder window with news selected
, cmd_ToolbarMode = 0 // ¥¥¥ FIX ME: common!! advanced <-> novice
, cmd_SendOutboxMail = 10702 // ¥¥¥ Message Menu
, cmd_CloseAll = 10703
, cmd_NextUnreadGroup = 10704
, cmd_NextFolder = 10705
, cmd_FirstFlagged = 10706
, cmd_PreviousFlagged = 10707
, cmd_NextFlagged = 10708
, cmd_NextUnreadThread = 10709
, cmd_SendMessage = 10610
, cmd_QuoteMessage = 10611
, cmd_SendMessageLater = 10612
, cmd_SaveDraft = 10613
, cmd_CopyMailMessages = 10614 //ioParam = (char *), BE name of filing folder
, cmd_MoveMailMessages = 10615 //ioParam = (char *), BE name of filing folder
, cmd_ViewAllThreads = 10616
, cmd_ViewKilledThreads = 10617
, cmd_ViewThreadsWithNew = 10618
, cmd_ViewWatchedThreadsWithNew= 10619
, cmd_ViewNewOnly = 10620
, cmd_ToggleThreadWatched = 10621
, cmd_ToggleThreadKilled = 10622
, cmd_AttachmentsInline = 10623
, cmd_AttachmentsAsLinks = 10624
, cmd_SearchAddresses = 10627 // LDAP address search
, cmd_ToggleOffline = 10628 // Go Offline/Go Online
, cmd_SelectForOffline = 10629
, cmd_FlaggedForOffline = 10630
, cmd_SynchronizeForOffline = 10631
, cmd_ToggleFolderPane = 10635
, cmd_SaveTemplate = 10636
, cmd_RelocateViewToFolder= 'MfPM' // same as the class ID of the button that does it.
, cmd_NewsFirst = 14000 // Subscribe window
, cmd_NewsToggleSubscribe = cmd_NewsFirst+0
, cmd_NewsExpandGroup = cmd_NewsFirst+1
, cmd_NewsExpandAll = cmd_NewsFirst+2
, cmd_NewsCollapseGroup = cmd_NewsFirst+3
, cmd_NewsCollapseAll = cmd_NewsFirst+4
, cmd_NewsGetGroups = cmd_NewsFirst+5
, cmd_NewsSearch = cmd_NewsFirst+6
, cmd_NewsGetNew = cmd_NewsFirst+7
, cmd_NewsClearNew = cmd_NewsFirst+8
, cmd_NewsHostChanged = cmd_NewsFirst+9
, cmd_NewsSetSubscribe = cmd_NewsFirst+10
, cmd_NewsClearSubscribe = cmd_NewsFirst+11
};
// String stuff for menus that change
enum
{
kMailNewsMenuStrings = 10500
, kOpenFolderStrID = 1
, kOpenDiscussionStrID
, kOpenMessageStrID
, kOpenMailServerStrID
, kOpenNewsServerStrID
, kNextChunkMessagesStrID
};
//
// Window PPob IDs
//
enum
{
kMailNewsWindowPPob = 10500
, kMailMessageWindowPPob = 10506
, kNewsgroupWindowPPob = 10507
, kRenameFolderDialogPPob = 10510
, kNewFolderDialogPPob = 10511
, kMailComposeWindowPPob = 10610
};
// MailNews window pane ID's
enum
{
kMailNewsTabSwitcherPaneID = 'TbSw'
, kMailNewsTabContainerPaneID = 'Cont'
, kMailNewsStatusPaneID = 'Stat'
, kOfflineButtonPaneID = 'SBof'
};
//
// Tab IDs
//
// The message ID's associated with each tab.
//
// Independent of tab-order.
//
// These also match the ppob id's of each view
//
enum
{
kInboxTabID = 10501
, kDraftsTabID = 10502
, kOutboxTabID = 10503
, kFiledMailTabID = 10504
, kNewsgroupsTabID = 10505
};
//
// Table Column IDs
//
// The column header panes must have these id's
//
enum
{
/* CThreadView */
kMarkedReadMessageColumn = 'Read'
, kThreadMessageColumn = 'Thrd' // also used for Icon column in dir. search results
, kSubjectMessageColumn = 'Subj'
, kSenderMessageColumn = 'Sndr'
, kAddresseeMessageColumn = 'SdTo'
, kDateMessageColumn = 'Date'
, kPriorityMessageColumn = 'Prio'
, kSizeMessageColumn = 'Size'
, kUnreadMessageColumn = 'Unrd'
, kStatusMessageColumn = 'Stus'
, kTotalMessageColumn = 'Totl'
, kFlagMessageColumn = 'Flag'
, kHiddenOrderReceivedColumn = 'Rcvd'
/* CMessageFolderView */
, kFolderNameColumn = 'FNam'
, kFolderNumUnreadColumn = 'NumU'
, kFolderNumTotalColumn = 'NumT'
/* COfflinePickerView */
, kSelectFolderColumn = 'SelF'
/* CSubscribeView */
, kNewsgroupNameColumn = 'NuNm'
, kNewsgroupSubscribedColumn = 'NuSb'
, kNewsgroupPostingsColumn = 'NuPo'
/* CSearchTableView */
, kStatusMessageLocation = 'Loca'
, kNameEntryColumn = 'Name'
, kEmailEntryColumn = 'Emal'
, kCompanyEntryColumn = 'Comp'
, kCityEntryColumn = 'City'
, kPhoneEntryColumn = 'Phon'
};
//
// ID#s of 'Cols' resources, for saving the column
// positions of the various table views...
//
enum
{
kSavedInboxColumnStateID = 10501,
kSavedDraftsColumnStateID = 10502,
kSavedOutboxColumnStateID = 10503,
kSavedFiledMailColumnStateID = 10504,
kSavedFiledMailFolderColumnStateID = 10506,
kSavedNewsgroupColumnStateID = 10505
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,561 @@
/* -*- 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.
*/
// SearchHelpers.h
#pragma once
/*======================================================================================
DESCRIPTION: Defines classes related to the Mail & News search dialog.
======================================================================================*/
/*====================================================================================*/
#pragma mark INCLUDE FILES
/*====================================================================================*/
#include "CDateView.h"
#include "CGAIconPopup.h"
#include "CSaveWindowStatus.h"
#include "LTableRowSelector.h"
#include "CMailFlexTable.h"
#include <LGAEditField.h>
#include <LGACheckbox.h>
// FE Stuff
#include "macutil.h"
class CFolderScopeGAPopup;
class CSearchPopupMenu;
class LBroadcasterEditField;
class CSearchDateField;
class CSearchTabGroup;
class LTableView;
class CString;
#pragma mark -
/*====================================================================================*/
#pragma mark TYPEDEFS
/*====================================================================================*/
typedef struct MSG_SearchMenuItem MSG_SearchMenuItem;
#pragma mark -
/*====================================================================================*/
#pragma mark CONSTANTS
/*====================================================================================*/
#pragma mark -
/*====================================================================================*/
#pragma mark EXTERNAL FUNCTION PROTOTYPES
/*====================================================================================*/
inline Boolean IsBetween(Int32 inVal, Int32 inMin, Int32 inMax) {
return ((inVal >= inMin) && (inVal <= inMax));
}
#ifdef DEBUGGER_ASSERTIONS
#undef AssertFail_
#undef Assert_
#ifdef Debug_Signal
#define AssertFail_(test) ThrowIfNot_(test)
#define Assert_(test) do { \
if ( !(test) ) { \
Try_ { \
Throw_(noErr); \
} \
Catch_(inErr) { \
} \
EndCatch_ \
} \
} while ( 0 )
#else // Debug_Signal
#define AssertFail_(test) ((void) 0)
#define Assert_(test) ((void) 0)
#endif // Debug_Signal
#endif // DEBUGGER_ASSERTIONS
#undef FailNILRes_
#define FailNILRes_(res) ThrowIfResFail_(res)
#undef FailResErr_
#define FailResErr_() ThrowIfResError_()
#pragma mark -
/*====================================================================================*/
#pragma mark CLASS DECLARATIONS
/*====================================================================================*/
// USearchHelper
class USearchHelper {
public:
// Indexes into STR#8600
enum {
uStr_AllMailFolders = 1
, uStr_AllNewsgroups
, uStr_AllMailFoldersNewsgroups
, uStr_OneMessageFoundSelected
, uStr_NoMessagesFound
, uStr_MultipleMessagesFound
, uStr_OneMessageFound
, uStr_MultipleMessagesSelected
, uStr_SelectedMailFolders
, uStr_SelectedNewsgroups
, uStr_SelectedMailFoldersNewsgroups
, uStr_InFrontFolder
, uStr_SearchForMessages
, uStr_SearchForAddresses
, uStr_FilterDefaultName
, uStr_FilterDefaultDescription
, uStr_SearchFunctionNotImplemented
, uStr_SearchFunctionParamError
, uStr_ExceptionErrorOccurred
, uStr_FilterFunctionNotImplemented
, uStr_FilterFunctionParamError
, uStr_SearchFunctionNothingToSearch
};
static void RegisterClasses();
static LControl *FindViewControl(LView *inView, PaneIDT inID);
static LPane *FindViewSubpane(LView *inView, PaneIDT inID);
static LPane *FindViewVisibleSubpane(LView *inView, PaneIDT inID);
static LView *FindViewSubview(LView *inView, PaneIDT inID);
static LBroadcasterEditField *FindViewEditField(LView *inView, PaneIDT inID);
static CSearchPopupMenu *FindSearchPopup(LView *inView, PaneIDT inID);
static CFolderScopeGAPopup *FindFolderScopePopup(LView *inView, PaneIDT inID);
static CSearchDateField *FindViewDateField(LView *inView, PaneIDT inID);
static CSearchTabGroup *FindWindowTabGroup(LArray *inSubcommanders);
static void RemoveSizeBoxFromVisRgn(LWindow *inWindow);
static void RefreshPortFrameRect(LPane *inPane, Rect *inPortRect);
static void RefreshLocalFrameRect(LPane *inPane, Rect *inLocalRect);
static LWindow *GetPaneWindow(LPane *inPane);
static void LinkListenerToBroadcasters(LView *inContainer, LListener *inListener);
static Int16 GetEditFieldLength(LEditField *inEditField);
static void AssignUString(Int16 inStringIndex, CString& outString);
static void EnableDisablePane(LPane *inPane, Boolean inEnable, Boolean inRefresh = true);
static void ShowHidePane(LPane *inPane, Boolean inDoShow);
static void SetPaneDescriptor(LPane *inPane, const CStr255& inDescriptor);
static void SetDefaultButton(LView *inView, PaneIDT inID, Boolean inIsDefault = true);
static void SelectEditField(LEditField *inEditField);
static void SelectDateView(CDateView *inDateView);
static Boolean LastPaneWasActiveClickPane();
static void CalcDiscreteWindowResizing(LWindow *inWindow, Rect *ioNewBounds,
const Int16 inHIncrement, const Int16 inVIncrement,
Boolean inCheckDesktop = true, Int16 inSizeBoxLeft = 15,
Int16 inSizeBoxTop = 15);
static void ScrollViewBits(LView *inView, Int32 inLeftDelta, Int32 inTopDelta);
enum {
char_OptionKey = 0x003A
, char_ControlKey = 0x003B
, char_CommandKey = 0x0037
, char_ShiftKey = 0x0038
};
static Boolean KeyIsDown(Int16 inKeyCode);
static void GenericExceptionAlert(OSErr inErr);
enum {
paneID_Okay = 'OKAY' // OK button
, paneID_Cancel = 'CNCL' // Cancel button
};
static Boolean HandleDialogKey(LView *inView, const EventRecord &inKeyEvent);
static Boolean MenuItemIsEnabled(MenuHandle inMenuH, Int16 inItem) {
return ((**inMenuH).enableFlags & (1L<<(inItem - 0)));
}
#ifdef NOT_YET
static void GetFolderDisplayName(const char *inFolderName,
CStr255& outFolderName);
#endif // NOT_YET
private:
// Instance variables ==========================================================
static CQDProcs sStdProcs;
};
////////////////////////////////////////////////////////////////////////////////////////////
// CSearchPopupMenu
class CSearchPopupMenu : public CGAIconPopup {
typedef CGAIconPopup Inherited;
public:
enum { class_ID = 'SPUP' };
CSearchPopupMenu(LStream *inStream);
Boolean IsLatentVisible() {
return ((mVisible == triState_Latent) || (mVisible == triState_On));
}
enum { cmd_InvalidMenuItem = -1, cmd_DividerMenuItem = -2 };
virtual CommandT GetCurrentItemCommandNum(Int16 inMenuItem = 0);
Int16 GetCommandItemIndex(CommandT inMenuCommand);
void SetCurrentItemByCommand(CommandT inMenuCommand);
Int16 GetNumCommands() {
return mCommands.GetCount();
}
CommandT GetOldItemCommand() const;
virtual void SetValue(Int32 inValue);
void SetToDefault() {
SetValue(mDefaultItem);
}
void PopulateMenu(MSG_SearchMenuItem *inMenuItems, const Int16 inNumItems,
CommandT inNewCommandIfInvalid, UInt32 inPopulateID = 0);
void ClearMenu(Int16 inStartItem = 1);
void AppendMenuItemCommand(CommandT inCommand, ConstStr255Param inName, Boolean inIsEnabled);
void SetMenuItemCommand(CommandT inOldCommand, CommandT inNewCommand,
ConstStr255Param inName, Boolean inIsEnabled);
void SetIndexCommand(Int16 inIndex, CommandT inCommand) {
mCommands.AssignItemsAt(1, inIndex, &inCommand);
}
void RemoveMenuItemCommand(CommandT inRemoveCommand,
CommandT inNewCommandIfInvalid);
// unused code - 11/21/97
//
// Boolean UpdateMenuItemCommand(Int16 inMenuItem, CommandT inNewCommand,
// ConstStr255Param inName, Boolean inIsEnabled);
// void SetCurrentItemByName(ConstStr255Param inName);
protected:
virtual void FinishCreateSelf();
virtual void BroadcastValueMessage();
virtual Boolean TrackHotSpot(Int16 inHotSpot, Point inPoint, Int16 inModifiers);
// Instance variables ==========================================================
LArray mCommands;
UInt32 mLastPopulateID;
Int16 mDefaultItem;
Int16 mOldValue;
}; // CSearchPopupMenu
// CSearchEditField
class CSearchEditField : public LGAEditField {
typedef LGAEditField Inherited;
public:
enum { class_ID = 'SEFD' };
// Broadcast messages
enum {
msg_UserChangedText = 'cTxt' // PaneIDT *
};
CSearchEditField(LStream *inStream) :
LGAEditField(inStream) {
SetRefreshAllWhenResized(false);
}
Int16 GetTextLength() {
return (**mTextEditH).teLength;
}
Boolean IsLatentVisible() {
return ((mVisible == triState_Latent) || (mVisible == triState_On));
}
virtual void UserChangedText() {
PaneIDT paneID = mPaneID;
BroadcastMessage(msg_UserChangedText, &paneID);
}
virtual void SetDescriptor(ConstStr255Param inDescriptor);
void SetText(const char *inText);
char *GetText(char *outText);
virtual void ResizeFrameBy(Int16 inWidthDelta, Int16 inHeightDelta,
Boolean inRefresh);
virtual Boolean HandleKeyPress(const EventRecord &inKeyEvent);
protected:
};
// CSearchDateField
class CSearchDateField : public CDateView {
public:
enum { class_ID = 'SDFD' };
CSearchDateField(LStream *inStream) :
CDateView(inStream) {
}
Boolean IsLatentVisible() {
return ((mVisible == triState_Latent) || (mVisible == triState_On));
}
protected:
};
// CSearchTabGroup
class CSearchTabGroup : public LTabGroup {
public:
// Stream creator method
enum { class_ID = 'SrTg' };
CSearchTabGroup(LStream* /*inStream*/) :
LTabGroup(),
mCanRotate(nil) {
}
CSearchTabGroup() :
LTabGroup(),
mCanRotate(nil) {
}
void SetRotateWatchValue(Boolean *inWatchValue) {
mCanRotate = inWatchValue;
}
virtual void RotateTarget(Boolean inBackward);
protected:
// Instance variables ==========================================================
Boolean *mCanRotate;
};
// CSearchCaption
class CSearchCaption : public LCaption {
public:
// Stream creator method
enum { class_ID = 'SrCp' };
CSearchCaption(LStream *inStream) :
LCaption(inStream) {
}
protected:
virtual void DrawSelf();
virtual void EnableSelf() {
Draw(nil);
}
virtual void DisableSelf() {
Draw(nil);
}
};
// StTableClipRgnState
class StSectClipRgnState {
public:
StSectClipRgnState(const Rect *inLocalRect, const Rect *inDisplayRect = nil);
~StSectClipRgnState();
static Boolean RectEnclosesRect(const Rect *inEnclosingRect, const Rect *inInsideRect);
protected:
// Instance variables ==========================================================
static RgnHandle sClipRgn;
static Boolean sSetClip;
#ifdef Debug_Signal
static Boolean sTableClipRgnAround;
#endif // Debug_Signal
};
#if 0
// CRowTableSelector
class CRowTableSelector : public LTableRowSelector {
public:
CRowTableSelector(LTableView *inTableView, Boolean inAllowMultiple = true) :
LTableRowSelector(inTableView, inAllowMultiple),
mRowCount(0) {
mItemSize = sizeof(UInt32);
mComparator = LLongComparator::GetComparator();
mKeepSorted = true;
}
virtual Boolean CellIsSelected(const STableCell &inCell) const;
virtual TableIndexT GetSelectedIndices(TableIndexT **outIndices, Int16 inBase) const;
virtual TableIndexT GetFirstSelectedRow() const;
UInt32 GetRowCount() const { return mRowCount; }
protected:
enum { eInvalidID = 0xFFFFFFFF };
virtual UInt32 GetRowUniqueID(const TableIndexT inRow) const = 0L;
virtual TableIndexT GetUniqueIDRow(const UInt32 inID) const = 0L;
virtual void DoSelect(const TableIndexT inRow, Boolean inSelect,
Boolean inHilite, Boolean inNotify);
virtual void InsertRows(UInt32 inHowMany, TableIndexT /*inAfterRow*/) {
mRowCount += inHowMany;
}
virtual void RemoveRows(Uint32 inHowMany, TableIndexT inFromRow);
// Instance variables ==========================================================
UInt32 mRowCount; // Count of the number of rows in the table. Need this
// since RemoveRows() is called after rows have been removed!
};
#endif //0
#if 0 //0
// CExTable
class CExTable : public CMailFlexTable {
private:
typedef CMailFlexTable Inherited;
public:
CExTable(LStream *inStream) :
CMailFlexTable(inStream),
mFlags(0),
mBlackAndWhiteHiliting(false) {
}
Boolean CellsAreSelected() {
return IsValidCell(GetFirstSelectedCell());
}
TableIndexT GetNumRows() {
return mRows;
}
void SelectScrollCell(const STableCell &inCell) {
SelectCell(inCell);
ScrollCellIntoFrame(inCell);
}
void RefreshRowRange(TableIndexT inStartRow, TableIndexT inEndRow) {
TableIndexT topRow, botRow;
if ( inStartRow < inEndRow ) {
topRow = inStartRow; botRow = inEndRow;
} else {
topRow = inEndRow; botRow = inStartRow;
}
RefreshCellRange(STableCell(topRow, 1), STableCell(botRow, mCols));
}
virtual void ReadSavedTableStatus(LStream *inStatusData);
virtual void WriteSavedTableStatus(LStream *outStatusData);
virtual Boolean CellHasDropFlag(const STableCell &/*inCell*/, Boolean &/*outIsExpanded*/) const { return false; }
protected:
enum { // Flags
flag_DontDrawHiliting = 0x01
, flag_IsDrawingSelf = 0x02
, flag_IsLoosingTarget = 0x04
};
virtual MSG_Pane *GetBEPane() const = 0L;
virtual Boolean IsMyPane(void* info) const {
return (GetBEPane() == reinterpret_cast<SMailCallbackInfo *>(info)->pane);
}
virtual void FindCommandStatus(CommandT inCommand, Boolean &outEnabled, Boolean &outUsesMark,
Char16 &outMark, Str255 outName);
virtual Boolean ObeyCommand(CommandT inCommand, void *ioParam = nil);
virtual void ScrollBits(Int32 inLeftDelta, Int32 inTopDelta);
virtual void DrawSelf();
virtual void ActivateSelf();
virtual void DeactivateSelf();
virtual void BeTarget();
virtual void DontBeTarget();
virtual void HiliteSelection(Boolean inActively, Boolean inHilite);
virtual void HiliteCellInactively(const STableCell &inCell, Boolean inHilite);
virtual void HiliteCellActively(const STableCell &inCell, Boolean inHilite);
Boolean GetBlackAndWhiteHiliting() {
return mBlackAndWhiteHiliting;
}
Boolean DrawHiliting() {
return !(mFlags & flag_DontDrawHiliting);
}
Boolean DrawFullHiliting() {
return !(mFlags & flag_IsLoosingTarget);
}
void FocusDrawSelectedCells(Boolean inHilite, const STableCell *inCell = nil);
void DrawCellRow(STableCell &inCell, Boolean inErase, Boolean inActive);
void PlaceHilitedTextInRect(const char *inText, Uint32 inTextLength, const Rect &inRect,
Int16 inHorizJustType, Int16 inVertJustType,
const FontInfo *inFontInfo, Boolean inDoTruncate,
TruncCode inTruncWhere);
Boolean GetVisibleRowRange(TableIndexT *inStartRow, TableIndexT *inEndRow);
// Backend methods
#if 0
virtual void MsgPaneChanged() = 0L;
virtual Int32 GetBENumRows() = 0L;
virtual void ChangeStarting(MSG_Pane *inPane, MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow, SInt32 inRowCount);
virtual void ChangeFinished(MSG_Pane *inPane, MSG_NOTIFY_CODE inChangeCode,
TableIndexT inStartRow, SInt32 inRowCount);
#endif
// Instance variables ==========================================================
UInt8 mFlags;
Boolean mBlackAndWhiteHiliting;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/* -*- 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) 1997 Netscape Communications Corporation. All Rights
* Reserved.
*/
// StGetInfoHandler.h
#pragma once
#include "UStdDialogs.h"
class LCommander;
class CMessageFolder;
class CServerListMediator;
class MSG_Host;
//======================================
class StGetInfoHandler : public StStdDialogHandler
//======================================
{
public:
StGetInfoHandler(ResIDT inDialogResID,
LCommander *inSuper)
: StStdDialogHandler(inDialogResID, inSuper)
, mDataWritten(false)
{}
virtual ~StGetInfoHandler();
virtual void ReadDataFields() = 0;
virtual void WriteDataFields() = 0;
virtual Boolean UserDismissed();
virtual MessageT DoDialog();
virtual void HideAndCripplePane(PaneIDT paneID); // crippled panes don't write their prefs out
virtual void ShowAndUncripplePane(PaneIDT paneID);
protected:
Boolean mDataWritten;
}; // class StGetInfoHandler
typedef Boolean (*ServerNameValidationFunc)(const CStr255& inServerName, Boolean inNewServer, const CServerListMediator* inServerList);
//======================================
class UGetInfo
//======================================
{
public:
static UInt32 CountIMAPServers();
static void ConductFolderInfoDialog(CMessageFolder&, LCommander* inSuper);
enum { kStandAloneDialog = false, kSubDialogOfPrefs = true };
static Boolean ConductMailServerInfoDialog(
CStr255& ioName,
Boolean& ioPOP,
Boolean inIsNewServer,
Boolean inAllowServerNameEdit = false,
Boolean inAllowTypeChange = false, // whether to allow the user to change POP to IMAP or v.v.
Boolean inFromPrefsDialog = false,
ServerNameValidationFunc inValidationFunc = nil,
CServerListMediator* inValidationServerMediator = nil,
LCommander* inSuper = nil);
static Boolean ConductNewsServerInfoDialog(
MSG_Host* inHost,
LCommander* inSuper = nil);
static void RegisterGetInfoClasses();
static void GetDefaultUserName(CStr255&);
};

View File

@ -0,0 +1,59 @@
/* -*- 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.
*/
// UIHelper.h
#pragma once
///////////////////////////////////////////////////////////////////////////////////
//
// This file contains some helper functions for UI manipulation.
//
///////////////////////////////////////////////////////////////////////////////////
//
// FindUIItemPtr - returns a pointer to the proper item
// Usage:
//
// LGAPushButton* button;
// LView view;
// PaneIDT paneID;
//
// FindUIItem( view, paneID, button );
//
// It will throw an exception if the element is missing or the passed
// pointer is the wrong type.
//
///////////////////////////////////////////////////////////////////////////////////
#include "PP_Types.h"
#include "LView.h"
#include "nc_exception.h"
///////////////////////////////////////////////////////////////////////////////////
// FindUIItemPtr
template <class T>
inline
void
FindUIItemPtr( LView *inView, long inID, T*& outItemPtr )
{
outItemPtr = dynamic_cast<T*>( inView->FindPaneByID( inID ) );
if( !outItemPtr )
throw nc_exception( eUIResourceError );
}

View File

@ -0,0 +1,89 @@
/* -*- 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.
*/
// This file implements a callback declared in msgcom.h, for presenting the IMAP
// subscription upgrade dialog.
#include "msgcom.h" // For the prototype, and the enum for the return value.
#include "PascalString.h"
#include "macutil.h"
#include "UStdDialogs.h"
#include "resgui.h" // for msg_Help
#include "xp_help.h"
#include <LGARadioButton.h>
#include <Sound.h> // for SysBeep()
//----------------------------------------------------------------------------------------
MSG_IMAPUpgradeType FE_PromptIMAPSubscriptionUpgrade(MWContext*, const char* hostName)
//----------------------------------------------------------------------------------------
{
StDialogHandler handler(14007, NULL);
LWindow* dialog = handler.GetDialog(); // initially invisible.
// Find the radio button for the "Automatic" choice.
LGARadioButton* autoButton = (LGARadioButton*)dialog->FindPaneByID('AUTO');
SignalIf_(!autoButton);
if (!autoButton)
return MSG_IMAPUpgradeDont;
// Replace ^0 in the radio button string with the host name that was given to us
CStr255 workString;
autoButton->GetDescriptor(workString);
StringParamText(workString, hostName);
autoButton->SetDescriptor(workString);
// Run the dialog
MSG_IMAPUpgradeType result = MSG_IMAPUpgradeAutomatic;
MessageT message = msg_Nothing;
if (UStdDialogs::TryToInteract())
{
dialog->Show();
do {
message = handler.DoDialog();
switch (message)
{
case msg_Help:
ShowHelp( HELP_IMAP_UPGRADE );
break;
#if 0
// This doesn't work, and here's why. When one of the radio buttons is
// clicked, first the value message gets broadcast (good), and then
// the radio group broadcasts "msg_ControlClicked". Unfortunately,
// StDialogHandler merely stores the last message it receives!
case 'AUTO':
result = MSG_IMAPUpgradeAutomatic;
break;
case 'PICK':
result = MSG_IMAPUpgradeCustom;
break;
#endif
}
} while (message != msg_OK && message != msg_Cancel);
}
// Use the OK/Cancel message together with the value of the the radio button for
// the automatic choice to determine the result.
if (message != msg_OK)
result = MSG_IMAPUpgradeDont;
else if (autoButton->GetValue() == Button_On)
result = MSG_IMAPUpgradeAutomatic;
else
result = MSG_IMAPUpgradeCustom;
return result;
} // FE_PromptIMAPSubscriptionUpgrade

Some files were not shown because too many files have changed in this diff Show More