410 lines
13 KiB
C
410 lines
13 KiB
C
/************************************************************/
|
||
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
||
/************************************************************/
|
||
|
||
/* doc.c -- MW document processing routines (non-resident) */
|
||
|
||
#define NOGDICAPMASKS
|
||
#define NOVIRTUALKEYCODES
|
||
#define NOWINMESSAGES
|
||
#define NOWINSTYLES
|
||
#define NOSYSMETRICS
|
||
#define NOMENUS
|
||
#define NOICON
|
||
#define NOKEYSTATE
|
||
#define NOSYSCOMMANDS
|
||
#define NORASTEROPS
|
||
#define NOSHOWWINDOW
|
||
#define NOATOM
|
||
#define NOBITMAP
|
||
#define NOBRUSH
|
||
#define NOCLIPBOARD
|
||
#define NOCOLOR
|
||
#define NOCREATESTRUCT
|
||
#define NOCTLMGR
|
||
#define NODRAWTEXT
|
||
#define NOFONT
|
||
#define NOGDI
|
||
#define NOHDC
|
||
#define NOMB
|
||
#define NOMEMMGR
|
||
#define NOMENUS
|
||
#define NOMETAFILE
|
||
#define NOMINMAX
|
||
#define NOMSG
|
||
#define NOOPENFILE
|
||
#define NOPEN
|
||
#define NOPOINT
|
||
#define NOREGION
|
||
#define NOSCROLL
|
||
#define NOSOUND
|
||
#define NOTEXTMETRIC
|
||
#define NOWH
|
||
#define NOWINOFFSETS
|
||
#define NOWNDCLASS
|
||
#define NOCOMM
|
||
#include <windows.h>
|
||
|
||
#include "mw.h"
|
||
#include "editdefs.h"
|
||
#include "docdefs.h"
|
||
#include "fontdefs.h"
|
||
#include "cmddefs.h"
|
||
#include "filedefs.h"
|
||
#include "str.h"
|
||
#include "fmtdefs.h"
|
||
#include "propdefs.h"
|
||
#include "fkpdefs.h"
|
||
#define NOKCCODES
|
||
#include "ch.h"
|
||
#include "stcdefs.h"
|
||
#include "printdef.h" /* printdefs.h */
|
||
#include "macro.h"
|
||
|
||
|
||
extern struct DOD (**hpdocdod)[];
|
||
extern int docMac;
|
||
extern int docScrap;
|
||
extern int docUndo;
|
||
#ifdef STYLES
|
||
#ifdef SAND
|
||
extern CHAR szSshtEmpty[];
|
||
#else
|
||
extern CHAR szSshtEmpty[];
|
||
#endif
|
||
#endif
|
||
|
||
/* E X T E R N A L S */
|
||
extern int docRulerSprm;
|
||
extern int vfSeeSel;
|
||
extern struct SEP vsepNormal;
|
||
extern struct CHP vchpNormal;
|
||
extern int docCur;
|
||
extern struct FLI vfli;
|
||
extern int vdocParaCache;
|
||
extern struct FCB (**hpfnfcb)[];
|
||
extern struct UAB vuab;
|
||
extern typeCP cpMacCur;
|
||
extern struct SEL selCur;
|
||
extern int vdocExpFetch;
|
||
extern CHAR (**hszSearch)[];
|
||
extern typeCP vcpFetch;
|
||
extern int vccpFetch;
|
||
extern CHAR *vpchFetch;
|
||
extern struct CHP vchpFetch;
|
||
#ifdef STYLES
|
||
extern struct PAP vpapCache;
|
||
extern CHAR mpusgstcBase[];
|
||
#endif
|
||
extern int vrefFile;
|
||
|
||
|
||
struct PGTB **HpgtbCreate();
|
||
|
||
|
||
#ifdef ENABLE /* This is never called */
|
||
int DocFromSz(sz, dty)
|
||
CHAR sz[];
|
||
/* Return doc if one with that name exists already */
|
||
{
|
||
int doc;
|
||
struct DOD *pdod = &(**hpdocdod)[0];
|
||
struct DOD *pdodMac = pdod + docMac;
|
||
|
||
if (sz[0] == 0)
|
||
return docNil;
|
||
|
||
for (doc = 0; pdod < pdodMac; ++pdod, ++doc)
|
||
if (pdod->hpctb != 0 && pdod->dty == dty &&
|
||
FSzSame(sz, **pdod->hszFile)
|
||
#ifdef SAND
|
||
&& (pdod->vref == vrefFile)
|
||
#endif
|
||
)
|
||
{
|
||
++pdod->cref;
|
||
return doc;
|
||
}
|
||
return docNil;
|
||
}
|
||
#endif
|
||
|
||
|
||
KillDoc(doc)
|
||
int doc;
|
||
{ /* Wipe this doc, destroying any changes since last save */
|
||
extern int vdocBitmapCache;
|
||
|
||
if (doc == docScrap)
|
||
return; /* Can't be killed no-how */
|
||
|
||
if (--(**hpdocdod)[doc].cref == 0)
|
||
{
|
||
struct FNTB **hfntb;
|
||
#ifdef CASHMERE
|
||
struct SETB **hsetb;
|
||
#else
|
||
struct SEP **hsep;
|
||
#endif
|
||
struct FFNTB **hffntb;
|
||
struct TBD (**hgtbd)[];
|
||
CHAR (**hsz)[];
|
||
int docSsht;
|
||
|
||
SmashDocFce( doc );
|
||
|
||
/* Kill style sheet doc if there is one. */
|
||
if ((docSsht = (**hpdocdod)[doc].docSsht) != docNil)
|
||
KillDoc(docSsht);
|
||
|
||
/* Free piece table, filename, and footnote (or style) table */
|
||
FreeH((**hpdocdod)[doc].hpctb);
|
||
(**hpdocdod)[doc].hpctb = 0; /* To show doc free */
|
||
if ((hsz = (**hpdocdod)[doc].hszFile) != 0)
|
||
FreeH(hsz);
|
||
if ((hfntb = (**hpdocdod)[doc].hfntb) != 0)
|
||
FreeH(hfntb);
|
||
#ifdef CASHMERE
|
||
if ((hsetb = (**hpdocdod)[doc].hsetb) != 0)
|
||
FreeH(hsetb);
|
||
#else
|
||
if ((hsep = (**hpdocdod)[doc].hsep) != 0)
|
||
FreeH(hsep);
|
||
#endif
|
||
|
||
if ((hgtbd = (**hpdocdod)[doc].hgtbd) != 0)
|
||
FreeH( hgtbd );
|
||
if ((hffntb = (**hpdocdod)[doc].hffntb) != 0)
|
||
FreeFfntb(hffntb);
|
||
|
||
if (doc == vdocBitmapCache)
|
||
FreeBitmapCache();
|
||
|
||
InvalidateCaches(doc);
|
||
if (docCur == doc)
|
||
docCur = docNil;
|
||
if (docRulerSprm == doc)
|
||
docRulerSprm = docNil;
|
||
if (vuab.doc == doc || vuab.doc2 == doc)
|
||
NoUndo();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#ifdef STYLES
|
||
struct SYTB **HsytbCreate(doc)
|
||
int doc;
|
||
{ /* Create a map from stc to cp for a style sheet */
|
||
typeCP cp, *pcp;
|
||
struct SYTB **hsytb;
|
||
typeCP cpMac;
|
||
int stc, usg, stcBase, stcMin;
|
||
int ch, cch, cchT;
|
||
int *pbchFprop, *mpstcbchFprop;
|
||
CHAR *pchFprop, *grpchFprop;
|
||
int iakd, iakdT, cakd, cakdBase;
|
||
struct AKD *rgakd, *pakd;
|
||
#ifdef DEBUG
|
||
int cakdTotal;
|
||
#endif
|
||
|
||
CHAR rgch[3];
|
||
CHAR mpchcakc[chMaxAscii];
|
||
typeCP mpstccp[stcMax];
|
||
|
||
/* First, clear out the stc-->cp map by filling with cpNil. */
|
||
for (stc = 0, pcp = &mpstccp[0]; stc < stcMax; stc++, pcp++)
|
||
*pcp = cpNil;
|
||
bltbc(mpchcakc, 0, chMaxAscii);
|
||
|
||
/* Now go through all entries in the style sheet. In this pass,
|
||
check for duplicates (and return 0 if in gallery mode), fill
|
||
mpstccp with appropriate entries for all defined stc's, and
|
||
count the length of all the styles so we can allocate the heap
|
||
block later. */
|
||
cpMac = (**hpdocdod)[doc].cpMac;
|
||
for (cp = 0, cch = 0, cakd = 1, cakdBase = 1; cp < cpMac; cp += ccpSshtEntry)
|
||
{
|
||
FetchRgch(&cchT, rgch, doc, cp, cpMac, 3);
|
||
stc = rgch[0]; /* stc is first cp of entry */
|
||
#ifdef DEBUG
|
||
Assert(stc < stcMax);
|
||
#endif
|
||
if (mpstccp[stc] != cpNil && doc == docCur)
|
||
{ /* Repeated entry */
|
||
Error(IDPMTStcRepeat);
|
||
goto ErrRet;
|
||
}
|
||
mpstccp[stc] = cp;
|
||
if (stc < stcSectMin)
|
||
{
|
||
FetchCp(doc, cp, 0, fcmProps);
|
||
cch += CchDiffer(&vchpFetch, &vchpNormal, cchCHP) + 1;
|
||
}
|
||
if (stc >= stcParaMin)
|
||
{
|
||
CachePara(doc, cp);
|
||
if (stc >= stcSectMin)
|
||
cch += CchDiffer(&vpapCache, &vsepNormal, cchSEP) + 1;
|
||
else
|
||
cch += CchDiffer(&vpapCache, &vpapStd, cchPAP) + 1;
|
||
}
|
||
ch = rgch[1];
|
||
if (ch != ' ')
|
||
{ /* Define an alt-key code for this style */
|
||
++cakd;
|
||
if (rgch[2] == ' ')
|
||
{
|
||
if (mpchcakc[ch]-- != 0)
|
||
{
|
||
Error(IDPMTAkcRepeat);
|
||
goto ErrRet;
|
||
}
|
||
++cakdBase;
|
||
}
|
||
else
|
||
{
|
||
++mpchcakc[ch]; /* increment before switch to avoid
|
||
the increment being taken
|
||
as for an int. */
|
||
switch (mpchcakc[ch])
|
||
{
|
||
case 0:
|
||
Error(IDPMTAkcRepeat);
|
||
goto ErrRet;
|
||
case 1:
|
||
++cakdBase;
|
||
++cakd;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Now allocate the heap block, using the total we got above. */
|
||
/* HEAP MOVEMENT */
|
||
hsytb = (struct SYTB **) HAllocate(cwSYTBBase + cwAKD * cakd +
|
||
CwFromCch(cch));
|
||
|
||
if (FNoHeap(hsytb))
|
||
return hOverflow;
|
||
|
||
/* Now go through the stc-->cp map, filling in the stc-->fprop map
|
||
in the sytb. For each stc that isn't defined, determine which
|
||
stc to alias it to (either the first of the usage or, if that
|
||
one isn't defined, the first one of the first usage). Copy the
|
||
actual CHP's, PAP's, and SEP's into grpchFprop. */
|
||
mpstcbchFprop = (**hsytb).mpstcbchFprop;
|
||
rgakd = (struct AKD *) (grpchFprop = (**hsytb).grpchFprop);
|
||
pchFprop = (CHAR *) &rgakd[cakd];
|
||
pcp = &mpstccp[0];
|
||
pbchFprop = &mpstcbchFprop[0];
|
||
*pbchFprop = bNil;
|
||
#ifdef DEBUG
|
||
cakdTotal = cakd;
|
||
#endif
|
||
for (stc = 0, usg = 0, stcBase = 0, stcMin = 0, iakd = 0;
|
||
stc < stcMax;
|
||
stc++, pcp++, pbchFprop++)
|
||
{
|
||
if (stc >= mpusgstcBase[usg + 1])
|
||
{ /* Crossed a usage or class boundary */
|
||
*pbchFprop = bNil;
|
||
stcBase = mpusgstcBase[++usg];
|
||
if (stcBase == stcParaMin || stcBase == stcSectMin)
|
||
{ /* Update the base; make std if none defined */
|
||
stcMin = stcBase;
|
||
}
|
||
}
|
||
if ((cp = *pcp) == cpNil)
|
||
{ /* No style defined; take first for usg or, failing
|
||
that, first style of this class. */
|
||
if ((*pbchFprop = mpstcbchFprop[stcBase]) == bNil)
|
||
*pbchFprop = mpstcbchFprop[stcMin];
|
||
}
|
||
else
|
||
{ /* New style; copy the looks and bump the pointers */
|
||
/* Char stc's have just FCHP; para has FPAP followed by
|
||
FCHP; sect has FSEP. */
|
||
*pbchFprop = pchFprop - grpchFprop;
|
||
if (stc >= stcParaMin)
|
||
{ /* Para or sect */
|
||
CachePara(doc, cp);
|
||
if (stc >= stcSectMin)
|
||
cchT = CchDiffer(&vpapCache, &vsepNormal, cchSEP);
|
||
else
|
||
cchT = CchDiffer(&vpapCache, &vpapStd, cchPAP);
|
||
if ((*pchFprop++ = cchT) != 0)
|
||
bltbyte(&vpapCache, pchFprop, cchT);
|
||
pchFprop += cchT;
|
||
}
|
||
if (stc < stcSectMin)
|
||
{ /* Char or para */
|
||
FetchCp(doc, cp, 0, fcmProps);
|
||
cchT = CchDiffer(&vchpFetch, &vchpNormal, cchCHP);
|
||
if ((*pchFprop++ = cchT) != 0)
|
||
bltbyte(&vchpFetch, pchFprop, cchT);
|
||
pchFprop += cchT;
|
||
}
|
||
/* Insert element in akd table */
|
||
FetchRgch(&cchT, rgch, doc, cp, cpMac, 3);
|
||
if ((ch = rgch[1]) == ' ')
|
||
continue;
|
||
if (rgch[2] == ' ')
|
||
{ /* Single-key akc */
|
||
pakd = &rgakd[iakd++];
|
||
pakd->ch = ch;
|
||
pakd->fMore = false;
|
||
pakd->ustciakd = stc;
|
||
}
|
||
else
|
||
{ /* Two-char akc */
|
||
for (iakdT = 0; iakdT < iakd; iakdT++)
|
||
if (rgakd[iakdT].ch == ch)
|
||
{
|
||
pakd = &rgakd[rgakd[iakdT].ustciakd +
|
||
--mpchcakc[ch]];
|
||
pakd->ch = rgch[2];
|
||
pakd->fMore = true;
|
||
pakd->ustciakd = stc;
|
||
do
|
||
if ((++pakd)->ch == rgch[2])
|
||
{
|
||
Error(IDPMTAkcRepeat);
|
||
FreeH(hsytb);
|
||
goto ErrRet;
|
||
}
|
||
while (pakd->fMore);
|
||
goto NextStc;
|
||
}
|
||
pakd = &rgakd[iakd++];
|
||
pakd->ch = ch;
|
||
pakd->fMore = true;
|
||
pakd->ustciakd = (cakd -= mpchcakc[ch]);
|
||
pakd = &rgakd[cakd + --mpchcakc[ch]];
|
||
pakd->ch = rgch[2];
|
||
pakd->fMore = false;
|
||
pakd->ustciakd = stc;
|
||
}
|
||
}
|
||
NextStc: ;
|
||
}
|
||
|
||
pakd = &rgakd[iakd++];
|
||
pakd->ch = ' ';
|
||
pakd->fMore = false;
|
||
pakd->ustciakd = stcNormal;
|
||
|
||
#ifdef DEBUG
|
||
Assert(grpchFprop + cchAKD * cakdTotal + cch == pchFprop && iakd == cakd);
|
||
#endif
|
||
return hsytb;
|
||
|
||
ErrRet:
|
||
Select(cp, cp + ccpSshtEntry);
|
||
vfSeeSel = true;
|
||
return 0;
|
||
}
|
||
#endif /* STYLES */
|
||
|
||
|