add msg db as idl
This commit is contained in:
Родитель
59bd4dcba6
Коммит
d0e76290e4
|
@ -16,7 +16,6 @@
|
|||
# This is a list of local files which get copied to the mozilla:dist:mailnews directory
|
||||
#
|
||||
|
||||
nsIMsgDatabase.h
|
||||
nsINewsDatabase.h
|
||||
nsMsgDatabase.h
|
||||
nsMailDatabase.h
|
||||
|
|
|
@ -26,7 +26,6 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
EXPORTS= \
|
||||
nsMsgHdr.h \
|
||||
nsIMsgDatabase.h \
|
||||
nsINewsDatabase.h \
|
||||
nsMsgDatabase.h \
|
||||
nsMailDatabase.h \
|
||||
|
@ -40,6 +39,7 @@ XPIDLSRCS = \
|
|||
nsIDBFolderInfo.idl \
|
||||
nsIDBChangeListener.idl \
|
||||
nsIDBChangeAnnouncer.idl \
|
||||
nsIMsgDatabase.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
|
|
@ -22,13 +22,13 @@ XPIDLSRCS = \
|
|||
.\nsIDBFolderInfo.idl \
|
||||
.\nsIDBChangeListener.idl \
|
||||
.\nsIDBChangeAnnouncer.idl \
|
||||
.\nsIMsgDatabase.idl \
|
||||
$(NULL)
|
||||
|
||||
################################################################################
|
||||
## exports
|
||||
|
||||
EXPORTS = \
|
||||
nsIMsgDatabase.h \
|
||||
nsINewsDatabase.h \
|
||||
nsMsgDatabase.h \
|
||||
nsMailDatabase.h \
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
nsImapMailDatabase();
|
||||
virtual ~nsImapMailDatabase();
|
||||
|
||||
NS_IMETHOD Open(nsIFileSpec *folderName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/);
|
||||
NS_IMETHOD Open(nsIFileSpec *folderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
|
||||
|
||||
NS_IMETHOD SetSummaryValid(PRBool valid = TRUE);
|
||||
|
||||
|
|
|
@ -40,8 +40,7 @@ class nsMailDatabase : public nsMsgDatabase
|
|||
public:
|
||||
nsMailDatabase();
|
||||
virtual ~nsMailDatabase();
|
||||
NS_IMETHOD Open(nsIFileSpec *aFolderName, PRBool create, nsIMsgDatabase** pMessageDB,
|
||||
PRBool upgrading = PR_FALSE);
|
||||
NS_IMETHOD Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
|
||||
|
||||
static nsresult CloneInvalidDBInfoIntoNewDB(nsFileSpec &pathName, nsMailDatabase** pMailDB);
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// nsIMsgDatabase methods:
|
||||
NS_IMETHOD Open(nsIFileSpec *folderName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading);
|
||||
NS_IMETHOD Open(nsIFileSpec *folderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
|
||||
NS_IMETHOD Close(PRBool forceCommit);
|
||||
|
||||
// argh, these two shouldn't be Interface methods, but I can't diddle the interfaces
|
||||
|
@ -66,7 +66,7 @@ public:
|
|||
NS_IMETHOD OpenMDB(const char *dbName, PRBool create);
|
||||
NS_IMETHOD CloseMDB(PRBool commit);
|
||||
|
||||
NS_IMETHOD Commit(nsMsgDBCommitType commitType);
|
||||
NS_IMETHOD Commit(nsMsgDBCommit commitType);
|
||||
// Force closed is evil, and we should see if we can do without it.
|
||||
// In 4.x, it was mainly used to remove corrupted databases.
|
||||
NS_IMETHOD ForceClosed(void);
|
||||
|
@ -128,9 +128,9 @@ public:
|
|||
NS_IMETHOD MarkHasAttachments(nsMsgKey key, PRBool bHasAttachments,
|
||||
nsIDBChangeListener *instigator);
|
||||
|
||||
NS_IMETHOD MarkThreadIgnored(nsThreadMessageHdr *thread, nsMsgKey threadKey, PRBool bIgnored,
|
||||
NS_IMETHOD MarkThreadIgnored(nsIMsgThread *thread, nsMsgKey threadKey, PRBool bIgnored,
|
||||
nsIDBChangeListener *instigator);
|
||||
NS_IMETHOD MarkThreadWatched(nsThreadMessageHdr *thread, nsMsgKey threadKey, PRBool bWatched,
|
||||
NS_IMETHOD MarkThreadWatched(nsIMsgThread *thread, nsMsgKey threadKey, PRBool bWatched,
|
||||
nsIDBChangeListener *instigator);
|
||||
|
||||
NS_IMETHOD IsRead(nsMsgKey key, PRBool *pRead);
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
nsIDBChangeListener *instigator);
|
||||
|
||||
// returns NS_OK on success, NS_COMFALSE on failure
|
||||
NS_IMETHOD AllMsgKeysImapDeleted(const nsMsgKeyArray *keys);
|
||||
NS_IMETHOD AllMsgKeysImapDeleted(nsMsgKeyArray *keys);
|
||||
|
||||
NS_IMETHOD MarkImapDeleted(nsMsgKey key, PRBool deleted,
|
||||
nsIDBChangeListener *instigator);
|
||||
|
@ -199,8 +199,8 @@ public:
|
|||
|
||||
//helper function to fill in nsStrings from hdr row cell contents.
|
||||
nsresult RowCellColumnTonsString(nsIMdbRow *row, mdb_token columnToken, nsString &resultStr);
|
||||
nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 *uint32Result);
|
||||
nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 &uint32Result);
|
||||
nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 *uint32Result, PRUint32 defaultValue = 0);
|
||||
nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 &uint32Result, PRUint32 defaultValue = 0);
|
||||
nsresult RowCellColumnToMime2EncodedString(nsIMdbRow *row, mdb_token columnToken, nsString &resultStr);
|
||||
nsresult RowCellColumnToCollationKey(nsIMdbRow *row, mdb_token columnToken, nsString &resultStr);
|
||||
|
||||
|
@ -241,7 +241,6 @@ protected:
|
|||
nsMsgHdr * GetMsgHdrForReference(nsString2 &reference);
|
||||
nsIMsgDBHdr * GetMsgHdrForMessageID(nsString2 &msgID);
|
||||
nsIMsgDBHdr * GetMsgHdrForSubject(nsString2 &msgID);
|
||||
nsMsgThread * GetThreadContainingMsgHdr(nsMsgHdr *msgHdr);
|
||||
// threading interfaces
|
||||
virtual nsresult CreateNewThread(nsMsgKey key, const char *subject, nsMsgThread **newThread);
|
||||
virtual PRBool ThreadBySubjectWithoutRe();
|
||||
|
@ -319,6 +318,7 @@ protected:
|
|||
mdb_token m_numReferencesColumnToken;
|
||||
mdb_token m_messageCharSetColumnToken;
|
||||
mdb_token m_threadParentColumnToken;
|
||||
mdb_token m_threadRootKeyColumnToken;
|
||||
nsIMsgHeaderParser *m_HeaderParser;
|
||||
};
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsIMdbRow *GetMDBRow() {return m_mdbRow;}
|
||||
PRBool IsParentOf(nsIMsgDBHdr *possibleChild);
|
||||
protected:
|
||||
nsresult SetStringColumn(const char *str, mdb_token token);
|
||||
nsresult SetUInt32Column(PRUint32 value, mdb_token token);
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
nsMsgThread(nsMsgDatabase *db, nsIMdbTable *table);
|
||||
virtual ~nsMsgThread();
|
||||
|
||||
friend class nsMsgThreadEnumerator;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD SetThreadKey(nsMsgKey threadKey);
|
||||
|
@ -52,6 +54,7 @@ public:
|
|||
NS_IMETHOD RemoveChildHdr(nsIMsgDBHdr *child);
|
||||
NS_IMETHOD MarkChildRead(PRBool bRead);
|
||||
NS_IMETHOD EnumerateMessages(nsMsgKey parent, nsIEnumerator* *result);
|
||||
NS_IMETHOD GetRootHdr(PRInt32 *resultIndex, nsIMsgDBHdr **result);
|
||||
|
||||
// non-interface methods
|
||||
PRBool TryReferenceThreading(nsIMsgDBHdr *newHeader);
|
||||
|
@ -66,6 +69,10 @@ protected:
|
|||
nsresult ChangeChildCount(PRInt32 delta);
|
||||
nsresult ChangeUnreadChildCount(PRInt32 delta);
|
||||
nsresult RemoveChild(nsMsgKey msgKey);
|
||||
nsresult SetThreadRootKey(nsMsgKey threadRootKey);
|
||||
nsresult GetChildHdrForKey(nsMsgKey desiredKey,
|
||||
nsIMsgDBHdr **result, PRInt32 *resultIndex);
|
||||
|
||||
|
||||
nsMsgKey m_threadKey;
|
||||
PRUint32 m_numChildren;
|
||||
|
@ -74,7 +81,7 @@ protected:
|
|||
nsIMdbTable *m_mdbTable;
|
||||
nsIMdbRow *m_metaRow;
|
||||
PRBool m_cachedValuesInitialized;
|
||||
|
||||
nsMsgKey m_threadRootKey;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,10 +37,10 @@ public:
|
|||
|
||||
virtual nsresult MessageDBOpenUsingURL(const char * groupURL);
|
||||
char *GetGroupURL() { return m_groupURL; }
|
||||
NS_IMETHOD Open(nsIFileSpec *newsgroupName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/);
|
||||
NS_IMETHOD Open(nsIFileSpec *newsgroupName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB);
|
||||
NS_IMETHOD Close(PRBool forceCommit);
|
||||
NS_IMETHOD ForceClosed();
|
||||
NS_IMETHOD Commit(nsMsgDBCommitType commitType);
|
||||
NS_IMETHOD Commit(nsMsgDBCommit commitType);
|
||||
virtual PRUint32 GetCurVersion();
|
||||
|
||||
// methods to get and set docsets for ids.
|
||||
|
|
|
@ -29,7 +29,7 @@ nsImapMailDatabase::~nsImapMailDatabase()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImapMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/)
|
||||
NS_IMETHODIMP nsImapMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
|
||||
{
|
||||
nsImapMailDatabase *mailDB;
|
||||
PRBool summaryFileExists;
|
||||
|
|
|
@ -38,7 +38,7 @@ nsMailDatabase::~nsMailDatabase()
|
|||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/)
|
||||
NS_IMETHODIMP nsMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
|
||||
{
|
||||
nsMailDatabase *mailDB;
|
||||
PRBool summaryFileExists;
|
||||
|
@ -485,7 +485,7 @@ nsresult nsMailDatabase::SetFolderInfoValid(nsFileSpec *folderName, int num, int
|
|||
}
|
||||
else if (pMessageDB)
|
||||
{
|
||||
err = pMessageDB->Commit(kSessionCommit);
|
||||
err = pMessageDB->Commit(nsMsgDBCommitType::kSessionCommit);
|
||||
pMessageDB->Release();
|
||||
}
|
||||
return err;
|
||||
|
@ -501,7 +501,7 @@ void nsMailDatabase::SetReparse(PRBool reparse)
|
|||
|
||||
|
||||
static PRBool gGotThreadingPrefs = PR_FALSE;
|
||||
static PRBool gThreadWithoutRe = PR_FALSE;
|
||||
static PRBool gThreadWithoutRe = PR_TRUE;
|
||||
|
||||
|
||||
// should we thread messages with common subjects that don't start with Re: together?
|
||||
|
@ -514,6 +514,7 @@ PRBool nsMailDatabase::ThreadBySubjectWithoutRe()
|
|||
gGotThreadingPrefs = PR_TRUE;
|
||||
}
|
||||
|
||||
gThreadWithoutRe = PR_TRUE; // we need to this to be true for now.
|
||||
return gThreadWithoutRe;
|
||||
}
|
||||
|
||||
|
|
|
@ -302,6 +302,7 @@ nsMsgDatabase::nsMsgDatabase()
|
|||
m_numReferencesColumnToken(0),
|
||||
m_messageCharSetColumnToken(0),
|
||||
m_threadParentColumnToken(0),
|
||||
m_threadRootKeyColumnToken(0),
|
||||
m_HeaderParser(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
@ -495,7 +496,7 @@ void nsMsgDatabase::NativeToUnix(char*& ioPath)
|
|||
}
|
||||
#endif /* XP_MAC */
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *folderName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/)
|
||||
NS_IMETHODIMP nsMsgDatabase::Open(nsIFileSpec *folderName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
|
||||
{
|
||||
NS_ASSERTION(FALSE, "must override");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
@ -620,7 +621,7 @@ NS_IMETHODIMP nsMsgDatabase::OpenMDB(const char *dbName, PRBool create)
|
|||
NS_IMETHODIMP nsMsgDatabase::CloseMDB(PRBool commit)
|
||||
{
|
||||
if (commit)
|
||||
Commit(kSessionCommit);
|
||||
Commit(nsMsgDBCommitType::kSessionCommit);
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
|
@ -657,28 +658,28 @@ NS_IMETHODIMP nsMsgDatabase::GetDBFolderInfo(nsIDBFolderInfo **result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::Commit(nsMsgDBCommitType commitType)
|
||||
NS_IMETHODIMP nsMsgDatabase::Commit(nsMsgDBCommit commitType)
|
||||
{
|
||||
nsresult err = NS_OK;
|
||||
nsIMdbThumb *commitThumb = NULL;
|
||||
|
||||
commitType = kCompressCommit; // ### until incremental writing works.
|
||||
commitType = nsMsgDBCommitType::kCompressCommit; // ### until incremental writing works.
|
||||
|
||||
if (m_mdbStore)
|
||||
{
|
||||
switch (commitType)
|
||||
{
|
||||
case kSmallCommit:
|
||||
case nsMsgDBCommitType::kSmallCommit:
|
||||
err = m_mdbStore->SmallCommit(GetEnv());
|
||||
break;
|
||||
case kLargeCommit:
|
||||
case nsMsgDBCommitType::kLargeCommit:
|
||||
err = m_mdbStore->LargeCommit(GetEnv(), &commitThumb);
|
||||
break;
|
||||
case kSessionCommit:
|
||||
case nsMsgDBCommitType::kSessionCommit:
|
||||
// comment out until persistence works.
|
||||
err = m_mdbStore->SessionCommit(GetEnv(), &commitThumb);
|
||||
break;
|
||||
case kCompressCommit:
|
||||
case nsMsgDBCommitType::kCompressCommit:
|
||||
err = m_mdbStore->CompressCommit(GetEnv(), &commitThumb);
|
||||
break;
|
||||
}
|
||||
|
@ -732,6 +733,7 @@ const char *kThreadUnreadChildrenColumnName = "unreadChildren";
|
|||
const char *kThreadSubjectColumnName = "threadSubject";
|
||||
const char *kMessageCharSetColumnName = "msgCharSet";
|
||||
const char *kThreadParentColumnName = "threadParent";
|
||||
const char *kThreadRootColumnName = "threadRoot";
|
||||
struct mdbOid gAllMsgHdrsTableOID;
|
||||
struct mdbOid gAllThreadsTableOID;
|
||||
|
||||
|
@ -840,6 +842,7 @@ nsresult nsMsgDatabase::InitMDBInfo()
|
|||
err = GetStore()->StringToToken(GetEnv(), kAllThreadsTableKind, &m_allThreadsTableKindToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kThreadHdrsScope, &m_threadRowScopeToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kThreadParentColumnName, &m_threadParentColumnToken);
|
||||
err = GetStore()->StringToToken(GetEnv(), kThreadRootColumnName, &m_threadRootKeyColumnToken);
|
||||
if (err == NS_OK)
|
||||
{
|
||||
// The table of all message hdrs will have table id 1.
|
||||
|
@ -941,7 +944,7 @@ NS_IMETHODIMP nsMsgDatabase::DeleteMessages(nsMsgKeyArray* nsMsgKeys, nsIDBChang
|
|||
if (err != NS_OK)
|
||||
break;
|
||||
}
|
||||
Commit(kSmallCommit);
|
||||
Commit(nsMsgDBCommitType::kSmallCommit);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -985,7 +988,7 @@ NS_IMETHODIMP nsMsgDatabase::DeleteHeader(nsIMsgDBHdr *msg, nsIDBChangeListener
|
|||
}
|
||||
|
||||
if (commit)
|
||||
Commit(kLargeCommit); // ### dmb is this a good time to commit?
|
||||
Commit(nsMsgDBCommitType::kLargeCommit); // ### dmb is this a good time to commit?
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1088,7 +1091,7 @@ NS_IMETHODIMP nsMsgDatabase::IsIgnored(nsMsgKey key, PRBool *pIgnored)
|
|||
if (!pIgnored)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
#ifdef WE_DO_THREADING_YET
|
||||
nsThreadMessageHdr *threadHdr = GetnsThreadHdrForMsgID(nsMsgKey);
|
||||
nsIMsgThread *threadHdr = GetnsThreadHdrForMsgID(nsMsgKey);
|
||||
// This should be very surprising, but we leave that up to the caller
|
||||
// to determine for now.
|
||||
if (threadHdr == NULL)
|
||||
|
@ -1182,14 +1185,14 @@ NS_IMETHODIMP nsMsgDatabase::MarkHasAttachments(nsMsgKey key, PRBool bHasAttachm
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDatabase::MarkThreadIgnored(nsThreadMessageHdr *thread, nsMsgKey threadKey, PRBool bIgnored,
|
||||
nsMsgDatabase::MarkThreadIgnored(nsIMsgThread *thread, nsMsgKey threadKey, PRBool bIgnored,
|
||||
nsIDBChangeListener *instigator)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDatabase::MarkThreadWatched(nsThreadMessageHdr *thread, nsMsgKey threadKey, PRBool bWatched,
|
||||
nsMsgDatabase::MarkThreadWatched(nsIMsgThread *thread, nsMsgKey threadKey, PRBool bWatched,
|
||||
nsIDBChangeListener *instigator)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
@ -1208,7 +1211,7 @@ NS_IMETHODIMP nsMsgDatabase::MarkOffline(nsMsgKey key, PRBool offline,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDatabase::AllMsgKeysImapDeleted(const nsMsgKeyArray *keys)
|
||||
nsMsgDatabase::AllMsgKeysImapDeleted(nsMsgKeyArray *keys)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -1324,7 +1327,7 @@ NS_IMETHODIMP nsMsgDatabase::MarkHdrRead(nsIMsgDBHdr *msgHdr, PRBool bRead,
|
|||
if (!!isRead != !!bRead)
|
||||
{
|
||||
#ifdef WE_DO_THREADING_YET
|
||||
nsThreadMessageHdr *threadHdr = GetnsThreadHdrForMsgID(msgHdr->GetMessageKey());
|
||||
nsIMsgThread *threadHdr = GetnsThreadHdrForMsgID(msgHdr->GetMessageKey());
|
||||
if (threadHdr != NULL)
|
||||
{
|
||||
threadHdr->MarkChildRead(bRead);
|
||||
|
@ -1366,7 +1369,7 @@ NS_IMETHODIMP nsMsgDatabase::MarkAllRead(nsMsgKeyArray *thoseMarked)
|
|||
}
|
||||
|
||||
if (numChanged > 0) // commit every once in a while
|
||||
Commit(kSmallCommit);
|
||||
Commit(nsMsgDBCommitType::kSmallCommit);
|
||||
// force num new to 0.
|
||||
PRInt32 numNewMessages;
|
||||
|
||||
|
@ -1418,7 +1421,7 @@ NS_IMETHODIMP nsMsgDatabase::MarkReadByDate (PRTime startDate, PRTime endDate, n
|
|||
NS_RELEASE(pHeader);
|
||||
}
|
||||
if (numChanged > 0)
|
||||
Commit(kSmallCommit);
|
||||
Commit(nsMsgDBCommitType::kSmallCommit);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2059,18 +2062,18 @@ nsIMsgHeaderParser *nsMsgDatabase::GetHeaderParser()
|
|||
}
|
||||
|
||||
|
||||
nsresult nsMsgDatabase::RowCellColumnToUInt32(nsIMdbRow *hdrRow, mdb_token columnToken, PRUint32 &uint32Result)
|
||||
nsresult nsMsgDatabase::RowCellColumnToUInt32(nsIMdbRow *hdrRow, mdb_token columnToken, PRUint32 &uint32Result, PRUint32 defaultValue)
|
||||
{
|
||||
return RowCellColumnToUInt32(hdrRow, columnToken, &uint32Result);
|
||||
return RowCellColumnToUInt32(hdrRow, columnToken, &uint32Result, defaultValue);
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::RowCellColumnToUInt32(nsIMdbRow *hdrRow, mdb_token columnToken, PRUint32 *uint32Result)
|
||||
nsresult nsMsgDatabase::RowCellColumnToUInt32(nsIMdbRow *hdrRow, mdb_token columnToken, PRUint32 *uint32Result, PRUint32 defaultValue)
|
||||
{
|
||||
nsresult err = NS_OK;
|
||||
nsIMdbCell *hdrCell;
|
||||
|
||||
if (uint32Result)
|
||||
*uint32Result = 0;
|
||||
*uint32Result = defaultValue;
|
||||
if (hdrRow) // ### probably should be an error if hdrRow is NULL...
|
||||
{
|
||||
err = hdrRow->GetCell(GetEnv(), columnToken, &hdrCell);
|
||||
|
@ -2327,7 +2330,7 @@ nsresult nsMsgDatabase::ThreadNewHdr(nsMsgHdr* newHdr, PRBool &newThread)
|
|||
newHdr->GetNumReferences(&numReferences);
|
||||
|
||||
#define SUBJ_THREADING 1// try reference threading first
|
||||
for (PRInt32 i = 0; i < numReferences; i++)
|
||||
for (PRInt32 i = numReferences - 1; i >= 0; i--)
|
||||
{
|
||||
nsString2 reference(eOneByte);
|
||||
|
||||
|
|
|
@ -592,3 +592,16 @@ const char *nsMsgHdr::GetPrevReference(const char *prevRef, nsString2 &reference
|
|||
return ptr;
|
||||
}
|
||||
|
||||
PRBool nsMsgHdr::IsParentOf(nsIMsgDBHdr *possibleChild)
|
||||
{
|
||||
PRUint16 numReferences = 0;
|
||||
possibleChild->GetNumReferences(&numReferences);
|
||||
nsAutoString2 reference(eOneByte);
|
||||
nsAutoString2 messageId(eOneByte);
|
||||
|
||||
GetMessageId(messageId);
|
||||
possibleChild->GetStringReference(numReferences - 1, reference);
|
||||
|
||||
return (messageId.Equals(reference));
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ nsMsgThread::nsMsgThread(nsMsgDatabase *db, nsIMdbTable *table)
|
|||
void nsMsgThread::Init()
|
||||
{
|
||||
m_threadKey = nsMsgKey_None;
|
||||
m_threadRootKey = nsMsgKey_None;
|
||||
m_numChildren = 0;
|
||||
m_numUnreadChildren = 0;
|
||||
m_flags = 0;
|
||||
|
@ -79,7 +80,7 @@ nsresult nsMsgThread::InitCachedValues()
|
|||
err = m_mdbDB->RowCellColumnToUInt32(m_metaRow, m_mdbDB->m_threadChildrenColumnToken, &m_numChildren);
|
||||
err = m_mdbDB->RowCellColumnToUInt32(m_metaRow, m_mdbDB->m_threadIdColumnToken, &m_threadKey);
|
||||
err = m_mdbDB->RowCellColumnToUInt32(m_metaRow, m_mdbDB->m_threadUnreadChildrenColumnToken, &m_numUnreadChildren);
|
||||
|
||||
err = m_mdbDB->RowCellColumnToUInt32(m_metaRow, m_mdbDB->m_threadRootKeyColumnToken, &m_threadRootKey, nsMsgKey_None);
|
||||
|
||||
if (NS_SUCCEEDED(err))
|
||||
m_cachedValuesInitialized = PR_TRUE;
|
||||
|
@ -92,6 +93,8 @@ NS_IMETHODIMP nsMsgThread::SetThreadKey(nsMsgKey threadKey)
|
|||
nsresult ret = NS_OK;
|
||||
|
||||
m_threadKey = threadKey;
|
||||
// by definition, the initial thread key is also the thread root key.
|
||||
SetThreadRootKey(threadKey);
|
||||
ret = m_mdbDB->UInt32ToRowCellColumn(m_metaRow, m_mdbDB->m_threadIdColumnToken, threadKey);
|
||||
// gotta set column in meta row here.
|
||||
return ret;
|
||||
|
@ -171,9 +174,12 @@ NS_IMETHODIMP nsMsgThread::AddChild(nsIMsgDBHdr *child, nsIMsgDBHdr *inReplyTo,
|
|||
nsresult ret = NS_OK;
|
||||
nsMsgHdr* hdr = NS_STATIC_CAST(nsMsgHdr*, child); // closed system, cast ok
|
||||
PRUint32 newHdrFlags = 0;
|
||||
nsMsgKey newHdrKey = 0;
|
||||
|
||||
nsIMdbRow *hdrRow = hdr->GetMDBRow();
|
||||
hdr->GetFlags(&newHdrFlags);
|
||||
hdr->GetMessageKey(&newHdrKey);
|
||||
|
||||
if (m_mdbTable)
|
||||
{
|
||||
m_mdbTable->AddRow(m_mdbDB->GetEnv(), hdrRow);
|
||||
|
@ -181,6 +187,74 @@ NS_IMETHODIMP nsMsgThread::AddChild(nsIMsgDBHdr *child, nsIMsgDBHdr *inReplyTo,
|
|||
if (! (newHdrFlags & MSG_FLAG_READ))
|
||||
ChangeUnreadChildCount(1);
|
||||
}
|
||||
if (inReplyTo)
|
||||
{
|
||||
nsMsgKey parentKey;
|
||||
inReplyTo->GetMessageKey(&parentKey);
|
||||
child->SetThreadParent(parentKey);
|
||||
}
|
||||
if (inReplyTo)
|
||||
{
|
||||
nsMsgKey parentKey;
|
||||
inReplyTo->GetMessageKey(&parentKey);
|
||||
child->SetThreadParent(parentKey);
|
||||
}
|
||||
// check if this header is a parent of one of the messages in this thread
|
||||
|
||||
PRUint32 numChildren;
|
||||
PRUint32 childIndex = 0;
|
||||
|
||||
GetNumChildren(&numChildren);
|
||||
|
||||
nsCOMPtr <nsIMsgDBHdr> curHdr;
|
||||
for (childIndex = 0; childIndex < numChildren; childIndex++)
|
||||
{
|
||||
nsMsgKey msgKey;
|
||||
|
||||
ret = GetChildHdrAt(childIndex, getter_AddRefs(curHdr));
|
||||
if (NS_SUCCEEDED(ret) && curHdr)
|
||||
{
|
||||
// ### check if this is the thead root key!
|
||||
if (hdr->IsParentOf(curHdr))
|
||||
{
|
||||
curHdr->GetMessageKey(&msgKey);
|
||||
curHdr->SetThreadParent(newHdrKey);
|
||||
#ifdef DEBUG_bienvenu
|
||||
if (newHdrKey != m_threadKey)
|
||||
printf("adding second level child\n");
|
||||
#endif
|
||||
// If this hdr was the root, then the new hdr is the root.
|
||||
if (msgKey == m_threadRootKey)
|
||||
SetThreadRootKey(newHdrKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If this header is not a reply to a header in the thread, and isn't a parent
|
||||
// check to see if it starts with Re: - if not, and the first header does start
|
||||
// with re, should we make this header the top level header?
|
||||
// If it's date is less (or it's ID?), then yes.
|
||||
if (numChildren > 0 && !(newHdrFlags & MSG_FLAG_HAS_RE) && !inReplyTo)
|
||||
{
|
||||
PRTime newHdrDate;
|
||||
PRTime topLevelHdrDate;
|
||||
|
||||
nsCOMPtr <nsIMsgDBHdr> topLevelHdr;
|
||||
ret = GetRootHdr(nsnull, getter_AddRefs(topLevelHdr));
|
||||
if (NS_SUCCEEDED(ret) && topLevelHdr)
|
||||
{
|
||||
child->GetDate(&newHdrDate);
|
||||
topLevelHdr->GetDate(&topLevelHdrDate);
|
||||
if (LL_CMP(newHdrDate, <, topLevelHdrDate))
|
||||
{
|
||||
#ifdef MOVE_ROW_IMPL
|
||||
mdb_pos outPos;
|
||||
m_mdbTable->MoveRow(m_mdbDB->GetEnv(), hdrRow, -1, 0, &outPos);
|
||||
#endif // MOVE_ROW_IMPL
|
||||
topLevelHdr->SetThreadParent(newHdrKey);
|
||||
SetThreadRootKey(newHdrKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -387,13 +461,15 @@ public:
|
|||
|
||||
nsMsgThreadEnumerator(nsMsgThread *thread, nsMsgKey startKey,
|
||||
nsMsgThreadEnumeratorFilter filter, void* closure);
|
||||
PRInt32 MsgKeyFirstChildIndex(nsMsgKey inMsgKey);
|
||||
virtual ~nsMsgThreadEnumerator();
|
||||
|
||||
protected:
|
||||
nsIMdbTableRowCursor* mRowCursor;
|
||||
nsIMsgDBHdr* mResultHdr;
|
||||
nsCOMPtr <nsIMsgDBHdr> mResultHdr;
|
||||
nsMsgThread* mThread;
|
||||
nsMsgKey mCurKey;
|
||||
nsMsgKey mThreadParentKey;
|
||||
nsMsgKey mFirstMsgKey;
|
||||
PRInt32 mChildIndex;
|
||||
PRBool mDone;
|
||||
nsMsgThreadEnumeratorFilter mFilter;
|
||||
|
@ -402,34 +478,71 @@ protected:
|
|||
|
||||
nsMsgThreadEnumerator::nsMsgThreadEnumerator(nsMsgThread *thread, nsMsgKey startKey,
|
||||
nsMsgThreadEnumeratorFilter filter, void* closure)
|
||||
: mRowCursor(nsnull), mResultHdr(nsnull), mDone(PR_FALSE),
|
||||
: mRowCursor(nsnull), mDone(PR_FALSE),
|
||||
mFilter(filter), mClosure(closure)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mCurKey = startKey;
|
||||
mChildIndex = 1;
|
||||
mThreadParentKey = startKey;
|
||||
mChildIndex = 0;
|
||||
mThread = thread;
|
||||
if (mCurKey != nsMsgKey_None)
|
||||
mFirstMsgKey = nsMsgKey_None;
|
||||
|
||||
nsresult rv = mThread->GetRootHdr(nsnull, getter_AddRefs(mResultHdr));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mResultHdr)
|
||||
mResultHdr->GetMessageKey(&mFirstMsgKey);
|
||||
|
||||
PRUint32 numChildren;
|
||||
mThread->GetNumChildren(&numChildren);
|
||||
|
||||
if (mThreadParentKey != nsMsgKey_None)
|
||||
{
|
||||
nsMsgKey msgKey = nsMsgKey_None;
|
||||
nsresult rv = mThread->GetChildHdrAt(0, &mResultHdr);
|
||||
if (NS_SUCCEEDED(rv) && mResultHdr)
|
||||
PRUint32 childIndex = 0;
|
||||
|
||||
|
||||
for (childIndex = 0; childIndex < numChildren; childIndex++)
|
||||
{
|
||||
// we're only doing one level of threading, so check if caller is
|
||||
// asking for children of the first message in the thread or not.
|
||||
// if not, we will tell him there are no children.
|
||||
mResultHdr->GetMessageKey(&msgKey);
|
||||
if (msgKey != mCurKey)
|
||||
mDone = PR_TRUE;
|
||||
rv = mThread->GetChildHdrAt(childIndex, getter_AddRefs(mResultHdr));
|
||||
if (NS_SUCCEEDED(rv) && mResultHdr)
|
||||
{
|
||||
mResultHdr->GetMessageKey(&msgKey);
|
||||
|
||||
NS_RELEASE(mResultHdr);
|
||||
mResultHdr = nsnull;
|
||||
if (msgKey == startKey)
|
||||
{
|
||||
mChildIndex = MsgKeyFirstChildIndex(msgKey);
|
||||
mDone = (mChildIndex < 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mDone)
|
||||
break;
|
||||
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE, "couldn't get child from thread");
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE, "couldn't get child from thread");
|
||||
mChildIndex = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_bienvenu
|
||||
nsCOMPtr <nsIMsgDBHdr> child;
|
||||
for (PRUint32 childIndex = 0; childIndex < numChildren; childIndex++)
|
||||
{
|
||||
rv = mThread->GetChildHdrAt(childIndex, getter_AddRefs(child));
|
||||
if (NS_SUCCEEDED(rv) && child)
|
||||
{
|
||||
nsMsgKey threadParent;
|
||||
nsMsgKey msgKey;
|
||||
// we're only doing one level of threading, so check if caller is
|
||||
// asking for children of the first message in the thread or not.
|
||||
// if not, we will tell him there are no children.
|
||||
child->GetMessageKey(&msgKey);
|
||||
child->GetThreadParent(&threadParent);
|
||||
|
||||
printf("index = %ld key = %ld parent = %lx\n", childIndex, msgKey, threadParent);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
NS_ADDREF(thread);
|
||||
}
|
||||
|
||||
|
@ -448,21 +561,84 @@ NS_IMETHODIMP nsMsgThreadEnumerator::First(void)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
rv = Next();
|
||||
NS_ASSERTION(mCurKey != nsMsgKey_None || NS_SUCCEEDED(rv), "first failed, can't have that");
|
||||
NS_ASSERTION(mThreadParentKey != nsMsgKey_None || NS_SUCCEEDED(rv), "first failed, can't have that");
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgThreadEnumerator::MsgKeyFirstChildIndex(nsMsgKey inMsgKey)
|
||||
{
|
||||
// if (msgKey != mThreadParentKey)
|
||||
// mDone = PR_TRUE;
|
||||
// look through rest of thread looking for a child of this message.
|
||||
// If the inMsgKey is the first message in the thread, then all children
|
||||
// without parents are considered to be children of inMsgKey.
|
||||
// Otherwise, only true children qualify.
|
||||
PRUint32 numChildren;
|
||||
nsCOMPtr <nsIMsgDBHdr> curHdr;
|
||||
PRInt32 firstChildIndex = -1;
|
||||
|
||||
mThread->GetNumChildren(&numChildren);
|
||||
|
||||
// if this is the first message in the thread, just check if there's more than
|
||||
// one message in the thread.
|
||||
if (inMsgKey == mThread->m_threadRootKey)
|
||||
return (numChildren > 1) ? 1 : -1;
|
||||
|
||||
for (PRUint32 curChildIndex = 0; curChildIndex < numChildren; curChildIndex++)
|
||||
{
|
||||
nsresult rv = mThread->GetChildHdrAt(curChildIndex, getter_AddRefs(curHdr));
|
||||
if (NS_SUCCEEDED(rv) && curHdr)
|
||||
{
|
||||
nsMsgKey parentKey;
|
||||
|
||||
curHdr->GetThreadParent(&parentKey);
|
||||
if (parentKey == inMsgKey)
|
||||
{
|
||||
firstChildIndex = curChildIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_bienvenu
|
||||
printf("first child index of %ld = %ld\n", inMsgKey, firstChildIndex);
|
||||
#endif
|
||||
return firstChildIndex;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgThreadEnumerator::Next(void)
|
||||
{
|
||||
nsresult rv;
|
||||
if (mCurKey == nsMsgKey_None)
|
||||
mResultHdr = nsnull;
|
||||
if (mThreadParentKey == nsMsgKey_None)
|
||||
{
|
||||
rv = mThread->GetChildHdrAt(0, &mResultHdr);
|
||||
mChildIndex = 1;
|
||||
rv = mThread->GetRootHdr(&mChildIndex, getter_AddRefs(mResultHdr));
|
||||
mChildIndex = 0; // since root can be anywhere, set mChildIndex to 0.
|
||||
}
|
||||
else if (!mDone)
|
||||
{
|
||||
rv = mThread->GetChildHdrAt(mChildIndex++, &mResultHdr);
|
||||
PRUint32 numChildren;
|
||||
mThread->GetNumChildren(&numChildren);
|
||||
|
||||
while (mChildIndex < (PRInt32) numChildren)
|
||||
{
|
||||
rv = mThread->GetChildHdrAt(mChildIndex++, getter_AddRefs(mResultHdr));
|
||||
if (NS_SUCCEEDED(rv) && mResultHdr)
|
||||
{
|
||||
nsMsgKey parentKey;
|
||||
nsMsgKey curKey;
|
||||
|
||||
mResultHdr->GetThreadParent(&parentKey);
|
||||
mResultHdr->GetMessageKey(&curKey);
|
||||
// if the parent is the same as the msg we're enumerating over,
|
||||
// or the parentKey isn't set, and we're iterating over the top
|
||||
// level message in the thread, then leave mResultHdr set to cur msg.
|
||||
if (parentKey == mThreadParentKey ||
|
||||
((parentKey == 0 || parentKey == nsMsgKey_None)
|
||||
&& mThreadParentKey == mFirstMsgKey && curKey != mThreadParentKey))
|
||||
break;
|
||||
mResultHdr = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mResultHdr)
|
||||
{
|
||||
|
@ -474,15 +650,22 @@ NS_IMETHODIMP nsMsgThreadEnumerator::Next(void)
|
|||
mDone = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
#ifdef DEBUG_bienvenu
|
||||
nsMsgKey debugMsgKey;
|
||||
mResultHdr->GetMessageKey(&debugMsgKey);
|
||||
printf("next for %ld = %ld\n", mThreadParentKey, debugMsgKey);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgThreadEnumerator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (mResultHdr) {
|
||||
*aItem = mResultHdr;
|
||||
NS_ADDREF(mResultHdr);
|
||||
NS_ADDREF(*aItem);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -507,6 +690,17 @@ NS_IMETHODIMP nsMsgThread::EnumerateMessages(nsMsgKey parentKey, nsIEnumerator*
|
|||
return ret;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgThread::GetRootHdr(PRInt32 *resultIndex, nsIMsgDBHdr **result)
|
||||
{
|
||||
if (m_threadRootKey == nsMsgKey_None)
|
||||
{
|
||||
*resultIndex = 0;
|
||||
return GetChildHdrAt(0, result);
|
||||
}
|
||||
else
|
||||
return GetChildHdrForKey(m_threadRootKey, result, resultIndex);
|
||||
}
|
||||
|
||||
nsresult nsMsgThread::ChangeChildCount(PRInt32 delta)
|
||||
{
|
||||
nsresult ret = NS_OK;
|
||||
|
@ -528,3 +722,45 @@ nsresult nsMsgThread::ChangeUnreadChildCount(PRInt32 delta)
|
|||
ret = m_mdbDB->UInt32ToRowCellColumn(m_metaRow, m_mdbDB->m_threadUnreadChildrenColumnToken, childCount);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult nsMsgThread::SetThreadRootKey(nsMsgKey threadRootKey)
|
||||
{
|
||||
nsresult ret = NS_OK;
|
||||
m_threadRootKey = threadRootKey;
|
||||
ret = m_mdbDB->UInt32ToRowCellColumn(m_metaRow, m_mdbDB->m_threadRootKeyColumnToken, threadRootKey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult nsMsgThread::GetChildHdrForKey(nsMsgKey desiredKey, nsIMsgDBHdr **result, PRInt32 *resultIndex)
|
||||
{
|
||||
PRUint32 numChildren;
|
||||
PRUint32 childIndex = 0;
|
||||
nsresult rv;
|
||||
|
||||
if (!result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
GetNumChildren(&numChildren);
|
||||
|
||||
for (childIndex = 0; childIndex < numChildren; childIndex++)
|
||||
{
|
||||
rv = GetChildHdrAt(childIndex, result);
|
||||
if (NS_SUCCEEDED(rv) && result)
|
||||
{
|
||||
nsMsgKey msgKey;
|
||||
// we're only doing one level of threading, so check if caller is
|
||||
// asking for children of the first message in the thread or not.
|
||||
// if not, we will tell him there are no children.
|
||||
(*result)->GetMessageKey(&msgKey);
|
||||
|
||||
if (msgKey == desiredKey)
|
||||
break;
|
||||
NS_RELEASE(*result);
|
||||
}
|
||||
}
|
||||
if (resultIndex)
|
||||
*resultIndex = childIndex;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ nsresult nsNewsDatabase::MessageDBOpenUsingURL(const char * groupURL)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsNewsDatabase::Open(nsIFileSpec *aNewsgroupName, PRBool create, nsIMsgDatabase** pMessageDB, PRBool upgrading /*=PR_FALSE*/)
|
||||
NS_IMETHODIMP nsNewsDatabase::Open(nsIFileSpec *aNewsgroupName, PRBool create, PRBool upgrading, nsIMsgDatabase** pMessageDB)
|
||||
{
|
||||
nsNewsDatabase *newsDB;
|
||||
|
||||
|
@ -159,7 +159,7 @@ nsresult nsNewsDatabase::ForceClosed()
|
|||
return nsMsgDatabase::ForceClosed();
|
||||
}
|
||||
|
||||
nsresult nsNewsDatabase::Commit(nsMsgDBCommitType commitType)
|
||||
nsresult nsNewsDatabase::Commit(nsMsgDBCommit commitType)
|
||||
{
|
||||
return nsMsgDatabase::Commit(commitType);
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ NS_IMETHODIMP nsNewsDatabase::MarkHdrRead(nsIMsgDBHdr *msgHdr, PRBool bRead,
|
|||
// since committing every time is expensive if we mark a
|
||||
// whole bunch of headers as read, we should commit after we are
|
||||
// done marking.
|
||||
Commit(kSessionCommit);
|
||||
Commit(nsMsgDBCommitType::kSessionCommit);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче