gecko-dev/lib/libmsg/msgundac.cpp

882 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* msgundac.cpp --- Msg undo actions implementation
*/
#include "msg.h"
#include "errcode.h"
#include "xp_str.h"
#include "xpgetstr.h"
#include "msgdbvw.h"
#include "maildb.h"
#include "msgmpane.h"
#include "msgundac.h"
#include "msgutils.h"
#include "msgprefs.h"
#include "msgtpane.h"
#include "msgfpane.h"
#include "prsembst.h"
#include "msgimap.h"
#include "imapoff.h"
extern "C"
{
extern int MK_MSG_ID_NOT_IN_FOLDER;
}
//////////////////////////////////////////////////////////////////////
// **** MarkMessageUndoAction
//////////////////////////////////////////////////////////////////////
MarkMessageUndoAction::MarkMessageUndoAction(MSG_Pane *pane,
MSG_CommandType command,
MSG_ViewIndex *indices,
int32 numIndices,
MSG_FolderInfo *folder)
{
XP_ASSERT (pane && folder);
MessageDBView *view = pane->GetMsgView();
if (view)
{
for (int i=0; i < numIndices; i++)
m_keyArray.Add( view->GetAt(*(indices+i)));
}
m_pane = pane;
m_command = command;
m_folder = folder;
}
MarkMessageUndoAction::MarkMessageUndoAction(MSG_Pane *pane,
MSG_CommandType command,
MSG_FolderInfo *folder)
{
XP_ASSERT (pane && folder);
m_pane = pane;
m_command = command;
m_folder = folder;
}
MarkMessageUndoAction::~MarkMessageUndoAction()
{
}
void
MarkMessageUndoAction::AddKey(MessageKey key)
{
XP_ASSERT(MSG_MESSAGEKEYNONE != key);
if (MSG_MESSAGEKEYNONE == key) return;
m_keyArray.Add(key);
}
MSG_CommandType
MarkMessageUndoAction::GetUndoMarkCommand()
{
if (m_owner->GetState() == UndoRedoing)
return m_command;
switch (m_command)
{
case MSG_MarkMessages:
return MSG_UnmarkMessages;
case MSG_UnmarkMessages:
return MSG_MarkMessages;
case MSG_MarkMessagesRead:
return MSG_MarkMessagesUnread;
case MSG_MarkMessagesUnread:
return MSG_MarkMessagesRead;
case MSG_ToggleMessageRead:
return MSG_ToggleMessageRead;
default:
return m_command;
}
}
UndoStatus
MarkMessageUndoAction::DoUndo()
{
XP_ASSERT (m_pane);
MessageDBView *view;
MSG_ViewIndex viewIndex = MSG_VIEWINDEXNONE;
uint i, size = m_keyArray.GetSize();
if (!size) return UndoFailed;
MsgERR status = eSUCCESS;
if (m_pane->GetFolder() != m_folder) {
if (m_pane->GetPaneType() == MSG_MESSAGEPANE)
((MSG_MessagePane*)m_pane)->LoadMessage(m_folder, m_keyArray.GetAt(size-1), NULL, TRUE);
else if (m_pane->GetPaneType() == MSG_THREADPANE)
((MSG_ThreadPane*)m_pane)->LoadFolder(m_folder);
}
view = m_pane->GetMsgView();
if (view) {
for (i=0; i < size; i++)
{
viewIndex = view->FindKey (m_keyArray.GetAt(i), TRUE);
if ( viewIndex != MSG_VIEWINDEXNONE )
{
m_pane->StartingUpdate(MSG_NotifyNone, viewIndex, 1);
status = m_pane->ApplyCommandToIndices(GetUndoMarkCommand(),
&viewIndex, 1);
m_pane->EndingUpdate(MSG_NotifyNone, viewIndex, 1);
}
}
}
if (status == eSUCCESS)
return UndoComplete;
else
return UndoFailed;
}
XP_Bool
MarkMessageUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_folder == folder);
}
//////////////////////////////////////////////////////////////////////////////
// UndoMarkChangeListener
//
UndoMarkChangeListener::UndoMarkChangeListener(MSG_Pane *pane,
MSG_FolderInfo *folderInfo,
MSG_CommandType command)
{
XP_ASSERT(pane && folderInfo);
m_pane = pane;
m_folderInfo = folderInfo;
m_undoAction = NULL;
m_command = command;
}
UndoMarkChangeListener::~UndoMarkChangeListener()
{
// if there is a undoAction add undo manager
if (m_undoAction)
m_pane->GetUndoManager()->AddUndoAction(m_undoAction);
}
void
UndoMarkChangeListener::OnKeyChange(MessageKey keyChanged,
int32 flags,
ChangeListener* /*instigator*/)
{
int32 tmpFlags = 0;
switch (m_command)
{
case MSG_MarkMessagesRead:
case MSG_ToggleMessageRead:
tmpFlags = kIsRead;
break;
case MSG_MarkMessagesUnread:
tmpFlags = ~kIsRead;
break;
case MSG_MarkMessages:
tmpFlags = kMsgMarked;
break;
case MSG_UnmarkMessages:
tmpFlags = ~kMsgMarked;
break;
default:
break;
}
if (flags & tmpFlags) {
if (!m_undoAction)
m_undoAction = new MarkMessageUndoAction (m_pane, m_command, m_folderInfo);
XP_ASSERT (m_undoAction);
m_undoAction->AddKey(keyChanged);
}
}
/////////////////////////////////////////////////////////////////////////////
// MoveCopyMessagesUndoAction
////////////////////////////////////////////////////////////////////////////
MoveCopyMessagesUndoAction::MoveCopyMessagesUndoAction (
MSG_FolderInfo *srcFolder,
MSG_FolderInfo *dstFolder,
XP_Bool isMove,
MSG_Pane *pane,
MessageKey prevKeyToLoad,
MessageKey nextKeyToLoad)
{
XP_ASSERT (srcFolder && dstFolder && pane);
m_srcFolder = srcFolder;
m_dstFolder = dstFolder;
m_isMove = isMove;
m_pane = pane;
m_prevKeyToLoad = prevKeyToLoad;
m_nextKeyToLoad = nextKeyToLoad;
m_mailDB = NULL;
}
XP_Bool
MoveCopyMessagesUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_srcFolder == folder ||
m_dstFolder == folder);
}
MoveCopyMessagesUndoAction::~MoveCopyMessagesUndoAction()
{
}
UndoStatus
MoveCopyMessagesUndoAction::DoUndo()
{
MailDB *srcDb = NULL, *dstDb = NULL;
MsgERR msgErr = MailDB::Open(m_dstFolder->GetMailFolderInfo()->GetPathname(),
FALSE, &dstDb);
if (eSUCCESS == msgErr)
{
msgErr = MailDB::Open(m_srcFolder->GetMailFolderInfo()->GetPathname(),
FALSE, &srcDb);
if (eSUCCESS == msgErr)
{
uint i, size;
MailMessageHdr* msgHdr;
MessageDBView *view = m_pane->GetMsgView();
if (m_owner->GetState() == UndoUndoing)
{
for (i=0, size = m_dstArray.GetSize(); i < size; i++)
{
if (m_isMove)
{
msgHdr = dstDb->GetMailHdrForKey(m_dstArray.GetAt(i));
if (!msgHdr) // the message must be deleted by someone else
{
// XP_ASSERT(msgHdr);
// *** need to post out some informative message
continue;
}
MailMessageHdr *newHdr = new MailMessageHdr;
XP_ASSERT(newHdr);
newHdr->CopyFromMsgHdr (msgHdr, dstDb->GetDB(), srcDb->GetDB());
newHdr->SetMessageKey(m_srcArray.GetAt(i));
msgErr = srcDb->UndoDelete(newHdr);
delete msgHdr;
delete newHdr;
}
dstDb->DeleteMessage(m_dstArray.GetAt(i));
}
if (m_isMove)
{
m_owner->SetUndoMsgFolder(m_srcFolder);
m_owner->AddMsgKey(m_prevKeyToLoad);
}
}
else
{
for (i=0, size=m_srcArray.GetSize(); i < size; i++)
{
msgHdr = srcDb->GetMailHdrForKey(m_srcArray.GetAt(i));
if (!msgHdr) // the message must be deleted by someone else
{
// XP_ASSERT(msgHdr);
// *** need to post out some informative message
continue;
}
MailMessageHdr *newHdr = new MailMessageHdr;
XP_ASSERT(newHdr);
newHdr->CopyFromMsgHdr (msgHdr, srcDb->GetDB(), dstDb->GetDB());
newHdr->SetMessageKey(m_dstArray.GetAt(i));
msgErr = dstDb->UndoDelete(newHdr);
delete msgHdr;
if (m_isMove)
{
srcDb->DeleteMessage(m_srcArray.GetAt(i));
}
}
if (m_isMove)
{
m_owner->SetUndoMsgFolder(m_srcFolder);
m_owner->AddMsgKey(m_nextKeyToLoad);
}
}
srcDb->Close();
dstDb->Close();
return UndoComplete;
}
else
{
dstDb->Close();
if (srcDb)
srcDb->Close();
return ReCreateMailDB(m_srcFolder);
}
}
else
{
if (dstDb)
dstDb->Close();
return ReCreateMailDB(m_dstFolder);
}
}
void
MoveCopyMessagesUndoAction::AddDstKey(MessageKey key)
{
m_dstArray.Add(key);
}
void
MoveCopyMessagesUndoAction::AddSrcKey(MessageKey key)
{
m_srcArray.Add(key);
}
UndoStatus
MoveCopyMessagesUndoAction::UndoPreExit()
{
if (m_mailDB)
{
m_mailDB->Close();
m_mailDB = NULL;
}
return DoUndo();
}
UndoStatus
MoveCopyMessagesUndoAction::ReCreateMailDB(MSG_FolderInfo *folder)
{
const char *pathname = folder->GetMailFolderInfo()->GetPathname();
char * url = PR_smprintf ("mailbox:%s", pathname);
URL_Struct *url_struct = NET_CreateURLStruct(url, NET_DONT_RELOAD);
MailDB *mailDB;
MsgERR status = eUNKNOWN;
XP_FileRemove(pathname, xpMailFolderSummary);
status = MailDB::Open(pathname, TRUE, &mailDB);
if (mailDB != NULL && (status == eSUCCESS || status == eNoSummaryFile))
{
// mailDB->Close(); // decrement ref count.
m_mailDB = mailDB;
ParseMailboxState *parseMailboxState = new ParseMailboxState(pathname);
// parseMailboxState->SetView(m_view);
parseMailboxState->SetIncrementalUpdate(FALSE);
parseMailboxState->SetMaster(m_pane->GetMaster());
parseMailboxState->SetDB(mailDB);
parseMailboxState->SetContext(m_pane->GetContext());
parseMailboxState->SetFolder(folder);
folder->GetMailFolderInfo()->SetParseMailboxState(parseMailboxState);
url_struct->msg_pane = m_pane;
UndoURLHook(url_struct);
m_pane->GetURL(url_struct, FALSE);
return UndoInProgress;
}
else
return UndoFailed;
}
///////////////////////////////////////////////////////////////////////////
// MoveFolderUndoAction
///////////////////////////////////////////////////////////////////////////
MoveFolderUndoAction::MoveFolderUndoAction (MSG_Pane *pane,
MSG_FolderInfo *srcParent,
MSG_FolderInfo *srcFolder,
MSG_FolderInfo *dstFolder)
{
XP_ASSERT (pane && srcFolder && dstFolder);
m_pane = pane;
m_srcParent = srcParent;
m_srcFolder = srcFolder;
m_dstFolder = dstFolder;
}
MoveFolderUndoAction::~MoveFolderUndoAction ()
{
}
XP_Bool
MoveFolderUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_srcParent == folder ||
m_srcFolder == folder ||
m_dstFolder == folder);
}
UndoStatus
MoveFolderUndoAction::DoUndo()
{
MSG_FolderPane *folderPane = (MSG_FolderPane*) m_pane;
MsgERR err = eUNKNOWN;
MSG_FolderInfo *destFolder, *srcFolder, *srcParent;
srcFolder = m_srcFolder;
if (m_owner->GetState() == UndoUndoing) {
srcParent = m_dstFolder;
destFolder = m_srcParent;
}
else {
srcParent = m_srcParent;
destFolder = m_dstFolder;
}
// If we're moving into an IMAP folder, start the URL here
if ( ((destFolder->GetType() == FOLDER_IMAPMAIL) ||
(destFolder == m_pane->GetMaster()->GetImapMailFolderTree())) &&
(srcFolder->GetType() == FOLDER_IMAPMAIL) )
{
const char *destinationName = ""; // covers promote to root
char destinationHierarchySeparator = 0; // covers promote to root
if (destFolder->GetType() == FOLDER_IMAPMAIL)
{
destinationName = ((MSG_IMAPFolderInfoMail *)destFolder)->GetOnlineName();
destinationHierarchySeparator = ((MSG_IMAPFolderInfoMail *)destFolder)->GetOnlineHierarchySeparator();
}
// the rename on the server has to happen first imap.h
char *renameMailboxURL = CreateImapMailboxMoveFolderHierarchyUrl
(m_pane->GetPrefs()->GetPopHost(),
((MSG_IMAPFolderInfoMail *) srcFolder)->GetOnlineName(),
((MSG_IMAPFolderInfoMail *) srcFolder)->GetOnlineHierarchySeparator(),
destinationName,destinationHierarchySeparator);
if (renameMailboxURL)
{
URL_Struct *url_struct = NET_CreateURLStruct(renameMailboxURL, NET_SUPER_RELOAD);
if (url_struct) {
url_struct->msg_pane = m_pane;
UndoURLHook(url_struct);
m_pane->GetURL(url_struct, FALSE);
}
XP_FREE(renameMailboxURL);
}
return UndoInProgress;
}
else
{
err = folderPane->UndoMoveFolder(srcParent, srcFolder, destFolder);
}
if (eSUCCESS == err)
return UndoComplete;
return UndoFailed;
}
//////////////////////////////////////////////////////////////////////////////
// RenameFolderUndoAction
//////////////////////////////////////////////////////////////////////////////
RenameFolderUndoAction::RenameFolderUndoAction(MSG_Pane *pane,
MSG_FolderInfo *folder,
const char *oldName,
const char *newName)
{
XP_ASSERT (pane && folder && oldName && newName);
m_pane = pane;
m_folder = folder;
m_oldName = XP_STRDUP(oldName);
m_newName = XP_STRDUP(newName);
}
XP_Bool
RenameFolderUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_folder == folder);
}
RenameFolderUndoAction::~RenameFolderUndoAction()
{
XP_FREE (m_oldName);
XP_FREE (m_newName);
}
UndoStatus
RenameFolderUndoAction::DoUndo()
{
MsgERR err = eUNKNOWN;
if (m_owner->GetState() == UndoUndoing)
err = ((MSG_FolderPane*)m_pane)->RenameFolder(m_folder, m_oldName);
else
err = ((MSG_FolderPane*)m_pane)->RenameFolder(m_folder, m_newName);
if (err == eSUCCESS)
return UndoComplete;
return UndoFailed;
}
///////////////////////////////////////////////////////////////////////////
// IMAPMoveMessagesUndoAction
///////////////////////////////////////////////////////////////////////////
IMAPMoveCopyMessagesUndoAction::IMAPMoveCopyMessagesUndoAction(
MSG_Pane *pane,
MSG_FolderInfo *srcFolder,
MSG_FolderInfo *dstFolder,
XP_Bool isMove,
MessageKey prevKeyToLoad,
MessageKey nextKeyToLoad)
{
XP_ASSERT(pane && srcFolder && dstFolder);
m_pane = pane;
m_srcFolder = srcFolder;
m_dstFolder = dstFolder; /* just for the record; cannot do anything */
m_prevKeyToLoad = prevKeyToLoad;
m_nextKeyToLoad = nextKeyToLoad;
m_isMove = isMove;
}
IMAPMoveCopyMessagesUndoAction::~IMAPMoveCopyMessagesUndoAction()
{
}
XP_Bool
IMAPMoveCopyMessagesUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_srcFolder == folder);
}
UndoStatus
IMAPMoveCopyMessagesUndoAction::DoUndo()
{
if (! m_keyArray.GetSize()) return UndoComplete;
if (((MSG_IMAPFolderInfoMail *)m_srcFolder)->UndoMoveCopyMessagesHelper(
m_pane, m_keyArray, this))
return UndoInProgress;
else
return UndoFailed;
}
UndoStatus
IMAPMoveCopyMessagesUndoAction::UndoPreExit()
{
if (m_owner->GetState() == UndoUndoing) {
if (m_isMove)
m_owner->AddMsgKey(m_prevKeyToLoad);
}
else {
if (m_isMove)
m_owner->AddMsgKey(m_nextKeyToLoad);
}
return UndoComplete;
}
void
IMAPMoveCopyMessagesUndoAction::AddKey(MessageKey key)
{
m_keyArray.Add(key);
}
////////////////////////////////////////////////////////////////////
// IMAPRenameFolderUndoAction
////////////////////////////////////////////////////////////////////
IMAPRenameFolderUndoAction::IMAPRenameFolderUndoAction(
MSG_Pane *pane,
MSG_FolderInfo *folder,
const char *oldName,
const char *newName)
{
XP_ASSERT (pane && folder && oldName && newName);
m_pane = pane;
m_folder = folder;
m_oldName = XP_STRDUP(oldName);
m_newName = XP_STRDUP(newName);
}
XP_Bool
IMAPRenameFolderUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return (m_folder == folder);
}
IMAPRenameFolderUndoAction::~IMAPRenameFolderUndoAction()
{
XP_FREE (m_oldName);
XP_FREE (m_newName);
}
UndoStatus
IMAPRenameFolderUndoAction::DoUndo()
{
char *renameMailboxURL = NULL;
if (m_owner->GetState() == UndoUndoing) {
renameMailboxURL = CreateImapMailboxRenameLeafUrl(
m_pane->GetPrefs()->GetPopHost(),
((MSG_IMAPFolderInfoMail *)m_folder)->GetOnlineName(),
((MSG_IMAPFolderInfoMail *)m_folder)->GetOnlineHierarchySeparator(),
m_oldName);
}
else {
renameMailboxURL = CreateImapMailboxRenameLeafUrl(
m_pane->GetPrefs()->GetPopHost(),
((MSG_IMAPFolderInfoMail *)m_folder)->GetOnlineName(),
((MSG_IMAPFolderInfoMail *)m_folder)->GetOnlineHierarchySeparator(),
m_newName);
}
if (renameMailboxURL) {
URL_Struct *url_struct =
NET_CreateURLStruct(renameMailboxURL, NET_SUPER_RELOAD);
XP_FREEIF(renameMailboxURL);
if (url_struct) {
url_struct->msg_pane = m_pane;
UndoURLHook(url_struct);
m_pane->GetURL(url_struct, FALSE);
return UndoInProgress;
}
}
return UndoFailed;
}
UndoStatus
IMAPRenameFolderUndoAction::UndoPreExit()
{
// this may work
return UndoComplete;
}
////////////////////////////////////////////////////////////
// OfflineIMAPUndoAction
////////////////////////////////////////////////////////////
UndoIMAPChangeListener::UndoIMAPChangeListener(OfflineIMAPUndoAction *action)
{
m_undoAction = action;
}
UndoIMAPChangeListener::~UndoIMAPChangeListener()
{
}
void UndoIMAPChangeListener::OnAnnouncerGoingAway(ChangeAnnouncer * /*instigator*/)
{
if (m_undoAction->m_db)
{
m_undoAction->m_db->RemoveListener(this);
m_undoAction->m_db = NULL;
}
}
OfflineIMAPUndoAction::OfflineIMAPUndoAction (MSG_Pane *pane, MSG_FolderInfo* folder,
MessageKey dbKey, int32 opType,
MSG_FolderInfo *srcFolder, MSG_FolderInfo *dstFolder,
imapMessageFlagsType flags, MailMessageHdr *hdr, XP_Bool addFlag)
{
XP_Bool dbWasCreated=FALSE;
m_pane = pane;
m_dbKey = dbKey;
m_folder = (MSG_IMAPFolderInfoMail*) folder;
m_srcFolder = (MSG_IMAPFolderInfoMail*) srcFolder;
m_dstFolder = (MSG_IMAPFolderInfoMail*) dstFolder;
m_opType = opType;
m_flags = flags;
m_header = NULL;
m_db = NULL;
m_addFlags = addFlag;
m_changeListener = NULL;
if (!m_srcFolder)
m_srcFolder = m_folder;
if (hdr)
{
MsgERR dbStatus = ImapMailDB::Open(m_srcFolder->GetMailFolderInfo()->GetPathname(), TRUE, // create if necessary
(MailDB**) &m_db, m_pane->GetMaster(), &dbWasCreated);
if (!m_db)
return;
m_header = new MailMessageHdr;
m_header->CopyFromMsgHdr (hdr, m_db->GetDB(), m_db->GetDB());
m_changeListener = new UndoIMAPChangeListener(this);
m_db->AddListener(m_changeListener);
}
}
XP_Bool OfflineIMAPUndoAction::HasFolder(MSG_FolderInfo *folder)
{
return ((MSG_FolderInfo*) m_folder == folder);
}
OfflineIMAPUndoAction::~OfflineIMAPUndoAction()
{
if (m_db)
{
delete m_header;
if (m_changeListener)
m_db->RemoveListener(m_changeListener);
m_db->Close();
m_db = NULL;
}
else
XP_ASSERT(!m_header);
}
// Open the database and find the key for the offline operation that we want to
// undo, then remove it from the database, we also hold on to this
// data for a redo operation.
// Lesson I learned the hard way, you do not RemoveReference after an Add or Delete operation on
// a header or op item.
UndoStatus OfflineIMAPUndoAction::DoUndo()
{
IDArray keys;
ImapMailDB *destdb = NULL;
DBOfflineImapOperation *op = NULL;
XP_Bool dbWasCreated=FALSE;
MailMessageHdr *restoreHdr = NULL;
MsgERR dbStatus = 0;
if (!m_folder || !m_pane)
return UndoFailed;
dbStatus = ImapMailDB::Open(m_srcFolder->GetMailFolderInfo()->GetPathname(), TRUE, // create if necessary
(MailDB**) &m_db, m_pane->GetMaster(), &dbWasCreated);
if (!m_db)
return UndoFailed;
if (m_owner->GetState() == UndoRedoing) // REDO
{
switch (m_opType)
{
case kMsgMoved:
case kMsgCopy:
op = m_db->GetOfflineOpForKey(m_dbKey, TRUE);
if (op)
{
if (m_opType == kMsgMoved)
op->SetMessageMoveOperation(m_dstFolder->GetOnlineName()); // offline move
if (m_opType == kMsgCopy)
op->AddMessageCopyOperation(m_dstFolder->GetOnlineName()); // offline copy
delete op;
op = NULL;
}
m_dstFolder->SummaryChanged();
break;
case kAddedHeader:
dbStatus = ImapMailDB::Open(m_dstFolder->GetMailFolderInfo()->GetPathname(), TRUE, // create if necessary
(MailDB**) &destdb, m_pane->GetMaster(), &dbWasCreated);
if (!destdb)
return UndoFailed;
restoreHdr = new MailMessageHdr;
if (restoreHdr)
{
if (m_header)
{
restoreHdr->CopyFromMsgHdr (m_header, m_db->GetDB(), destdb->GetDB());
int err = destdb->AddHdrToDB(restoreHdr, NULL, FALSE);
}
}
op = destdb->GetOfflineOpForKey(m_dbKey, TRUE);
if (op)
{
op->SetSourceMailbox(m_srcFolder->GetOnlineName(), m_dbKey);
delete op;
}
m_dstFolder->SummaryChanged();
destdb->Close();
break;
case kDeletedMsg:
m_db->DeleteMessage(m_dbKey);
break;
case kMsgMarkedDeleted:
m_db->MarkImapDeleted(m_dbKey, TRUE, NULL);
break;
case kFlagsChanged:
op = m_db->GetOfflineOpForKey(m_dbKey, TRUE);
if (op)
{
if (m_addFlags)
op->SetImapFlagOperation(op->GetNewMessageFlags() | m_flags);
else
op->SetImapFlagOperation(op->GetNewMessageFlags() & ~m_flags);
delete op;
}
break;
default:
break;
}
m_db->Close();
m_db = NULL;
m_srcFolder->SummaryChanged();
return UndoComplete;
}
switch (m_opType) // UNDO
{
case kMsgMoved:
case kMsgCopy:
case kAddedHeader:
case kFlagsChanged:
op = m_db->GetOfflineOpForKey(m_dbKey, FALSE);
if (op)
{
m_db->DeleteOfflineOp(m_dbKey);
delete op;
op = NULL;
}
if (m_header && (m_opType == kAddedHeader))
{
MailMessageHdr *mailHdr = m_db->GetMailHdrForKey(m_header->GetMessageKey());
if (mailHdr)
m_db->DeleteHeader(mailHdr, NULL, FALSE);
delete mailHdr;
}
break;
case kDeletedMsg:
restoreHdr = new MailMessageHdr;
if (restoreHdr)
{
dbStatus = ImapMailDB::Open(m_dstFolder->GetMailFolderInfo()->GetPathname(), TRUE, // create if necessary
(MailDB**) &destdb, m_pane->GetMaster(), &dbWasCreated);
if (!destdb)
return UndoFailed;
if (m_header)
{
restoreHdr->CopyFromMsgHdr (m_header, destdb->GetDB(), m_db->GetDB());
m_db->AddHdrToDB(restoreHdr, NULL, TRUE);
}
destdb->Close();
m_dstFolder->SummaryChanged();
}
break;
case kMsgMarkedDeleted:
m_db->MarkImapDeleted(m_dbKey, FALSE, NULL);
break;
default:
break;
}
m_db->Close();
m_db = NULL;
m_srcFolder->SummaryChanged();
return UndoComplete;
}