223 lines
5.8 KiB
C
223 lines
5.8 KiB
C
/************************************************************/
|
||
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
||
/************************************************************/
|
||
|
||
#define NOCLIPBOARD
|
||
#define NOGDICAPMASKS
|
||
#define NOCTLMGR
|
||
#define NOVIRTUALKEYCODES
|
||
#define NOWINMESSAGES
|
||
#define NOWINSTYLES
|
||
#define NOSYSMETRICS
|
||
#define NOMENUS
|
||
#include <windows.h>
|
||
#include "mw.h"
|
||
#include "doslib.h"
|
||
#include "cmddefs.h"
|
||
#include "docdefs.h"
|
||
#include "filedefs.h"
|
||
#include "str.h"
|
||
#include "debug.h"
|
||
|
||
extern int vfnWriting;
|
||
|
||
|
||
#define IibpHash(fn,pn) ((int) ((fn + 1) * (pn + 1)) & 077777) % iibpHashMax
|
||
|
||
#define FcMin(a,b) CpMin(a,b)
|
||
|
||
extern CHAR *rgibpHash;
|
||
extern int vfSysFull;
|
||
extern struct BPS *mpibpbps;
|
||
extern struct FCB (**hpfnfcb)[];
|
||
extern typeTS tsMruBps;
|
||
extern CHAR (*rgbp)[cbSector];
|
||
#ifdef CKSM
|
||
#ifdef DEBUG
|
||
extern unsigned (**hpibpcksm) [];
|
||
#endif
|
||
#endif
|
||
|
||
/* WriteDirtyPages kicks out of memory as much of the previous files as it can
|
||
in order to fill the page buffers with a new file. This is called on
|
||
every transfer load of a file. */
|
||
WriteDirtyPages()
|
||
{/*
|
||
Description: Cleans the buffer pool of all dirty pages by writing them
|
||
out to disk. If a disk full condition is reached, only
|
||
pages which actually made it to disk are marked as non
|
||
dirty.
|
||
Returns: nothing.
|
||
*/
|
||
int ibp;
|
||
struct BPS *pbps = &mpibpbps [0];
|
||
|
||
for (ibp = 0; ibp < ibpMax; ++ibp, ++pbps)
|
||
{
|
||
#ifdef CKSM
|
||
#ifdef DEBUG
|
||
if (pbps->fn != fnNil && !pbps->fDirty)
|
||
Assert( (**hpibpcksm) [ibp] == CksmFromIbp( ibp ) );
|
||
#endif
|
||
#endif
|
||
if (pbps->fn != fnNil && pbps->fDirty)
|
||
{
|
||
FFlushFn(pbps->fn);
|
||
/* keep on flushing if failure ? */
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
ReadFilePages(fn)
|
||
int fn;
|
||
{
|
||
/*
|
||
Description: ReadFilePages tries to read in as much of a file as
|
||
it can. The idea is to fill the page buffers in anticipation of
|
||
much access. This is called on every Transfer Load of a file.
|
||
If fn == fnNil or there are no characters in the file, ReadFilePages
|
||
simply returns.
|
||
Returns: nothing
|
||
*/
|
||
int ibp;
|
||
int cfcRead;
|
||
int cpnRead;
|
||
int dfcMac;
|
||
typeFC fcMac;
|
||
int ibpReadMax;
|
||
int cfcLastPage;
|
||
int iibp;
|
||
struct FCB *pfcb;
|
||
typeTS ts;
|
||
|
||
if (fn == fnNil)
|
||
return;
|
||
|
||
/* Write ALL dirty pages to disk */
|
||
WriteDirtyPages(); /* Just in case */
|
||
|
||
pfcb = &(**hpfnfcb)[fn];
|
||
|
||
/* we read as much of the file as will fit in the page buffers */
|
||
/* Note that we assume that fcMax is coercable to an integer. This
|
||
is valid as long as ibpMax*cbSector < 32k */
|
||
dfcMac = (int) FcMin(pfcb->fcMac, (typeFC) (ibpMax * cbSector));
|
||
if (dfcMac == 0)
|
||
return;
|
||
if (vfSysFull) /* call to FFlushFn in WriteDirtyPages failed.
|
||
the buffer algorithm assures us that the first
|
||
cbpMustKeep ibp's do not contain scratch file
|
||
information. Thus, there is no danger in overwriting
|
||
these ibps. */
|
||
dfcMac = imin( dfcMac, (cbpMustKeep * cbSector) );
|
||
|
||
Assert( ((int)dfcMac) >= 0 );
|
||
|
||
/* Read pages from the file */
|
||
|
||
cfcRead = CchReadAtPage( fn, (typePN) 0, rgbp [0], (int) dfcMac, FALSE );
|
||
|
||
/* cfcRead contains a count of bytes read from the file */
|
||
ibpReadMax = ((cfcRead-1) / cbSector) + 1;
|
||
cfcLastPage = cfcRead - (ibpReadMax-1)*cbSector;
|
||
ts = ibpMax;
|
||
|
||
/* order time stamps so the beginning slots have the greatest ts.
|
||
Lru allocation will start at the end of the buffer table and work
|
||
backward. Thus, the first page of the current file is considered
|
||
the most recently used item.
|
||
*/
|
||
|
||
/* describe the newly filled pages */
|
||
for(ibp = 0; ibp < ibpReadMax; ++ibp)
|
||
{
|
||
struct BPS *pbps = &mpibpbps[ibp];
|
||
pbps->fn = fn;
|
||
pbps->pn = ibp;
|
||
pbps->ts = --ts;
|
||
pbps->fDirty = false;
|
||
pbps->cch = cbSector;
|
||
pbps->ibpHashNext = ibpNil;
|
||
}
|
||
|
||
#ifdef CKSM
|
||
#ifdef DEBUG
|
||
{
|
||
int ibpT;
|
||
|
||
for ( ibpT = 0; ibpT < ibpReadMax; ibpT++ )
|
||
(**hpibpcksm) [ibpT] = CksmFromIbp( ibpT );
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
/* fix some boundary conditions */
|
||
mpibpbps[ibpReadMax-1].cch = cfcLastPage; /* ?????? */
|
||
#ifdef CKSM
|
||
#ifdef DEBUG
|
||
(**hpibpcksm) [ibpReadMax - 1] = CksmFromIbp( ibpReadMax - 1 );
|
||
#endif
|
||
#endif
|
||
|
||
/* update descriptions of untouched page buffers */
|
||
for (ibp=ibpReadMax; ibp < ibpMax; ibp++)
|
||
{
|
||
struct BPS *pbps = &mpibpbps[ibp];
|
||
pbps->ts = --ts;
|
||
pbps->fDirty = false;
|
||
pbps->ibpHashNext = ibpNil;
|
||
|
||
#ifdef CKSM
|
||
#ifdef DEBUG
|
||
if (pbps->fn != fnNil)
|
||
(**hpibpcksm) [ibp] = CksmFromIbp( ibp );
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
tsMruBps = ibpMax - 1;
|
||
|
||
/* recalculate the hash table */
|
||
RehashRgibpHash();
|
||
|
||
} /* end of R e a d F i l e P a g e s */
|
||
|
||
|
||
RehashRgibpHash()
|
||
{
|
||
int iibp;
|
||
register struct BPS *pbps;
|
||
struct BPS *pbpsMax = &mpibpbps[ibpMax];
|
||
int iibpHash;
|
||
int ibpT;
|
||
int ibpPrev;
|
||
int ibp;
|
||
|
||
for (iibp = 0; iibp < iibpHashMax; iibp++)
|
||
rgibpHash[iibp] = ibpNil;
|
||
|
||
for (ibp = 0, pbps = &mpibpbps[0]; pbps < pbpsMax; pbps++, ibp++)
|
||
{
|
||
if (pbps->fn == fnNil)
|
||
continue;
|
||
iibpHash = IibpHash(pbps->fn, pbps->pn);
|
||
ibpT = rgibpHash[iibpHash];
|
||
ibpPrev = ibpNil;
|
||
while (ibpT != ibpNil)
|
||
{
|
||
ibpPrev = ibpT;
|
||
ibpT = mpibpbps[ibpT].ibpHashNext;
|
||
}
|
||
if (ibpPrev == ibpNil)
|
||
rgibpHash[iibpHash] = ibp;
|
||
else
|
||
mpibpbps[ibpPrev].ibpHashNext = ibp;
|
||
}
|
||
#ifdef DEBUG
|
||
CheckIbp();
|
||
#endif
|
||
} /* end of RehashRgibpHash */
|
||
|
||
|
||
|