/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ /* CreateWw.c -- WRITE window & document creation */ #define NOCLIPBOARD #define NOGDICAPMASKS #define NOVIRTUALKEYCODES #define NOWINMESSAGES #define NOSYSMETRICS #define NOMENUS #define NOICON #define NOKEYSTATE #define NOSYSCOMMANDS #define NORASTEROPS //#define NOATOM #define NOBITMAP #define NOPEN #define NODRAWTEXT #define NOCOLOR #define NOCREATESTRUCT #define NOHDC #define NOMB #define NOMETAFILE #define NOMSG #define NOPOINT #define NORECT #define NOREGION #define NOSCROLL #define NOWH #define NOWINOFFSETS #define NOSOUND #define NOCOMM #define NOOPENFILE #define NORESOURCE #include #include "mw.h" #include "dispdefs.h" #define NOUAC #include "cmddefs.h" #include "wwdefs.h" #include "docdefs.h" #include "fontdefs.h" #include "editdefs.h" #include "filedefs.h" #include "propdefs.h" #include "fkpdefs.h" #define NOSTRUNDO #define NOSTRMERGE #include "str.h" #include "code.h" #include "prmdefs.h" #if defined(OLE) #include "obj.h" #endif #define PAGEONLY #include "printdef.h" /* printdefs.h */ /* #include "dlgdefs.h" */ #ifdef KOREA #include #endif /* These defines replace dlgdefs.h to combat compiler heap overflows */ #define idiYes IDOK #define idiNo 3 #define idiCancel IDCANCEL /* These defines replace heapdefs.h and heapdata.h for the same irritating reason */ #define cwSaveAlloc (128) #define cwHeapMinPerWindow (50) #define cwHeapSpaceMin (60) /* E X T E R N A L S */ extern CHAR (**vhrgbSave)[]; extern HANDLE hParentWw; extern HANDLE hMmwModInstance; extern struct WWD rgwwd[]; extern int wwMac; extern struct FCB (**hpfnfcb)[]; extern struct DOD (**hpdocdod)[]; extern int docMac; extern struct WWD *pwwdCur; extern int fnMac; extern CHAR stBuf[]; /* *** Following declarations used by ValidateHeaderFooter */ /* Min, Max cp's for header, footer */ extern typeCP cpMinHeader; extern typeCP cpMacHeader; extern typeCP cpMinFooter; extern typeCP cpMacFooter; extern typeCP cpMinDocument; extern typeCP vcpLimParaCache; extern struct PAP vpapAbs; /* Current allowable cp range for display/edit/scroll */ extern typeCP cpMinCur; extern typeCP cpMacCur; /* cpFirst and selection are saved in these during header/footer edit */ extern typeCP cpFirstDocSave; extern struct SEL selDocSave; short WCompSzC(); CHAR (**HszCreate())[]; struct FNTB **HfntbCreate(); #ifdef CASHMERE struct SETB **HsetbCreate(); #else struct SEP **HsepCreate(); #endif struct PGTB **HpgtbCreate(); CHAR *PchFromFc( int, typeFC, CHAR * ); CHAR *PchGetPn( int, typePN, int *, int ); typeFC FcMacFromUnformattedFn( int ); int CchReadAtPage( int, typePN, CHAR *, int, int ); /* W W N E W */ /* allocates and initializes a new wwd structure at wwMac. ypMin, ypMax are estimates of the height of window used to allocate dl's. wwMac++ is returned. Errors: message is made and wwNil is returned. remains to be initialized: xp, yp. Many fields must be reset if lower pane. */ WwNew(doc, ypMin, ypMax) int doc, ypMin, ypMax; { extern CHAR szDocClass[]; struct EDL (**hdndl)[]; register struct WWD *pwwd = &rgwwd[wwMac]; int dlMax = (ypMax - ypMin) / dypAveInit; int cwDndl = dlMax * cwEDL; #ifdef CASHMERE /* WwNew is only called once in MEMO */ if (wwMac >= wwMax) { Error(IDPMT2ManyWws); return wwNil; } #endif bltc(pwwd, 0, cwWWDclr); if (!FChngSizeH( vhrgbSave, cwSaveAlloc + wwMac * cwHeapMinPerWindow, false ) || FNoHeap( pwwd->hdndl = (struct EDL (**)[]) HAllocate( cwDndl )) ) { /* Could not alloc addtl save space or dl array */ return wwNil; } else bltc( *pwwd->hdndl, 0, cwDndl ); #ifdef SPLITTERS pwwd->ww = wwNil; #endif /* SPLITTERS */ /* contents of hdndl are init to 0 when allocated */ pwwd->dlMac = pwwd->dlMax = dlMax; pwwd->ypMin = ypMin; pwwd->doc = doc; pwwd->wwptr = CreateWindow( (LPSTR)szDocClass, (LPSTR)"", (WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE), 0, 0, 0, 0, (HWND)hParentWw, (HMENU)NULL, /* use class menu */ (HANDLE)hMmwModInstance, /* handle to window instance */ (LPSTR)NULL); /* no params to pass on */ if (pwwd->wwptr == NULL) return wwNil; /* inefficient pwwd->cpFirst = cp0; pwwd->ichCpFirst = 0; pwwd->dcpDepend = 0; pwwd->fCpBad = false; pwwd->xpMin = 0; pwwd->xpMac = 0; pwwd->ypMac = 0; pwwd->fFtn = false; pwwd->fSplit= false; pwwd->fLower = false; pwwd->cpMin = cp0; pwwd->drElevator = 0; pwwd->fRuler = false; pwwd->sel.CpFirst = cp0; pwwd->sel.CpFirst = cp0; */ pwwd->sel.fForward = true; pwwd->fDirty = true; pwwd->fActive = true; pwwd->cpMac = CpMacText(doc); /* this is to compensate for the "min" in InvalBand */ pwwd->ypFirstInval = ypMaxAll; return wwMac++; #ifdef KOREA /* for level 3, 90.12.12 by Sangl */ { HANDLE hKs; LPIMESTRUCT lpKs; hKs = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE,(LONG)sizeof(IMESTRUCT)); lpKs = (LPIMESTRUCT)GlobalLock(hKs); lpKs->fnc = IME_SETLEVEL; lpKs->wParam = 3; GlobalUnlock(hKs); SendIMEMessage (pwwd->wwptr, MAKELONG(hKs,0)); GlobalFree(hKs); } #endif } /* end of W w N e w */ ChangeWwDoc( szDoc ) CHAR szDoc[]; { /* Set up wwd fields for a new document to be held in wwdCurrentDoc. docCur is used as the document */ extern HANDLE hParentWw; extern int docCur; extern struct SEL selCur; extern typeCP cpMinDocument; extern int vfInsEnd; extern int vfPrPages; extern int vfDidSearch; extern typeCP cpWall; register struct WWD *pwwd = &rgwwd[wwDocument]; pwwd->fDirty = true; ValidateHeaderFooter( docCur ); pwwd->doc = docCur; pwwd->drElevator = 0; pwwd->ichCpFirst = 0; pwwd->dcpDepend = 0; pwwd->cpMin = pwwd->cpFirst = selCur.cpLim = selCur.cpFirst = cpMinDocument; selCur.fForward = TRUE; selCur.fEndOfLine = vfInsEnd = FALSE; pwwd->cpMac = CpMacText(docCur); TrashWw( wwDocument ); SetScrollPos( pwwd->hVScrBar, pwwd->sbVbar, pwwd->drElevator = 0, TRUE); SetScrollPos( pwwd->hHScrBar, pwwd->sbHbar, pwwd->xpMin = 0, TRUE); NewCurWw(0, true); TrashCache(); /* Invalidate Scrolling cache */ vfPrPages = FALSE; if (pwwd->fRuler) { ResetTabBtn(); } SetTitle(szDoc); /* Since we are changing document, ensure that we don't use parameters set by a search in a previous window by setting flag false */ vfDidSearch = FALSE; cpWall = selCur.cpLim; } /* F N C R E A T E S Z */ int FnCreateSz(szT, cpMac, dty ) CHAR *szT; typeCP cpMac; int dty; { /* Create & Open a new file of the specified type. */ /* If cpMac != cpNil, write an FIB to the file */ /* if dty==dtyNetwork, generate a unique name in the current directory and copy it to szT */ /* WARNING: dty != dtyNetwork SUPPORT HAS BEEN REMOVED */ int fn; struct FCB *pfcb; /* Be VERY careful of heap movement when using pfcb */ struct FIB fib; CHAR (**hsz)[]; CHAR sz[cchMaxFile]; bltsz(szT, sz); sz[cchMaxFile - 1] = 0; if ((fn = FnAlloc()) == fnNil) return fnNil; pfcb = &(**hpfnfcb)[fn]; pfcb->mdExt = pfcb->dty = dtyNormal; pfcb->mdFile = mdBinary; Assert( dty == dtyNetwork ); if (!FCreateFile( sz, fn )) /* Sets pfcb->hszFile, pfcb->rfn */ return fnNil; FreezeHp(); pfcb = &(**hpfnfcb)[fn]; /* Copy unique filename to parm */ bltsz( **pfcb->hszFile, szT ); #ifdef INEFFICIENT pfcb->fcMac = fc0; pfcb->pnMac = pn0; #endif if (cpMac == cpNil) { /* Unformatted file */ #ifdef INEFFICIENT pfcb->fFormatted = false; #endif MeltHp(); } else { /* Formatted file; write FIB */ bltbc(&fib, 0, cchFIB); pfcb->fFormatted = true; #ifdef INEFFICIENT pfcb->pnChar = pfcb->pnPara = pfcb->pnFntb = pfcb->pnSep = pfcb->pnSetb = pfcb->pnBftb = pn0; #endif MeltHp(); fib.wIdent = wMagic; fib.dty = dtyNormal; fib.wTool = wMagicTool; fib.fcMac = cpMac + cfcPage; WriteRgch(fn, &fib, (int)cfcPage); } return fn; } /* end of F n C r e a t e S z */ int DocCreate(fn, hszFile, dty) int fn, dty; CHAR (**hszFile)[]; { /* Create a document */ extern int vfTextOnlySave; struct FNTB **HfntbCreate(); struct TBD (**HgtbdCreate())[]; int doc; int fFormatted, fOldWord; struct DOD *pdod; struct SEP **hsep = (struct SEP **)0; /* MEMO only; for CASHMERE, use hsetb */ struct PGTB **hpgtb=(struct PGTB **)0; struct FFNTB **hffntb=(struct FFNTB **)0; struct TBD (**hgtbd)[]=(struct TBD (**)[])0; struct FNTB **hfntb = (struct FNTB **) 0; CHAR (**hszSsht)[]; fFormatted = (fn == fnNil) || (**hpfnfcb)[fn].fFormatted; fOldWord = FALSE; if ((doc = DocAlloc()) == docNil || /* HEAP MOVEMENT */ !FInitPctb(doc, fn)) /* HEAP MOVEMENT */ return docNil; pdod = &(**hpdocdod)[doc]; pdod->fReadOnly = (fn != fnNil) && ((**hpfnfcb)[fn].mdFile == mdBinRO); pdod->cref = 1; pdod->fFormatted = fFormatted; pdod->dty = dty; pdod->fBackup = false; /* Default: don't automatically make backup */ pdod->fDisplayable = TRUE; switch(dty) { /* HEAP MOVEMENT */ case dtyHlp: if (FNoHeap(hpgtb = HpgtbCreate(fn))) goto ErrFree; if (FNoHeap(hffntb = HffntbCreateForFn(fn, &fOldWord))) goto ErrFree; break; case dtyNormal: if (fn != fnNil && fFormatted) { #ifdef FOOTNOTES if (FNoHeap(hfntb = HfntbCreate(fn))) goto ErrFree; #endif if (FNoHeap(hsep = HsepCreate(fn))) goto ErrFree; if (FNoHeap(hpgtb = HpgtbCreate(fn))) goto ErrFree; if (FNoHeap(hgtbd = HgtbdCreate(fn))) goto ErrFree; } if (FNoHeap(hffntb = HffntbCreateForFn(fn, &fOldWord))) goto ErrFree; break; case dtySsht: goto DtyCommon; case dtyBuffer: if (fn != fnNil) { #ifdef FOOTNOTES if (FNoHeap(hfntb = HfntbCreate(fn))) goto ErrFree; #endif if (FNoHeap(hsep = HsepCreate(fn))) goto ErrFree; if (FNoHeap(hgtbd = HgtbdCreate(fn))) goto ErrFree; } DtyCommon: hpgtb = 0; } pdod = &(**hpdocdod)[doc]; pdod->hszFile = hszFile; pdod->docSsht = docNil; pdod->hfntb = hfntb; pdod->hsep = hsep; pdod->hpgtb = hpgtb; pdod->hffntb = hffntb; pdod->hgtbd = hgtbd; if (fOldWord) if (!FApplyOldWordSprm(doc)) goto ErrFree; ApplyRHMarginSprm( doc ); vfTextOnlySave = !fFormatted; return doc; ErrFree: FreeH( hsep ); FreeFfntb( hffntb ); FreeH(hgtbd); FreeH(hpgtb); #ifdef FOOTNOTES FreeH(hfntb); #endif FreeH((**hpdocdod)[doc].hpctb); (**hpdocdod)[doc].hpctb = 0; return docNil; } /* end of D o c C r e a t e */ ApplyRHMarginSprm( doc ) int doc; { /* Apply a sprm to adjust paper-relative running head indents to be margin-relative */ extern typeCP cpMinDocument; extern struct SEP vsepNormal; ValidateHeaderFooter( doc ); if (cpMinDocument != cp0) { /* Doc has running head/foot, apply sprm */ CHAR rgb[ 2 + (2 * sizeof( int )) ]; struct SEP **hsep = (**hpdocdod) [doc].hsep; struct SEP *psep = (hsep == NULL) ? &vsepNormal : *hsep; rgb[0] = sprmPRhcNorm; rgb[1] = 4; *((int *) (&rgb[2])) = psep->xaLeft; *((int *) (&rgb[2 + sizeof(int)])) = psep->xaMac - (psep->xaLeft + psep->dxaText); AddSprmCps( rgb, doc, cp0, cpMinDocument ); } } int DocAlloc() { int doc; struct DOD *pdod = &(**hpdocdod)[0]; struct DOD *pdodMac = pdod + docMac; for (doc = 0; pdod < pdodMac; ++pdod, ++doc) if (pdod->hpctb == 0) return doc; if (!FChngSizeH((int **)hpdocdod, cwDOD * ++docMac, false)) { --docMac; return docNil; } return docMac - 1; } /* end of D o c A l l o c */ FInitPctb(doc, fn) int doc, fn; { /* Initialize the piece table for a doc, given its initial fn */ struct PCTB **hpctb; struct DOD *pdod; struct PCTB *ppctb; struct PCD *ppcd; typeFC dfc; typeCP cpMac; hpctb = (struct PCTB **)HAllocate(cwPCTBInit); /* HM */ if (FNoHeap(hpctb)) return false; pdod = &(**hpdocdod)[doc]; ppctb = *(pdod->hpctb = hpctb); /* Beware hp mvmt above */ ppcd = ppctb->rgpcd; dfc = (fn != fnNil && (**hpfnfcb)[fn].fFormatted ? cfcPage : fc0); cpMac = (fn == fnNil ? cp0 : (**hpfnfcb)[fn].fcMac - dfc); ppctb->ipcdMax = cpcdInit; ppctb->ipcdMac = (cpMac == cp0 ) ? 1 : 2; /* One real piece and one end piece */ ppcd->cpMin = cp0; if ((pdod->cpMac = cpMac) != cp0) { ppcd->fn = fn; ppcd->fc = dfc; SETPRMNIL(ppcd->prm); ppcd->fNoParaLast = false; (++ppcd)->cpMin = cpMac; } ppcd->fn = fnNil; SETPRMNIL(ppcd->prm); ppcd->fNoParaLast = true; pdod->fDirty = false; return true; } /* end of F I n i t P c t b */ int FnAlloc() { /* Allocate an fn number */ int fn; struct FCB *pfcb; for (fn = 0 ; fn < fnMac ; fn++) if ((**hpfnfcb)[fn].rfn == rfnFree) goto DoAlloc; if (!FChngSizeH(hpfnfcb, (fnMac + 1) * cwFCB, false)) return fnNil; fn = fnMac++; DoAlloc: bltc(pfcb = &(**hpfnfcb)[fn], 0, cwFCB); pfcb->rfn = rfnFree; return fn; } /* end of F n A l l o c */ fnNewFile() { /* Open a new, fresh, untitled document in our MEMO window */ /* Offer confirmation if the current doc is dirty & permit save */ extern HANDLE hMmwModInstance; extern HANDLE hParentWw; extern int docCur; extern struct SEL selCur; extern typeCP cpMinDocument; extern int vfTextOnlySave, vfBackupSave; extern CHAR szUntitled[]; if (FConfirmSave()) /* Allow the user to save if docCur is dirty */ { #if defined(OLE) if (ObjClosingDoc(docCur,szUntitled)) return; #endif KillDoc( docCur ); docCur = DocCreate( fnNil, HszCreate( "" ), dtyNormal ); Assert( docCur != docNil ); ChangeWwDoc( "" ); #if defined(OLE) ObjOpenedDoc(docCur); // very unlikely to fail, not fatal if it does #endif #ifdef WIN30 FreeUnreferencedFns(); #endif } } /* end of f n N e w F i l e */ struct FFNTB **HffntbCreateForFn(fn, pfOldWord) /* returns heap copy of ffntb (font names) for fn */ int fn, *pfOldWord; { struct FFNTB **hffntb; typePN pn; struct FCB *pfcb; typePN pnMac; #ifdef NEWFONTENUM BOOL fCloseAfterward; #endif if (FNoHeap(hffntb = HffntbAlloc())) return(hffntb); pfcb = &(**hpfnfcb)[fn]; pn = pfcb->pnFfntb; if (fn == fnNil || !pfcb->fFormatted) { #if WINVER >= 0x300 /* WINBUG 8992: Clean up so don't lose alloc'd memory! ..pault 2/12/90 */ FreeFfntb(hffntb); #endif hffntb = HffntbNewDoc(FALSE); } else if (pn != (pnMac=pfcb->pnMac)) { /* "normal" memo file - has a font table */ CHAR *pch; int cch; int iffn; int iffnMac; /* Read the first page: bytes 0..1 iffnMac 0..n sections of: bytes 0..1 cbFfn bytes 2..cbFfn+2 Ffn bytes x..x+1 0xFFFF (end of page) OR bytes x..x+1 0x0000 (end of font table) */ pch = PchGetPn( fn, pn, &cch, FALSE ); if (cch != cbSector) goto Error; iffnMac = *( (int *) pch); pch += sizeof (int); #ifdef NEWFONTENUM /* Since we now support multiple charsets, but write 2 and write 1 documents did not save these in their ffntb's, we have to do an extra step now in order to "infer" the proper charset values. We enumerate all the possible fonts, and then as we read in each new document font we try to match it up with what the system knows about ..pault 10/18/89 */ fCloseAfterward = FInitFontEnum(docNil, 32767, FALSE); #endif for ( iffn = 0; ; ) { /* Add ffn entries from one disk page to the font table */ while ( TRUE ) { int cb = *((int *) pch); if (cb == 0) goto LRet; /* Reached end of table */ else if (cb == -1) break; /* Reached end of disk page */ else { #ifdef NEWFONTENUM /* Having added the chs field to the (RAM) FFN structure, we now get screwed reading FFN's from the document directly. And because Write was designed very early without regard to variable charsets, we can't store the charset value along with the fontname, so we have to infer it! ..pault */ CHAR rgbFfn[ibFfnMax]; struct FFN *pffn = (struct FFN *)rgbFfn; pch += sizeof(int); bltsz(pch + sizeof(BYTE), pffn->szFfn); pffn->ffid = *((FFID *) pch); pffn->chs = ChsInferred(pffn); if (FtcAddFfn(hffntb, pffn) == ftcNil) #else if (FtcAddFfn( hffntb, pch += sizeof(int) ) == ftcNil) #endif { Error: #ifdef NEWFONTENUM if (fCloseAfterward) EndFontEnum(); #endif FreeFfntb( hffntb ); return (struct FFNTB **) hOverflow; } iffn++; if (iffn >= iffnMac) /* Reached last item in table, by count */ /* This is so we can read old WRITE files, */ /* in which the table was not terminated by 0 */ goto LRet; pch += cb; } } /* end while */ /* Read the next page from the file. Page format is like the first ffntb page (see above) but without the iffnMac */ if (++pn >= pnMac) break; pch = PchGetPn( fn, pn, &cch, FALSE ); if (cch != cbSector) goto Error; } /* end for */ } else { /* word file - create a simple font table that we can map word's fonts onto */ /* temporarily we map them all onto one font - soon we'll have a set */ #if WINVER >= 0x300 /* WINBUG 8992: Clean up so don't lose alloc'd memory! ..pault 2/12/90 */ FreeFfntb(hffntb); #endif hffntb = HffntbNewDoc(TRUE); *pfOldWord = TRUE; } LRet: #ifdef NEWFONTENUM if (fCloseAfterward) EndFontEnum(); #endif return(hffntb); } struct FFNTB **HffntbNewDoc(fFullSet) /* creates a font table with the default font for this doc */ int fFullSet; { struct FFNTB **hffntb; hffntb = HffntbAlloc(); if (FNoHeap(hffntb)) return(hffntb); /* make sure we at least have a "standard" font */ #ifdef KOREA /* ROMAN as family of standard font(myoungjo). sangl 91.4.17 */ if (!FEnsurePffn(hffntb, PffnDefault(FF_ROMAN))) #else if (!FEnsurePffn(hffntb, PffnDefault(FF_DONTCARE))) #endif { goto BadAdd; } if (fFullSet) /* we need a full set of fonts for word ftc mapping */ if (!FEnsurePffn(hffntb, PffnDefault(FF_MODERN)) || #ifdef KOREA !FEnsurePffn(hffntb, PffnDefault(FF_DONTCARE)) || #else !FEnsurePffn(hffntb, PffnDefault(FF_ROMAN)) || #endif !FEnsurePffn(hffntb, PffnDefault(FF_SWISS)) || !FEnsurePffn(hffntb, PffnDefault(FF_SCRIPT)) || !FEnsurePffn(hffntb, PffnDefault(FF_DECORATIVE))) BadAdd: { FreeFfntb(hffntb); hffntb = (struct FFNTB **)hOverflow; } return(hffntb); } CHAR * PchBaseNameInUpper(szName) CHAR *szName; { CHAR * pchStart = szName; #ifdef DBCS CHAR * pchEnd = AnsiPrev( pchStart, pchStart + CchSz(szName) ); #else CHAR * pchEnd = pchStart + CchSz(szName) - 1; #endif while (pchEnd >= pchStart) { #ifdef DBCS if (*pchEnd == '\\' || *pchEnd == ':') break; else if (!IsDBCSLeadByte(*pchEnd)) *pchEnd = ChUpper(*pchEnd); { LPSTR lpstr = AnsiPrev( pchStart, pchEnd ); if( pchEnd == lpstr ) break; pchEnd = lpstr; } #else if (*pchEnd == '\\' || *pchEnd == ':') break; else *pchEnd = ChUpper(*pchEnd); pchEnd--; #endif } #ifdef DBCS return(AnsiUpper(pchEnd)); #else return(pchEnd+1); #endif } SetTitle(szSource) CHAR *szSource; { extern CHAR szUntitled[]; extern int vfIconic; extern CHAR szAppName[]; extern CHAR szSepName[]; CHAR *pch = stBuf; CHAR szDocName[cchMaxFile]; pch += CchCopySz((PCH)szAppName, stBuf); pch += CchCopySz((PCH)szSepName, pch); if (szSource[0] == '\0') { CchCopySz( szUntitled, pch ); } else { /* get the pointer to the base file name and convert to upper case */ CchCopySz(szSource, szDocName); CchCopySz(PchBaseNameInUpper(szDocName), pch); } SetWindowText(hParentWw, (LPSTR)stBuf); } ValidateHeaderFooter( doc ) { /* Look for a MEMO-style running header and/or footer in the document. We scan from the beginning of the document, taking the first contiguous sequence of running head paragraphs as the running head region, and the first contiguous sequence of running foot paragraphs as the running foot region. We break the process at the first non-running paragraph or when we have both runs Update values of cpMinDocument, cpMinFooter, cpMacFooter, cpMinHeader, cpMacHeader. These ranges INCLUDE the EOL (and Return, if CRLF) at the end of the header/footer If we are currently editing a header or footer in the passed doc, adjust the values of cpFirstDocSave, selDocSave to reflect the change */ extern int docScrap; extern typeCP vcpFirstParaCache; extern typeCP vcpLimParaCache; #define fGot 0 #define fGetting 1 #define fNotGot 2 int fGotHeader=fNotGot; int fGotFooter=fNotGot; typeCP cpMinDocT=cpMinDocument; typeCP cpMinCurT = cpMinCur; typeCP cpMacCurT = cpMacCur; typeCP cp; if (doc == docNil || doc == docScrap) return; /* Want access to the entire doc cp range for this operation */ cpMinCur = cp0; cpMacCur = (**hpdocdod) [doc].cpMac; cpMinDocument = cpMinFooter = cpMacFooter = cpMinHeader = cpMacHeader = cp0; for ( cp = cp0; (cp < cpMacCur) && (CachePara( doc, cp ), vpapAbs.rhc); cp = vcpLimParaCache ) { int fBottom=vpapAbs.rhc & RHC_fBottom; if (fBottom) { if (fGotHeader == fGetting) fGotHeader = fGot; switch (fGotFooter) { case fGot: /* Already have footer from earlier footer run */ return; case fNotGot: cpMinFooter = vcpFirstParaCache; fGotFooter = fGetting; /* FALL THROUGH */ case fGetting: cpMacFooter = cpMinDocument = vcpLimParaCache; break; } } else { if (fGotFooter == fGetting) fGotFooter = fGot; switch (fGotHeader) { case fGot: /* Already have header from earlier header run */ return; case fNotGot: cpMinHeader = vcpFirstParaCache; fGotHeader = fGetting; /* FALL THROUGH */ case fGetting: cpMacHeader = cpMinDocument = vcpLimParaCache; break; } } } /* end of for loop through paras */ /* Restore saved cpMacCur, cpMinCur */ cpMinCur = cpMinCurT; cpMacCur = cpMacCurT; /* Adjust saved cp's that refer to the document to reflect header/footer changes */ if ((wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter) && wwdCurrentDoc.doc == doc ) { typeCP dcpAdjust=cpMinDocument - cpMinDocT; if (dcpAdjust != (typeCP) 0) { selDocSave.cpFirst += dcpAdjust; selDocSave.cpLim += dcpAdjust; cpFirstDocSave += dcpAdjust; } } }