/************************************************************/
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
/************************************************************/
/* Open.c -- WRITE document opening */
#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 NOMETAFILE
#define NOMSG
#define NOPOINT
#define NORECT
#define NOREGION
#define NOSCROLL
#define NOWH
#define NOWINOFFSETS
#define NOSOUND
#define NOCOMM
#define NORESOURCE
#include <windows.h>
#include "mw.h"
#include "doslib.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"
#include "obj.h"
#define PAGEONLY
#include "printdef.h" /* printdefs.h */
/*
#include "dlgdefs.h"
*/
/* 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[];
#if WINVER >= 0x300
extern BOOL fError;
#endif
short WCompSzC();
CHAR (**HszCreate())[];
struct FNTB **HfntbCreate();
#ifdef CASHMERE
struct SETB **HsetbCreate();
#else
struct SEP **HsepCreate();
#endif
struct PGTB **HpgtbCreate();
CHAR *PchFromFc( int, typeFC, int * );
CHAR *PchGetPn( int, typePN, int *, int );
typeFC FcMacFromUnformattedFn( int );
int CchReadAtPage( int, typePN, CHAR *, int, int );
struct TBD (**HgtbdCreate(fn))[]
int fn;
{ /* Create a MEMO tab table by reading the properties of the first
para of the passed fn and returning a handle. The handle returned will
be 0 if the tab table is not present or null */
struct TBD (**hgtbd)[] = 0;
struct PAP pap;
Assert( (fn != fnNil) && (**hpfnfcb)[fn].fFormatted );
bltc((int *)&pap, 0, cwPAP); /* else we will have garbage tabs */
FcParaLim( fn, (typeFC)cfcPage, (**hpfnfcb)[fn].fcMac, &pap );
if (pap.rgtbd[0].dxa && !FNoHeap( hgtbd = (struct TBD (**)[])HAllocate( cwTBD *
itbdMax )))
{
register struct TBD *ptbd = &pap.rgtbd[0];
pap.rgtbd[itbdMax - 1].dxa = 0; /* just in case a WORD document has more
than 12 tabs */
/* overwrite tabs and leading tab char that WRITE does not support */
for ( ; ptbd->dxa != 0; ptbd++)
{
ptbd->tlc = tlcWhite;
ptbd->opcode = 0;
ptbd->chAlign = 0;
if (ptbd->jc == jcCenter)
ptbd->jc = jcLeft;
else if (ptbd->jc == jcRight)
ptbd->jc = jcBoth;
}
blt( &pap.rgtbd[0], *hgtbd, cwTBD * itbdMax );
}
return hgtbd;
}
struct SEP **HsepCreate(fn)
int fn;
{ /* Given an fn for a formatted file, return a handle to an SEP
giving section properties for the file. Returns NULL if
standard properties should be used. If the file has a section
table, the properties from the first section in the table are used */
extern struct SEP vsepNormal;
struct SETB *psetbFile;
typePN pn;
struct SEP **hsep;
struct SED *psed;
CHAR *pchFprop;
int cch;
Assert(fn != fnNil && (**hpfnfcb)[fn].fFormatted);
if ((pn = (**hpfnfcb)[fn].pnSetb) == (**hpfnfcb)[fn].pnBftb)
return (struct SEP **) 0;
psetbFile = (struct SETB *) PchGetPn(fn, pn, &cch, false);
if (psetbFile->csed == 0)
return (struct SEP **)0;
/* File has a section table; copy properties from first SEP */
hsep = (struct SEP **) HAllocate( cwSEP );
if (FNoHeap( hsep ))
return (struct SEP **) hOverflow;
blt( &vsepNormal, *hsep, cwSEP );
psed = &psetbFile->rgsed [0];
if (psed->fc == fcNil)
return (struct SEP **)0;
pchFprop = PchFromFc( fn, psed->fc, &cch );
if (*pchFprop != 0)
{
struct SEP *psep = *hsep;
bltbyte( pchFprop+1, psep, *pchFprop );
#ifndef FIXED_PAGE
/* Some of the section properties must be adjusted to the current page size
(stored in vsepNormal). */
if (psep->xaMac != vsepNormal.xaMac)
{
int dxa = vsepNormal.xaMac - psep->xaMac;
psep->xaMac += dxa;
psep->dxaText = max(psep->dxaText + dxa, dxaMinUseful);
psep->xaPgn += dxa;
}
if (psep->yaMac != vsepNormal.yaMac)
{
int dya = vsepNormal.yaMac - psep->yaMac;
psep->yaMac += dya;
psep->dyaText = max(psep->dyaText + dya, dyaMinUseful);
psep->yaRH2 += dya;
}
#endif /* not FIXED_PAGE */
}
return hsep;
} /* end of H s e p C r e a t e */
struct PGTB **HpgtbCreate(fn)
int fn;
{ /* Create a page table from a formatted file */
struct PGTB *ppgtbFile;
typePN pn;
int cchT;
int cpgd;
struct PGTB **hpgtb;
int *pwPgtb;
int cw;
Assert(fn != fnNil && (**hpfnfcb)[fn].fFormatted);
if ((pn = (**hpfnfcb)[fn].pnBftb) == (**hpfnfcb)[fn].pnFfntb)
return (struct PGTB **)0;
ppgtbFile = (struct PGTB *) PchGetPn(fn, pn, &cchT, false);
if ((cpgd = ppgtbFile->cpgd) == 0)
return (struct PGTB **)0;
hpgtb = (struct PGTB **) HAllocate(cw = cwPgtbBase + cpgd * cwPGD);
if (FNoHeap(hpgtb))
return (struct PGTB **)hOverflow;
pwPgtb = (int *) *hpgtb;
blt(ppgtbFile, pwPgtb, min(cwSector, cw));
while ((cw -= cwSector) > 0)
{ /* Copy the pgd's to heap */
blt(PchGetPn(fn, ++pn, &cchT, false), pwPgtb += cwSector,
min(cwSector, cw));
}
(*hpgtb)->cpgdMax = cpgd;
return hpgtb;
} /* end of H p g t b C r e a t e */
int FnFromSz( sz ) /* filename is expected as ANSI */
CHAR *sz;
{
int fn;
struct FCB *pfcb;
if (sz[0] == 0)
return fnNil;
/* Mod for Sand: Only return fn if it is on the "current" volume (disk) */
for (fn = 0; fn < fnMac; fn++)
if ((pfcb = &(**hpfnfcb)[fn])->rfn != rfnFree && (WCompSzC((PCH)sz, (PCH)**pfcb->hszFile) == 0)
#ifdef SAND
&& (pfcb->vref == vrefFile)
#endif /* SAND */
)
return fn;
return fnNil;
} /* end of F n F r o m S z */
int FnOpenSz( szT, dty, fSearchPath ) /* filename is expected as ANSI */
CHAR *szT;
int dty;
int fSearchPath;
{ /* Open an existing file. Returns fnNil if not found */
int fn;
struct FIB fib;
struct FCB *pfcb;
CHAR (**hsz)[];
CHAR sz[cchMaxFile];
bltsz( szT, sz );
sz[cchMaxFile - 1] = 0;
#ifdef DFILE
CommSzSz("FnOpenSz: sz presumed ANSI = ",sz);
#endif
if (sz[0]=='\0')
return fnNil;
if ((fn = FnFromSz(sz)) != fnNil)
{ /* File is already open -- re-open it, in case it was changed by
another app */
FreeFn( fn );
}
if ((fn = FnAlloc()) == fnNil)
return fnNil;
if (FNoHeap((hsz = HszCreate((PCH)sz))))
return fnNil;
pfcb = &(**hpfnfcb)[fn];
Assert( !pfcb->fSearchPath );
if (fSearchPath)
pfcb->fSearchPath = TRUE;
pfcb->mdFile = mdBinary; /* Try R/W first, will be smashed to RO if needed */
pfcb->dty = pfcb->mdExt = (dty == dtyNormNoExt) ? dtyNormal : dty;
pfcb->hszFile = hsz;
{
OFSTRUCT of;
SetErrorMode(1);
if (OpenFile(sz, (LPOFSTRUCT) &of, OF_EXIST) == -1)
/* this is much cleaner than FAccessFn() for check existance */
{
char szMsg[cchMaxSz];
extern int vfInitializing;
int fT = vfInitializing;
vfInitializing = FALSE; /* Report this err, even during inz */
MergeStrings ((of.nErrCode == dosxSharing) ? IDPMTCantShare:IDPMTCantOpen, sz, szMsg);
IdPromptBoxSz(vhWndMsgBoxParent ? vhWndMsgBoxParent : hParentWw, szMsg, MB_OK|MB_ICONEXCLAMATION);
vfInitializing = fT;
FreeH( (**hpfnfcb) [fn].hszFile);
return fnNil;
}
}
/* dtyNormNoExt is directed at this call */
if (!FAccessFn( fn, dty )) /* HM if error */
{
FreeH( (**hpfnfcb) [fn].hszFile);
return fnNil;
}
/* stupid kludge management (6.21.91) v-dougk */
dty = (dty == dtyNormNoExt) ? dtyNormal : dty;
Assert( (sizeof (struct FIB) == cfcPage) && (cfcPage == cbSector) );
Assert( pfcb == &(**hpfnfcb) [fn] ); /* No HM if FAccessFn succeeds */
if ( (CchReadAtPage( fn, (typePN) 0,
(CHAR *) &fib, cbSector, TRUE ) != cbSector) ||
(fib.wTool != wMagicTool) )
{ /* Not a formatted file */
typeFC fcMac = fc0;
int cfc;
if (dty != dtyNormal)
{
char szMsg[cchMaxSz];
PchFillPchId( szMsg, IDPMTBadFile, sizeof(szMsg) );
if (MessageBox(hPARENTWINDOW, (LPSTR)szMsg,
(LPSTR)szAppName, MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2) == IDNO)
goto ErrRet;
}
pfcb->fFormatted = false;
/* Obtain file size by seeking to end-of-file */
if ((pfcb->fcMac = fcMac = FcMacFromUnformattedFn( fn )) == (typeFC) -1)
/* Serious error while seeking to file's end */
goto ErrRet;
pfcb->pnMac = (fcMac + cfcPage - 1) / cfcPage;
}
else
{ /* File is formatted; use stored fcMac, create run table */
if ((((fib.wIdent != wMagic) && (fib.wIdent != wOleMagic)) ||
(fib.dty != dty)) ||
// some bigwig media guy sent us a Write file whose fcMac was
// trashed (all else was OK). We gotta try to detect this obsure
// potentiality.
(fib.fcMac >= (typeFC)fib.pnPara*128 ) ||
(fib.fcMac > FcMacFromUnformattedFn( fn ))
)
{ /* Wrong type of file or corrupted file */
char szMsg[cchMaxSz];
PchFillPchId( szMsg, IDPMTBadFile, sizeof(szMsg) );
if (MessageBox(hPARENTWINDOW, (LPSTR)szMsg,
(LPSTR)szAppName, MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2) == IDNO)
goto ErrRet;
}
if ((fib.wIdent == wOleMagic) && !fOleEnabled)
Error(IDPMTFileContainsObjects);
if (fib.pnMac == (typePN)0)
/* KLUDGE to load word files, which don't have ffntb entries. */
fib.pnMac = fib.pnFfntb;
pfcb->fFormatted = true;
pfcb->fcMac = fib.fcMac;
#ifdef p2bSector
pfcb->pnChar = (fib.fcMac + cfcPage - 1) / cfcPage;
#else
pfcb->pnChar = (fib.fcMac + cfcPage - 1) / cfcPage;
#endif
pfcb->pnPara = fib.pnPara;
pfcb->pnFntb = fib.pnFntb;
pfcb->pnSep = fib.pnSep;
pfcb->pnSetb = fib.pnSetb;
pfcb->pnBftb = fib.pnBftb;
pfcb->pnFfntb = fib.pnFfntb;
pfcb->pnMac = fib.pnMac;
if (dty != dtyPrd)
{
if (FNoHeap(hsz = HszCreate((PCH)fib.szSsht)))
goto ErrRet;
(**hpfnfcb)[fn].hszSsht = hsz;
if (!FMakeRunTables(fn))
goto ErrRet;
}
}
return fn;
ErrRet:
(pfcb = &(**hpfnfcb)[fn])->rfn = rfnFree;
FreeH(pfcb->hszFile);
return fnNil;
} /* end of F n O p e n S z */
/*---------------------------------------------------------------------------
-- Routine: WCompSzC(psz1,psz2)
-- Description and Usage:
Alphabetically compares the two null-terminated strings psz1 and psz2.
Upper case alpha characters are mapped to lower case.
Comparison of non-alpha characters is by ascii code.
Returns 0 if they are equal, a negative number if psz1 precedes psz2, and
a non-zero positive number if psz2 precedes psz1.
-- Arguments:
psz1, psz2 - pointers to two null-terminated strings to compare
-- Returns:
a short - 0 if strings are equal, negative number if psz1 precedes psz2,
and non-zero positive number if psz2 precedes psz1.
-- Side-effects: none
-- Bugs:
-- History:
3/14/83 - created (tsr)
----------------------------------------------------------------------------*/
short
WCompSzC(psz1,psz2)
PCH psz1;
PCH psz2;
{
int ch1;
int ch2;
for(ch1=ChLowerC(*psz1++),ch2=ChLowerC(*psz2++);
ch1==ch2;
ch1=ChLowerC(*psz1++),ch2=ChLowerC(*psz2++))
{
if(ch1 == '\0')
return(0);
}
return(ch1-ch2);
} /* end of W C o m p S z C */
/*---------------------------------------------------------------------------
-- Routine: ChLowerC(ch)
-- Description and Usage:
Converts its argument to lower case iff its argument is upper case.
Returns the de-capitalized character or the initial char if it wasn't caps.
-- Arguments:
ch - character to be de-capitalized
-- Returns:
a character - initial character, de-capitalized if needed.
-- Side-effects:
-- Bugs:
-- History:
3/14/83 - created (tsr)
----------------------------------------------------------------------------*/
int
ChLowerC(ch)
register CHAR ch;
{
if(isupper(ch))
return(ch + ('a' - 'A')); /* foreign is taken care of */
else
return ch;
} /* end of C h L o w e r C */
#ifdef JAPAN
// Compare ch with halfsize-KANA code range, then return whether it is or not.
BOOL IsKanaInDBCS(int ch)
{
ch &= 0x00ff;
if(ch>=0xA1 && ch <= 0xDF) return TRUE;
else return FALSE;
}
#endif
typeFC (**HgfcCollect(fn, pnFirst, pnLim))[]
typePN pnFirst, pnLim;
{ /* Create a table indexing fc's by fkp number */
typeFC fcMac;
typePN pn;
int ifcMac, ifc;
typeFC (**hgfc)[];
struct FKP fkp;
fcMac = (**hpfnfcb)[fn].fcMac;
pn = pnFirst + 1;
ifcMac = ifcMacInit; /* Length of table */
hgfc = (typeFC (**)[])HAllocate((ifcMacInit * sizeof(typeFC)) / sizeof(int));
if (FNoHeap(hgfc))
return (typeFC (**)[])hOverflow;
for (ifc = 0; ; ++ifc, ++pn)
{ /* Put first fcLim of each fkp in table */
if (ifc >= ifcMac)
{ /* Must grow table */
int cw = ((ifcMac += ifcMacInit) * sizeof (typeFC)) / sizeof(int);
if (!FChngSizeH(hgfc, cw, false))
{
LHFGCErrRet:
FreeH(hgfc);
return (typeFC (**)[])hOverflow;
}
}
if (pn < pnLim)
{ /* Get fcLimFkb from fcFirst of next page */
int cch;
cch = CchReadAtPage( fn, pn, (CHAR *) &fkp, cbSector, TRUE );
if (cch != cfcPage)
goto LHFGCErrRet;
(**hgfc)[ifc] = fkp.fcFirst;
}
else
{ /* fcLimFkb is fcMac + 1 */
(**hgfc)[ifc] = fcMac + 1;
if (!FChngSizeH(hgfc, ((ifc + 1) * sizeof(typeFC)) / sizeof(int), true))
{
/* Previously ignored bad return value here ..pault 11/3/89 */
goto LHFGCErrRet;
}
return hgfc;
}
}
} /* end of H g f c C o l l e c t */
/* F M A K E R U N T A B L E S */
int FMakeRunTables(fn)
{ /* Create two tables of fc-dpn pairs, one for chr's and one for par's */
typeFC (**hgfc)[];
if (FNoHeap(hgfc = HgfcCollect(fn, (**hpfnfcb)[fn].pnChar, (**hpfnfcb)[fn].pnPara)))
return false;
(**hpfnfcb)[fn].hgfcChp = hgfc;
if (FNoHeap(hgfc = HgfcCollect(fn, (**hpfnfcb)[fn].pnPara, (**hpfnfcb)[fn].pnFntb)))
{
FreeH( (**hpfnfcb) [fn].hgfcChp );
return false;
}
(**hpfnfcb)[fn].hgfcPap = hgfc;
return true;
} /* end of F M a k e R u n T a b l e */
FApplyOldWordSprm(doc)
/* applies a sprm to this doc which causes all "old word" fonts to be remapped
into new windows ones */
{
CHAR rgbSprm[7];
extern int vfSysFull;
/* set up the OldFtc sprm mapping */
rgbSprm[0] = sprmCOldFtc;
rgbSprm[1] = 5;
rgbSprm[2 + iftcModern] = FtcScanDocFfn(doc, PffnDefault(FF_MODERN));
rgbSprm[2 + iftcRoman] = FtcScanDocFfn(doc, PffnDefault(FF_ROMAN));
rgbSprm[2 + iftcScript] = FtcScanDocFfn(doc, PffnDefault(FF_SCRIPT));
rgbSprm[2 + iftcDecorative] = FtcScanDocFfn(doc, PffnDefault(FF_DECORATIVE));
rgbSprm[2 + iftcSwiss] = FtcScanDocFfn(doc, PffnDefault(FF_SWISS));
AddSprmCps(rgbSprm, doc, (typeCP)0, (**hpdocdod)[doc].cpMac);
return(vfSysFull == 0);
}