📄 mhfolderc.c
字号:
/* * $Id: MhFolderC.C,v 1.4 2000/08/07 11:05:16 evgeny Exp $ * * Copyright (c) 1994 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 "MhFolderC.h"#include "MhMsgC.h"#include "FileMisc.h"#include "IshAppC.h"#include "AppPrefC.h"#include "MainWinC.h"#include "MsgItemC.h"#include "SortMgrC.h"#include "UndelWinC.h"#include "MsgListC.h"#include "MsgPartC.h"#include <hgl/SysErr.h>#include <hgl/VBoxC.h>#include <unistd.h>#include <dirent.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>extern int debuglev;/*------------------------------------------------------------------------ * Function to determine if all the characters in name are numbers */inline BooleanAllNumbers(const char *name){ if ( *name == ',' ) name++; // An initial comma is allowed in deleted msgs//// strspn returns the length of the initial segment of name that consists// entirely of numbers. If this is not the same as strlen(name), then// there are some non-numbers in the string.// return (strspn(name, "0123456789") == strlen(name));}/*------------------------------------------------------------------------ * Function to determine if a name corresponds to a message file */inline BooleanIsMessage(char *msg){ return (AllNumbers(msg) && !IsDir(msg));}/*------------------------------------------------------------------------ * Function to convert a file name into a message number */inline intMessageNumber(CharC name){ CharC file = BaseName(name); int sign = 1; if ( file.StartsWith(',') ) { file.CutBeg(1); sign = -1; } return (sign * atoi(file.Addr()));}/*------------------------------------------------------------------------ * Function to convert a message number into a file name */inline voidGetMsgFile(CharC dir, int num, StringC& file){ file = dir; if ( !file.EndsWith('/') ) file += '/'; if ( num < 0 ) { file += ','; num = -num; } file += num;}/*------------------------------------------------------------------------ * Function to determine if a message is in a message list */inline BooleanListContains(MsgListC *list, int num){ u_int count = list->size(); int i=0; for (i=0; i<count; i++) { MhMsgC *msg = (MhMsgC*)(*list)[i]; int msgnum = MessageNumber(msg->filename); if ( num == msgnum ) return True; } return False;}/*------------------------------------------------------------------------ * MhFolderC constructor */MhFolderC::MhFolderC(const char *n, Boolean create): FolderC(n, MH_FOLDER, create){ lastDirTime = 0; changedWhileSleeping = False; dirList.AllowDuplicates(FALSE); dirList.SetSorted(FALSE);//// Get the date of the directory// if ( stat(name, &stats) != 0 ) {//// Create the directory if necessary// if ( errno == ENOENT && create ) { if ( debuglev > 0 ) cout <<"Creating MH folder: " <<name <<endl; if ( !MakeDir(name) ) return; stat(name, &stats); } else { StringC errmsg = "Could not stat "; errmsg += name; errmsg += "\n" + SystemErrorMessage(errno); halApp->PopupMessage(errmsg); return; } }//// Make sure this is a directory// if ( !S_ISDIR(stats.st_mode) ) { StringC errmsg = name; errmsg += " is not an MH-format mail folder (a directory)."; halApp->PopupMessage(errmsg); return; }//// See if directory is writable// writable = (access(name, W_OK) == 0); if ( !writable ) { StringC errmsg = "Folder \""; errmsg += name; errmsg += "\" is not writable and will be opened read-only"; halApp->PopupMessage(errmsg, XmDIALOG_WARNING); } opened = True;} // End MhFolderC constructor/*------------------------------------------------------------------------ * MhFolderC destructor */MhFolderC::~MhFolderC(){ if ( delFiles ) RemoveDir(name);}/*------------------------------------------------------------------------ * Method to build message list */BooleanMhFolderC::Scan(){ time_t timeIn = 0; if ( debuglev > 0 ) { cout <<"Entering MhFolderC(" <<BaseName(name) <<")::Scan" <<endl; timeIn = time(0); } Boolean firstTime = (lastDirTime == 0); Boolean showCount = (firstTime && ishApp->mainWin->IsShown() && !ishApp->mainWin->IsIconified());//// Read the directory// time_t saveTime = lastDirTime; if ( !ReadDirectory() ) return False;//// See if there are any changes// if ( msgList->size() == 0 || lastDirTime != saveTime ) { if ( debuglev > 0 ) cout <<"Directory changed since last read" <<endl; VBoxC& vbox = ishApp->mainWin->MsgVBox(); MsgItemC *firstNew = NULL; MsgItemC *lastNew = NULL;//// If there are any messages not in directory list, start from scratch// Boolean dirOk = True; u_int count = msgList->size(); int i=0; for (i=0; dirOk && i<count; i++) { MhMsgC *msg = (MhMsgC*)(*msgList)[i]; int num = MessageNumber(msg->filename); if ( !dirList.includes(num) ) { StringC errmsg = "Message "; errmsg += msg->filename; errmsg += " has disappeared.\nThe folder will be re-read."; halApp->PopupMessage(errmsg, XmDIALOG_WARNING); dirOk = False; } } if ( !dirOk ) DeleteAllMessages();//// Create messages for directory entries that aren't in the message list.// if ( debuglev > 0 ) cout <<"Checking for new messages" <<endl; StringC file; StringC statusStr; count = dirList.size(); for (i=0; i<count; i++) {//// Update progress message if necessary// if ( showCount /*&& (i % 10) == 0*/ ) { statusStr = abbrev; statusStr += " - Scanning messages: "; statusStr += i; ishApp->mainWin->Message(statusStr); } int num = *dirList[i]; if ( !ListContains(msgList, num) ) { GetMsgFile(name, num, file); if ( debuglev > 1 ) cout <<"Found new message: " <<num <<endl; MhMsgC *msg = new MhMsgC(this, file, num); msgList->add(msg);//// Create a message icon for this message// if ( !firstTime && active ) { msg->CreateIcon(); InsertInThread(msg->icon); msgItemList->add(msg->icon); vbox.AddItem(*msg->icon); if ( !firstNew ) firstNew = msg->icon; lastNew = msg->icon; } // End if folder is active//// If this is a partial message, process it// if ( msg->IsPartial() ) AddPartial(msg); } // End if new message found } // End for each directory entry//// Update progress message if necessary// if ( showCount ) { statusStr = abbrev; statusStr += " - Scanning messages: "; statusStr += i; ishApp->mainWin->Message(statusStr); } if ( !firstTime && active ) {//// Scroll to the last then the first to display as many new messages// as possible// if ( lastNew ) { vbox.View()->ScrollToItem(*lastNew); vbox.View()->ScrollToItem(*firstNew); } vbox.Refresh(); } } // End if directory changed scanned = True; SetChanged(False); if ( firstTime ) ScanIndex(); else UpdateIndex();//// Make sure any comma files are marked as deleted// u_int count = msgList->size(); int i=0; for (i=0; i<count; i++) { MsgC *msg = (*msgList)[i]; if ( msg->Number() < 0 && !msg->IsDeleted() ) msg->SetDeleted(); } UpdateIcon(); ishApp->mainWin->ClearMessage(); if ( debuglev > 0 ) { time_t timeOut = time(0); cout <<"Leaving MhFolderC(" <<BaseName(name) <<")::Scan after " <<(timeOut-timeIn) <<" seconds" <<endl; } return True;} // End Scan/*--------------------------------------------------------------- * Method to read the entries from the directory and sort them */BooleanMhFolderC::ReadDirectory(){//// If the time has not changed, our list is current.// if ( stat(name, &stats) == 0 && stats.st_mtime <= lastDirTime ) return True; dirList.removeAll();//// Open the directory// if ( debuglev > 0 ) cout <<"Reading directory" <<endl; DIR *dirp = opendir(name); if ( !dirp ) { int err = errno; StringC errmsg("Cannot open directory: "); errmsg += name + ".\n" + SystemErrorMessage(err); halApp->PopupMessage(errmsg); return False; } char savedir[MAXPATHLEN+1]; getcwd(savedir, MAXPATHLEN); chdir(name);//// Gather names of new files.// struct dirent *dp; Boolean error = False; while ( !error && (dp=readdir(dirp)) != NULL ) {//// Ignore names that aren't mail message files// if ( !IsMessage(dp->d_name) ) continue; char *np = dp->d_name; Boolean deleted = False; if ( *np == ',' ) { deleted = True; np++; }//// Add this number to the list// int number = atoi(np); if ( deleted ) number = -number; dirList.add(number); } // End for each directory entry chdir(savedir); closedir(dirp); lastDirTime = stats.st_mtime;//// Sort the list// if ( debuglev > 0 ) cout <<"Sorting directory" <<endl; dirList.sort(); return True;} // End ReadDirectory/*------------------------------------------------------------------------ * Method to save the folder. Used to update status, get rid of deleted * messages and renumber remaining ones. */BooleanMhFolderC::Save(){ if ( !writable ) return False; if ( debuglev > 0 ) cout <<"Saving folder: " <<name NL; if ( !scanned ) Scan();//// Loop through messages// StringC statusStr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -