1 line
32 KiB
C
Executable File
1 line
32 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
|
the limitations in the disclaimer below) provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
|
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE. */
|
|
|
|
#define FILE_NUM 72
|
|
#include "toc.h"
|
|
|
|
#pragma segment TOC
|
|
|
|
OSErr WriteRForkTOC(TOCHandle tocH);
|
|
Boolean HasExternalTOC(FSSpecPtr spec);
|
|
OSErr PeekRTOC(FSSpecPtr spec,TOCType *tocPart);
|
|
void FixBoxUnread(TOCHandle tocH);
|
|
TOCHandle FixErrantTOC(FSSpecPtr spec,TOCHandle tocH,short why);
|
|
Boolean WantRebuildTOC(UPtr boxName,OSErr why, Boolean isIMAP);
|
|
OSErr PeekDTOC(FSSpecPtr spec,TOCType *tocPart);
|
|
void CheckStringLen(UPtr s, char maxLen, short fillLen);
|
|
#define TOCSizeShouldBe(tocH) (sizeof(TOCType)+MAX(0,(*(tocH))->count-1)*sizeof(MSumType))
|
|
#define TOCCountShouldBe(tocH) (1+(GetHandleSize_(tocH)-sizeof(TOCType))/sizeof(MSumType))
|
|
/************************************************************************
|
|
* TOCBySpec - take a spec, return a TOC
|
|
************************************************************************/
|
|
TOCHandle TOCBySpec(FSSpecPtr spec)
|
|
{
|
|
if (!GetMailbox(spec,False)) return(FindTOC(spec));
|
|
return(nil);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetTOCByFSS - open a toc from an FSS
|
|
************************************************************************/
|
|
short GetTOCByFSS(FSSpecPtr specPtr,TOCHandle *tocH)
|
|
{
|
|
*tocH = TOCBySpec(specPtr);
|
|
return(*tocH ? noErr : 1);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* KillTOC - kill the toc for a file
|
|
**********************************************************************/
|
|
OSErr KillTOC(short refN,FSSpecPtr spec)
|
|
{
|
|
Boolean sane;
|
|
OSErr err;
|
|
Handle r;
|
|
OSType type;
|
|
Str255 name;
|
|
short id;
|
|
short oldResF = CurResFile();
|
|
|
|
/*
|
|
* if the resource fork is bad or we can't open it, just remove it
|
|
*/
|
|
if (!refN && (FSpRFSane(spec,&sane) || !sane || -1==(refN=FSpOpenResFile(spec,fsRdWrPerm))))
|
|
err = FSpKillRFork(spec);
|
|
else
|
|
{
|
|
/*
|
|
* delete the backup resource
|
|
*/
|
|
Zap1Resource(TOC_TYPE,1002);
|
|
|
|
if (PrefIsSet(PREF_NO_RF_TOC_BACKUP))
|
|
{
|
|
/*
|
|
* remove old resource
|
|
*/
|
|
Zap1Resource(TOC_TYPE,1001);
|
|
err = ResError();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* try to move the old resource
|
|
*/
|
|
SetResLoad(False);
|
|
r = Get1Resource(TOC_TYPE,1001);
|
|
err = ResError();
|
|
if (!r && !err) err = resNotFound;
|
|
SetResLoad(True);
|
|
if (!err)
|
|
{
|
|
GetResInfo(r, &id, &type, name);
|
|
if (!(err = ResError()))
|
|
{
|
|
SetResInfo(r,1002,name);
|
|
if (spec && !(err = ResError()))
|
|
err = MyUpdateResFile(refN);
|
|
}
|
|
}
|
|
}
|
|
if (spec) CloseResFile(refN);
|
|
|
|
/*
|
|
* if we couldn't delete the resource, kill the resource fork
|
|
*/
|
|
if (spec && err && err!=resNotFound) err = FSpKillRFork(spec);
|
|
}
|
|
UseResFile (oldResF);
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CheckTOC - check a file for a table of contents, and build it if
|
|
* necessary.
|
|
* slated for removal
|
|
**********************************************************************/
|
|
TOCHandle CheckTOC(FSSpecPtr spec)
|
|
{
|
|
uLong box, res, file, mod;
|
|
Boolean resource;
|
|
OSErr err;
|
|
|
|
if ((err=TOCDates(spec,&box,&res,&file)) && err!=fnfErr) return(nil);
|
|
|
|
/*
|
|
* Which one do we want?
|
|
*/
|
|
if (res && res>=file) // resource exists and is newer
|
|
{
|
|
resource = True;
|
|
mod = res;
|
|
}
|
|
else if (file) // file exists and is newer
|
|
{
|
|
resource = False;
|
|
mod = file;
|
|
}
|
|
else return(BuildTOC(spec)); // no dice
|
|
|
|
#ifdef NEVER
|
|
/*
|
|
* Is it new enough?
|
|
*/
|
|
if (!PrefIsSet(PREF_IGNORE_OUTDATE) && box>mod)
|
|
switch (AlertStr(NEW_TOC_ALRT,Caution,spec->name))
|
|
{
|
|
case TOC_CREATE_NEW: return(RebuildTOC(spec,nil,resource)); break;
|
|
case CANCEL_ITEM:
|
|
case TOC_CANCEL:
|
|
return(nil); break;
|
|
default: AFSpSetMod(spec,mod); break;
|
|
}
|
|
#endif
|
|
|
|
return(ReadTOC(spec,resource));
|
|
}
|
|
|
|
/**********************************************************************
|
|
* TOCDates - get the dates off a mailbox
|
|
**********************************************************************/
|
|
OSErr TOCDates(FSSpecPtr spec, uLong *box, uLong *res, uLong *file)
|
|
{
|
|
FSSpec tocSpec;
|
|
TOCType partTOC;
|
|
OSErr err;
|
|
long boxSize = FSpDFSize(spec);
|
|
|
|
*box = AFSpGetMod(spec);
|
|
|
|
Box2TOCSpec(spec,&tocSpec);
|
|
*file = AFSpGetMod(&tocSpec);
|
|
|
|
if (!(err=PeekRTOC(spec,&partTOC)))
|
|
{
|
|
*res = partTOC.writeDate;
|
|
|
|
if (boxSize==partTOC.boxSize-1)
|
|
*res = *box; // if the sizes match, forget the date
|
|
|
|
if (!*res)
|
|
{
|
|
// somebody didn't fill in writeDate
|
|
if (*file)
|
|
;// we have a file-based toc. Let's assume it has the good info
|
|
else
|
|
*res = *box-1; // no date in resource toc; might be bad
|
|
}
|
|
}
|
|
else
|
|
*res = 0;
|
|
if (err && boxSize>0) ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\pTOCDates(%p): %d",spec->name,err);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* Box2TOCSpec - make a toc spec out of a mailbox spec
|
|
************************************************************************/
|
|
FSSpecPtr Box2TOCSpec(FSSpecPtr boxSpec,FSSpecPtr tocSpec)
|
|
{
|
|
Str31 suffix;
|
|
*tocSpec = *boxSpec;
|
|
PCat(tocSpec->name,GetRString(suffix,TOC_SUFFIX));
|
|
return(tocSpec);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* ReadTOC - read the toc file for a mailbox
|
|
**********************************************************************/
|
|
TOCHandle ReadTOC(FSSpecPtr spec, Boolean resource)
|
|
{
|
|
TOCHandle tocH=nil;
|
|
OSErr insane = noErr;
|
|
|
|
insane = resource ? ReadRForkTOC(spec,&tocH) : ReadDForkTOC(spec,&tocH);
|
|
|
|
if (tocH)
|
|
{
|
|
/*
|
|
* don't take these for granted...
|
|
*/
|
|
(*tocH)->durty = (*tocH)->reallyDirty = False;
|
|
(*tocH)->mailbox.spec = *spec;
|
|
(*tocH)->refN = 0;
|
|
(*tocH)->win = nil;
|
|
(*tocH)->volumeFree = 0;
|
|
(*tocH)->previewID = 0;
|
|
(*tocH)->previewPTE = 0;
|
|
(*tocH)->lastSameTicks = 0;
|
|
(*tocH)->mouseTicks = 0;
|
|
(*tocH)->mouseSpot.h = (*tocH)->mouseSpot.v = 0;
|
|
(*tocH)->userActive = 0;
|
|
(*tocH)->drawerWin = 0;
|
|
#ifdef IMAP
|
|
LDRef(tocH);
|
|
(*tocH)->imapTOC = IsIMAPMailboxFileLo(spec, &((*tocH)->imapMBH))?1:0;
|
|
UL(tocH);
|
|
#endif
|
|
/*
|
|
* and make sure it hasn't become special or unspecial
|
|
*/
|
|
(*tocH)->which = GetMailboxType(spec);
|
|
|
|
/*
|
|
* make sure we don't have any leftovers
|
|
*/
|
|
CleanseTOC(tocH);
|
|
|
|
/*
|
|
* check toc for reasonableness
|
|
*/
|
|
if (insane=InsaneTOC(tocH)) return(FixErrantTOC(spec,tocH,insane));
|
|
|
|
/*
|
|
* and sizes
|
|
*/
|
|
GetTOCK(tocH,&(*tocH)->usedK,&(*tocH)->totalK);
|
|
(*tocH)->updateBoxSizes = true;
|
|
|
|
/*
|
|
* check unread status
|
|
*/
|
|
(*tocH)->unread = TOCUnread(tocH);
|
|
|
|
/*
|
|
* hurray for our side!
|
|
*/
|
|
UL(tocH);
|
|
return(tocH);
|
|
}
|
|
else if (CommandPeriod || insane==memFullErr)
|
|
return(nil);
|
|
else
|
|
return (FixErrantTOC(spec,nil,euCorruptTOC));
|
|
}
|
|
|
|
/**********************************************************************
|
|
*
|
|
**********************************************************************/
|
|
OSErr ReadDForkTOC(FSSpecPtr aSpec,TOCHandle *inTOC)
|
|
{
|
|
long count;
|
|
int err=noErr;
|
|
short refN=0;
|
|
TOCHandle tocH=nil;
|
|
FSSpec tocSpec;
|
|
|
|
/*
|
|
* toc is kept in name.toc; try to open it
|
|
*/
|
|
Box2TOCSpec(aSpec,&tocSpec);
|
|
if (!(err=AFSpOpenDF(&tocSpec,&tocSpec,fsRdPerm,&refN)))
|
|
{
|
|
/*
|
|
* allocate space for the toc
|
|
*/
|
|
if (!(err = GetEOF(refN, &count)))
|
|
if (count < sizeof(TOCType))
|
|
err = sizeof(TOCType)-count;
|
|
else if (tocH = NuHTempOK(count))
|
|
{
|
|
/*
|
|
* try to read it
|
|
*/
|
|
LDRef(tocH);
|
|
err = ARead(refN,&count,(void*)*tocH);
|
|
(void) MyFSClose(refN), refN = 0;
|
|
if (err) ZapHandle(tocH);
|
|
}
|
|
else
|
|
{
|
|
MyFSClose(refN);
|
|
WarnUser(MEM_ERR,err=MemError());
|
|
}
|
|
}
|
|
|
|
if (err) FileSystemError(READ_TOC,aSpec->name,err);
|
|
|
|
*inTOC = tocH;
|
|
ComposeLogS(err ? LOG_ALRT|LOG_TOC : LOG_TOC,nil,"\pReadDForkTOC(%p): %d",aSpec->name,err);
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ReadRForkTOC - read a TOC from the resource fork
|
|
**********************************************************************/
|
|
OSErr ReadRForkTOC(FSSpecPtr aSpec,TOCHandle *inTOC)
|
|
{
|
|
short refN=0;
|
|
Handle r;
|
|
TOCHandle tocH=nil;
|
|
long size;
|
|
OSErr err;
|
|
FSSpec lSpec = *aSpec;
|
|
short oldResF = CurResFile();
|
|
|
|
IsAlias(aSpec,&lSpec);
|
|
|
|
if (-1!=(refN=FSpOpenResFile(&lSpec,fsRdPerm)))
|
|
{
|
|
SetResLoad(False);
|
|
r = Get1Resource(TOC_TYPE,1001);
|
|
if (!r) r = Get1Resource(TOC_TYPE,1002);
|
|
SetResLoad(True);
|
|
if (r)
|
|
{
|
|
size = GetResourceSizeOnDisk(r);
|
|
if (err = ResError())
|
|
FileSystemError(CORRUPT_RFORK,&lSpec.name,err);
|
|
else
|
|
{
|
|
tocH = NuHTempOK(size);
|
|
if (!tocH)
|
|
WarnUser(MEM_ERR,err=MemError());
|
|
else
|
|
{
|
|
ReadPartialResource(r,0,LDRef(tocH),size);
|
|
if (err = ResError())
|
|
FileSystemError(CORRUPT_RFORK,&lSpec.name,err);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
FileSystemError(CORRUPT_RFORK,&lSpec.name,resNotFound);
|
|
}
|
|
|
|
if (refN) CloseResFile(refN);
|
|
if (err) ZapHandle(tocH);
|
|
|
|
ComposeLogS(err ? LOG_ALRT|LOG_TOC : LOG_TOC,nil,"\pReadRForkTOC(%p): %d",aSpec->name,err);
|
|
*inTOC = tocH;
|
|
UseResFile (oldResF);
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* HasExternalTOC - does a file have an external table of contents?
|
|
**********************************************************************/
|
|
Boolean HasExternalTOC(FSSpecPtr spec)
|
|
{
|
|
FSSpec tocSpec;
|
|
Box2TOCSpec(spec,&tocSpec);
|
|
return(noErr==FSpExists(&tocSpec));
|
|
}
|
|
|
|
/**********************************************************************
|
|
* WriteTOC - write a toc to the proper file
|
|
**********************************************************************/
|
|
int WriteTOC(TOCHandle tocH)
|
|
{
|
|
int err;
|
|
short refN=0;
|
|
long count;
|
|
FSSpec tocSpec, spec;
|
|
uLong writeDate = LocalDateTime() & ~(1L); /* make it even because of idiot novell */
|
|
uLong size;
|
|
uLong deadTicks;
|
|
|
|
// Avoid multiple simultaneous writes
|
|
ASSERT(!(*tocH)->beingWritten);
|
|
deadTicks = TickCount();
|
|
while ((*tocH)->beingWritten && (TickCount()-deadTicks< 5*60)) // wait up to 5 seconds
|
|
{
|
|
MyYieldToAnyThread();
|
|
MiniEvents();
|
|
}
|
|
ASSERT(!(*tocH)->beingWritten);
|
|
if ((*tocH)->beingWritten++)
|
|
{
|
|
// Oh, sxxt. Somebody either left the beingWritten flag set, or there's a verrrrrrryyyyy long
|
|
// write going on.
|
|
(*tocH)->beingWritten = 1; // rest the counter and hope for the best
|
|
}
|
|
|
|
// Save this dainty little morsel
|
|
if ((*tocH)->which==OUT) BMD(&NoAdsRec,&(*tocH)->internalUseOnly,sizeof((*tocH)->internalUseOnly));
|
|
|
|
spec = GetMailboxSpec(tocH,-1);
|
|
size = FSpDFSize(&spec);
|
|
|
|
(*tocH)->boxSize = size+1; /* add 1 to signal that we know it's ok */
|
|
(*tocH)->writeDate = writeDate;
|
|
|
|
if (PrefIsSet(PREF_NEW_TOC))
|
|
err = WriteRForkTOC(tocH);
|
|
|
|
LDRef(tocH);
|
|
|
|
/*
|
|
* build the name
|
|
*/
|
|
Box2TOCSpec(&spec,&tocSpec);
|
|
|
|
if (PrefIsSet(PREF_NEW_TOC))
|
|
{
|
|
if (!err)
|
|
{
|
|
ChainDelete(&tocSpec);
|
|
AFSpSetMod(&spec,writeDate);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* open the file
|
|
*/
|
|
err = AFSpOpenDF(&tocSpec,&tocSpec,fsRdWrPerm,&refN);
|
|
if (err == fnfErr)
|
|
{
|
|
if (err=FSpCreate(&tocSpec,CREATOR,TOC_TYPE,smSystemScript))
|
|
goto failure;
|
|
err = FSpOpenDF(&tocSpec,fsRdWrPerm,&refN);
|
|
}
|
|
if (err) goto failure;
|
|
|
|
|
|
/*
|
|
* write the file
|
|
*/
|
|
count = GetHandleSize_(tocH);
|
|
(*tocH)->unreadBase = (*tocH)->count;
|
|
if (err = AWrite(refN,&count,(void*)*tocH)) goto failure;
|
|
|
|
/*
|
|
* fix up menu items
|
|
*/
|
|
FixBoxUnread(tocH);
|
|
|
|
/*
|
|
* done
|
|
*/
|
|
GetFPos(refN,&count);
|
|
SetEOF(refN,count);
|
|
(void) MyFSClose(refN);
|
|
(*tocH)->durty = (*tocH)->reallyDirty = False;
|
|
AFSpSetMod(&tocSpec,writeDate);
|
|
AFSpSetMod(&spec,writeDate);
|
|
ComposeLogS(LOG_FLOW,nil,"\pWriteTOC %p\015",tocSpec.name);
|
|
UL(tocH);
|
|
|
|
/*
|
|
* the size area
|
|
*/
|
|
if ((*tocH)->win&&IsWindowVisible(GetMyWindowWindowPtr((*tocH)->win)))
|
|
InvalBoxSizeBox((*tocH)->win);
|
|
|
|
(*tocH)->beingWritten--;
|
|
ComposeLogS(err ? LOG_ALRT|LOG_TOC : LOG_TOC,nil,"\pWriteTOC(%p): %d",tocSpec.name,err);
|
|
return(noErr);
|
|
|
|
failure:
|
|
ComposeLogS(err ? LOG_ALRT|LOG_TOC : LOG_TOC,nil,"\pWriteTOC(%p): %d",tocSpec.name,err);
|
|
FileSystemError(WRITE_TOC,tocSpec.name,err);
|
|
UL(tocH);
|
|
if (refN)
|
|
{ /* get rid of partial file */
|
|
(void) MyFSClose(refN);
|
|
(void) FSpDelete(&tocSpec);
|
|
}
|
|
}
|
|
UL(tocH);
|
|
(*tocH)->beingWritten--;
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* FixBoxUnread - fix the unread status of a mailbox in the menus
|
|
************************************************************************/
|
|
void FixBoxUnread(TOCHandle tocH)
|
|
{
|
|
Boolean unread=TOCUnread(tocH);
|
|
short myMenu;
|
|
short myItem;
|
|
FSSpec spec;
|
|
uLong total, used;
|
|
|
|
(*tocH)->unread = unread;
|
|
(*tocH)->unreadBase = (*tocH)->count;
|
|
|
|
myItem = 0;
|
|
spec = GetMailboxSpec(tocH,-1);
|
|
Spec2Menu(&spec,False,&myMenu,&myItem);
|
|
|
|
if (myItem>0)
|
|
{
|
|
FixSpecUnread(&spec,unread);
|
|
FixMenuUnread(GetMHandle(myMenu),myItem,unread);
|
|
}
|
|
|
|
GetTOCK(tocH,&used,&total);
|
|
if ((*tocH)->usedK!=used || (*tocH)->totalK!=total)
|
|
{
|
|
(*tocH)->usedK = used;
|
|
(*tocH)->totalK = total;
|
|
(*tocH)->updateBoxSizes = true;
|
|
}
|
|
|
|
}
|
|
|
|
/**********************************************************************
|
|
* WriteRForkTOC - write a table of contents to the resource fork of a file
|
|
**********************************************************************/
|
|
OSErr WriteRForkTOC(TOCHandle tocH)
|
|
{
|
|
FSSpec spec = GetMailboxSpec(tocH,-1);
|
|
short refN;
|
|
OSErr err;
|
|
Boolean sane;
|
|
short oldResF = CurResFile();
|
|
|
|
IsAlias(&spec,&spec);
|
|
if (FSpRFSane(&spec,&sane) || !sane) FSpKillRFork(&spec);
|
|
FSpCreateResFile(&spec,CREATOR,'TEXT',smSystemScript);
|
|
|
|
if (-1!=(refN=FSpOpenResFile(&spec,fsRdWrPerm)))
|
|
{
|
|
KillTOC(refN,nil);
|
|
(*tocH)->unreadBase = (*tocH)->count;
|
|
AddResource((Handle)tocH,TOC_TYPE,1001,"");
|
|
err = ResError();
|
|
if (!err) MyUpdateResFile(refN);
|
|
DetachResource((Handle)tocH);
|
|
CloseResFile(refN);
|
|
}
|
|
else err = ResError();
|
|
|
|
if (err) FileSystemError(WRITE_TOC,spec.name,err);
|
|
else
|
|
{
|
|
/*
|
|
* fix up menu items
|
|
*/
|
|
FixBoxUnread(tocH);
|
|
|
|
/*
|
|
* the size area
|
|
*/
|
|
if ((*tocH)->win&&IsWindowVisible(GetMyWindowWindowPtr((*tocH)->win)))
|
|
InvalBoxSizeBox((*tocH)->win);
|
|
|
|
/*
|
|
* done
|
|
*/
|
|
(*tocH)->durty = (*tocH)->reallyDirty = False;
|
|
}
|
|
UseResFile (oldResF);
|
|
ComposeLogS(err ? LOG_ALRT|LOG_TOC : LOG_TOC,nil,"\pWriteRForkTOC(%p): %d",spec.name,err);
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* TOCUnread - does a table of contents contain unread messages?
|
|
**********************************************************************/
|
|
Boolean TOCUnread(TOCHandle tocH)
|
|
{
|
|
Boolean unread = False;
|
|
uLong minDate;
|
|
short myItem;
|
|
|
|
// don't underline Junk if the user has asked us not to.
|
|
if ((((*tocH)->which==JUNK) || (IsIMAPJunkMailbox(TOCToMbox(tocH))))
|
|
&& JunkPrefBoxNoUnread())
|
|
return false;
|
|
|
|
minDate = GetRLong(UNREAD_LIMIT)*24*3600;
|
|
if (minDate) minDate = GMTDateTime()-minDate;
|
|
|
|
for (myItem=0;myItem<(*tocH)->count;myItem++)
|
|
if ((*tocH)->sums[myItem].state==UNREAD &&
|
|
(!minDate || (*tocH)->sums[myItem].seconds>minDate))
|
|
{
|
|
unread = True;
|
|
break;
|
|
}
|
|
return(unread);
|
|
}
|
|
|
|
/************************************************************************
|
|
* TOCUnreadCount - how many messages are unread in this toc?
|
|
************************************************************************/
|
|
short TOCUnreadCount(TOCHandle tocH,Boolean recentOnly)
|
|
{
|
|
short count = 0;
|
|
short i;
|
|
uLong minDate;
|
|
|
|
if (!tocH) return 0;
|
|
|
|
if (recentOnly)
|
|
{
|
|
minDate = GetRLong(UNREAD_LIMIT)*24*3600;
|
|
if (minDate) minDate = GMTDateTime()-minDate;
|
|
}
|
|
|
|
if (recentOnly && minDate)
|
|
{
|
|
for (i=(*tocH)->count-1;i>=0;i--)
|
|
if ((*tocH)->sums[i].state==UNREAD && (*tocH)->sums[i].seconds>minDate) count++;
|
|
}
|
|
else
|
|
{
|
|
for (i=(*tocH)->count-1;i>=0;i--)
|
|
if ((*tocH)->sums[i].state==UNREAD) count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FindTOC - find a TOC in the TOC window list
|
|
**********************************************************************/
|
|
TOCHandle FindTOC(FSSpecPtr spec)
|
|
{
|
|
TOCHandle tocH;
|
|
FSSpec boxSpec;
|
|
FSSpec newSpec;
|
|
|
|
for (tocH=TOCList; tocH; tocH = (*tocH)->next)
|
|
{
|
|
boxSpec = GetMailboxSpec(tocH,-1);
|
|
if (SameSpec(&boxSpec,spec)) break;
|
|
if (IsAlias(&boxSpec,&boxSpec) && SameSpec(&boxSpec,spec)) break;
|
|
}
|
|
|
|
if (!tocH && IsAlias(spec,&newSpec) && !SameSpec(spec,&newSpec)) return(FindTOC(&newSpec));
|
|
else return(tocH);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* FlushTOCs - make sure all toc's are quiescent
|
|
************************************************************************/
|
|
int FlushTOCs(Boolean andClose,Boolean canSkip)
|
|
{
|
|
TOCHandle tocH, nextTocH;
|
|
WindowPtr tocWinWP;
|
|
int shdBe;
|
|
short err;
|
|
static long lastTime;
|
|
static short delay;
|
|
Boolean dontCloseIMAPToc;
|
|
|
|
#ifdef THREADING_ON
|
|
if (GetNumBackgroundThreads()) // thread might be using toc, so don't close 'em
|
|
return (noErr);
|
|
#endif
|
|
|
|
if (canSkip && lastTime && TickCount()-lastTime < delay)
|
|
return(noErr);
|
|
|
|
err = 0;
|
|
|
|
for (tocH=TOCList; tocH; tocH = nextTocH)
|
|
{
|
|
if ((long)*tocH & 1)
|
|
{
|
|
#ifdef DEBUG
|
|
if (RunType != Production) DebugStr("\pbad tocH!");
|
|
#endif DEBUG
|
|
if (tocH==TOCList)
|
|
TOCList = nil;
|
|
else
|
|
{
|
|
for (nextTocH=TOCList;
|
|
(*nextTocH)->next!=tocH;nextTocH=(*nextTocH)->next);
|
|
(*nextTocH)->next = nil;
|
|
}
|
|
break;
|
|
}
|
|
|
|
shdBe = TOCSizeShouldBe(tocH);
|
|
if (GetHandleSize_(tocH)!=shdBe)
|
|
{
|
|
#ifdef DEBUG
|
|
if (RunType != Production)
|
|
{
|
|
Str127 debug;
|
|
Str32 name;
|
|
GetMailboxName(tocH,-1,name);
|
|
ComposeString(debug,"\p%p: size %d, should be %d (%d + (%d-1)*%d)",
|
|
name,GetHandleSize_(tocH),shdBe,sizeof(TOCType),(*tocH)->count,
|
|
sizeof(MSumType));
|
|
SysBreakStr(debug);
|
|
}
|
|
#endif DEBUG
|
|
SetHandleBig_(tocH,shdBe);
|
|
}
|
|
nextTocH = (*tocH)->next;
|
|
|
|
if (err=BoxFClose(tocH,true)) break;
|
|
if ((*tocH)->reallyDirty)
|
|
{
|
|
if (err=WriteTOC(tocH))
|
|
break;
|
|
}
|
|
else if ((*tocH)->unreadBase!=(*tocH)->count)
|
|
FixBoxUnread(tocH);
|
|
tocWinWP = GetMyWindowWindowPtr((*tocH)->win);
|
|
|
|
// Make sure the toc we're about to close isn't an IMAP toc that's in use somewhere ...
|
|
if (andClose)
|
|
dontCloseIMAPToc = (*tocH)->imapTOC && IMAPTOCInUse(TOCToMbox(tocH));
|
|
|
|
if (andClose && !IsWindowVisibleClassic(tocWinWP) && !(MyNMRec && (*tocH)->which==IN) && !dontCloseIMAPToc)
|
|
{
|
|
int sNum;
|
|
for (sNum=0;sNum<(*tocH)->count;sNum++)
|
|
if ((*tocH)->sums[sNum].messH) break;
|
|
if (sNum==(*tocH)->count)
|
|
CloseMyWindow(tocWinWP);
|
|
}
|
|
if (NEED_YIELD) break;
|
|
}
|
|
|
|
if (err)
|
|
{
|
|
lastTime = TickCount();
|
|
if (!delay)
|
|
delay = 60*30;
|
|
else
|
|
delay = MIN(60*60*5,(delay*3)/2);
|
|
}
|
|
else
|
|
lastTime = delay = 0;
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetSpecialTOC - find the toc of a special mailbox
|
|
************************************************************************/
|
|
TOCHandle GetSpecialTOC(short nameId)
|
|
{
|
|
FSSpec spec;
|
|
Str31 name;
|
|
|
|
GetRString(name,nameId);
|
|
|
|
#ifdef THREADING_ON
|
|
if (nameId == IN_TEMP || nameId == OUT_TEMP)
|
|
{
|
|
OSErr err;
|
|
FSSpec spool;
|
|
long dirID;
|
|
|
|
err=SubFolderSpec(SPOOL_FOLDER,&spool);
|
|
|
|
if (!err)
|
|
{
|
|
dirID = SpecDirId(&spool);
|
|
err = FSMakeFSSpec(spool.vRefNum,spool.parID,name,&spec);
|
|
}
|
|
ASSERT (!err);
|
|
if (err)
|
|
return nil;
|
|
}
|
|
else
|
|
#endif
|
|
|
|
FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,name,&spec);
|
|
return(TOCBySpec(&spec));
|
|
}
|
|
|
|
/**********************************************************************
|
|
* PeekRTOC - peek at a resource fork toc
|
|
**********************************************************************/
|
|
OSErr PeekRTOC(FSSpecPtr spec,TOCType *tocPart)
|
|
{
|
|
FSSpec tocSpec;
|
|
Boolean sane;
|
|
OSErr err;
|
|
Handle res;
|
|
short refN;
|
|
short oldResF = CurResFile();
|
|
Boolean emptyBox = FSpDFSize(spec)==0;
|
|
|
|
IsAlias(spec,&tocSpec);
|
|
if (err=FSpRFSane(&tocSpec,&sane))
|
|
ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\pFSpRFSane(%p): %d",spec->name,err);
|
|
else
|
|
{
|
|
if (!sane)
|
|
{
|
|
ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\pTOC %p insane",spec->name);
|
|
err = fnfErr;
|
|
}
|
|
else if (-1!=(refN=FSpOpenResFile(&tocSpec,fsRdWrPerm)))
|
|
{
|
|
SetResLoad(False);
|
|
res = Get1Resource(TOC_TYPE,1001);
|
|
SetResLoad(True);
|
|
|
|
if (!res && !emptyBox) ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\p%p primary toc missing",spec->name);
|
|
|
|
if (!res)
|
|
{
|
|
SetResLoad(False);
|
|
res = Get1Resource(TOC_TYPE,1002);
|
|
SetResLoad(True);
|
|
|
|
if (!res && !emptyBox) ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\p%p secondary toc missing",spec->name);
|
|
}
|
|
|
|
if (!res) err = fnfErr;
|
|
else
|
|
{
|
|
ReadPartialResource(res,0,tocPart,sizeof(TOCType));
|
|
err = ResError();
|
|
if (err) ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\pReadPartialResource(%p): %d",spec->name,err);
|
|
|
|
}
|
|
CloseResFile(refN);
|
|
}
|
|
else
|
|
{
|
|
ComposeLogS(LOG_TOC|LOG_ALRT,nil,"\p%p can't open resource fork",spec->name);
|
|
err = fnfErr;
|
|
}
|
|
}
|
|
UseResFile (oldResF);
|
|
return(err);
|
|
}
|
|
|
|
|
|
#ifdef BATCH_DELIVERY_ON //NEVER
|
|
/**********************************************************************
|
|
* PeekDTOC - peek at a data fork toc
|
|
**********************************************************************/
|
|
OSErr PeekDTOC(FSSpecPtr spec,TOCType *tocPart)
|
|
{
|
|
FSSpec tocSpec;
|
|
OSErr err;
|
|
short refN;
|
|
long bytes;
|
|
|
|
Box2TOCSpec(spec,&tocSpec);
|
|
if (!(err=AFSpOpenDF(&tocSpec,&tocSpec,fsRdPerm,&refN)))
|
|
{
|
|
bytes = sizeof(TOCType);
|
|
err = FSRead(refN,&bytes,tocPart);
|
|
if (!err && bytes!=sizeof(TOCType)) err = eofErr;
|
|
// close it
|
|
FSClose(refN);
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
#endif
|
|
|
|
/**********************************************************************
|
|
* PeekTOC - peek into a .toc file
|
|
**********************************************************************/
|
|
OSErr PeekTOC(FSSpecPtr spec,TOCType *tocPart)
|
|
{
|
|
uLong box, file, res;
|
|
OSErr err;
|
|
TOCHandle tocH = FindTOC(spec);
|
|
|
|
if (tocH) // already open; I hope the caller is being careful
|
|
{
|
|
*tocPart = **tocH;
|
|
return(noErr);
|
|
}
|
|
|
|
err = TOCDates(spec,&box,&res,&file);
|
|
|
|
if (err) return(err);
|
|
|
|
if (res && res>=file) return(PeekRTOC(spec,tocPart));
|
|
else if (file) return(PeekDTOC(spec,tocPart));
|
|
else return(fnfErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* InsaneTOC - see if a TOC is nuts
|
|
************************************************************************/
|
|
OSErr InsaneTOC(TOCHandle tocH)
|
|
{
|
|
long boxSize;
|
|
MSumPtr start,stop;
|
|
Str31 name;
|
|
short tocSize = sizeof(TOCType);
|
|
short sumSize = sizeof(MSumType);
|
|
long handleSize = GetHandleSize_(tocH);
|
|
FSSpec spec = GetMailboxSpec(tocH,-1);
|
|
|
|
PCopy(name,spec.name);
|
|
|
|
/*
|
|
* is the toc the right size?
|
|
*/
|
|
if ((*tocH)->count<0) return(True);
|
|
if (sizeof(TOCType)+((*tocH)->count?(*tocH)->count-1:0)*sizeof(MSumType)!=
|
|
GetHandleSize_(tocH))
|
|
{
|
|
ComposeLogS(LOG_ALRT|LOG_TOC,nil,"\p%p toc/count size mismatch; #%d != %d",name,
|
|
(*tocH)->count,GetHandleSize_(tocH));
|
|
return(euCorruptTOC);
|
|
}
|
|
|
|
/*
|
|
* figure out how big the mailbox is
|
|
*/
|
|
boxSize = FSpDFSize(&spec);
|
|
|
|
/*
|
|
* right size?
|
|
*/
|
|
if ((*tocH)->boxSize && (*tocH)->boxSize-1!=boxSize)
|
|
{
|
|
ComposeLogS(LOG_ALRT|LOG_TOC,nil,"\p%p file size mismatch; #%d != %d",name,
|
|
(*tocH)->boxSize,boxSize);
|
|
return(euMismatchTOC);
|
|
}
|
|
|
|
/*
|
|
* right date?
|
|
*/
|
|
// don't do the date check anymore, since it breaks under HFS+
|
|
//if ((*tocH)->writeDate && (*tocH)->writeDate!=AFSpGetMod(&spec)) return(euMismatchTOC);
|
|
|
|
/*
|
|
* check for out of range pointers
|
|
*/
|
|
for (start=(*tocH)->sums,stop=start+(*tocH)->count;start<stop;start++)
|
|
{
|
|
if ((start->offset<0&&!(*tocH)->imapTOC) ||start->length<0 ||start->bodyOffset<0 ||
|
|
start->bodyOffset>start->length ||
|
|
((start->offset+start->length > boxSize)&&!(*tocH)->imapTOC))
|
|
{
|
|
ComposeLogS(LOG_ALRT|LOG_TOC,nil,"\p%p bad sum; o%d b%d l%d s%d",name,
|
|
start->offset,start->bodyOffset,start->length,boxSize);
|
|
return(euCorruptTOC);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* wrong version number?
|
|
*/
|
|
if ((*tocH)->version > CURRENT_TOC_VERS)
|
|
{
|
|
ComposeLogS(LOG_ALRT|LOG_TOC,nil,"\p%p version mismatch; #%d != %d",name,
|
|
(*tocH)->version,CURRENT_TOC_VERS);
|
|
return(euBadVersion);
|
|
}
|
|
|
|
/*
|
|
* everything looks ok
|
|
*/
|
|
return(noErr);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetMailboxType
|
|
************************************************************************/
|
|
short GetMailboxType(FSSpecPtr spec)
|
|
{
|
|
short which = 0;
|
|
|
|
if (IsRoot(spec))
|
|
{
|
|
if (EqualStrRes(spec->name,IN))
|
|
which = IN;
|
|
else if (EqualStrRes(spec->name,OUT))
|
|
which = OUT;
|
|
else if (EqualStrRes(spec->name,TRASH))
|
|
which = TRASH;
|
|
else if (EqualStrRes(spec->name,JUNK))
|
|
which = JUNK;
|
|
}
|
|
#ifdef THREADING_ON
|
|
else
|
|
if (IsSpool(spec))
|
|
{
|
|
if (EqualStrRes(spec->name,IN_TEMP))
|
|
which = IN_TEMP;
|
|
else
|
|
if (EqualStrRes(spec->name,OUT_TEMP))
|
|
which = OUT_TEMP;
|
|
}
|
|
#ifdef BATCH_DELIVERY_ON
|
|
else
|
|
if (IsDelivery(spec))
|
|
which = DELIVERY_BATCH;
|
|
#endif
|
|
#endif
|
|
return which;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* FixErrantTOC - we have determined that something is wrong with a TOC
|
|
* fix or cancel
|
|
**********************************************************************/
|
|
TOCHandle FixErrantTOC(FSSpecPtr spec,TOCHandle tocH,short why)
|
|
{
|
|
short result = -1;
|
|
|
|
#ifdef THREADING_ON
|
|
// if we're any of the temp tocs, automatically rebuild them
|
|
short which = GetMailboxType(spec);
|
|
if (which == IN_TEMP || which == OUT_TEMP || which == DELIVERY_BATCH )
|
|
return(RebuildTOC(spec,tocH,False,True));
|
|
#endif
|
|
|
|
switch (result = WantRebuildTOC(spec->name,why,((*tocH)->imapTOC!=0)))
|
|
{
|
|
case 0:
|
|
if (tocH)
|
|
{
|
|
TOCSetDirty(tocH,true);
|
|
(*tocH)->reallyDirty = True; /* see that it gets updated */
|
|
}
|
|
return(tocH);
|
|
case 1: return(RebuildTOC(spec,tocH,False, False));
|
|
case 2: ZapHandle(tocH); return(nil);
|
|
}
|
|
ASSERT (result != -1);
|
|
return nil;
|
|
}
|
|
|
|
/************************************************************************
|
|
* WantRebuildTOC - see if the user wants us to remake the toc
|
|
************************************************************************/
|
|
Boolean WantRebuildTOC(UPtr boxName,OSErr why, Boolean isIMAP)
|
|
{
|
|
if (!PrefIsSet(PREF_TOC_REBUILD_ALERTS)) return true;
|
|
if (why==euMismatchTOC)
|
|
{
|
|
short whatToDo;
|
|
|
|
if (isIMAP) whatToDo = AlertStr(NEW_IMAP_TOC_ALRT,Caution,boxName);
|
|
else
|
|
{
|
|
// "Encourage" users to rebuild
|
|
if (TOC_USE_OLD==(whatToDo = AlertStr(NEW_TOC_ALRT,Caution,boxName)) &&
|
|
TOC_USE_OLD==(whatToDo = ComposeStdAlert(Caution,REBUILD_TOC_ALRT_2,boxName)))
|
|
whatToDo = ComposeStdAlert(Stop,REBUILD_TOC_ALRT_3,boxName);
|
|
}
|
|
|
|
switch (whatToDo)
|
|
{
|
|
case TOC_CREATE_NEW: return(1);
|
|
case TOC_USE_OLD: return(0);
|
|
case CANCEL_ITEM: case TOC_CANCEL: return(2);
|
|
}
|
|
}
|
|
else
|
|
switch (AlertStr(REB_TOC_ALRT,Caution,boxName))
|
|
{
|
|
case 1: return(1);
|
|
default: return(2);
|
|
}
|
|
ASSERT ( false );
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetTOCK - grab the K counts for a mailbox
|
|
************************************************************************/
|
|
short GetTOCK(TOCHandle tocH,uLong *usedK, uLong *totalK)
|
|
{
|
|
MSumPtr sum;
|
|
long used=0;
|
|
short err;
|
|
CInfoPBRec info;
|
|
FSSpec spec;
|
|
|
|
for (sum=(*tocH)->sums;sum<(*tocH)->sums+(*tocH)->count;sum++)
|
|
{
|
|
if (sum->offset >= 0)
|
|
used += sum->length;
|
|
}
|
|
*usedK = used/1024;
|
|
LDRef(tocH);
|
|
spec = GetMailboxSpec(tocH,-1);
|
|
*totalK = (err=AFSpGetHFileInfo(&spec,&info)) ?
|
|
0:info.hFileInfo.ioFlLgLen/1024;
|
|
UL(tocH);
|
|
ASSERT(*totalK<4096 K);
|
|
return(err);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CheckStringLen - make sure string field is not too long
|
|
************************************************************************/
|
|
void CheckStringLen(UPtr s, char maxLen, short fillLen)
|
|
{
|
|
if (*s > fillLen)
|
|
{
|
|
// total junk; destroy
|
|
WriteZero(s,fillLen);
|
|
}
|
|
else if (*s>maxLen)
|
|
{
|
|
// oops, too long
|
|
WriteZero(s+maxLen+1,fillLen-maxLen-1); // zero out remainder
|
|
*s = maxLen;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsTOCValid - is the toc on the list of currently-opened toc's
|
|
************************************************************************/
|
|
TOCHandle IsTOCValid(TOCHandle testTOC)
|
|
{
|
|
TOCHandle tocH;
|
|
for (tocH=TOCList;tocH;tocH=(*tocH)->next)
|
|
if (tocH==testTOC) return(tocH);
|
|
return(nil);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CleanseTOC - free a newly-read toc of vestiges of its past life
|
|
************************************************************************/
|
|
void CleanseTOC(TOCHandle tocH)
|
|
{
|
|
short count, i;
|
|
MSumPtr sum;
|
|
Byte vers = (*tocH)->version;
|
|
short minor = (*tocH)->minorVersion;
|
|
long size = GetHandleSize((Handle)tocH);
|
|
Boolean needSerialNum = vers < 1 || (vers==1 && minor<2);
|
|
Boolean zeroMood = vers < 1 || (vers==1 && minor<TOC_MINOR_HAS_MOOD);
|
|
Boolean fixOutlookisms = vers==1 && minor<TOC_MINOR_FIXED_OUTLOOKISMS;
|
|
Boolean fixUTF8 = vers==1 && minor<TOC_MINOR_NO_UNNECESSARY_UTF8;
|
|
uLong now = GMTDateTime();
|
|
Str63 subj;
|
|
|
|
if (needSerialNum)
|
|
(*tocH)->nextSerialNum = 1;
|
|
|
|
/*
|
|
* unset the selected flags; they might have been saved from last time
|
|
* unset the messH; it may have been filled the last time
|
|
*/
|
|
count = TOCCountShouldBe(tocH);
|
|
count = MIN((*tocH)->count,count);
|
|
for (i=0;i<count;i++)
|
|
{
|
|
sum = (*tocH)->sums+i;
|
|
sum->mesgErrH = 0;
|
|
sum->messH = 0;
|
|
|
|
// let's see about restoring the selection... */ sum->selected = False;
|
|
sum->cache = 0;
|
|
if (vers<1)
|
|
{
|
|
DBNoteUIDHash(sum->uidHash,kNeverHashed);
|
|
sum->uidHash = sum->msgIdHash = kNeverHashed;
|
|
}
|
|
if (minor<1)
|
|
sum->msgIdHash = kNeverHashed;
|
|
|
|
if (zeroMood) sum->score = 0;
|
|
|
|
// make sure older versions don't have strings that are too long
|
|
CheckStringLen(sum->from, sizeof(sum->from)-1,64);
|
|
CheckStringLen(sum->subj, sizeof(sum->subj)-1,64);
|
|
if ((*tocH)->minorVersion < TOC_MINOR_NO_DATE_STRING)
|
|
{
|
|
short j;
|
|
sum->spamScore = -1;
|
|
sum->spamBecause = 0;
|
|
sum->spare21 = 0;
|
|
sum->arrivalSeconds = 0;
|
|
for (j=0;j<sizeof(sum->spare)/sizeof(sum->spare[0]);j++) sum->spare[j] = 0;
|
|
}
|
|
|
|
if (fixOutlookisms)
|
|
{
|
|
PSCopy(subj,sum->subj);
|
|
BeautifySubj(subj,sizeof(sum->subj));
|
|
PSCopy(sum->subj,subj);
|
|
}
|
|
|
|
if (fixUTF8) RemoveUTF8FromSum(sum);
|
|
|
|
if (!sum->arrivalSeconds) sum->arrivalSeconds = sum->seconds;
|
|
|
|
if (needSerialNum)
|
|
sum->serialNum = (*tocH)->nextSerialNum++;
|
|
}
|
|
if ((*tocH)->minorVersion<TOC_MINOR_HAS_LONG_K) (*tocH)->oldKValues = 0;
|
|
if ((*tocH)->minorVersion<TOC_MINOR_HAS_PROFILE) (*tocH)->profile[0] = (*tocH)->profile[1] = 0;
|
|
if ((*tocH)->minorVersion < TOC_MINOR_NO_DATE_STRING) (*tocH)->spareLong = 0;
|
|
(*tocH)->version = CURRENT_TOC_VERS;
|
|
(*tocH)->minorVersion = CURRENT_TOC_MINOR;
|
|
(*tocH)->virtualTOC = false; // not a virtual toc, nossir!
|
|
(*tocH)->beingWritten = false; // not being written at the moment
|
|
(*tocH)->analScanned = false; // need to do a scan for flames
|
|
(*tocH)->hFileView = nil;
|
|
|
|
// Junk processing
|
|
if ((*tocH)->which==JUNK) JunkTOCCleanse(tocH);
|
|
}
|
|
|
|
#pragma segment Main
|
|
/************************************************************************
|
|
* RedoTOCs - make sure right info is displayed in all TOC's
|
|
************************************************************************/
|
|
void RedoTOCs(void)
|
|
{
|
|
TOCHandle tocH = TOCList;
|
|
|
|
overAgain:
|
|
for (tocH=TOCList; tocH && !NeedYield(); tocH = (*tocH)->next)
|
|
// only do this for visible windows
|
|
if (IsWindowVisible(GetMyWindowWindowPtr((*tocH)->win)) && RedoTOC(tocH))
|
|
{
|
|
// we just did some work.
|
|
|
|
if (NeedYield()) break; // need to go process events
|
|
|
|
goto overAgain; // take it from the top; trying to avoid
|
|
// race condition with threading.
|
|
}
|
|
}
|
|
|
|
|