From 3e9bd176d9db47e7d6cd161c730c1c1a8a3ea9bc Mon Sep 17 00:00:00 2001 From: "alecf%netscape.com" Date: Mon, 11 Jan 1999 20:56:39 +0000 Subject: [PATCH] adding new nsNNTPNewsgroupList and nsNNTPArticleList objects git-svn-id: svn://10.0.0.236/trunk@17510 18797224-902f-48f8-a5cc-f745e15eee43 --- .../mailnews/news/src/nsNNTPArticleList.cpp | 138 ++++ .../mailnews/news/src/nsNNTPNewsgroupList.cpp | 695 ++++++++++++++++++ .../mailnews/news/src/nsNNTPNewsgroupList.h | 64 ++ 3 files changed, 897 insertions(+) create mode 100644 mozilla/mailnews/news/src/nsNNTPArticleList.cpp create mode 100644 mozilla/mailnews/news/src/nsNNTPNewsgroupList.cpp create mode 100644 mozilla/mailnews/news/src/nsNNTPNewsgroupList.h diff --git a/mozilla/mailnews/news/src/nsNNTPArticleList.cpp b/mozilla/mailnews/news/src/nsNNTPArticleList.cpp new file mode 100644 index 00000000000..f93277f0e7c --- /dev/null +++ b/mozilla/mailnews/news/src/nsNNTPArticleList.cpp @@ -0,0 +1,138 @@ +/* -*- 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 "nsNNTPNewsgroupListState.h" +#include "nsMsgNewsHost.h" + + +class ListNewsGroupArticleKeysState +#ifdef HAVE_CHANGELISTENER + : public ChangeListener +#endif +{ +public: + nsNNTPArticleList(); + /* , MSG_Pane *pane); */ + ~nsNNTPArticleList(); + + // nsINNTPArticleKeysState + NS_IMETHOD Init(const char *newsHost, const nsIMsgNewsgroup *newsgroup); + NS_IMETHOD AddArticleKey(PRInt32 key); + NS_IMETHOD FinishAddingArticleKeys(); + + // other stuff +protected: + struct MSG_NewsKnown m_idsOnServer; +#ifdef HAVE_PANES + MSG_Pane *m_pane; +#endif + const char * m_groupName; + nsIMsgNewsHost *m_host; +#ifdef HAVE_NEWSDB + NewsGroupDB *m_newsDB; +#endif + IDArray m_idsInDB; +#ifdef DEBUG_bienvenu + IDArray m_idsDeleted; +#endif + int32 m_dbIndex; + MessageKey m_highwater; +}; + +nsNNTPArticleList::nsNNTPArticleList(const char* newshost, + const nsIMsgNewsgroup* newsgroup) +{ + NS_INIT_REFCNT(); + Initialize(newsHost, newsgroup); +} + +ListNewsgroupArticleKeysState::Initialize(const char* newsHost, + const nsIMsgNewsgroup* newsgroup) +{ + m_host = host; + m_groupName = groupName; +#ifdef HAVE_PANES + m_pane = pane; +#endif +#ifdef HAVE_NEWSDB + m_newsDB = NULL; +#endif + m_idsOnServer.set = msg_NewsArtSet::Create(); +#ifdef HAVE_PANES + MSG_FolderInfoNews *newsFolder = m_pane->GetMaster()->FindNewsFolder(host, groupName, FALSE); + if (newsFolder) + { + char *url = newsFolder->BuildUrl(NULL, MSG_MESSAGEKEYNONE); +#ifdef HAVE_NEWSDB + if (url) + NewsGroupDB::Open(url, m_pane->GetMaster(), &m_newsDB); + if (m_newsDB) + m_newsDB->ListAllIds(m_idsInDB); +#endif + m_dbIndex = 0; + + FREEIF(url); + } +#endif +} + +nsNNTPArticleList::~nsNNTPArticleList() +{ +#ifdef HAVE_NEWSDB + if (m_newsDB) + m_newsDB->Close(); +#endif +} + +int nsNNTPArticleList::AddArticleKey(int32 key) +{ + m_idsOnServer.set->Add(key); + if (m_dbIndex < m_idsInDB.GetSize()) + { + int32 idInDBToCheck = m_idsInDB.GetAt(m_dbIndex); + // if there are keys in the database that aren't in the newsgroup + // on the server, remove them. We probably shouldn't do this if + // we have a copy of the article offline. + while (idInDBToCheck < key) + { +#ifdef HAVE_NEWSDB + m_newsDB->DeleteMessage(idInDBToCheck, NULL, FALSE); +#endif +#ifdef DEBUG_bienvenu + m_idsDeleted.Add(idInDBToCheck); +#endif + if (m_dbIndex >= m_idsInDB.GetSize()) + break; + idInDBToCheck = m_idsInDB.GetAt(++m_dbIndex); + } + if (idInDBToCheck == key) + m_dbIndex++; + } + return 0; +} + +int nsNNTPArticleList::FinishAddingArticleKeys() +{ + // make sure none of the deleted turned up on the idsOnServer list +#ifdef DEBUG_bienvenu + for (int32 i = 0; i < m_idsDeleted.GetSize(); i++) + XP_ASSERT (!m_idsOnServer.set->IsMember(m_idsDeleted.GetAt(i))); +#endif + return 0; +} + diff --git a/mozilla/mailnews/news/src/nsNNTPNewsgroupList.cpp b/mozilla/mailnews/news/src/nsNNTPNewsgroupList.cpp new file mode 100644 index 00000000000..963f1774f70 --- /dev/null +++ b/mozilla/mailnews/news/src/nsNNTPNewsgroupList.cpp @@ -0,0 +1,695 @@ +/* -*- 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. + */ + +/* + * formerly listngst.cpp + * This class should ultimately be part of a news group listing + * state machine - either by inheritance or delegation. + * Currently, a folder pane owns one and libnet news group listing + * related messages get passed to this object. + */ + +#ifdef HAVE_PANES +class MSG_Master; +#endif +#ifdef HAVE_NEWSDB +class NewsGroupDB; +#endif +#ifdef HAVE_DBVIEW +class MessageDBView; +#endif +class msg_NewsArtSet; + +#include "nsNNTPNewsgroupList.h" + +#ifdef HAVE_NEWSDB +#include "newsdb.h" +#endif + +#ifdef HAVE_DBVIEW +#include "msgdbvw.h" +#endif + +#include "newsset.h" +#ifdef HAVE_PANES +#include "msgpane.h" +#endif + + +extern "C" +{ + extern int MK_OUT_OF_MEMORY; + extern int MK_DISK_FULL; + extern int MK_HDR_DOWNLOAD_COUNT; + extern int MK_NO_NEW_DISC_MSGS; +} + + +// This class should ultimately be part of a news group listing +// state machine - either by inheritance or delegation. +// Currently, a folder pane owns one and libnet news group listing +// related messages get passed to this object. +class nsNNTPNewsgroupList : public nsIMsgNewsArticleList +#ifdef HAVE_CHANGELISTENER + ,public ChangeListener +#endif +{ +public: + nsNNTPNewsgroupList(); + ~nsNNTPNewsgroupList(); + // nsIMsgNewsArticleList + NS_IMETHOD GetRangeOfArtsToDownload(MSG_NewsHost* host, + const char* group_name, + int32 first_possible, + int32 last_possible, + int32 maxextra, + int32* first, + int32* lastprotected); + NS_IMETHOD AddToKnownArticles(MSG_NewsHost* host, + const char* group_name, + int32 first, int32 last); + + // nsIMsgXOVERParser + NS_IMETHOD InitXOVER(MSG_NewsHost* host, + const char *group_name, + uint32 first_msg, uint32 last_msg, + uint32 oldest_msg, uint32 youngest_msg); + NS_IMETHOD ProcessXOVER(char *line); + NS_IMETHOD ResetXOVER(); + NS_IMETHOD ProcessNonXOVER(char *line); + NS_IMETHOD FinishXOVER(int status); + + MSG_Master *GetMaster() {return m_master;} + void SetMaster(MSG_Master *master) {m_master = master;} +#ifdef HAVE_DBVIEW + void SetView(MessageDBView *view); +#endif +#ifdef HAVE_PANES + void SetPane(MSG_Pane *pane) {m_pane = pane;} +#endif + PRBool m_finishingXover; + MSG_NewsHost* GetHost() {return m_host;} + const char * GetGroupName() {return m_groupName;} + const char * GetURL() {return m_url;} +#ifdef HAVE_CHANGELISTENER + virtual void OnAnnouncerGoingAway (ChangeAnnouncer *instigator); +#endif + void SetGetOldMessages(XP_Bool getOldMessages) {m_getOldMessages = getOldMessages;} + XP_Bool GetGetOldMessages() {return m_getOldMessages;} + +protected: +#ifdef HAVE_NEWSDB + NewsGroupDB *m_newsDB; +#endif +#ifdef HAVE_DBVIEW + MessageDBView *m_msgDBView; // open view on current download, if any +#endif +#ifdef HAVE_PANES + MSG_Pane *m_pane; +#endif + XP_Bool m_startedUpdate; + XP_Bool m_getOldMessages; + XP_Bool m_promptedAlready; + XP_Bool m_downloadAll; + int32 m_maxArticles; + char *m_groupName; + MSG_NewsHost *m_host; + char *m_url; // url we're retrieving + MSG_Master *m_master; + + MessageKey m_lastProcessedNumber; + MessageKey m_firstMsgNumber; + MessageKey m_lastMsgNumber; + int32 m_firstMsgToDownload; + int32 m_lastMsgToDownload; + + struct MSG_NewsKnown m_knownArts; + msg_NewsArtSet *m_set; +}; + + + +nsNNTPNewsgroupList::nsNNTPNewsgroupList() +{ + NS_INIT_REFCNT(); +} + +nsNNTPNewsgroupList::~nsNNTPNewsgroupList() +{ +} + +NS_IMPL_ADDREF(nsNNTPNewsgroupList); +NS_IMPL_RELEASE(nsNNTPNewsgroupList); +NS_IMPL_QUERYINTERFACE(nsNNTPNewsgroupList); + + +nsNNTPNewsgroupList::InitnsNNTPNewsgroupList(const char *url, const char *groupName, MSG_Pane *pane); +{ +#ifdef HAVE_NEWSDB + m_newsDB = NULL; +#endif +#ifdef HAVE_DBVIEW + m_msgDBView = NULL; +#endif + m_groupName = XP_STRDUP(groupName); + m_host = NULL; + m_url = XP_STRDUP(url); + m_lastProcessedNumber = 0; + m_lastMsgNumber = 0; + m_set = NULL; +#ifdef HAVE_PANES + XP_ASSERT(pane); + m_pane = pane; + m_master = pane->GetMaster(); +#endif + m_finishingXover = PR_FALSE; + + m_startedUpdate = FALSE; + XP_MEMSET(&m_knownArts, 0, sizeof(m_knownArts)); + m_knownArts.group_name = m_groupName; + char* host_and_port = NET_ParseURL(url, GET_HOST_PART); + m_host = m_master->FindHost(host_and_port, + (url[0] == 's' || url[0] == 'S'), + -1); + FREEIF(host_and_port); + m_knownArts.host = m_host; + m_getOldMessages = FALSE; + m_promptedAlready = FALSE; + m_downloadAll = FALSE; + m_maxArticles = 0; + m_firstMsgToDownload = 0; + m_lastMsgToDownload = 0; +} + +nsNNTPNewsgroupList::~nsNNTPNewsgroupList() +{ + XP_FREE(m_url); + XP_FREE(m_groupName); + +#ifdef HAVE_DBVIEW + if (m_msgDBView != NULL) + m_msgDBView->Remove(this); +#endif + +#ifdef HAVE_NEWSDB + if (m_newsDB) + m_newsDB->Close(); +#endif + delete m_knownArts.set; +} + +void nsNNTPNewsgroupList::SetView(MessageDBView *view) +{ +#ifdef HAVE_DBVIEW + m_msgDBView = view; + if (view) + view->Add(this); +#endif +} + +#ifdef HAVE_CHANGELISTENER +void nsNNTPNewsgroupList::OnAnnouncerGoingAway (ChangeAnnouncer *instigator) +{ +#ifdef HAVE_DBVIEW + if (m_msgDBView != NULL) + { + m_msgDBView->Remove(this); + m_msgDBView->NotifyAnnouncerGoingAway(instigator); // shout it to the world! + m_msgDBView = NULL; + } +#endif +} +#endif + +int nsNNTPNewsgroupList::GetRangeOfArtsToDownload(MSG_NewsHost* host, + const char* group_name, + int32 first_possible, + int32 last_possible, + int32 maxextra, + int32* first, + int32* last) +{ + int status = 0; + XP_Bool emptyGroup_p = FALSE; + MsgERR err; + + XP_ASSERT(first && last); + if (!first || !last) return -1; + + *first = 0; + *last = 0; + +#ifdef HAVE_PANES + if (m_pane != NULL && !m_finishingXover && !m_startedUpdate) + { + m_startedUpdate = TRUE; + m_pane->StartingUpdate(MSG_NotifyNone, 0, 0); + } +#endif + +#ifdef HAVE_NEWSDB + if (!m_newsDB) + { + if ((err = NewsGroupDB::Open(m_url, m_master, &m_newsDB)) != eSUCCESS) + return ConvertMsgErrToMKErr(err); + else + { + m_set = m_newsDB->GetNewsArtSet(); + m_set->SetLastMember(last_possible); // make sure highwater mark is valid. + NewsFolderInfo *newsGroupInfo = m_newsDB->GetNewsFolderInfo(); + if (newsGroupInfo) + { + ENeoString knownArtsString; + newsGroupInfo->GetKnownArtsSet(knownArtsString); + if (last_possible < newsGroupInfo->GetHighWater()) + newsGroupInfo->SetHighWater(last_possible, TRUE); + m_knownArts.set = msg_NewsArtSet::Create(knownArtsString); + } + else + { + m_knownArts.set = msg_NewsArtSet::Create(); + m_knownArts.set->AddRange(m_newsDB->GetLowWaterArticleNum(), m_newsDB->GetHighwaterArticleNum()); + } +#ifdef HAVE_PANES + m_pane->StartingUpdate(MSG_NotifyNone, 0, 0); + m_newsDB->ExpireUpTo(first_possible, m_pane->GetContext()); + m_pane->EndingUpdate(MSG_NotifyNone, 0, 0); +#endif + if (m_knownArts.set->IsMember(last_possible)) // will this be progress pane? + { + char *noNewMsgs = XP_GetString(MK_NO_NEW_DISC_MSGS); +#ifdef HAVE_PANES + MWContext *context = m_pane->GetContext(); + MSG_Pane* parentpane = m_pane->GetParentPane(); + // send progress to parent pane, if any, because progress pane is going down. + if (parentpane) + context = parentpane->GetContext(); + FE_Progress (context, noNewMsgs); +#endif + } + } + } +#endif + + if (maxextra <= 0 || last_possible < first_possible || last_possible < 1) + { + emptyGroup_p = TRUE; + } + + if (m_knownArts.host != host || + m_knownArts.group_name == NULL || + XP_STRCMP(m_knownArts.group_name, group_name) != 0 || + !m_knownArts.set) + { + /* We're displaying some other group. Clear out that display, and set up + everything to return the proper first chunk. */ + XP_ASSERT(FALSE); // ### dmb todo - need nwo way of doing this + if (emptyGroup_p) + return 0; + } + else + { + if (emptyGroup_p) + return 0; + } + + m_knownArts.first_possible = first_possible; + m_knownArts.last_possible = last_possible; + + /* Determine if we only want to get just new articles or more messages. + If there are new articles at the end we haven't seen, we always want to get those first. + Otherwise, we get the newest articles we haven't gotten, if we're getting more. + My thought for now is that opening a newsgroup should only try to get new articles. + Selecting "More Messages" will first try to get unseen messages, then old messages. */ + + if (m_getOldMessages || !m_knownArts.set->IsMember(last_possible)) + { +#ifdef HAVE_PANES + XP_Bool notifyMaxExceededOn = (m_pane && !m_finishingXover && m_pane->GetPrefs() && m_pane->GetPrefs()->GetNewsNotifyOn()); +#else + XP_Bool notifyMaxExceededOn = FALSE; +#endif + // if the preference to notify when downloading more than x headers is not on, + // and we're downloading new headers, set maxextra to a very large number. + if (!m_getOldMessages && !notifyMaxExceededOn) + maxextra = 0x7FFFFFFFL; + + status = m_knownArts.set->LastMissingRange(first_possible, last_possible, + first, last); + if (status < 0) + return status; + if (*first > 0 && *last - *first >= maxextra) + { + if (!m_getOldMessages && !m_promptedAlready && notifyMaxExceededOn) + { +#ifdef HAVE_PANES + MSG_FolderInfoNews *newsFolder = m_pane->GetMaster()->FindNewsFolder(m_host, m_groupName, FALSE); + XP_Bool result = FE_NewsDownloadPrompt(m_pane->GetContext(), + *last - *first + 1, + &m_downloadAll, newsFolder); +#endif + if (result) + { + m_maxArticles = 0; + + PREF_GetIntPref("news.max_articles", &m_maxArticles); + NET_SetNumberOfNewsArticlesInListing(m_maxArticles); + maxextra = m_maxArticles; + if (!m_downloadAll) + { + XP_Bool markOldRead = FALSE; + PREF_GetBoolPref("news.mark_old_read", &markOldRead); + if (markOldRead && m_set) + m_set->AddRange(*first, *last - maxextra); + *first = *last - maxextra + 1; + } + } + else + *first = *last = 0; + m_promptedAlready = TRUE; + } + else if (m_promptedAlready && !m_downloadAll) + *first = *last - m_maxArticles + 1; + else if (!m_downloadAll) + *first = *last - maxextra + 1; + } + } +#ifdef DEBUG_bienvenu + XP_Trace("GetRangeOfArtsToDownload(first possible = %ld, last possible = %ld, first = %ld, last = %ld maxextra = %ld\n", + first_possible, last_possible, *first, *last, maxextra); +#endif + m_firstMsgToDownload = *first; + m_lastMsgToDownload = *last; + return 0; +} + +int nsNNTPNewsgroupList::AddToKnownArticles(MSG_NewsHost* host, + const char* group_name, + int32 first, int32 last) +{ + int status; + if (m_knownArts.host != host || + m_knownArts.group_name == NULL || + XP_STRCMP(m_knownArts.group_name, group_name) != 0 || + !m_knownArts.set) + { + m_knownArts.host = host; + FREEIF(m_knownArts.group_name); + m_knownArts.group_name = XP_STRDUP(group_name); + delete m_knownArts.set; + m_knownArts.set = msg_NewsArtSet::Create(); + + if (!m_knownArts.group_name || !m_knownArts.set) { + return MK_OUT_OF_MEMORY; + } + + } + + status = m_knownArts.set->AddRange(first, last); +#ifdef HAVE_NEWSDB + if (m_newsDB) + { + NeoDBStack dbStack(m_newsDB->GetDB()); + + NewsFolderInfo *newsGroupInfo = m_newsDB->GetNewsFolderInfo(); + if (newsGroupInfo) + { + char *output = m_knownArts.set->Output(); + if (output) + newsGroupInfo->SetKnownArtsSet(output); + delete[] output; + } + } +#endif + return status; +} + + + + +nsIM + +nsresult +nsNNTPNewsgroupList::InitXOVER(MSG_NewsHost* /*host*/, + const char * /*group_name*/, + uint32 first_msg, uint32 last_msg, + uint32 /*oldest_msg*/, uint32 /*youngest_msg*/) +{ + + int status = 0; + + // Tell the FE to show the GetNewMessages progress dialog +#ifdef HAVE_PANES + FE_PaneChanged (m_pane, FALSE, MSG_PanePastPasswordCheck, 0); +#endif + /* Consistency checks, not that I know what to do if it fails (it will + probably handle it OK...) */ + XP_ASSERT(first_msg <= last_msg); + + /* If any XOVER lines from the last time failed to come in, mark those + messages as read. */ + if (m_lastProcessedNumber < m_lastMsgNumber) + { + m_set->AddRange(m_lastProcessedNumber + 1, m_lastMsgNumber); + } + m_firstMsgNumber = first_msg; + m_lastMsgNumber = last_msg; + m_lastProcessedNumber = first_msg > 1 ? first_msg - 1 : 1; + + return status; +} + +#define NEWS_ART_DISPLAY_FREQ 10 + +nsresult +nsNNTPNewsgroupList::ProcessXOVER(char *line) +{ + int status = 0; + char *next; + uint32 message_number; + // int32 lines; + XP_Bool read_p = FALSE; + + XP_ASSERT (line); + if (!line) + return -1; +#ifdef HAVE_DBVIEW + if (m_msgDBView != NULL) + { + status = ConvertMsgErrToMKErr( m_msgDBView->AddHdrFromServerLine(line, &message_number)); + if (status < 0) + { +#ifdef HAVE_PANES + if (status == MK_DISK_FULL || status == MK_OUT_OF_MEMORY) + FE_Alert(m_pane->GetContext(), XP_GetString(status)); +#endif + return status; + } + } + else +#endif +#ifdef HAVE_NEWSDB + if (m_newsDB != NULL) + { + status = ConvertMsgErrToMKErr(m_newsDB->AddHdrFromXOver(line, &message_number)); + } + else + return -1; +#endif + + next = line; + + + XP_ASSERT(message_number > m_lastProcessedNumber || + message_number == 1); + if (m_set && message_number > m_lastProcessedNumber + 1) + { + /* There are some articles that XOVER skipped; they must no longer + exist. Mark them as read in the newsrc, so we don't include them + next time in our estimated number of unread messages. */ + if (m_set->AddRange(m_lastProcessedNumber + 1, message_number - 1)) + { + /* This isn't really an important enough change to warrant causing + the newsrc file to be saved; we haven't gathered any information + that won't also be gathered for free next time. + */ + } + } + + m_lastProcessedNumber = message_number; + if (m_knownArts.set) + { + status = m_knownArts.set->Add(message_number); + if (status < 0) return status; + } + + if (message_number > m_lastMsgNumber) + m_lastMsgNumber = message_number; + else if (message_number < m_firstMsgNumber) + m_firstMsgNumber = message_number; + + if (m_set) { + read_p = m_set->IsMember(message_number); + } + + /* Update the thermometer with a percentage of articles retrieved. + */ + if (m_lastMsgNumber > m_firstMsgNumber) + { + int32 totToDownload = m_lastMsgToDownload - m_firstMsgToDownload; + int32 lastIndex = m_lastProcessedNumber - m_firstMsgNumber + 1; + int32 numDownloaded = lastIndex; + int32 totIndex = m_lastMsgNumber - m_firstMsgNumber + 1; + int32 percent = (totIndex) ? (int32)(100.0 * (double)numDownloaded / (double)totToDownload) : 0; + +#ifdef HAVE_PANES + FE_SetProgressBarPercent (m_pane->GetContext(), percent); +#endif + + /* only update every 10 articles for speed */ + if ( (totIndex <= NEWS_ART_DISPLAY_FREQ) || ((lastIndex % NEWS_ART_DISPLAY_FREQ) == 0) || (lastIndex == totIndex)) + { + char *statusTemplate = XP_GetString (MK_HDR_DOWNLOAD_COUNT); + char *statusString = PR_smprintf (statusTemplate, numDownloaded, totToDownload); +#ifdef HAVE_PANES + FE_Progress (m_pane->GetContext(), statusString); +#endif + XP_FREE(statusString); + } + } + return status; +} + +nsresult +nsNNTPNewsgroupList::XOVERReset() +{ + m_lastMsgNumber = m_firstMsgNumber; + m_lastProcessedNumber = m_lastMsgNumber; + return 0; +} + +/* When we don't have XOVER, but use HEAD, this is called instead. + It reads lines until it has a whole header block, then parses the + headers; then takes selected headers and creates an XOVER line + from them. This is more for simplicity and code sharing than + anything else; it means we end up parsing some things twice. + But if we don't have XOVER, things are going to be so horribly + slow anyway that this just doesn't matter. + */ + +nsresult +nsNNTPNewsgroupList::ProcessNonXOVER (char * /*line*/) +{ + // ### dmb write me + int status = 0; + return status; +} + + +nsresult +nsNNTPNewsgroupList::FinishXOVER (int status) +{ + struct MSG_NewsKnown* k; + + /* If any XOVER lines from the last time failed to come in, mark those + messages as read. */ + + if (status >= 0 && m_lastProcessedNumber < m_lastMsgNumber) + { + m_set->AddRange(m_lastProcessedNumber + 1, m_lastMsgNumber); + } + +#ifdef HAVE_DBVIEW + if (m_msgDBView != NULL) + { + // we should think about not doing this if status != MK_INTERRUPTED, but we'd need to still clean up the view. + m_msgDBView->AddNewMessages(); + m_msgDBView->Remove(this); + m_msgDBView = NULL; + } +#endif +#ifdef HAVE_NEWSDB + if (m_newsDB) + { + m_newsDB->Close(); + m_newsDB = NULL; + } +#endif + + k = &m_knownArts; + + if (k->set) + { + int32 n = k->set->FirstNonMember(); + if (n < k->first_possible || n > k->last_possible) + { + /* We know we've gotten all there is to know. Take advantage of that to + update our counts... */ + // ### dmb + } + } + + if (m_finishingXover) + { + // turn on m_finishingXover - this is a horrible hack to avoid recursive + // calls which happen when the fe selects a message as a result of getting EndingUpdate, + // which interrupts this url right before it was going to finish and causes FinishXOver + // to get called again. + m_finishingXover = TRUE; + // if we haven't started an update, start one so the fe + // will know to update the size of the view. + if (!m_startedUpdate) + { +#ifdef HAVE_PANES + m_pane->StartingUpdate(MSG_NotifyNone, 0, 0); +#endif + m_startedUpdate = TRUE; + } +#ifdef HAVE_PANES + m_pane->EndingUpdate(MSG_NotifyNone, 0, 0); +#endif + m_startedUpdate = FALSE; + + if (m_lastMsgNumber > 0) + { +#ifdef HAVE_PANES + MWContext *context = m_pane->GetContext(); + MSG_Pane* parentpane = m_pane->GetParentPane(); + // send progress to parent pane, if any, because progress pane is going down. + if (parentpane) + context = parentpane->GetContext(); + + char *statusTemplate = XP_GetString (MK_HDR_DOWNLOAD_COUNT); + char *statusString = PR_smprintf (statusTemplate, m_lastProcessedNumber - m_firstMsgNumber + 1, m_lastMsgNumber - m_firstMsgNumber + 1); + + if (statusString) + { + FE_Progress (context, statusString); + XP_FREE(statusString); + } +#endif + } + MSG_FolderInfoNews *newsFolder = NULL; +#ifdef HAVE_PANES + newsFolder = (m_pane) ? savePane->GetMaster()->FindNewsFolder(m_host, m_groupName, FALSE) : 0; + FE_PaneChanged(m_pane, FALSE, MSG_PaneNotifyFolderLoaded, (uint32)newsFolder); +#endif + } + return 0; + // nsNNTPNewsgroupList object gets deleted by the master when a new one is created. +} diff --git a/mozilla/mailnews/news/src/nsNNTPNewsgroupList.h b/mozilla/mailnews/news/src/nsNNTPNewsgroupList.h new file mode 100644 index 00000000000..1472fffbf47 --- /dev/null +++ b/mozilla/mailnews/news/src/nsNNTPNewsgroupList.h @@ -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) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +/* + * formerly listngst.h + * This class should ultimately be part of a news group listing + * state machine - either by inheritance or delegation. + * Currently, a folder pane owns one and libnet news group listing + * related messages get passed to this object. + */ +#ifndef nsNNTPNewsgroupListState_h___ +#define nsNNTPNewsgroupListState_h___ + + +/* The below is all stuff that we remember for netlib about which + articles we've already seen in the current newsgroup. */ + +typedef struct MSG_NewsKnown { + MSG_NewsHost* host; + char* group_name; + msg_NewsArtSet* set; /* Set of articles we've already gotten + from the newsserver (if it's marked + "read", then we've already gotten it). + If an article is marked "read", it + doesn't mean we're actually displaying + it; it may be an article that no longer + exists, or it may be one that we've + marked read and we're only viewing + unread messages. */ + + int32 first_possible; /* The oldest article in this group. */ + int32 last_possible; /* The newest article in this group. */ + + XP_Bool shouldGetOldest; +} MSG_NewsKnown; + +extern NS_COM nsresult +NS_NewMsgXOVERParser(nsIMsgXOVERParser **aInstancePtrResult, + nsIMsgNewsHost *newsHost, + PRInt32 m_firstArticle, + PRInt32 m_lastArticle, + PRInt32 m_firstPossibleArticle, + PRInt32 m_lastPossibleArticle); + +extern NS_COM nsresult +NS_NewMsgNewsArticleList(nsIMsgNewsArticleList **aInstancePtrResult, + nsIMsgNewsHost *newsHost, + nsIMsgNewsgroup *newsgroup); + +#endif