📄 folderc.c
字号:
/* * $Id: FolderC.C,v 1.10 2001/07/22 16:04:57 evgeny Exp $ * * Copyright (c) 1993 HAL Computer Systems International, Ltd. * * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. * 1315 Dell Avenue * Campbell, CA 95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * http://www.gnu.org/copyleft/gpl.html * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include "FolderC.h"#include "IshAppC.h"#include "MainWinC.h"#include "MsgC.h"#include "FileMisc.h"#include "FolderPrefC.h"#include "AppPrefC.h"#include "MsgItemC.h"#include "SortMgrC.h"#include "SortPrefC.h"#include "UndelWinC.h"#include "ReadWinC.h"#include "PartialMsgDictC.h"#include "ParamC.h"#include "MsgPartC.h"#include "HeaderC.h"#include "FileMsgC.h"#include "MsgStatus.h"#include "ImapFolderC.h"#include <hgl/SysErr.h>#include <hgl/VBoxC.h>#include <hgl/VItemC.h>#include <hgl/ViewC.h>#include <hgl/RegexC.h>#include <Xm/ScrollBar.h>#include <unistd.h>#include <errno.h>#include <sys/stat.h>PartialMsgDictC *FolderC::partialMsgDict = NULL;/*------------------------------------------------------------------------ * FolderC constructor */FolderC::FolderC(const char *n, FolderTypeT t, Boolean /*create - used by derived class*/){ type = t; if ( !partialMsgDict ) partialMsgDict = new PartialMsgDictC; name = n; isInBox = (name == ishApp->appPrefs->inBox); if ( isInBox ) abbrev = "In-box"; else { abbrev = name; ishApp->AbbreviateFolderName(abbrev); } if ( debuglev > 0 ) cout <<"Opening folder " <<abbrev <<endl; writable = True; scanned = False; changed = False; opened = False; active = False; delFiles = False; lastVScroll = 0;//// These aren't created until the folder is activated// icon = NULL; msgList = new MsgListC; msgList->AllowDuplicates(FALSE); msgList->SetSorted(FALSE); msgItemList = new VItemListC; msgItemList->AllowDuplicates(FALSE); msgItemList->SetSorted(FALSE); delItemList = new VItemListC; delItemList->AllowDuplicates(FALSE); delItemList->SetSorted(FALSE); lastSelList = new VItemListC; lastSelList->AllowDuplicates(FALSE); lastSelList->SetSorted(FALSE);//// Set up index file// if ( type != IMAP_FOLDER ) {//// If this folder is a symbolic link, we'll use the index file for the// real folder// StringC realFile = name; struct stat lstats; if ( lstat(name, &lstats) == 0 && S_ISLNK(lstats.st_mode) ) { realFile = FullPathname(name); if ( debuglev > 0 ) cout <<"Folder is a link to: " <<realFile <<endl; }//// Set index file directory to name specified by $ISHIDX, or to// the same directory as the associated folder if $ISHIDX not set.// CharC dir = ishApp->idxDir; if ( dir == "" ) dir = DirName(realFile); CharC base = BaseName(realFile); if ( debuglev > 0 ) { cout <<"Dir name is \"" <<dir <<"\"" <<endl; cout <<"Base name is \"" <<base <<"\"" <<endl; }//// Remove old toc file if present// StringC tocFile(dir); tocFile += "/."; tocFile += base; tocFile += "-toc"; if ( access(tocFile, F_OK) == 0 ) { if ( debuglev > 0 ) cout <<"Removing old toc file \"" <<tocFile <<"\"" <<endl; unlink(tocFile); }//// Generate name for index file// indexFile = dir; indexFile += "/."; indexFile += base; indexFile += "-idx"; if ( debuglev > 0 ) cout <<"Index file name is \"" <<indexFile <<"\"" <<endl; stat(indexFile, &istats); } // End if not an IMAP folder indexOpenLevel = 0; indexfp = NULL; indexSum = 0; indexSumTime = 0;//// Create a sort manager if this folder has it's own sort keys// RegexC tmp = name; StringC *keys = ishApp->sortPrefs->folderSortKeys.definitionOf(tmp); if ( keys ) sortMgr = new SortMgrC(*keys); else sortMgr = NULL;} // End constructor/*------------------------------------------------------------------------ * FolderC destructor */FolderC::~FolderC(){ Reset(); CloseIndex(True/*force*/); delete lastSelList; delete msgItemList; delete delItemList; delete msgList; if ( icon ) { ishApp->mainWin->FolderVBox().RemoveItem(*icon); delete icon; } delete sortMgr; if ( delFiles && indexFile.size() > 0 ) unlink(indexFile);} // End destructor/*------------------------------------------------------------------------ * Method to delete all messages */voidFolderC::DeleteAllMessages(){ u_int count; int i;//// These are deleted when messages are deleted//#if 0 u_int count = msgItemList->size(); int i=0; for (i=0; i<count; i++) { MsgItemC *item = (MsgItemC *)(*msgItemList)[i]; delete item; } count = delItemList->size(); for (i=0; i<count; i++) { MsgItemC *item = (MsgItemC *)(*delItemList)[i]; delete item; }#endif count = msgList->size(); for (i=0; i<count; i++) { MsgC *msg = (*msgList)[i]; delete msg; } msgItemList->removeAll();; delItemList->removeAll(); msgList->removeAll();//// Remove any partial message entries for this folder// count = partialMsgDict->size(); for (i=count-1; i>=0; i--) { PartialMsgPtr& pm = partialMsgDict->valOf(i); if ( pm->folder != this ) continue; StringC& id = partialMsgDict->keyOf(i); partialMsgDict->remove(id); delete pm; } // End for each incomplete partial UpdateIcon();} // End DeleteAllMessages/*------------------------------------------------------------------------ * Method to show this folder in the folder window */voidFolderC::CreateIcon(){ if ( icon ) return; icon = new VItemC(abbrev); icon->SetUserData(this); UpdateIcon();} // End CreateIcon/*------------------------------------------------------------------------ * Method to set the icon pixmap according to the current state */voidFolderC::UpdateIcon(){ if ( !icon ) return; XpmT lgIcon; XpmT smIcon; Boolean showStatus = (isInBox || ishApp->folderPrefs->showStatus); Boolean someNew = showStatus && HasNewMessages(); if ( isInBox ) { if ( active ) { if ( someNew ) { lgIcon = ishApp->folderPrefs->sysOpenNewXpm; smIcon = ishApp->folderPrefs->smSysOpenNewXpm; } else { lgIcon = ishApp->folderPrefs->sysOpenXpm; smIcon = ishApp->folderPrefs->smSysOpenXpm; } } else { if ( someNew ) { lgIcon = ishApp->folderPrefs->sysClosedNewXpm; smIcon = ishApp->folderPrefs->smSysClosedNewXpm; } else { lgIcon = ishApp->folderPrefs->sysClosedXpm; smIcon = ishApp->folderPrefs->smSysClosedXpm; } } } else { // Not in-box if ( active ) { if ( someNew ) { lgIcon = ishApp->folderPrefs->userOpenNewXpm; smIcon = ishApp->folderPrefs->smUserOpenNewXpm; } else { lgIcon = ishApp->folderPrefs->userOpenXpm; smIcon = ishApp->folderPrefs->smUserOpenXpm; } } else { if ( someNew ) { lgIcon = ishApp->folderPrefs->userClosedNewXpm; smIcon = ishApp->folderPrefs->smUserClosedNewXpm; } else { lgIcon = ishApp->folderPrefs->userClosedXpm; smIcon = ishApp->folderPrefs->smUserClosedXpm; } } } icon->SetPixmaps(lgIcon, smIcon); icon->ValidDropSite(!active && !isInBox && writable); if ( ishApp->folderPrefs->showStatus ) { char *tag; if ( Changed() ) tag = (char *) (someNew ? "bold-italic" : "bold"); else tag = (char *) (someNew ? "italic" : "plain"); icon->SetLabelTag(tag); }} // End UpdateIcon/*------------------------------------------------------------------------ * Method to delete all message objects */voidFolderC::Reset(){ if ( active ) { ishApp->mainWin->MsgVBox().RemoveAllItems(); if ( ishApp->undelWin ) ishApp->undelWin->Clear(); } DeleteAllMessages(); scanned = False;} // End Reset/*------------------------------------------------------------------------ * Method to re-scan folder */BooleanFolderC::Rescan(){ Lock(True); if ( active ) { halApp->BusyCursor(True);//// Close any reading windows open to this folder// u_int count = ishApp->readWinList.size(); int i=0; for (i=0; i<count; i++) { ReadWinC *readWin = (ReadWinC*)*ishApp->readWinList[i]; if ( readWin->IsShown() && readWin->msg->folder == this ) readWin->Hide(); } } Reset(); if ( indexFile.size() > 0 ) unlink(indexFile); Boolean success = Scan(); if ( active ) { CreateIcons(); ishApp->mainWin->MsgVBox().Refresh(); halApp->BusyCursor(False); } ishApp->mainWin->FolderVBox().Refresh(); ishApp->mainWin->EnableButtons(); ishApp->mainWin->UpdateTitle(); Lock(False); return success;}/*--------------------------------------------------------------- * Method to open index file */BooleanFolderC::OpenIndex(){ indexOpenLevel++; if ( indexfp ) return True;//// Open the file// if ( debuglev > 1 ) cout <<"Opening index file " <<indexFile <<endl; indexfp = fopen(indexFile, writable ? "r+" : "r"); if ( !indexfp ) { if ( errno != ENOENT ) { StringC errmsg("Could not open index file: "); errmsg += indexFile; errmsg += "\n" + SystemErrorMessage(errno); halApp->PopupMessage(errmsg); } indexOpenLevel = 0; return False; } return True;} // End OpenIndex/*--------------------------------------------------------------- * Method to close index file */voidFolderC::CloseIndex(Boolean force){ if ( !indexfp ) return; if ( force ) indexOpenLevel = 0; else indexOpenLevel--; if ( indexOpenLevel > 0 ) return; if ( indexOpenLevel < 0 ) indexOpenLevel = 0; if ( debuglev > 1 ) cout <<"Closing index file " <<indexFile <<endl; fclose(indexfp); indexfp = NULL;}/*------------------------------------------------------------------------ * Method to initialize the index file */voidFolderC::ScanIndex(){//// If the folder isn't writable, we won't try to write the index either// if ( !writable ) { ReadIndex(); return; }//// If the index file doesn't exist, create it from scratch// if ( access(indexFile, F_OK) != 0 ) { CreateIndex(); return; } Lock(True);//// If the index file does exist, open it and read any entries that are present// if ( !OpenIndex() ) { Lock(False); return; }//// Loop through each message.// u_int msgCount = msgList->size(); Boolean hitEOF = feof(indexfp); int i=0; for (i=0; i<msgCount; i++) { MsgC *msg = (*msgList)[i];//// See if the entry for this message can be read// if ( !hitEOF ) { msg->indexOffset = ftell(indexfp); if ( !msg->ReadIndex(indexfp) ) {//// If we're at eof, it means we need to create a new entry// if ( feof(indexfp) ) hitEOF = True;//// If we're not at eof, it means we have a bogus file// else { msg->indexOffset = -1; CloseIndex(); CreateIndex(); Lock(False); return; } } }//// If we hit the end of the file, we need to create a new entry// if ( hitEOF ) msg->indexOffset = AddIndexEntry(msg->status, msg->BodyBytes(), msg->BodyLines(), msg->Id()); } // End for each message CloseIndex(); Lock(False);} // End ScanIndex/*------------------------------------------------------------------------ * Method to bring the index file up to date */voidFolderC::UpdateIndex(){//// IMAP folders don't have an index// if ( IsImap() ) return; if ( !writable ) return;//// If the index file doesn't exist, create it from scratch// if ( access(indexFile, F_OK) != 0 ) { CreateIndex(); return; } Lock(True); if ( debuglev > 0 ) cout <<"Updating index file \"" <<indexFile <<"\"" <<endl;//// If the index file does exist, open it and read any entries that are present// if ( !OpenIndex() ) { Lock(False); return; }//// Loop through each message. If there isn't an index entry, create one// u_int msgCount = msgList->size(); int i=0; for (i=0; i<msgCount; i++) { MsgC *msg = (*msgList)[i]; if ( msg->indexOffset < 0 ) msg->indexOffset = AddIndexEntry(msg->status, msg->BodyBytes(), msg->BodyLines(), msg->Id()); } // End for each message CloseIndex(); Lock(False);} // End UpdateIndex/*------------------------------------------------------------------------ * Method to create the index file */voidFolderC::CreateIndex(){ Lock(True); CloseIndex(/*force=*/True); if ( debuglev > 0 ) cout <<"Creating index file " <<indexFile <<endl; indexfp = fopen(indexFile, "w"); if ( !indexfp ) { StringC errmsg("Could not create index file \""); errmsg += indexFile; errmsg += "\".\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); Lock(False); return; } indexOpenLevel = 1;//// Loop through messages and create an index entry for each// u_int msgCount = msgList->size(); int i=0; for (i=0; i<msgCount; i++) { MsgC *msg = (*msgList)[i]; msg->indexOffset = AddIndexEntry(msg->status, msg->BodyBytes(), msg->BodyLines(), msg->Id()); } CloseIndex(); chmod(indexFile, ishApp->folderPrefs->folderFileMask); stat(indexFile, &istats); Lock(False);} // End CreateIndex/*------------------------------------------------------------------------ * Method to read the index file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -