/* I N I T W I N . C */

#define NONCMESSAGES
#define NODRAWFRAME
#define NORASTEROPS
#define NOCTLMGR
#define NOMINMAX
#define NOSCROLL
#define NOKEYSTATE
#define NOCREATESTRUCT
#define NOICON
#define NOPEN
#define NOREGION
#define NODRAWTEXT
#define NOWINOFFSETS
#define NOMETAFILE
#define NOCLIPBOARD
#define NOSOUND
#define NOCOMM
#define NOKANJI

#define SBMGR
#include "word.h"
DEBUGASSERTSZ            /* WIN - bogus macro for assert string */
#include "version.h"
#include "heap.h"
#define NOSPECMSG
#include "wininfo.h"
#include "doc.h"
#include "props.h"
#include "disp.h"
#include "file.h"
#include "fkp.h"
#include "sel.h"
#include "format.h"
#include "print.h"
#include "layout.h"
#include "preview.h"
#include "resource.h"
#include "keys.h"
#include "cmdtbl.h"
#include "menu2.h"
#include "opuscmd.h"
/*#include "field.h"*/
#include "inter.h"
#define AUTOSAVE
#include "autosave.h"
#define REVMARKING
#include "compare.h"
#include "help.h"
#include "screen.h"
#include "doslib.h"
#include "scc.h"
#include "debug.h"
#include "dmdefs.h"
#include "status.h"
#include "core.h"
#include "preffile.h"
#include "ibdefs.h"
#include "outline.h"
#include "ch.h"
#include "rsb.h"
#include "error.h"
#include "rareflag.h"
#include "table.h"

extern MUD ** HmudInit();

extern BOOL             vfScratchFile;
extern struct DMQD        DMQueryD;
extern struct DMFLAGS     DMFlags;
extern struct DMQFLAGS    DMQFlags;
extern BOOL             vfFileCacheDirty;
extern int              docGlobalDot;
extern HMENU            vhMenuLongFull;
extern int              vwWinVersion;
extern struct FTI       vfti;
extern struct FTI       vftiDxt;
extern struct STTB      **vhsttbFont;
extern struct STTB      **vhsttbOpen;
extern struct PRI       vpri;
extern struct PRSU      vprsu;
extern CHAR             szEmpty[];
extern CHAR             stEmpty[];
extern HCURSOR          vhcBarCur;
extern HCURSOR          vhcHourGlass;
extern HCURSOR          vhcIBeam;
extern HCURSOR          vhcArrow;
extern HCURSOR          vhcSplit;
extern HCURSOR          vhcStyWnd;
extern HCURSOR          vhcRecorder;
extern HCURSOR          vhcHelp;
extern HCURSOR		vhcOtlCross;
extern HCURSOR		vhcOtlVert;
extern HCURSOR		vhcOtlHorz;
extern HCURSOR		vhcColumn;
extern HICON            vhiWord;
extern HANDLE           vhInstance;
extern HWND             vhwndApp;
extern HWND             vhwndSizeBox;
extern int              vfAllocGuaranteed;
extern HWND             vhwndCBT;
extern struct SCI	vsci;
extern struct STTB    **vhsttbWnd;
extern int              vfInitializing;
extern int              vfMouseExist;
extern uns              cbMemChunk;
extern BOOL             vfSingleApp;
extern int              vdbmgDevice;
extern BOOL             vfLargeFrameEMS;
extern struct ITR	vitr;
extern PVS		vpvs;
#ifdef OPUS_X64
extern HANDLE HLoadRes0();
extern HANDLE HFromIbmds0();
extern CHAR **HReadCbFromPrstream();
extern int OpusValidateSttb();
#endif
#ifdef WIN23
extern HFONT		hfontStatLine;
extern int			vdxpDigit;
#ifdef OPUS_X64
extern LRESULT CALLBACK IconDlgWndProc(HWND, UINT, WPARAM, LPARAM);
extern WNDPROC lpfnIconDlgWndProc;
#else
extern LONG FAR PASCAL IconDlgWndProc();
extern FARPROC  lpfnIconDlgWndProc;
#endif
#endif /* WIN23 */

/* G L O B A L S */
struct FTI      vfti;           /* primary device connection */
struct FTI      vftiDxt;        /* secondary device connection */
struct FCE      rgfce[ifceMax]; /* font cache */
struct STTB     **vhsttbFont;   /* Master font table */
struct WWD      **hwwdCur; /* handle to the current pane inside a child window */
int             wwCur; /* index to the current window pane */
struct MWD      **hmwdCur; /* handle to the current child window */
int             mwCur; /* index to the current child window */
/* tsMruOsfn is the Most Recently Used Operating System File timestamp.
	It is used by low level file routines to implement a LRU strategy for
	opening and closing files. */
TS              tsMruOsfn;

struct BPTB     vbptbExt;
/* indicates that the scratch file exists; if false, scratch file is kept
	entirely in memory */
int             vfScratchFile;
/* indicates that we have not yet tried to create the scratch file */
int		vfTriedScratchFile;

/* stores handles to paths for template, ini, utilities, program */
struct EFPI dnfpi[fpiStoreMax];
int             docGlsy = docNil;
int             docGlobalDot = docNil;
int             vdocTemp = docNil;      /* temporary doc used for fSpec characters */
int             vdocScratch = docNil;   /* globally available scratch doc */
int             vdocHdrEdit = docNil;
BOOL				 vfAs400 = fFalse;

#ifdef DEBUG
BOOL            fDocScratchInUse = fFalse;
#endif /* DEBUG */

int             cfRTF = cfNil;    /* registered clipboard formats */
int             cfLink = cfNil;
int             cfPrPic = cfNil;
KMP **  hkmpTable = NULL;

FARPROC lpFontNameEnum;
FARPROC lpFontSizeEnum;

FARPROC lpFPrContinue;
FARPROC lpFCheckPopupRect;

/* for metafile display interruption */
FARPROC lpFMFContinue;

#ifdef DEBUG
struct DBS vdbs;
int	vfCheckPlc = fTrue;	/* PLC checking */
int	vfInt3Handler = fFalse;
#endif
#ifdef PROFILE
int vpfi = -1;
#endif /* PROFILE */

/* Window class strings.  Must be < 39 char long.  Do not localize. */
char szClsApp[] =       "OpusApp";
char szClsMwd[] =       "OpusMwd";
char szClsPgPrvw[] =    "OpusPrvw";
char szClsStatLine[] =  "OpusStat";
char szClsSplitBar[] =  "OpusSBar";
char szClsRSB[] = 	"OpusRSB";
char szClsRulerMark[] = "OpusRul";
char szClsDeskTop[] =   "OpusDesk";
char szClsWwPane[] =    "OpusWwd";
char szClsPrompt[] =    "OpusPmt";
char szClsStaticEdit[]= "OpusSEdit";
char szClsDdeChnl[] =   "OpusDde";
char szClsFedt[] =      "OpusFedt";
char szClsStart[] =     "OpusStart";
char szClsIconBar[] =   "OpusIcnBar";
int             vwWinVersion;   /* WIN version #, BCD: maj in hi, min in lo */
int             vfLargeFrameEMS;/* kernel is using large frame EMS */
int             vfSmallFrameEMS;/* interesting?? */
int				vcbitSegmentShift; /* shift segment by this at seg bounds */

int vkPlus;
int vkMinus;
int vkStar;

#ifdef INTL
int vkUnderline;
int vkEquals;
int vkQuestionmark;
#endif /* INTL */

long tickNextYield = 0; /* last time we called PeekMessage or otherwise yielded */


/* E X T E R N A L S */
extern struct PREF      vpref;
extern struct PREF      vprefCBT;  /* pref's before CBT run; restore after */
/* extern struct SAB       vsab; */

extern struct BPTB      vbptbExt;
extern int              vrgsbReserve[];
extern struct SEL       selCur;

extern struct FKPD      vfkpdChp;
extern struct FKPD      vfkpdPap;
extern struct FKPD      vfkpdText;
extern BYTE             fProtectModeWindows;
extern struct WWD       **mpwwhwwd[];
extern struct FCB       **mpfnhfcb[];
extern struct WWD       **hwwdCur;

extern struct SCC       vsccAbove;

extern struct FLI       vfli;
extern CHAR             **vhgrpchr;
extern int              vbchrMax;

extern struct PLC    **vhplcfrl;
extern struct FLS       vfls;

extern struct DOD       **mpdochdod[];

extern struct MERR      vmerr;
extern struct UAB       vuab;
extern struct AAB       vaab;
extern int              cfRTF;
extern int              cfLink;
extern CHAR             szApp[];

extern CHAR           **hstDMQPath;
extern struct DMFLAGS   DMFlags;

#ifdef DEBUG
extern BOOL		fForce8087Fail;
#endif

/* Clipboard formats */
#ifdef OPUS_X64
csconst CHAR szClipRTF[] = "Rich Text Format";
csconst CHAR szClipLink[] = "Link";
csconst CHAR szClipPrPic[] = "Printer_Picture";
#else
csconst CHAR szClipRTF[] = SzSharedKey("Rich Text Format",RichTextFormat);
csconst CHAR szClipLink[] = SzSharedKey("Link",Link);
csconst CHAR szClipPrPic[] = SzSharedKey("Printer_Picture",PrPic);
#endif

#ifdef DEBUG
CHAR vchRTFTest = 0; /* indicates special RTF test option specified */
#endif /* DEBUG */

extern BOOL FAR PASCAL  FontNameEnum();
extern BOOL FAR PASCAL  FontSizeEnum();
extern FARPROC          lpFontNameEnum;
extern FARPROC          lpFontSizeEnum;

#ifdef DEBUG
extern struct SCC       *vpsccSave;
extern int    vcwHeapMacDbg;   /* max that can be allocated on heap */
#endif  /* DEBUG */

/* W I N D O W   C L A S S   I N F O R M A T I O N */

extern long FAR PASCAL NatAppWndProc();
extern long FAR PASCAL NatMwdWndProc();
extern long FAR PASCAL NatStatLineWndProc();
extern LONG FAR PASCAL NatPgPrvwWndProc();
extern LONG FAR PASCAL NatSplitBarWndProc();
extern LONG FAR PASCAL NatPromptWndProc();
extern LONG FAR PASCAL NatDeskTopWndProc();
extern LONG FAR PASCAL NatWwPaneWndProc();
extern LONG FAR PASCAL NatRulerMarkWndProc();
extern LONG FAR PASCAL NatIconBarWndProc();
extern LONG FAR PASCAL NatDdeChnlWndProc();
extern LONG FAR PASCAL NatRSBWndProc();
extern LONG FAR PASCAL NatFedtWndProc();
extern LONG FAR PASCAL NatStaticEditWndProc();
extern LONG FAR PASCAL NatStartWndProc();
extern LONG FAR PASCAL StaticEditWndProc();


extern char szClsApp[];
extern char szClsMwd[];
extern char szClsPgPrvw[];
extern char szClsStatLine[];
extern char szClsSplitBar[];
extern char szClsRulerMark[];
extern char szClsDeskTop[];
extern char szClsWwPane[];
extern char szClsPrompt[];
extern char szClsStaticEdit[];
extern char szClsDdeChnl[];
extern char szClsRSB[];
extern char szClsFedt[];
extern char szClsStart[];
extern char szClsIconBar[];

#define idColorNil     (-1)

	struct WC  {
	WORD    style;
	int     cbWndExtra;
	int     idBackgroundColor;       /* COLOR constant, e.g. COLOR_BACKGROUND */
	CHAR  * szCls;
	FARPROC lpfnWndProc;
};

/* NOTE: Casts to FARPROC in initializer are a workaround for a CS
	compiler bug */

csconst struct WC rgwc [] =
	{ 
		{ CS_BYTEALIGNCLIENT,                                 /* Parent */
	0, COLOR_APPWORKSPACE+1, szClsApp, (FARPROC)NatAppWndProc },
	

	{ 0,                                                  /* MDI window */
	CBWEMW, idColorNil, szClsMwd, (FARPROC)NatMwdWndProc },
	

	{ CS_DBLCLKS,                                         /* Page Preview */
	0, idColorNil, szClsPgPrvw, (FARPROC)NatPgPrvwWndProc },
	

	{ CS_DBLCLKS,                                         /* Status Line */
	0, idColorNil, szClsStatLine, (FARPROC)NatStatLineWndProc },
	

	{ 0,                                                  /* Split Bar */
	0, COLOR_WINDOW+1, szClsSplitBar, (FARPROC)NatSplitBarWndProc },
	

	{ CS_DBLCLKS,                                         /* RulerMark */
	0, COLOR_WINDOW+1, szClsRulerMark, (FARPROC)NatRulerMarkWndProc },
	

	{ 0,                                                  /* DeskTop */
	0, COLOR_APPWORKSPACE+1, szClsDeskTop, (FARPROC)NatDeskTopWndProc },
	

	{ CS_OWNDC | CS_DBLCLKS,                              /* WwPane */
	CBWEWW, idColorNil, szClsWwPane, (FARPROC)NatWwPaneWndProc },
	

	{ 0,                                                  /* Prompt */
	0, idColorNil, szClsPrompt, (FARPROC)NatPromptWndProc },
	

	{ 0,                                                  /* Static Edit */
	CBWESTATICEDIT, idColorNil, szClsStaticEdit, (FARPROC)NatStaticEditWndProc },
	

	{ 0,                                                  /* Dde Channel */
	CBWEDDECHNL, idColorNil, szClsDdeChnl, (FARPROC)NatDdeChnlWndProc },
	

	{ CS_DBLCLKS | CS_HREDRAW,                            /* Our Editcontrol */
	CBWEFEDT, idColorNil, szClsFedt, (FARPROC)NatFedtWndProc },
	
	
	{ 0,	    	    	    	    	    	    	/* Startup dialog */
	0, idColorNil, szClsStart, (FARPROC)NatStartWndProc },
	

	{ CS_DBLCLKS,                                         /* Icon Bar */
	CBWEICONBAR, COLOR_WINDOW+1, szClsIconBar, (FARPROC)NatIconBarWndProc },
	

	{ CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,		/* Rational Scrl Bar */
	cbweRSB, idColorNil, szClsRSB, (FARPROC)NatRSBWndProc },

};


#define iwcApp	0
#define iwcRSB	14
#define iwcMax	15 /* # of entries in rgwc above */

#ifdef WIN23
#define iwcStatLine 3
#define iwcSplitBar 4
#define iwcRulerMark 5
#define iwcIconBar 13
#endif /* WIN23 */

/* L O C A L   D E C L A R A T I O N S */

extern HBRUSH vhbrLtGray;
extern HBRUSH vhbrGray;
extern HBRUSH vhbrWhite;
extern HBRUSH vhbrBlack;
extern HBRUSH vhbrDkGray;

extern HWND vhwndRibbon;
extern HWND vhwndStatLine;
extern HWND vhwndDeskTop;
extern HWND vhwndStartup;

extern FARPROC lpFCheckPopupRect;
BOOL FAR PASCAL FCheckPopupRect();
extern FARPROC lpprocStaticEditWndProc;
/* Already extern declared */
/* LONG FAR PASCAL StaticEditWndProc; */

extern FARPROC lpprocBlinkCaretSEdit;
BOOL FAR PASCAL BlinkCaretSEdit();


extern FARPROC lpFPrContinue;
BOOL FAR PASCAL FPrContinue();

extern FARPROC  lpFMFContinue;
extern BOOL FAR PASCAL FMFContinue();

extern FARPROC lpFBltOutlineSplat;
BOOL FAR PASCAL FBltOutlineSplat();

/* Dialog key mapper stuff */
extern FARPROC        vlppFWHChain;
extern FARPROC        lppFWHKey;
LONG FAR PASCAL       FWHKey();

/*               F  I n i t  P a r t 1
*  Called from FInitWinInfo to do first part 1 of initialization of the 
*  whole world. Returns FALSE if the initialization failed, TRUE if it 
*  succeeded. After calling FInitPart1 you should call FInitPart2. Parts
*  1 and 2 have been split up to reduce the amount of code space needed
*  during initialization. */

/* %%Function:FInitPart1 %%Owner:PETERJ */
int FInitPart1( hInstance, hPrevInstance, lpszCmdLine, 
rgchCmdLine, rgpchArg, pipchArgMac, pfOpenUntitled, pfTutorial  )
HANDLE hInstance, hPrevInstance;
LPSTR  lpszCmdLine;
CHAR rgchCmdLine [ichMaxCmdLine+1];
CHAR *rgpchArg [ipchArgMax];
int *pipchArgMac;
BOOL *pfOpenUntitled;
BOOL *pfTutorial;
{
	extern int vwWinVersion;
	int eidFail = eidCantRunM;
	int ipchArgMac;

	vhInstance = hInstance;

/* NOTE: At this point we know how much memory we have (we can calculate the
	worst case for memory allocations against our minimum heap size,
	defined in out .DEF file).  For that reason we do not need to check for
	failure on the allocations that follow. This is true up until the first
	user variable -- reading WINWORD.INI. */

	Debug(vfAllocGuaranteed = fTrue);

	if (!FNativeInit())
		{
		eidFail = eidWrongWinOrDos;
		goto InzFailed0;
		}
	/* This should be very early in initialization! */
	/* Opus does not currently support multiple instances; return if the user
		tries it */
	if (hPrevInstance)
		{
		eidFail = eidWordRunning;
		goto InzFailed0;
		}

#ifdef WIN23
	if (vwWinVersion >= 0x0300)
		{
		/* we need to know what device we are running on to decide whether
			or not to do Win3Stuff, so do this here */
		HDC hdc;
		int wNewLook = GetProfileInt( szApp, SzShared("NewLook"), 2);
		vsci.fWin3 = fTrue;
		if ((hdc = GetDC(NULL)) == NULL)
			goto InzFailed0;
		vsci.dypScreen = GetDeviceCaps(hdc,VERTRES);
		vsci.fMonochrome = (GetDeviceCaps(hdc, NUMCOLORS) == 2);
		/****
		If wNewLook == 0, then we never use Win3Visuals
		If wNewLook == 1, then we run Win3Visuals on EGA or greater.
		If wNewLook == 2 (it wasn't in the ini), then we run Win3Visuals
			on VGA or greater.
		****/
		/* 350 (EGA) will pass for wNewLook == 1, but not == wNewLook == 2 */
		vsci.fWin3Visuals = wNewLook && !vsci.fMonochrome &&
			(vsci.dypScreen >= 350 - 1 + wNewLook);
		ReleaseDC( NULL, hdc);
		}
#endif /* WIN23 */
#ifdef DEBUG
	/* This should also be very early in initialization!  (i.e., second) */
	ReadDebugStateInfo();
	vdbs.fReports |= GetProfileInt( szApp, SzShared("fReports"), 0);
	Debug(vdbs.fCkStruct ? CkStruct() : 0);
#endif /* DEBUG */

	Debug( CkTlbx (fTrue) ); /* record checksums for toolbox */

#ifdef DEBUG
	if (vwWinVersion < 0x0300)
		{
		WORD FAR * lpw;
		BYTE FAR * lpb;

		lpw = (WORD FAR *) 0xe;
		lpb = MAKELONG(0x100, *lpw);
		/* This code is taken from debug.c to avoid installing the
		int 3 handler when running under the debugger */
		if (*lpb++ != 'S' || *lpb++ != 'E' || *lpb++ != 'G' ||
				*lpb++ != 'D' || *lpb++ != 'E' ||
				*lpb++ != 'B' || *lpb++ != 'U' || *lpb != 'G')
			{
			vfInt3Handler = fTrue;
			InstallInt3Handler();
			}
		}
#endif /* DEBUG */

		{
		extern BOOL fFillBlock;
		extern WORD wFillBlock;
		extern BOOL fShakeHeap, fCheckHeap;
		extern int FAR pascal FFailLmemOpus();
		extern PFN pfnAssertVerify;
		extern int AssertForSdm();
		extern BYTE fCoverActive, fCoverWasActive;

#ifdef DEBUG
	/* set debug options */
		fFillBlock = !vdbs.fNoFillBlock;
		fShakeHeap = vdbs.fShakeHeap;
		fCheckHeap = vdbs.fCkHeap;
		lpfnFailLmemFilter = FFailLmemOpus;
	/* Mathpack for EL */
		fForce8087Fail = vdbs.fFail8087;
		pfnAssertVerify = AssertForSdm;
		fCoverActive = fCoverWasActive && vdbs.fCoverActive;
#endif /* DEBUG */
#ifdef HYBRID
	/* Turn off automatic filling of stack frame variables by DWINTER */
		fFillBlock = GetProfileInt( szApp, SzShared("HybridfFillBlock"), fFalse);
		wFillBlock = GetProfileInt( szApp, SzShared("HybridwFillBlock"), 0xCCCC);
#endif /* HYBRID */
		}

/* parse command line into chunks */
		{
		CHAR *pch, *pchT;
#ifdef DEBUG
		BOOL fReportFailSettings = fFalse;
#endif /* DEBUG */

		CchCopyLpszCchMax( lpszCmdLine, (LPSTR)rgchCmdLine, ichMaxCmdLine );
		rgchCmdLine [ichMaxCmdLine] = 0;
		ipchArgMac = 0;
		pch = rgchCmdLine;

#ifdef PCJ
		CommSz(SzShared("Command line:\r\n"));
		CommSz(rgchCmdLine);
		CommSz(SzShared("\r\n"));
#endif /* PCJ */

/* if msdos is not loaded, we have to skip our name on cmd line */
		if (vfSingleApp)
			{
			while (*pch == ' ')
				pch++;
			while (*pch && *pch != ' ')
				pch++;
			}

		while (fTrue)
			{
			while (*pch == ' ' ||  *pch == '\t')
				pch++;
			if (*pch == '\0')
				break;
			if (ipchArgMac >= ipchArgMax)
				break;
			rgpchArg [ipchArgMac++] = pch;
			while (!(*pch == ' ' ||  *pch == '\t' || *pch == '\0'))
				pch++;
			if (*pch != '\0')
				*pch++ = '\0';
/* check for command line flags(if we find one, don't include in rgpchArg) */
			pchT = rgpchArg [ipchArgMac-1];
			if (*pchT == '-' || *pchT == '/')
				{
				switch (*++pchT)
					{
				default:
				/* other options, leave in */
					ipchArgMac++;
					break;
				case chCmdLineNoFile1:
				case chCmdLineNoFile2:
					*pfOpenUntitled = fFalse;
					break;
				case chCmdLineTutorial1:
				case chCmdLineTutorial2:
					*pfTutorial = fTrue;
					break;
#ifdef PROFILE
				case 'p': 
				case 'P':
					vpfi = 0;
					while (FDigit(*(pchT+1)))
						vpfi = (10*vpfi) + *(++pchT) - '0';
					break;
#endif /* PROFILE */

#ifdef BATCH
				case 'b': 
				case 'B':  /* batch processing */
				/* during a batch process, we don't want asserts coming up */
					vfBatchMode = fTrue;
					CchCopySz(SzShared("\r\n* * * * * * * * *\r\n"), szBatchString);
					SzSzAppend(szBatchString, ++pchT);
					SzSzAppend(szBatchString,SzShared("\r\n* * * * * * * * *\r\n"));
					break;

				case 'i': 
				case 'I':  /* Do not exit upon idle in batch mode */
					vfBatchIdle = fTrue;
					break;
#endif /* BATCH */

#ifdef DEBUG
				case 'f': 
				case 'F':  /* initialization failure switch */
						/*  format:
						/fms<num>  -memory succeed
						/fmf<num>  -memory fail
						/fws<num>  -windows succeed
						/fwf<num>  -windows fail
						*/
						{
						int *pw;
						fReportFailSettings = fTrue;
						switch (*++pchT)
							{
						case 'm': 
						case 'M':
							pw = &vdbs.cLmemSucceed;
							break;
						case 'w': 
						case 'W':
							pw = &vdbs.cWinSucceed;
							break;
						default:
							goto LBogus;
							}
						switch (*++pchT)
							{
						case 's': 
						case 'S':
							break;
						case 'f': 
						case 'F':
							pw++;
							break;
						default:
							goto LBogus;
							}
						*pw = 0;
						while (FDigit(*++pchT))
							*pw = (*pw * 10) + (*pchT - '0');
LBogus:
						break;
						}

				case 'r': 
				case 'R':
					vchRTFTest = 'r';
					break;
				case 'd': 
				case 'D':
					vchRTFTest = 'd';
					break;
				case 'c': 
				case 'C':
					vchRTFTest = 'c';
					break;
#endif
					}
				ipchArgMac--;
				}
			}

		*pipchArgMac = ipchArgMac;

#ifdef DEBUG
		if (fReportFailSettings)
			CommSzRgNum( 
					SzShared("Failure settings (memSuc,memFail,winSuc,winFail): "),
					&vdbs.cLmemSucceed, 4);
#endif /* DEBUG */
		}


#ifdef PROFILE
#ifdef DEBUG
	if (vpfi != -1)
		CommSzNum (SzShared("vpfi="),vpfi);
#endif /* DEBUG */
#endif /* PROFILE */

	Profile( vpfi == pfiInit ? StartProf( 30 ) : 0 );

#ifndef OPUS_X64
	GlobalMemInit(); /* expand GDI's and USER's DS */

/* grow our DS bigger */
	if (!fProtectModeWindows || 
		 CbReallocSb(sbDds, cbMaxSbDds-33, HMEM_MOVEABLE) == 0) 
  	 	{
  	 	uns cbMin = CbSizeSb(sbDds);
  	 	uns cbDesired = (uns)(long)CpMin((long)(uns)cbMin+cbExtraDS,0xfff0L);
  	 	while (cbDesired > cbMin &&
  	 		CbReallocSb(sbDds, cbDesired, HMEM_MOVEABLE) == 0)
  	 	cbDesired -= 0x0200;
  	 	}

/* force DS into low memory */
	if (!fProtectModeWindows)
		{
		GlobalUnlock(hInstance);
		Assert (GlobalFlags(hInstance) & GMEM_DISCARDABLE);
		GlobalWire(hInstance);
		}

/* ask for a moderately large swap area */
	SetSwapAreaSize(100*64);
#endif /* !OPUS_X64 */

#ifdef PCJ
	CommSzNum(SzShared("vfSingleApp = "), vfSingleApp);
	CommSzNum(SzShared("MS-DOS module handle = "),
			GetModuleHandle(SzShared("MSDOS")));
	CommSzLong(SzShared("cb(sbDds) = "), (long)(uns)CbSizeSb(sbDds));
#endif /* PCJ */

	vfMouseExist = GetSystemMetrics( SM_MOUSEPRESENT );

	/* Load the cursors... */
	if (!FInitHandles())
		{
		ReportSz("Win handle init failure");
		goto InzFailed0;
		}

	/* we can't use LongOp yet so put up the hour glass.  don't put up if no
		mouse since it will go in a random place.  LongOp will put it in the
		right place later. */
	if (vfMouseExist)
		SetCursor(vhcHourGlass);

	/* read internationalizable characters/strings from user profile */
	ReadUserProfile(fFalse);

	/* check if we're running under CBT */
	/* this code needs to be in for CBT development - please leave it
		in, even for the ship version, as they may need to look at
		post-ship bug reports, etc. */

	vhwndCBT = FindWindow( (LPSTR) SzShared(szCbtWinDef), (LPSTR) NULL );

	if (vhwndCBT != (HWND) NULL)
		{
		if (!SendMessage(vhwndCBT, WM_CBTINIT, vhInstance, CBT_OpusID))
			vhwndCBT = NULL;
		}

	/* register our window classes */

	if (!FRegisterWnd ())
		{
		ReportSz("Window register failure");
		goto InzFailed0;
		}

	/* register other windows information */

	if (!FRegisterWinInfo ())
		{
		ReportSz("FRegisterWinInfo failed");
		goto InzFailed0;
		}

	/* Now initialize the pointers to far procedures (thunks). */
	if (!FInitFarprocs())
		{
		ReportSz("Far Proc init failure");
		goto InzFailed0;
		}

	/* Set up the windows hook so that we can intercept key message
		going to dialogs. */
	vlppFWHChain = SetWindowsHook(WH_MSGFILTER, lppFWHKey);

		{
#ifndef OPUS_X64
		extern int FAR pascal chkstk();
		GlobalLruOldest(GetCodeHandle((FARPROC)chkstk));
#endif
		}


/* Initialize our fundamental WP structures */
/* if failing, still go to InzFailed0 because heap may not have been created */
	if (!FInitStructs())
		{
		ReportSz("FInitStructs failed");
		goto InzFailed0;
		}

	Debug(InitTrackGdiHandles());

/* initialize file system */
	if (!FInitFn())
		{
		ReportSz("FInitFn failed");
		goto InzFailed;
		}

/*  End of "known memory use" period.  From here on out, anything can fail! */
	Assert(!vmerr.fMemFail);
	Debug(vfAllocGuaranteed = fFalse);

/* initialize document management globals - before opus.ini is read */
	SetBytes(&DMQueryD, 0, sizeof(struct DMQD));
#ifdef OPUS_X64
	SetBytes(&DMFlags, 0, sizeof(struct DMFLAGS));
	SetBytes(&DMQFlags, 0, sizeof(struct DMQFLAGS));
#else
	(int)DMFlags = 0;    /* only works as long as DMFlags is 2 bytes */
	(int)DMQFlags = 0;   /* only works as long as DMQFlags is 2 bytes */
#endif

	SetWindowColors();

/* Must init vpri handles before FInitGlobalDot */
/* Read current printer, port, etc from WIN.INI */
	SetBytes(&vpri, 0, cbPRI);
	FGetPrinterFromProfile();

/* Read the session preferences file (.ini) */
	if (!FReadUserState())
		{
		ReportSz("read user state failed");
		goto InzFailed;
		}

/* Initialize the autosave descriptor from vpref. (open code) */
		{
		extern ASD         asd;
		/* SetBytes(&asd, 0, sizeof(asd)); IE*/
		asd.mscBase = GetTickCount();
		asd.dmscLastPostpone = dmscPostponeDef;
		}

/* Set fundamental constants relating to the screen */
	if (!FInitScreenConstants())
		{
		ReportSz("Screen constants init failure");
		goto InzFailed;
		}

	if (!FCreatePatternBitmaps())
		{
		ReportSz("Pattern Bitmap allocation failure");
		goto InzFailed;
		}

/* Initialize the command name-function binding table and keymap */
	Profile( vpfi == pfiInitCmds ? StartProf( 30 ) : 0 );
	if (!FInitCommands())
		{
		ReportSz("Command init failure");
		goto InzFailed;
		}
	Profile( vpfi == pfiInitCmds ? StopProf() : 0 );

/* Initialize table keymap.  Need to do it up front even before we
   know we have a table in a document, because AdjustCps could
   cause selCur to jump into a table before the keymap had been set
   up, and the heap is frozen during AdjustCp's so we can't do it
   then. */

	if ((hkmpTable = HkmpCreate(cKmeTable, kmfPlain)) == hNil)
		{
		ReportSz("Table keymap allocation failure");
		goto InzFailed;
		}
	AddKeyToKmp(hkmpTable, kcTab, bcmNextCell);
	AddKeyToKmp(hkmpTable, KcShift(kcTab), bcmPrevCell);
	return fTrue;

InzFailed:
	Profile( vpfi == pfiInit ? StopProf() : 0 );
	SetFlm( flmIdle );

    /* CreateHeap is not done until FInitStructs; avoid SetFlm call until
       heap established. bz
    */
InzFailed0:
	EndLongOp(fFalse/*fAll*/);

	/* note: don't use ErrorEid here, things are not set up enough yet */
	ErrorEidStartup(eidFail);
	return fFalse;
}



/* %%Function:FRegisterWnd %%Owner:PETERJ */
STATIC BOOL NEAR FRegisterWnd()
	{   /* Register all of our window classes. Return TRUE on success,
	FALSE on failure.  Failure is fatal. */

	int iwc;
	WNDCLASS wndclass;
	int idcolor;

	/* Note: rgwc is a csconst structure. Don't try to pass a pointer to it or
		loop using a pointer if a call to another segment will take place.
		Consider it to be like quirky static data.
	*/

	for ( iwc = 0; iwc < iwcMax; iwc++ )
		{
		SetBytes( &wndclass, 0, sizeof (WNDCLASS) );

		if (iwc == iwcApp)
			wndclass.hIcon = vhiWord;

	/* WndProcs now must take care of their own cursors - call
			OurSetCursor with preferred cursor on WM_SETCURSOR */

		wndclass.style = rgwc [iwc].style;
		wndclass.cbWndExtra = rgwc [iwc].cbWndExtra;
		wndclass.hInstance = vhInstance;
		wndclass.lpfnWndProc = rgwc [iwc].lpfnWndProc;
#ifdef WIN23
		/* On a VGA or greater, use a LtGray brush. On EGA use a gray brush */
		/* On a CGA we shouldn't have Win3Visuals set */
		if (vsci.fWin3Visuals && (iwc == iwcIconBar || iwc == iwcStatLine || iwc == iwcRulerMark))
			wndclass.hbrBackground = (vsci.dypScreen >= 480 ? vhbrLtGray : vhbrGray);
		else
#endif /* WIN23 */
		if ((idcolor = rgwc [iwc].idBackgroundColor) != idColorNil)
			wndclass.hbrBackground = (HBRUSH)idcolor;
		wndclass.lpszClassName = (LPSTR)rgwc [iwc].szCls;
		if (!RegisterClass( (LPWNDCLASS) &wndclass ))
			return fFalse;
		}
	return fTrue;
}



/* %%Function:FRegisterWinInfo  %%Owner:PETERJ */
STATIC int NEAR FRegisterWinInfo ()
{
	/* Register other windows information */

	/* Register clipboard formats */
	cfRTF = RegisterClipboardFormat( (LPSTR)SzNear(szClipRTF) );
	cfLink = RegisterClipboardFormat( (LPSTR)SzNear(szClipLink) );

	if (GetProfileInt(szApp, SzShared("AskForPrinterPicture"), 1))
		/* some users might not like this format (esp JohnPa) */
		cfPrPic = RegisterClipboardFormat( (LPSTR)SzNear(szClipPrPic) );

	/* ok if cfPrPic == cfNil */
	return (cfRTF != cfNil && cfLink != cfNil);
}



/* Thunk Initialization Descriptor */
typedef struct _tid
	{
	FARPROC * plpfn;
	FARPROC lpfn;
} TID;

csconst TID rgtid [] =
{
			{ &lpFCheckPopupRect,           FCheckPopupRect },
	
		{ &lppFWHKey,                   FWHKey },
	
		{ &lpprocBlinkCaretSEdit,       BlinkCaretSEdit },
	
		{ &lpprocStaticEditWndProc,     StaticEditWndProc },
	
		{ &lpFontSizeEnum,              FontSizeEnum },
	
		{ &lpFontNameEnum,              FontNameEnum },
	
		{ &lpFPrContinue,               FPrContinue },
	
		{ &lpFMFContinue,               FMFContinue },
#ifdef WIN23
		{ &lpfnIconDlgWndProc, IconDlgWndProc	},
#endif /* WIN23 */
	
	{ &lpFBltOutlineSplat,		FBltOutlineSplat }
	};		


#define itidMax (sizeof (rgtid) / sizeof (TID))


/* F  I N I T  F A R P R O C S */
/* This routine initializes all of the far pointer to procedures. */
/* %%Function:FInitFarprocs %%Owner:PETERJ */
int FInitFarprocs()
{
	int itid;

	for (itid = 0; itid < itidMax; ++itid)
		{
		if ((*rgtid[itid].plpfn =
				MakeProcInstance(rgtid[itid].lpfn, vhInstance)) == NULL)
			{
			return fFalse;
			}
		}

	return fTrue;
}


/* determine how much useable conventional memory to require */
csconst int rgcparaReserve[2] [2] = {
			/*  norm    lrg frm */
/* with emm */{ 30*64,   22*64   },
/* no emm */  { 40*64,   30*64   },
};

/* REVIEW - ship */
int vcsbMaxAvailInit = 0; /* for AppInfo */

/* %%Function:FInitStructs %%Owner:PETERJ */
FInitStructs()
{
	int ww, mw;
	struct MWD *pmwd;
	int sbBPS, sbNext;
	SB sb;
	int isb = 0;
	int ibpExtMaxT;
	int cbCacheInfo;
	int cbHash;
	int cbTimeStamps;
	int csbGrab;
	int csbEmmAvail;
	int csbMaxAvail;
	extern int vcparaReserve;
	extern int vfNoCoreLoad;
#ifdef UNUSED
	extern far PASCAL appcache_seg();
#endif /* UNUSED */
	extern far PASCAL clsplc_q();

#ifdef OPUS_X64
	/* Flat-memory replacement for the Win16 EMM/segment-cache setup.  The
	 * original cache topology is retained, but all regions are native heap
	 * allocations rather than selector-indexed segments. */
	vcsbMaxAvailInit = 0;
	vfNoCoreLoad = fTrue;
	vcparaReserve = 0;
	cbMemChunk = 16 * 1024;

	BuildScc(&vsccAbove, 0, 0);
	vfti.fcid.lFcid = vftiDxt.fcid.lFcid = fcidNil;

	vbptbExt.ibpMac = vbptbExt.ibpMax = 24;
	vbptbExt.iibpHashMax = 16;
	vbptbExt.hprgibpHash = (int HUGE *)HpAlloc(
		vbptbExt.iibpHashMax * sizeof(int));
	vbptbExt.hpmpibpbps = (struct BPS HUGE *)HpAlloc(
		vbptbExt.ibpMax * cbBPS);
	vbptbExt.hprgbpExt = (HPRGBPEXT)HpAlloc(
		vbptbExt.ibpMax * cbSector);
	vbptbExt.hpmpispnts = (TS HUGE *)HpAlloc(8 * sizeof(TS));
	if (vbptbExt.hprgibpHash == NULL || vbptbExt.hpmpibpbps == NULL ||
			vbptbExt.hprgbpExt == NULL || vbptbExt.hpmpispnts == NULL)
		return fFalse;
	vbptbExt.tsMruBps = 0;
	vbptbExt.cbBp = cbSector;
	vbptbExt.cbpChunk = vbptbExt.ibpMax;
	vbptbExt.cqbpspn = 3 * 4;
#else

	vrf.fExtendedMemory = GetProfileInt( szApp, SzShared("ExtendedMemory"), 1);
#ifndef NO_DIALOG_HACK
	if (vrf.fExtendedMemory)
		CacheCodeSegment( GetCodeHandle( clsplc_q ), 1);
#ifdef UNUSED
	else
		GlobalDiscard( GetCodeHandle(appcache_seg));
#endif /* UNUSED */
#endif
#ifdef UNUSED
	if (!vrf.fExtendedMemory)
		GlobalDiscard( GetCodeHandle(appcache_seg));
#endif /* UNUSED */


/* see how much memory is available & how much we can use */

	if (fProtectModeWindows)
		{
		/* WIN3 pmode - in order to minimize changes to Opus, we try to map
			pmode win3 onto real mode EMM, then proceed to act like we were
			using EMM.  The EMM strategy of taking almost everything isn't
			too good of an idea for pmode (since EMM does not conflict with
			"conventional memory" under real mode but is does in protect 
			mode) so we have a few heuristics to reduce what we take.
		*/
		long (FAR PASCAL *lpfn)();
		Assert(vwWinVersion >= 0x0300);

		lpfn = GetProcAddress(GetModuleHandle(SzFrame("KERNEL")),
				MAKEINTRESOURCE(idoGetFreeSpace));
		Assert(lpfn != NULL);

		/* available global memory (units of 16K) */
		csbMaxAvail = CpMin((*lpfn)(0)/(16*1024L),0x00007fffL);

		/* random heuristic #1: if it says >= 2Mb, then they may be
		   using virtual memory, we want to ask for less.  drop half of
		   everything over 2Mb (128 pages). */
		if (csbMaxAvail >= 128)
			csbMaxAvail -= ((csbMaxAvail - 128) / 2);

		/* random heuristic #2: act as though 1/3 of available memory 
			was real mode EMM memory available to us. */
		csbMaxAvail /= 3;

		/* random heuristic #3: if result is less than 512K (32 pages)
			use only 3/4s to leave a reasonable amount. */
		if (csbMaxAvail < 32)
			csbMaxAvail = (3*csbMaxAvail)/4;
		}
	else
		csbMaxAvail = max(0,CpageAvailStartEmm());
#ifdef DEBUG
	if (vdbs.fNoEmm)
		csbMaxAvail = 0;
#endif /* DEBUG */

	vcsbMaxAvailInit = csbMaxAvail;

	if (csbMaxAvail >= csbEmmMin)
		{
		int cKEmm = GetProfileInt(szApp, SzShared("EmmLimit"), -1);

		if (cKEmm >= 0)
/* take what the user specified */
			csbEmmAvail = min(cKEmm/16, csbMaxAvail);

/* by default take a reasonable amount */
		else
			{
			if (csbMaxAvail < csbEmmReserve)
				csbEmmAvail = csbMaxAvail;
			else  if (csbMaxAvail < 2*csbEmmReserve)
				csbEmmAvail = csbEmmReserve;
			else
				csbEmmAvail = csbMaxAvail - csbEmmReserve;
			}

		csbEmmAvail = min(csbEmmAvail, csbCacheMax+csbStructsMax);
		}
	else
		csbEmmAvail = 0;

/* enable use of EMM, if available. */
	if (fProtectModeWindows)
		{
		cbMemChunk = (16*1024)-32; /* simulate EMM values */
		smtMemory = smtProtect;
		}
	else  if (csbEmmAvail > 0)
		{
		cbMemChunk = CbInitEmm(1, 0, csbMaxAvail-csbEmmAvail);
		smtMemory = smtLIM;
		}
	else
		{
		cbMemChunk = 4*1024;
		smtMemory = smtReal;
		}

#ifdef SHOWEMM
	if (smtMemory == smtLIM)
		CommSzLong(SzShared("initial CbFreeEmm = "), CbFreeEmm());
#endif /* SHOWEMM */

	/* assert: cbMemChunk == 4*1024 or 15.5K < cbMemChunk < 16K */
	Assert(cbMemChunk == 4*1024 || (uns)(cbMemChunk - ((16*1024)-511)) < 510);

#ifdef DEBUG
	if (vfLargeFrameEMS && csbEmmAvail < 16)
		/* kernel is using all our memory!!!! */
		{
		if (csbEmmAvail == 0)
			ReportSz("Kernel took all of EMM!");
		else  if (csbEmmAvail < 8)
			ReportSz("Kernel left less than 128K of EMM!");
		else
			ReportSz("Kernel left less than 256K of EMM!");
		}
#endif /* DEBUG */


/* grab some sbs for our use if needed */
	/* subtract 3 here for cache management sb, and initial heap sb, cmdtbl */
	if (smtMemory == smtLIM && 
			(csbGrab = min((csbEmmAvail/2)-2, csbGrabMax)) > 0)
		{
		for (; isb < csbGrab; isb++)
			{
			sb = SbScanNext(fFalse);
			if (!CbAllocSb(sb, cbMemChunk, hmemLmemHeap))
				{
				ReportSz("Grabbing Memory failed!");
				break;
				}
			vrgsbReserve[isb] = sb;
			}
		}

	for (; isb < csbGrabMax; isb++)
		vrgsbReserve[isb] = sbNil;

/* initialize heap */
	CreateHeap(sbDds);


#ifdef NOTUSED  /* bobz (bz) kill win heap - changed multiline edits to be fedts  */
	if (!FCreateWindowsHeap(sbDds, cbWindowsHeap))
		{
		ReportSz("cant create windows heap");
		return(fFalse);
		}
#endif /* NOTUSED */

/* initialize display line buffer and scc's */
	BuildScc(&vsccAbove, 0, 0);

/* initialize font stuff */
/* rgfce = { {0,0,..}, {0,0,..},... } */
	vfti.fcid.lFcid = vftiDxt.fcid.lFcid = fcidNil;

	/* create an sb for non-cache far heap objects */
	sbNext = SbScanNext (fFalse);
	if (sbNext == sbNil)
		goto LBpFail;
	if (!CbAllocSb( sbNext, cbLmemHeap, hmemLmemHeap))
		goto LBpFail;

	CreateHeap (sbNext);
	Debug (vdbs.fCkHeap ? CheckHeap (sbNext) : 0);

		{
		struct SBHI sbhi;
		extern struct PLSBHI **vhplsbhi;
		FreePpv(sbNext, PpvAllocCb(sbNext, 0)); /* to get handles allocated */
		SetBytes(&sbhi, 0, cbSBHI);
		sbhi.sb = sbNext;
		sbhi.fHasHeap = fTrue;
		sbhi.fHasFixed = fTrue;
		vhplsbhi = HplInit(cbSBHI, 1);
		if (vhplsbhi == hNil || !FInsertInPl(vhplsbhi, 0, &sbhi))
			goto LBpFail;

		Debug (vdbs.fCkHeap ? CheckHeap (sbNext) : 0);
		}

/* initialize bp's */
/* allocate an sb for the mpibpbps, the hash table, and the mpispnts */
	sbBPS = SbScanNext (fFalse);
	Assert (sbBPS != sbNil);
	if (sbBPS == sbNil)
		goto LBpFail;

/* determine size of file cache */
#ifdef DEBUG
	if (vdbs.fSmallFileCache)
		ibpExtMaxT = ibpMaxNoEmm;
	else
#endif /* DEBUG */
		if (csbEmmAvail > 2*csbStructsMax)
			ibpExtMaxT = (csbEmmAvail-csbStructsMax)*cbpChunkWEmm;
		else
			ibpExtMaxT = max(ibpMaxNoEmm, (csbEmmAvail/2)*cbpChunkWEmm);

	if (ibpExtMaxT > csbCacheMax * cbpChunkWEmm)
		/* safety, make sure it can't get too big */
		{
		Assert(fFalse);
		ibpExtMaxT = csbCacheMax * cbpChunkWEmm;
		}

	cbCacheInfo = ibpExtMaxT * cbBPS;
#ifdef DEBUG
	if (csbEmmAvail && !vdbs.fSmallFileCache)
#else
		if (csbEmmAvail)
#endif
			{
			cbCacheInfo += (cbHash=iibpHashMaxEmm*sizeof(int)) /* for hash table */
					+ (cbTimeStamps = 57 * sizeof(int)); /* for span time stamps */
			}
		else
			{
			cbCacheInfo += (cbHash=iibpHashMaxNoEmm*sizeof(int)) /* for hash table*/
					+ (cbTimeStamps = 8 * sizeof(int)); /* for span time stamps */
			}

	Assert (cbCacheInfo < cbMemChunk);

	if (!CbAllocSb( sbBPS, cbCacheInfo, HMEM_MOVEABLE | HMEM_EMM))
		{
LBpFail:
		ReportSz("Page Table init failure");
		return fFalse;
		}

	vbptbExt.ibpMac = ibpExtMaxT;
	vbptbExt.ibpMax = ibpExtMaxT;
	vbptbExt.iibpHashMax = cbHash / sizeof(int);

	/* allocate space for cache hash table and page descriptors */
	vbptbExt.hpmpispnts = HpOfSbIb(sbBPS, 0);
	vbptbExt.hprgibpHash = HpOfSbIb(sbBPS, cbTimeStamps);
	vbptbExt.hpmpibpbps = HpOfSbIb(sbBPS, cbTimeStamps + cbHash);

	vbptbExt.tsMruBps = 0;
	SetBytes(LpOfHp(vbptbExt.hprgibpHash), 0, cbTimeStamps);
	vbptbExt.cbBp = cbSector;
	vbptbExt.cqbpspn = (csbEmmAvail ?
			(ibpExtMaxT > 57 * 31 / 4 ? 31 * 4 : 31) : 
	3 * 4);

		{
		uns cbpRemain = vbptbExt.ibpMax;

		vbptbExt.cbpChunk = (smtMemory != smtReal ? cbpChunkWEmm : cbpChunkNoEmm);
		vbptbExt.hprgbpExt = (CHAR (huge *)[])HpOfSbIb( sbNext = sbBPS + 1, 0 );
		while (cbpRemain > 0)
			{
			uns cbp = umin(vbptbExt.cbpChunk, cbpRemain);

			if (sbNext == sbMac ||
					!CbAllocSb(sbNext++, cbp * cbSector, HMEM_MOVEABLE | HMEM_EMM))
				{
				ReportSz("External cache allocation failure");
				return fFalse;
				}
			cbpRemain -= cbp;
			}
	/* shrink to just what we need */
		FInitSegTable(sbNext+1 /* sbMacReq */);
		ResetSbCur();
		}

	vfNoCoreLoad = !FFromProfile(fTrue, ipstCoreLoad);
	vcparaReserve = fProtectModeWindows ? 5*64 : 
			rgcparaReserve[smtMemory!=smtLIM][vfLargeFrameEMS];

#ifdef SHOWEMM
	CommSzNum(SzShared("csbEmmAvail: "), csbEmmAvail);
	CommSzNum(SzShared("csbGrab: "), csbGrab);
	CommSzNum(SzShared("ibpExtMaxT: "), ibpExtMaxT);
	CommSzNum(SzShared("sbBPS: "), sbBPS);
	CommSzNum(SzShared("cb hpmpibpbps: "), cbCacheInfo - cbHash - cbTimeStamps);
	CommSzNum(SzShared("cb hprgibpHash: "), cbHash);
	CommSzNum(SzShared("cb hpmpispnts: "), cbTimeStamps);
	CommSzNum(SzShared("vbptbExt.cbpChunk: "), vbptbExt.cbpChunk);
	CommSzNum(SzShared("vbptbExt.cqbpspn: "), vbptbExt.cqbpspn);
	CommSzNum(SzShared("vfNoCoreLoad: "), vfNoCoreLoad);
	CommSzNum(SzShared("vcparaReserve: "), vcparaReserve);
#endif /* SHOWEMM */

#ifdef DEBUG
	if (vdbs.fReportHeap)
		ReportHeapSz(SzShared("initial"),0);
#endif /* DEBUG */
#endif /* OPUS_X64 */

/* NOTE: we know none of this will fail, see comment above */

/* initialize memory error state */
	vmerr.hrgwEmerg1 = HAllocateCw(cwEmerg1);
	vmerr.hrgwEmerg2 = HAllocateCw(cwEmerg2);
	vmerr.hrgwEmerg3 = HAllocateCw(cwEmerg3);
	Assert(vmerr.hrgwEmerg1);
	Assert(vmerr.hrgwEmerg2);
	Assert(vmerr.hrgwEmerg3);
/*	vmerr.fSentCBTMemErr = fFalse; IE - don't clear in TopOfMainLoop! */

/* initialize wwTemp */
	AssertDo(IAllocCls(clsWWD, cwWWD) == wwTemp);
	AssertDo(IAllocCls(clsMWD, cwMWD) == mwTemp);
	PwwdWw(wwTemp)->mw = mwTemp;

/* initialize wwPreview */
	AssertDo(IAllocCls(clsWWD, cwWWD) == wwPreview);
	AssertDo(IAllocCls(clsMWD, cwMWD) == mwPreview);
	PwwdWw(wwPreview)->mw = mwPreview;
	pmwd = PmwdMw(mwPreview);
	pmwd->fActive = fFalse;
	pmwd->wwUpper = pmwd->wwActive = wwPreview;

/* initialize wwLayout */
	AssertDo(IAllocCls(clsWWD, cwWWD) == wwLayout);
	AssertDo(IAllocCls(clsMWD, cwMWD) == mwLayout);
	PwwdWw(wwLayout)->mw = mwLayout;

/* Initialize wwSccAbove */
	InitStructScc2();

/* initialize undo and again */
	vuab.uac = uacNil;
	vuab.bcm = bcmNil;
	vaab.bcm = bcmNil;

/* initialize format */
	InvalFli();
	vbchrMax = bchrMaxInit;
	vhgrpchr = HAllocateCw(CwFromCch(vbchrMax + cbCHRE));

/* initialize print set-up */
	SetWords(&vprsu, 0, cwPRSU);
	vprsu.fShowResults = TRUE;
	vpvs.fLoadPrvwFon = fTrue;

/* initialize layout */
	vhplcfrl = HplcInit(sizeof(struct FRL), 1, cp0, fTrue /* ext rgFoo */);
	vfls.hplclnh = HplcInit(sizeof(struct LNH), 1, cp0, fTrue /* ext rgFoo */);

/* initialize hash table */
	SetWords(LpOfHp(&vbptbExt.hprgibpHash[0]), ibpNil, vbptbExt.iibpHashMax);

/* initialize internal page state descriptors */
	InitHpbps(vbptbExt.hpmpibpbps, vbptbExt.ibpMax);

/* initialize undo (open code interesting parts of SetUndoNil) */
	vuab.bcm = bcmNil;
	vuab.uac = uacNil;
	vaab.bcm = bcmNil;
	vaab.doc = docNil;

/* initialize selCur stuff for ruler and ribbon */
	selCur.fUpdateChp = fTrue;
	selCur.fUpdateChpGray = fTrue;
	selCur.fUpdatePap = fTrue;
	selCur.fUpdateStatLine = fTrue;

/* initialize fonts */
		/* Set up master font table with ftcMinUser entries
			for the default fonts */

		{
		CHAR rgbFfn [cbFfnLast];
#define pffn	((struct FFN *) rgbFfn)

		vhsttbFont = HsttbInit(30, fFalse/*fExt*/);
		Assert( vhsttbFont != NULL );

	/*  Tms Rmn */
		pffn->cbFfnM1 = CbFfnFromCchSzFfn(
				CchCopySz( SzSharedKey("Tms Rmn",TmsRmn),
				((struct FFN *)rgbFfn)->szFfn ) /* +1 */) /* -1 */;
		pffn->ffid = FF_ROMAN;
		pffn->prq = VARIABLE_PITCH;
		ChsPffn(pffn) = ANSI_CHARSET;
		AssertDo( IbstAddStToSttb( vhsttbFont, rgbFfn ) == ibstFontDefault );

	/*  Symbol */
		pffn->cbFfnM1 = CbFfnFromCchSzFfn(
				CchCopySz(SzSharedKey("Symbol",Symbol), 
				((struct FFN *) rgbFfn)->szFfn) /* + 1 */) /* -1 */;
		pffn->ffid = FF_DECORATIVE;
		Assert( DEFAULT_PITCH == 0 );
	/* 	pffn->prq = DEFAULT_PITCH;	IE */
		ChsPffn(pffn) = ANSI_CHARSET;	/* weirdly,this is correct for
			Postscript; other printers 
			will have to tell us what they do
			(enumeration will override these
			settings if necessary) */
		AssertDo(IbstAddStToSttb(vhsttbFont, rgbFfn) == ibstFontDefault + 1);

	/*  Helv */
		pffn->cbFfnM1 = CbFfnFromCchSzFfn(
				CchCopySz( SzSharedKey("Helv",Helv),
				((struct FFN *)rgbFfn)->szFfn )/* +1 */) /* -1 */;
		pffn->ffid = FF_SWISS;
		pffn->prq = VARIABLE_PITCH;
		ChsPffn(pffn) = ANSI_CHARSET;
		AssertDo(IbstAddStToSttb(vhsttbFont, rgbFfn) == ibstFontDefault + 2);

	/*  Courier */
		pffn->cbFfnM1 = CbFfnFromCchSzFfn(
				CchCopySz( SzSharedKey("Courier",Courier),
				((struct FFN *)rgbFfn)->szFfn )/* +1 */) /* -1 */;
		pffn->ffid = FF_MODERN;
		pffn->prq = FIXED_PITCH;
		ChsPffn(pffn) = ANSI_CHARSET;
		Assert( ibstCourier == ibstFontDefault + 3 );
		AssertDo(IbstAddStToSttb(vhsttbFont, rgbFfn) == ibstFontDefault + 3);


#undef pffn
		}

/* initialize window cache */
	vhsttbWnd = HsttbInit(5, fFalse/*fExt*/);
	Assert(vhsttbWnd != hNil);

	return fTrue;
}


/* %%Function:InitHpbps %%Owner:PETERJ */
InitHpbps(hpbps, ibpMax)
struct BPS HUGE *hpbps;
int ibpMax;
{
	struct BPS far *lpbps;

#ifdef SLOW
	struct BPS HUGE *hpbspMac = hpbps + ibpMax;

	for (; hpbps < hpbpsMac; hpbps++)
		{
		hpbps->fn = fnNil;
		hpbps->fDirty = fFalse;
		hpbps->ts = 0;
		hpbps->ibpHashNext = ibpNil;
		}
#endif /* SLOW */
	Assert(fnNil == 0);
	SetWords((lpbps = LpOfHp(hpbps)), 0,
			ibpMax * (sizeof(struct BPS)/sizeof(int)));
		{{  /* NATIVE for small loop in InitHpbps to init ibpHashNext's */
		for (; ibpMax > 0; lpbps++, ibpMax--)
			lpbps->ibpHashNext = ibpNil;
		}}
}

#ifdef DEBUG
BOOL vfNovellNetInited = fFalse;
#endif /* DEBUG */

/* F  I N I T  F N */
/* %%Function:FInitFn %%Owner:PETERJ */
FInitFn()
{
	struct PLCBTE **hplcbteChp, **hplcbtePap;
	struct FCB *pfcb;
	CHAR st [ichMaxFile];

	vmerr.fNovellNet = FFromProfile(fFalse, ipstNovellNet);
	vfAs400 = FFromProfile(fFalse, ipstAs400);
	Debug(vfNovellNetInited = fTrue);

	UpdateStDOSPath();              /* Store away current path */

	AssertDo(IAllocCls(clsFCB,cwFCB) == fnScratch);
	hplcbteChp = HplcInit(cbBTE, 0, (CP) 0, fTrue /* ext rgFoo */);
	hplcbtePap = HplcInit(cbBTE, 0, (CP) 0, fTrue /* ext rgFoo */);
	/* See comment re init mem use above */
	Assert(hplcbteChp != hNil && hplcbtePap != hNil);

	/* tells the file system that we have not yet tried to create
		scratch file */
	vmerr.fPostponeScratch = fTrue;
	vfScratchFile = fTrue;  /* we can pretend to write stuff to it */
	vmerr.fScratchFileInit = fTrue; /* ditto */

	pfcb = PfcbFn(fnScratch);
	SetBytes( pfcb, 0, sizeof( struct FCB ));
	pfcb->hplcbteChp = hplcbteChp;
	pfcb->hplcbtePap = hplcbtePap;
	pfcb->osfn = osfnNil;
	pfcb->fTemp = fTrue;
	pfcb->nFib = nFibCurrent;
	/* this is a lie which allows FetchCp and CachePara to know that
		the scratch file does have PLCBTEs that can be used to find
		character and paragraph formatting. This works because we
		create the FCB ourselves instead of using FnOpenSt and because
		we will not be issuing a SAVE command for the scratch file. */
	pfcb->fHasFib = fTrue;
/* length avoids heap movement when scratch file gets actually created */
	st [0] = ichMaxFile;
	FChngSizeHCw( mpfnhfcb[fnScratch], cwFCB + CwFromCch(st[0] - 1), fTrue );
	bltbyte( st, PfcbFn(fnScratch)->stFile, st[0] + 1);
	Assert(!vmerr.fMemFail);/* See comment re init mem use above */

/* the scratch file will start with cbMac = 0. The fkpd's will be set
up so that any insertion will start a new page */
	vfkpdPap.bFreeFirst = 1;
	/* .bFreeLim = 0; .fcFirst = 0 */
	vfkpdChp.bFreeFirst = 1;
	/* .bFreeLim = 0; .fcFirst = 0 */
	vfkpdText.pn = pnNil;

	StandardChp(&vfkpdChp.chp);
	return fTrue;
}


#include "opuscmd2.h"  /* contains sizes for initial tables (from mkcmd) */


/* F  I N I T  C O M M A N D S */
/* Create the command table and base keymap and initialize with the
prebuilt tables generated from opuscmd.cmd */
/* %%Function:FInitCommands %%Owner:PETERJ */
FInitCommands()
{
	extern HPSYT vhpsyt;
	extern KMP ** hkmpBase;
	extern KMP ** hkmpCur;
	extern KMP ** vhkmpUser;
	extern MUD ** vhmudBase;
	extern MUD ** vhmudUser;
	extern struct STTB ** hsttbMenu;

	SYT FAR * lpsyt;
	int FAR *lprgbst;
	HQ hq;
	int imnu, imtm, imtmMac;
	MTM * pmtm;
	MUD * pmud;
	HMENU hmenu;
	CHAR rgch [cchMaxSt];


		{
		extern int vkPlus, vkMinus,  vkStar;
#ifdef INTL
		extern int vkUnderline, vkEquals, vkQuestionmark;
#endif

		extern int vwWinVersion;

#ifndef OPUS_X64
		FARPROC lpfnVkKeyScan;
		HANDLE hKeyboard;
#endif

	/* Get real scan codes for +, -, and * keys (not on keypad) from
		the keyboard driver if it supports VkKeyScan, use the
		suggestions from the Windows manual otherwise. */
#ifndef INTL
#ifdef OPUS_X64
		/* Win16 exposed VkKeyScan through KEYBOARD ordinal 129.  Win64 has no
		 * KEYBOARD module; use the equivalent user32 entry point directly. */
		vkPlus = VkKeyScanA('+') & 0xff;
		vkMinus = VkKeyScanA('-') & 0xff;
		vkStar = VkKeyScanA('*') & 0xff;
#else
		hKeyboard = GetModuleHandle((LPSTR) SzShared("KEYBOARD"));
		Assert(hKeyboard != NULL);
		lpfnVkKeyScan = vwWinVersion >= 0x0210 ? GetProcAddress(hKeyboard,
				MAKEINTRESOURCE(idoVkKeyScan)) : NULL;
		if (lpfnVkKeyScan != NULL)
			{
			vkPlus = (*lpfnVkKeyScan)('+') & 0xff;
			vkMinus = (*lpfnVkKeyScan)('-') & 0xff;
			vkStar = (*lpfnVkKeyScan)('*') & 0xff;
			}
		else
			{
		/* Use values suggested in Windows manual */
			vkPlus = 0xbb;
			vkMinus = 0xbd;
			vkStar = '8';
			}
#endif /* OPUS_X64 */
#else /* INTL */
#ifndef OPUS_X64
		hKeyboard = GetModuleHandle((LPSTR) SzShared("KEYBOARD"));
		Assert(hKeyboard != NULL);
		lpfnVkKeyScan = vwWinVersion >= 0x0210 ? GetProcAddress(hKeyboard,
				MAKEINTRESOURCE(idoVkKeyScan)) : NULL;
#endif
		if (lpfnVkKeyScan != NULL)
			{
			vkPlus = (*lpfnVkKeyScan)('+');
			vkPlus = ((vkPlus & 0x100) ? (KcShift(vkPlus & 0xff)) : (vkPlus & 0xff));
			vkMinus = (*lpfnVkKeyScan)('-');
			vkMinus = ((vkMinus & 0x100) ? (KcShift(vkMinus & 0xff)) : (vkMinus & 0xff));
			vkStar = (*lpfnVkKeyScan)('*');
			vkStar = ((vkStar & 0x100) ? (KcShift(vkStar & 0xff)) : (vkStar & 0xff));
			vkUnderline = (*lpfnVkKeyScan)('_');
			vkUnderline = ((vkUnderline & 0x100) ? (KcShift(vkUnderline & 0xff)) : (vkUnderline & 0xff));
			vkEquals = (*lpfnVkKeyScan)('=');
			vkEquals = ((vkEquals & 0x100) ? (KcShift(vkEquals & 0xff)) : (vkEquals & 0xff));
			vkQuestionmark = (*lpfnVkKeyScan)('?');
			vkQuestionmark = ((vkQuestionmark & 0x100) ? (KcShift(vkQuestionmark & 0xff)) : (vkQuestionmark & 0xff));
			}
		else
			{
			vkPlus = vkPlusDef;
			vkMinus = vkMinusDef;
			vkStar = vkStarDef;
			vkUnderline = vkUnderlineDef;
			vkEquals = vkEqualsDef;
			vkQuestionmark = vkQuestionmarkDef;
			}
#endif /* INTL */
		}

	/* Allocate menu string table */
	Assert(cwsttbMenuBase == cwSTTBBase);
	if ((hsttbMenu = HAllocateCb(cbSTTB)) == 0)
		return fFalse;

	Assert(offset(STTB, hqrgbst) == (cwsttbMenuBase*sizeof(int)));
	if ((hq = (*hsttbMenu)->hqrgbst = HqAllocLcb((long)cbsttbMenuRgbst))
			== hqNil)
		return fFalse;

	/* Allocate menu base */
	if ((vhmudBase = HAllocateCw(cwmudBase)) == 0)
		return fFalse;

	/* Allocate keymap */
	/* open code HkmpNew */
	/* don't have to initialize *hkmp, will be done in MoveCmds */
	if ((hkmpBase = HAllocateCw(cwKMP + ckmeInit * cwKME)) == hNil)
		return fFalse;

	Assert(hkmpCur == hNil);
	hkmpCur = hkmpBase;

	/* Allocate command (symbol) table */
	if ((vhpsyt = HpOfSbIb(SbAllocEmmCb(cbsytInit), 0)) == hpNil)
		return fFalse;

	lpsyt = LpLockHp(vhpsyt);
	lprgbst = LpLockHq(hq);

	if (lpsyt == NULL || lprgbst == NULL)
		{
		ReportSz("cannot lock handles");
		return fFalse;
		}

	/* Fill command table and keymap with initial functions */
	MoveCmds(lpsyt, (KMP FAR *) *hkmpBase, (LPSTR) *vhmudBase,
			(LPSTR) *hsttbMenu, lprgbst);

#ifdef OPUS_X64
	if (!OpusValidateSttb((void **)hsttbMenu))
		{
		ReportSz("Generated command menu STTB is invalid");
		return fFalse;
		}
#endif

	UnlockHp(vhpsyt);
	UnlockHq(hq);

	Assert((*hsttbMenu)->fExternal && (*hsttbMenu)->hqrgbst == hq);

	(*hkmpBase)->grpf = kmfTranslate | kmfBeep;

	/* Create Standard Menu Bar */
	if ((vhMenuLongFull = CreateMenu()) == NULL)
		return fFalse;

	pmud = *vhmudBase;
	imnu = -1;
	imtmMac = pmud->imtmMac;
	for (pmtm = &pmud->rgmtm[0], imtm = 0; imtm < imtmMac; ++imtm, ++pmtm)
		{
		extern int vbsySepCur;

		if (imnu != pmtm->imnu)
			{
			CHAR * sz;

			/* add menu to menubar */
			imnu = pmtm->imnu;
			hmenu = CreateMenu();
			GetSzFromSttb(hsttbMenu, imnu, rgch);
			sz = &rgch[0];
			if (!ChangeMenu(vhMenuLongFull, 0, (LPSTR) sz, hmenu,
					MF_POPUP | MF_APPEND))
				return fFalse;
			}
		/* FUTURE: mkcmd could do this for us */
		else  if ((int) pmtm->bsy == bcmSeparator)
			pmtm->bsy = vbsySepCur++;
		}

	return fTrue;
}


/* array of actual y-size of ribbon bitmaps for each group  */
/* must be sorted in decreasing order */
#ifdef WIN23
/****
This set is used for Win 3 visuals under Win 3
****/
csconst int mpdbmgdypLH3 [] = { 
	26, 20, 12 };
/****
This set is used for Win 2 visuals under Win 3. We need a seperate
set because the value used to search the list is calc'd using the
Win 3 sysfont, but we want an index as if it was a Win 2 font. We can't
use the Win2 font size, because the index we find here is used to set
the fake font sizes below (circular dependency). 
****/
csconst int mpdbmgdypLH23 [] = { 
	26, 21, 20, 12, 8 };
/****
This is the set used for Win 2 visuals under Win 2. The same as in 1.0
****/
csconst int mpdbmgdypLH2 [] = { 
	26, 20, 19, 11, 8 };
#else
csconst int mpdbmgdypLH [] = { 
	26, 20, 19, 11, 8 };
#endif /* WIN23 */


/* D I S P L A Y - D E P E N D E N T   V A L U E S */

/* Table of twip constants that get converted to screen pixel values in vsci */
/* This table must match the corresponding one in screen.h */
/* It's called rgdxa but has a mix of xa, dxa, ya, dya */

/* Note this is a csconst structure and must be treated specially */

csconst int rgdxaConvert [] = {  
	dxaMinScroll, xaSelBar,
			xaLeftMinRaw, xaRightMaxRaw,  dxaGrayOutside,
			dyaMinAveLine, dyaMacAveLine, dyaMinWwInit,
			yaSubSuper,
			dyaWwMin, dyaPastPage, dyaPageReveal,
			dyaGrayOutside };


#define cchPatLast   10     /* largest allowable repeat interval in pattern */

#define cPatVert    1
/* note we have now 8 pixels of gray, 8 of black */
csconst CHAR rgchPatVert[] = { 
	8, 0x00, 0x00, 0xFF, 0x00,   /* Gray, Black */
	0x00, 0x00, 0xFF, 0x00
};


#define cPatHorz    3
csconst CHAR rgchPatHorz[] = { 
	1, 0x55,                  /* Gray */
	3, 0x6d, 0xB6, 0xdb,      /* Light Gray */
	1, 0x00                   /* Black */
};

#ifdef WIN23
#define cbPatDither 16
csconst CHAR rgchPatDither[] = {
	0xAA,	0xAA,		/* 10101010 */	/* each scan line is rounded to a word */
	0x55,	0x55,		/* 01010101 */
	0xAA,	0xAA,		/* 10101010 */
	0x55,	0x55,		/* 01010101 */
	0xAA,	0xAA,		/* 10101010 */
	0x55,	0x55,		/* 01010101 */
	0xAA,	0xAA,		/* 10101010 */
	0x55,	0x55		/* 01010101 */
};


#endif /* WIN23 */
/* F  C r e a t e  P a t t e r n  B i t m a p s */
/* Create monochrome bitmaps to be used as an alternative to color
	pattern brushes for drawing vertical and horizontal lines.

	Input: data tables above

	Output: vhbmPatVert - a tall, thin bitmap containing vertical line
							patterns, each 2 pixels wide
			vhbmPatHorz - a short, wide bitmap containing horizontal
							line patterns, each vsci.dypBorder high
*/

/* %%Function:FCreatePatternBitmaps %%Owner:bryanl */
FCreatePatternBitmaps()
{
	extern HBITMAP vhbmPatVert, vhbmPatHorz;

	CHAR rgchPat [cchPatLast];
	int c;
	CHAR *pch, *pb;
	int ichPat, ichPatNext;
	CHAR **hrgbBits;
	int f = fFalse;
	int cbHorz, cbVert, cbAlloc;

	Assert( dxpHbmHorz % 16 == 0 && dxpHbmHorz % 3 == 0 && dypHbmVert % 8 == 0 );

	cbHorz = (dxpHbmHorz / 8) * vsci.dypBorder;
	/* 8 byte repeating pattern handled differently */
	/*   cbVert = 8 * (dypHbmVert / 8) * (2);  below equivalent to this bz */
	cbVert = (dypHbmVert) * (2);
	cbAlloc = max( cPatHorz * cbHorz, cPatVert * cbVert);
#ifdef WIN23
	cbAlloc = max( cbAlloc, cbPatDither);
#endif /* WIN23 */
	if ((hrgbBits = HAllocateCw( CwFromCch( cbAlloc ))) == hNil)
		return fFalse;

/* Build bits and create bitmap for horizontal patterns */

	for ( c = cPatHorz, pb = *hrgbBits, ichPat = 0; c--; )
		{
		int cchPat = rgchPatHorz [ichPat++];

		Assert( cchPat <= cchPatLast );
		ichPatNext = ichPat + cchPat;
		for ( pch = rgchPat; ichPat < ichPatNext; ichPat++ )
			*pch++ = rgchPatHorz [ichPat];

		FillBytePattern( pb, rgchPat, cchPat, cbHorz );
		pb += cbHorz;
		}

	if ((vhbmPatHorz = CreateBitmap( dxpHbmHorz, cPatHorz * vsci.dypBorder,
			1, 1, (LPSTR)*hrgbBits)) == NULL)
		{
		goto LRet;
		}
	LogGdiHandle(vhbmPatHorz, 1022);

/* Build bits and create bitmap for vertical patterns */

	for ( c = cPatVert, pb = *hrgbBits, ichPat = 0; c--; )
		{
		int cchPat = rgchPatVert [ichPat++];

		Assert( cchPat <= cchPatLast );
		ichPatNext = ichPat + cchPat;
		for ( pch = rgchPat; ichPat < ichPatNext; ichPat++ )
			*pch++ = rgchPatVert [ichPat];

		FillBytePattern( pb, rgchPat, cchPat, cbVert );
		pb += cbVert;
		}

#ifdef DBLDBMP
		{
		int cb = 8 * 2 * dypHbmVert / 8;

		CommSzRgNum(SzShared("PatVert before build bitmap: "),
				*hrgbBits, cb / 2);

		}
#endif

	if ((vhbmPatVert = CreateBitmap( 16, dypHbmVert,
			1, 1, (LPSTR)*hrgbBits)) == NULL)
		{
		UnlogGdiHandle(vhbmPatHorz, 1022);
		DeleteObject( vhbmPatHorz );
		goto LRet;
		}
	LogGdiHandle(vhbmPatVert, 1021);

#ifdef DBLDBMP
		{
		long lcb = 2 * dypHbmVert ;
		CHAR rgchx[2 * dypHbmVert];
		BITMAP bm;

		GetObject( vhbmPatVert, sizeof( BITMAP ), (LPSTR)&bm );
		CommSzRgNum(SzShared("PatVert struct bitmap: "), &bm,
				sizeof(BITMAP)/2);
		GetBitmapBits( vhbmPatVert, lcb,
				(LPSTR)rgchx );
		CommSzNum(SzShared("PatVert lcb: "), (int)lcb);
		CommSzRgNum(SzShared("PatVert bitmap: "),
				rgchx, (int)lcb >> 1);
		}
#endif
#ifdef WIN23
	if (vsci.fWin3Visuals)
		{
		HBITMAP hbmTmp;
		bltbx(rgchPatDither, (LPSTR)*hrgbBits, cbPatDither);
		if (
			((hbmTmp = CreateBitmap( 8, 8, 1, 1, (LPSTR)*hrgbBits)) == NULL) ||
			((vsci.hbrLitButton = CreatePatternBrush(hbmTmp)) == NULL)
			)
			{
			vsci.hbrLitButton = GetStockObject(WHITE_BRUSH);
			}
		if (hbmTmp)
			DeleteObject(hbmTmp);
		}
#endif /* WIN23 */

	f = fTrue;

LRet:
	Debug( vdbs.fCkHeap ? CkHeap() : 0 ); /* just until I'm sure this works */
	FreeH( hrgbBits );
	return f;
}


typedef struct
{
	HANDLE *ph;
	int id;
} LRD;

csconst LRD rglrdStockObj[] =
{
			{ &vhbrLtGray,      LTGRAY_BRUSH    },
	
		{ &vhbrGray,        GRAY_BRUSH      },
	
		{ &vhbrWhite,       WHITE_BRUSH     },
	
		{ &vhbrBlack,       BLACK_BRUSH     },
	
		{ &vhbrDkGray,      DKGRAY_BRUSH    },

};


#define ilrdStockObjMax (sizeof(rglrdStockObj)/sizeof(LRD))

csconst LRD rglrdSysCur[] =
{
			{ &vhcHourGlass,        IDC_WAIT    },
	
		{ &vhcIBeam,            IDC_IBEAM   },
	
		{ &vhcArrow,            IDC_ARROW   },
	
		{ &vhcArrow,            IDC_ARROW   },

};


#define ilrdSysCurMax (sizeof(rglrdSysCur)/sizeof(LRD))

csconst LRD rglrdRcdsCur[] =
{
			{ &vhcSplit,        ircdsSplit     },
	
		{ &vhcColumn,		ircdsColumn    },
	
		{ &vhcBarCur,       ircdsRight     },

};


#define ilrdRcdsCurMax (sizeof(rglrdRcdsCur)/sizeof(LRD))

csconst LRD rglrdRcdsIco[] =
{
			{ &vhiWord,             ircdsWordIcon  },

};


#define ilrdRcdsIcoMax (sizeof(rglrdRcdsIco)/sizeof(LRD))



/*  F  I N I T  H A N D L E S */
/* %%Function:FInitHandles %%Owner:PETERJ */
FInitHandles()
{
	int ilrd;
	BOOL fRes;

	for (ilrd = 0; ilrd < ilrdStockObjMax; ilrd++)
		if ((*rglrdStockObj[ilrd].ph = GetStockObject(rglrdStockObj[ilrd].id))
				== NULL)
			return fFalse;

	for (ilrd = 0; ilrd < ilrdSysCurMax; ilrd++)
		if ((*rglrdSysCur[ilrd].ph = LoadCursor(NULL, rglrdSysCur[ilrd].id))
				== NULL)
			return fFalse;

	/* we have 32X32 version, otherwise have to load from resource */
#ifdef OPUS_X64
	/* The archive's resources use the pre-Win3 serialized format.  HLoadRes0
	 * creates native Win64 cursor handles from the original BITAPP masks. */
	fRes = fFalse;
#else
	fRes = (GetSystemMetrics(SM_CXCURSOR) != 32 ||
			GetSystemMetrics(SM_CYCURSOR) != 32);
#endif /* OPUS_X64 */
	vsci.fUseResCursors = fRes;
	for (ilrd = 0; ilrd < ilrdRcdsCurMax; ilrd++)
		if ((*rglrdRcdsCur[ilrd].ph = fRes ?
				LoadCursor(vhInstance, rglrdRcdsCur[ilrd].id+1) :
				HLoadRes0(rglrdRcdsCur[ilrd].id))
				== NULL)
			return fFalse;

	/* we have 32X32 version, otherwise have to load from resource */
	/* ICON internal format changed for Win3.0, must load from resource */
#ifdef OPUS_X64
	/* HLoadRes0 likewise creates the native HICON from the archived masks. */
	fRes = fFalse;
#else
	fRes = (GetSystemMetrics(SM_CXICON) != 32 ||
			GetSystemMetrics(SM_CYICON) != 32 || 
			vwWinVersion > 0x0299);
#endif /* OPUS_X64 */
	for (ilrd = 0; ilrd < ilrdRcdsIcoMax; ilrd++)
		if ((*rglrdRcdsIco[ilrd].ph = fRes ?
				LoadIcon(vhInstance, rglrdRcdsIco[ilrd].id+1) :
				HLoadRes0(rglrdRcdsIco[ilrd].id))
				== NULL)
			return fFalse;

	return fTrue;
}

#ifdef WIN23
csconst int mpdbmgPmTmHeight[] = {20, 16, 12};
csconst int mpdbmgPmTmWidth[] = {8, 6, 6};
	/* REVIEW: I don't know the correct values for the Win 2 system font
		on VGA, 8514 and SIGMA */
	/* note that this is height (ascent+descent),
		not including external leading */
csconst int mpdbmgWin2TmHeight[] = {20, 15, 15, 10, 8};
csconst int mpdbmgWin2TmWidth[] = {10, 8, 8, 8, 8};
#endif /* WIN23 */

/* %%Function:FInitScreenConstants %%Owner:PETERJ */
int FInitScreenConstants()
{
	/* This routine sets the value of a variety of global variables that used to
	be constants in Mac Word, but are now varibles because screen resolution can
	only be determined at run time. */

	extern struct BMI           vbmiEmpty;
#ifdef WIN23
	extern struct BMI           *mpidrbbmi;
	extern struct BMI           mpidrbbmi2[];
	extern struct BMI           mpidrbbmi3[];
#else
	extern struct BMI           mpidrbbmi[];
#endif /* WIN23 */
	extern int              vdxpStagger;
	extern int              vdypStagger;
	HDC hdc;
	int xaRightMac;
	TEXTMETRIC tm;
	int dbmg;
	int dypLH;
#ifdef WIN23
	LOGFONT lf;
	HFONT hfontOld = NULL;
	HDC hdcTStatLine;
	int dyp ; 
#endif /* WIN23 */
	/* Get the DC of the parent window to use to obtain screen attributes */

	if ((hdc = GetDC(NULL)) == NULL)
		return fFalse;

#ifdef WIN23
	/* need to be sure mpidrbbmi is set up for calls below */
	if (vsci.fWin3 && vsci.fWin3Visuals)
		{
		vsci.dyRuler = dyRuler3;
		vsci.dccStatLine = dccStatLine3;
		vsci.dccIconBar = dccIconBar3;
		vsci.dypOtlPat = dypOtlPat3;
		mpidrbbmi = mpidrbbmi3;	/* set up for Win 3 bitmaps */
		/* find the address of CreateDIBitmap */
		/* magic: 442 is entrypoint for CreateDIBitmap under Win 3 */
		vsci.lpfnCreateDIBitmap = GetProcAddress(GetModuleHandle(SzFrame("GDI")),
			MAKEINTRESOURCE(442));
		Assert(vsci.lpfnCreateDIBitmap);
		}
	else
		{
		vsci.dyRuler = dyRuler2;
		vsci.dccStatLine = dccStatLine2;
		vsci.dccIconBar = dccIconBar2;
		mpidrbbmi = mpidrbbmi2;	/* set up for Win 2 bitmaps */
		vsci.dypOtlPat = dypOtlPat2;
		}
#endif /* WIN23 */
	/* determine screen pixel dimensions */
	vfli.dxsInch = GetDeviceCaps(hdc, LOGPIXELSX);
	vfli.dysInch = GetDeviceCaps(hdc, LOGPIXELSY);
#ifdef BRYANL
		{
		int rgw [2];

		rgw [0] = vfli.dxsInch;
		rgw [1] = vfli.dysInch;
		CommSzRgNum( SzShared("dxsInch, dysInch: "), rgw, 2 );
		}
#endif

		/* Compute screen pixel values that are derived from twip constants */

		{
		int *pdxp;
		int cw;
		int idxa;

		pdxp = (int *) ((CHAR *) &vsci + brgdxpConvert);
		cw = cDxpConvert;

	/* Note: rgdxaConvert is a csconst structure, so we reevaluate its address
		each time rather than setting up a pdxa++ */

		idxa = 0;
		while (cw--)
			{
			*pdxp++ = (int) umin (0x7FFF,
					NMultDiv( rgdxaConvert[idxa], vfli.dxsInch, czaInch ));
			idxa++;
			}
		cw = cDypConvert;
		while (cw--)
			{
			*pdxp++ = (int) umin (0x7FFF,
					NMultDiv( rgdxaConvert[idxa], vfli.dysInch, czaInch ));
			idxa++;
			}
		}

	vsci.xaRightMax = xaRightMaxRaw;
	if (((long)(uns)xaRightMaxRaw * (long)(uns)vfli.dxsInch  >
			(0x7FFFL * (long) czaInch)))
		{
		/* Can't represent xaRightMaxRaw worth of text; truncate */

		vsci.xpRightMax = 0x7FFF;
		vsci.xaRightMax = UMultDiv( 0x7fff,czaInch,vfli.dxsInch);
		}
	Assert( vsci.xpRightMax > 0 && (uns)vsci.xpRightMax < 0x8000 );

	/* round dxwSelBar to the next highest multiple of 8; this lets us use the
		byte-aligned fast case for Windows TextOut */
	vsci.dxwSelBar += 7;
	vsci.dxwSelBar -= vsci.dxwSelBar % 8;

	/* set up vsci.xpLeftMin separately; unlike the others, it is negative */

	vsci.xpLeftMin = -(vsci.xpRightMax>>1);
	vsci.xaLeftMin = NMultDiv( vsci.xpLeftMin, czaInch, vfli.dxsInch );

	vsci.dxpBorder = GetSystemMetrics(SM_CXBORDER);
	vsci.dypBorder = GetSystemMetrics(SM_CYBORDER);
	vsci.dypSplitBar = 3 * vsci.dypBorder;

	vsci.dxpScrlBar   = GetSystemMetrics(SM_CXVSCROLL);
	vsci.dypScrlBar   = GetSystemMetrics(SM_CYHSCROLL);
	vsci.dypScrollArrow = GetSystemMetrics(SM_CYVSCROLL);
	vsci.dypSplitBox  =  vsci.dypScrollArrow / 3;

	GetTextMetrics( hdc, (LPTEXTMETRIC)&tm );
	vsci.dypTmHeight = tm.tmHeight;
	vsci.dxpTmWidth = tm.tmAveCharWidth;
	vsci.dypTmAscent = tm.tmAscent;                         /* HACK !!!!! */
	vsci.dypTmInternalLeading = tm.tmInternalLeading;
#ifndef WIN23
	/* else done below */
	vsci.dypRibbon = NMultDiv( dyRibbon, vsci.dypTmHeight, 8 ) + 1;
#endif /* WIN23 */
#ifdef WIN23
	/* Needs to happen after a scratch DC is careted  */
	if (!vsci.fWin3)
#endif /* WIN23 */
	vsci.dypStatLine = vsci.dypTmHeight + 3 * vsci.dypBorder;

	/* adjust min line height to be no greater than system font, so we get
		single line scrolling in draft view */
	vsci.dysMinAveLine = min( vsci.dysMinAveLine, vsci.dypTmHeight );

/* vsci.dypRuler and vsci.dypIconBar are the dyp that is used for all normal
	window manipulation, assuming that the ruler and iconbar both overlap
	whatever is above them by one border width.  That is why when these two
	are created, we add one border width.  This is just to avoid having to
	have lots of "- vsci.dypBorder"s all over the code to adjust for the
	overlapping borders */

#ifndef WIN23
	/* else it's done below */
	vsci.dypRuler = NMultDiv( dyRuler, vsci.dypTmHeight, 8 );
	vsci.dypIconBar = NMultDiv( dyIconBar, vsci.dypTmHeight, 8 );
#endif /* WIN23 */

	vdxpStagger = vsci.dxpScrlBar >> 2;
	vdypStagger = vsci.dypScrlBar >> 2;

	vsci.xpScrollMax  = vsci.xpRightMax - (GetSystemMetrics( SM_CXFULLSCREEN ) -
			vsci.dxwSelBar - vsci.dxpScrlBar);
	vsci.dxpScreen = GetDeviceCaps(hdc,HORZRES);
#ifdef WIN23
	if (!vsci.fWin3)
		{	/* if fWin3 then these two were done above in FInitPart1 */
		vsci.dypScreen = GetDeviceCaps(hdc,VERTRES);
		vsci.fMonochrome = (GetDeviceCaps(hdc, NUMCOLORS) == 2);
		}
#else
    vsci.dypScreen = GetDeviceCaps(hdc,VERTRES);
	vsci.fMonochrome = (GetDeviceCaps(hdc, NUMCOLORS) == 2);
#endif /* WIN23 */

	vsci.dxmmScreen = GetDeviceCaps(hdc,HORZSIZE);
	vsci.dymmScreen = GetDeviceCaps(hdc,VERTSIZE);

	/* choose among available device bitmap groups */
	/* algorithm is: look for largest bitmap <= correct size */

	dypLH = NMultDiv( dyRibbon-ddyIconLH, vsci.dypTmHeight, 8)
			- (vsci.dypBorder << 2);
#ifdef WIN23
	{
	int dbmgLast;
	int FAR *pmpdbmgdypLH;

	if (vsci.fWin3Visuals)
		{
		dbmgLast = dbmgLast3;
		pmpdbmgdypLH = &mpdbmgdypLH3[0];
		}
	else if (vsci.fWin3)
		{
		dbmgLast = dbmgLast2;
		pmpdbmgdypLH = &mpdbmgdypLH23[0];
		}
	else
		{
		dbmgLast = dbmgLast2;
		pmpdbmgdypLH = &mpdbmgdypLH2[0];
		}
	for (dbmg = 0; dbmg < dbmgLast && dypLH < pmpdbmgdypLH[dbmg]; dbmg++)
		;
	}
#else
	for (dbmg = 0; dbmg < dbmgLast && dypLH < mpdbmgdypLH[dbmg]; dbmg++)
		;
#endif /* WIN23 */
	vdbmgDevice = dbmg;
#ifdef WIN23
	/* set up the fake font height and width based on the screen device.
		If we are running Win3 Visuals, this is the PM font height and
		width for the screen resolution. We'll use this this for iconbars
		in the 3D mode, so that all the scaling works as is does under PM.
		If we are running without 3D visuals, this is the Win 2 sys font
		height and width. These will be used to size the iconbars in 2D
		mode, so all the old templates still work.
	*/
	if (vsci.fWin3)
		{
		if (vsci.fWin3Visuals)
			{
			vsci.dypFakeTmHeight = mpdbmgPmTmHeight[dbmg];
			vsci.dxpFakeTmWidth = mpdbmgPmTmWidth[dbmg];
			}
		else
			{
			vsci.dypFakeTmHeight = mpdbmgWin2TmHeight[dbmg];
			vsci.dxpFakeTmWidth = mpdbmgWin2TmWidth[dbmg];
			}
		}
	/*****
	If under win3 and not under fWin3Visuals then we want to use
	the faketmheight (win2 sys font) to size the ruler and ribbon
	*****/
#ifdef REVIEW
	dyp = (vsci.fWin3 && !vsci.fWin3Visuals) ? vsci.dypFakeTmHeight :
		vsci.dypTmHeight ;
#else
	dyp = (vsci.fWin3) ? vsci.dypFakeTmHeight :	vsci.dypTmHeight ;
#endif /* REVIEW */
	vsci.dypRuler = NMultDiv( vsci.dyRuler, dyp, 8 );
	vsci.dypIconBar = NMultDiv( dyIconBar, dyp, 8 );
	vsci.dypRibbon = NMultDiv( dyRibbon, dyp, 8 ) + 1;
#endif /* WIN23 */
#ifdef DCSRC
	CommSzNum(SzShared("vdbmgDevice = "), vdbmgDevice);
#endif /* DCSRC */

/* create two memory DCs.  We need two to create grey resource bitmaps; also
	to paint visi characters into the screen cache. */

	if (!FCreatePmdcd(&vsci.mdcdScratch,hdc))
		return fFalse;
	LogGdiHandle(vsci.mdcdScratch.hdc, 1073);
	if (!FCreatePmdcd(&vsci.mdcdBmp,hdc))
		return fFalse;
	LogGdiHandle(vsci.mdcdBmp.hdc, 1074);
#ifdef WIN23
	if (vsci.fWin3)
		{
		/*
	 	* Create the status line font.  Use tm; it is unused at this point. 
	 	* 200 twips == 10 pts.  Get the widths of a digit for later
	 	* Add an extra pixel to height of status line for a shadow line and
	 	* for a blank line at the bottom.
	 	*/
 		SetWords( &lf, NULL, sizeof(LOGFONT)/sizeof(int) );
 		lf.lfHeight = NMultDiv( 240, vfli.dysInch, czaInch );  
 		lf.lfCharSet = ANSI_CHARSET;
 		lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;

		if (hfontStatLine = CreateFontIndirect( &lf )) {
			hfontOld = SelectObject( (hdcTStatLine = vsci.mdcdScratch.hdc),
								 	hfontStatLine );
			GetTextMetrics( hdcTStatLine, (LPTEXTMETRIC)&tm );
			GetCharWidth( hdcTStatLine, '8', '8', (LPINT) &vdxpDigit );

			vsci.dypStatLine = tm.tmHeight + 4 + 3 * vsci.dypBorder;
			if (hfontOld)
				SelectObject( hdcTStatLine, hfontOld );
		}
		else {
			vsci.dypStatLine = vsci.dypTmHeight + 1 + 3 * vsci.dypBorder;
		}
	}

#endif /* WIN23 */
/* Preload visichars bitmap so we don't load it later in the middle
	of the critical part of screen cache fill. */

	vsci.mdcdScratch.pbmi = &mpidrbbmi [idrbChVis];
	if ((vsci.mdcdScratch.pbmi->hbm = HFromIbmds0(idrbChVis))
			== NULL)
		return fFalse;

		{
		extern int far pascal rcinit_q();
		GlobalLruOldest(GetCodeHandle((FARPROC)rcinit_q));
		}

	/* Discover the handle to the NULL bitmap. This is an undocumented Windows
		object, analogous to SYSTEM_FONT.  It is the bitmap selected into
		a newly created DC.  The way to get it is to look at the return
		value from a SelectObject call for a newly created DC */

	if ((vbmiEmpty.hbm = SelectObject( vsci.mdcdScratch.hdc, 
			vsci.mdcdScratch.pbmi->hbm)) == NULL)
		return fFalse;

	/* We don't need the DC any more. */
	ReleaseDC( NULL, hdc);

	vsci.dypMenuBar = GetSystemMetrics(SM_CYMENU);
	vsci.dypBdrCapt = GetSystemMetrics(SM_CYFRAME) + 
			GetSystemMetrics(SM_CYCAPTION);
	vsci.dxpBmpSystem = 0; /* this is filled in later */

	return fTrue;
}



/* %%Function:FCreatePmdcd %%Owner:PETERJ */
FCreatePmdcd(pmdcd, hdcCompat)
struct MDCD *pmdcd;  
HDC hdcCompat;
{
	extern struct BMI vbmiEmpty;

	if ((pmdcd->hdc = CreateCompatibleDC(hdcCompat)) == NULL)
		return fFalse;

	if (!FSetDcAttribs( pmdcd->hdc, dccScratch & dccmColors ))
		return fFalse;
	pmdcd->pbmi = &vbmiEmpty;
	return fTrue;
}



/* B U I L D  S C C */
/* %%Function:BuildScc %%Owner:PETERJ */
BuildScc(pscc, dxp, dyp)
struct SCC *pscc;
int dxp, dyp;
{
	SetWords(pscc, 0, cwSCC);
	pscc->hplcedl = &pscc->pplcedl;
	pscc->pplcedl = &pscc->plcedl;
	pscc->dlFirstInval = pscc->dlMax = dlSccMax;
	pscc->plcedl.cb = cchEDL;
	pscc->plcedl.dlMax = dlSccMax + 1;
	pscc->plcedl.fExternal = fFalse;

	pscc->plcedl.icpAdjust = 1;
	/* pscc->plcedl.dcpAdjust = cp0; */
	/* pscc->plcedl.icpHint = 0; */
	pscc->idrMac = 1;
	pscc->idrMax = 1;
	pscc->cbDr = sizeof(struct DR);
	pscc->brgdr = offset(SCC, rgdr);

	pscc->ww = wwNil;
	pscc->bmi.fDiscardable = fTrue;
	/* pscc->bmi.dxp = pscc->bmi.dyp = 0; */
}


/* F R e a d  U s e r  S t a t e */
/* %%Function:FReadUserState %%Owner:bryanl */
FReadUserState()
{
/* initialize these to standard values */
	/* vpref */
	/* ass   */
	/* vcdi  */
	/* vpref = { 0, 0, ... } */

	Assert(vhsttbOpen == hNil);

	/* if no winword.ini, need to initialize default prefs */
	if (!FReadOpusIni() && !FInitDefaultPrefs(fFalse))
		return fFalse;

#ifdef OPUS_X64
	/*
	 * Page View has to be activated after FCreateMw finishes constructing its
	 * layout records.  The Win95 shell requests it from its post-startup timer;
	 * prevent a saved preference from entering it too early here.
	 */
	vpref.fPageView = fFalse;
#endif

	/*  this is not a *user* view preference, used internally only! */
	vpref.grpfvisi.fForceField = fFalse;

	vfFileCacheDirty = fTrue;

	return fTrue;
}


/*  F  I N I T  D E F A U L T  P R E F S  */
/*  Initialize user prefs to defaults.  This will either be called if
	there was no winword.ini file, or the user ran the tutorial (CBT
	likes to start out with the defaults).
*/
/* %%Function:FInitDefaultPrefs %%Owner:bryanl */
FInitDefaultPrefs(fTutorial)
BOOL fTutorial;
{
	/* don't wipe out user name and initials if tutorial */
	SetBytes (&vpref, 0, fTutorial ? cbPREFShort : cbPREF);
	vpref.ut = fTutorial ? utCBT : vitr.fMetric ? utCm : utInch;
	if (!fTutorial)
		{
		/* these default to fFalse for tutorial */
		vpref.fDisplayAsPrint   = fTrue;
		vpref.fBkgrndPag        = fTrue;
		vpref.fShortMenus       = fTrue;
		vpref.fRibbon           = fTrue; /* since winword 1.1 */
		vpref.fRuler            = fTrue; /* since winword 1.1 */
		vpref.fAutoDelete       = fTrue; /* since winword 1.1 */
		}
	vpref.fPromptSI         = fTrue;
	vpref.fStatLine         = fTrue;
	vpref.fVertScrollBar    = fTrue;
	vpref.fZoomApp          = fTrue;
	vpref.fZoomMwd          = fTrue;
	vpref.fPrDirty		= fTrue;
	vpref.grpfvisi.fDrawTableDrs = fTrue;
	
#ifdef INEFFICIENT
	vpref.fShowFormulas     = fFalse;
	vpref.fvisiTabs         = fFalse;
	vpref.fvisiSpaces       = fFalse;
	vpref.fvisiParaMarks    = fFalse;
	vpref.fvisiFtnRefMarks  = fFalse;
	vpref.fvisiCondHyphens  = fFalse;
	vpref.fvisiShowAll      = fFalse;
	vpref.fSeeHidden        = fFalse;
	vpref.dxaStyWnd         = 0;
	vpref.fPPGlossaryExp    = fFalse;
	vpref.fForceField       = fFalse;
	vpref.fHorzScrollBar    = fFalse;
	vpref.fNoShowPictures   = fFalse;
#endif  /* INEFFICIENT */

	vpref.grpfvisi.grpfShowResults   = -1;
	vpref.iAS                        = iASNever;
	/* vpref.fEllip                  = fTrue; */
	vpref.fShowF                     = fTrue;

	return ((vhsttbOpen = HsttbInit(0, fFalse/*fExt*/)) != hNil);
}


/* RSTREAM - Read STREAM. Special sequential read only stream used by 
*  FReadOpusIni and supporting code to reduce number of disk reads while
*  reading winword.ini.
*
*  WARNING: Do not use any of this stuff outside of FReadOpusIni.
*/
#define cbMaxRstream	(1024*4)
typedef struct _rstream
	{
	int osfn;
	int ib;
	int ibMac;
	char rgb[cbMaxRstream];
} RSTREAM;


/* F  R E A D  O P U S  I N I */
/* %%Function:FReadOpusIni %%Owner:bryanl */
BOOL FReadOpusIni()
	{ /* Read vpref structure in from opus.ini file. Note:  if this routine fails
			due to insufficient heap, we free what we used and use our defaults
			(ignoring their opus.ini all together).
	*/

	int fn;
	int ifdb;
	struct PREFD prefd;
	CHAR sz[cchMaxFile];
	RSTREAM rstream;
	struct OFS ofs;

	Assert(hstDMQPath == hNil);

	if (!FFindFileSpec(StSharedKey("WINWORD.INI",OpusIni), sz, grpfpiIni, nfoNormal))
		/* can't find file */
		return fFalse;

	StToSzInPlace(sz);

#ifdef DFILEPATHS
	CommSzSz(SzShared("Looking for: "), sz);
#endif /* DFILEPATHS */

	rstream.ib = rstream.ibMac = cbMaxRstream; /* Init rstream */
	if ((rstream.osfn = OpenFile(sz, &ofs, OF_READ|bSHARE_DENYWR)) >= 0)
		{
		if (CchReadPrstream(&rstream, ((CHAR FAR *) &prefd), cbPREFD) < 0)
			goto LErrorRet;

		if (prefd.nPrefPrefdVer != nPrefPrefdVerCur)
			{
			/* Special case reading 1.00 .ini file into version 1.00a to allow
				for transparent conversion from 1.00 to 1.00a.  The only diff-
				erence between them is the size of the printer metrics.
			*/
			if (prefd.nPrefPrefdVer == nPrefPrefdVer100
					&& nPrefPrefdVerCur == nPrefPrefdVer100a)
				{
				/* Update size of printer metrics and continue; Everything but
					printer information (metrics) will be read from the .ini file.
				*/
				prefd.cbPrinterMetrics = bMaxPriFile - bMinPriFile;
				}
			else
				goto LErrorRet;
			}

		if (!prefd.cbSttbFileCache || 
				(vhsttbOpen = HReadCbFromPrstream(&rstream, prefd.cbSttbFileCache))
				== hNil)
			{
			if ((vhsttbOpen = HsttbInit(0, fFalse/*fExt*/)) == hNil)
				goto LErrorRet;
			}

		Assert(vhsttbOpen != hNil && !(*vhsttbOpen)->fExternal);

		DMFlags.fIniQPath = fFalse;
		if (prefd.cbStDMQPath > 0)
			{
			if ((hstDMQPath = HReadCbFromPrstream(&rstream, prefd.cbStDMQPath))
					== hNil)
				{
				goto LErrorRet;
				}
			DMFlags.fIniQPath = fTrue;
			}

		/* read info about the printer */
		if (vpri.hszPrinter && prefd.cbPrNameAndDriver)
			{
			CHAR grpsz [ichMaxProfileSz*2];

			Assert( prefd.cbPrNameAndDriver <= ichMaxProfileSz*2);
			if (CchReadPrstream(&rstream,(CHAR FAR *)grpsz,prefd.cbPrNameAndDriver) < 0)
				goto LErrorRet;
			if (!FNeNcSz(grpsz, *vpri.hszPrinter) &&
					!FNeNcSz(grpsz+CchSz(grpsz), *vpri.hszPrDriver))
				{
				InitVpriFromFile( &rstream, &prefd );
				}
			}

		Debug( vdbs.fCkHeap ? CkHeap() : 0 );

		/* close if file access was successful */
		FCloseDoshnd(rstream.osfn);

		if (vmerr.fMemFail)
			goto LErrorRet;
		vpref = prefd.pref;
		return fTrue;
		}
	else
		{
LErrorRet:
		FreePhsttb(&vhsttbOpen);
		/* file access failure or out of memory if here */
		ErrorEid(eidBadOpusIni, "ReadOpusIni");
		if (rstream.osfn > 0)
			FCloseDoshnd(rstream.osfn);
		/* don't fail to boot because of bogus ini file */
		vmerr.mat = matNil;
		return fFalse;
		}
}


/* %%Function:InitStructScc2 %%Owner:PETERJ */
InitStructScc2()
{
	static struct SCC **hsccAbove, *psccAbove;

	psccAbove = &vsccAbove;
	hsccAbove = &psccAbove;
	/* wwSccAbove = */ AssertDo(IAllocClsH(clsWWD, hsccAbove, cwSCC) == wwSccAbove);
}


/* I n i t V p r i F r o m F i l e */

/* %%Function:InitVpriFromFile %%Owner:bryanl */
InitVpriFromFile(prstream,pprefd)
RSTREAM *prstream;
struct PREFD *pprefd;
{
	extern struct FCE rgfce[];
	extern int vflm;
	struct STTB **hsttbFont = hNil;
	int ibstPaf, ibstFont;
	int cbFontWidths;
	int ifce;
	int ifceMac;
#ifdef IFONLYWECOULD
	char 	**hprenv = hNil;
#endif
	struct FCE *pfce;

	/* Don't use printer info if reading a 1.00 ini file into 1.00a.
		This allows transparent migration from 1.00 to 1.00a, since only
		printer information changed between the two ini file versions.
	*/
	if (pprefd->nPrefPrefdVer == nPrefPrefdVer100
			&& nPrefPrefdVerCur == nPrefPrefdVer100a)
		{
		/* We rely on SetFlm to update printer info, so vpri.hdc must be NULL */
		Assert(vpri.hdc == NULL);
		goto LError;	/* Don't use printer information from ini file */
		}

	if (CchReadPrstream(prstream,
			(CHAR FAR *)((CHAR *)&vpri+bMinPriFile),
			pprefd->cbPrinterMetrics) < 0)
		goto LError;

#ifdef IFONLYWECOULD
	if (pprefd->cbPrenv && 
			(hprenv = HReadCbFromPrstream(prstream, pprefd->cbPrenv)) == hNil)
		goto LError;

/* if printer environment has changed, can't use pref file info */
	GetPrintEnv();
	if ( !(pprefd->cbPrenv == 0 && vpri.hprenv == hNil) &&
			(!pprefd->cbPrenv != !vpri.hprenv ||
			CbOfH(vpri.hprenv) != CbOfH(hprenv) ||
			FNeRgch( *vpri.hprenv, *hprenv, CbOfH(hprenv) )))
		{
		FreeH( hprenv );
		goto LError;
		}
	FreeH( hprenv );
#else
	if (pprefd->cbPrenv && 
			(vpri.hprenv = HReadCbFromPrstream(prstream, pprefd->cbPrenv)) == hNil)
		goto LError;
#endif

	Assert( vpri.hsttbPaf == hNil );
	if (pprefd->cbSttbFont &&
			(hsttbFont = HReadCbFromPrstream(prstream, pprefd->cbSttbFont)) == hNil)
		goto LError;

	Assert(hsttbFont == hNil || !(*hsttbFont)->fExternal);

	if (pprefd->cbSttbPaf)
		{
		Assert( hsttbFont != hNil );
		if ((vpri.hsttbPaf = HReadCbFromPrstream(prstream, pprefd->cbSttbPaf)) == hNil)
			goto LError;

		Assert(vpri.hsttbPaf != hNil && !(*vpri.hsttbPaf)->fExternal);

/* adjust ibstFont's in Paf to point to current font table, adding
	fonts as necessary */

		for ( ibstPaf = 0 ; ibstPaf < (*vpri.hsttbPaf)->ibstMac; ibstPaf++ )
			{
			struct PAF *ppaf = (struct PAF *)PstFromSttb( vpri.hsttbPaf, ibstPaf );

			if ((ibstFont = IbstXlate( hsttbFont, ppaf->ibst)) == iNil)
				goto LError;

			((struct PAF *)PstFromSttb( vpri.hsttbPaf, ibstPaf ))->ibst = ibstFont;
			}
		}
	else
		goto LError; /* cannot use printer info */

/* read font cache contents */

	if (pprefd->cbRgfce)
		{
		Assert( hsttbFont != hNil );
		ifceMac = pprefd->cbRgfce/sizeof(struct FCE);
	/* verify that cbRgfce isn't bigger than rgfce!. Should always
		be true unless in a version change the FCE changes or ifceMax
		gets smaller. To handle those we bag out here. bz  */
		if (ifceMac >= ifceMax || ifceMac * sizeof(struct FCE) != pprefd->cbRgfce)
			{
			Assert (fFalse);
			goto LError;
			}
		if (CchReadPrstream( prstream, (CHAR FAR *)rgfce, pprefd->cbRgfce)
				< pprefd->cbRgfce)
			goto LError;
		cbFontWidths = ifceMac == 0 ? 0 : pprefd->cbFontWidths / ifceMac;
		if (ifceMac != 0 &&
				(pprefd->cbFontWidths % ifceMac != 0 ||
				(cbFontWidths != 512 &&
				 cbFontWidths != 256 * sizeof(int))))
			goto LError;
		for ( ifce = 0, pfce = rgfce; ifce < ifceMac; ifce++,pfce++ )
			{
			if (!pfce->fFixedPitch)
				{
				int FAR *lpdxp;
				int cch;
#ifdef OPUS_X64
				short rgdxp16[256];
				int ich;

				if ((pfce->hqrgdxp = HqAllocLcb(
						(long)(256 * sizeof(int)))) == hqNil)
/* Peter, these do not need to be "freeded" on error, as the caller
	will recogize vmerr.fMemFail and refuse to bring Opus up. */
					goto LError;
				lpdxp = LpLockHq( pfce->hqrgdxp );
				Assert( lpdxp != NULL );	/* should be guaranteed */
				if (cbFontWidths == 512)
					{
					cch = CchReadPrstream(prstream, rgdxp16, 512);
					if (cch == 512)
						for (ich = 0; ich < 256; ++ich)
							lpdxp[ich] = rgdxp16[ich];
					}
				else
					cch = CchReadPrstream(prstream, lpdxp,
							256 * sizeof(int));
				UnlockHq( pfce->hqrgdxp );
				if (cch < cbFontWidths)
					goto LError;
#else
				if ((pfce->hqrgdxp = HqAllocLcb((long)512)) == hqNil)
					goto LError;
				lpdxp = LpLockHq(pfce->hqrgdxp);
				cch = CchReadPrstream(prstream, lpdxp, 512);
				UnlockHq(pfce->hqrgdxp);
				if (cch < 512)
					goto LError;
#endif
				}

			pfce->pfcePrev = pfce-1;
			pfce->pfceNext = pfce+1;
			pfce->hfont = hfontSpecNil;
			if ((pfce->fcidRequest.ibstFont = IbstXlate( hsttbFont, 
					pfce->fcidRequest.ibstFont )) == iNil)
				goto LError;
			if ((pfce->fcidActual.ibstFont = IbstXlate( hsttbFont, 
					pfce->fcidActual.ibstFont )) == iNil)
				goto LError;
			}

		rgfce [0].pfcePrev = NULL;
		if (ifceMac)
			rgfce [ifceMac-1].pfceNext = NULL;
		}
	else
		goto LError; /* cannot use printer info */

	if (hsttbFont != hNil)
		FreeHsttb( hsttbFont );

/* everything succeeded!  Now set up to simulate as though we are in flm
	Repaginate and the printer DC has been gotten, then tossed. */

	vflm = flmRepaginate;
	vpri.fIC = fTrue;
	vpref.fPrDirty = fTrue;
	vpri.pfti = &vfti;
	if (pprefd->cbRgfce)
		vfti.pfce = &rgfce [0];
	vfti.fPrinter = fTrue;
	vfti.fTossedPrinterDC = fTrue;
	vfli.fPrint = fTrue;
	vfli.fFormatAsPrint = fFalse;
	vftiDxt.dxpInch = vfti.dxpInch = vfli.dxuInch = vpri.dxuInch;
	vftiDxt.dypInch = vfti.dypInch = vfli.dyuInch = vpri.dyuInch;
	Debug( vdbs.fCkFont ? CkFont() : 0 );
#ifdef BRYANL
	CommSzSz(SzShared("Used printer info from pref file"),szEmpty);
#endif
	return;

LError:
#ifdef BRYANL
	CommSzSz(SzShared("Didn't use printer info from pref file"),szEmpty);
#endif
	FreePh(&vpri.hprenv);
	FreePhsttb(&vpri.hsttbPaf);
	if (hsttbFont != hNil)
		FreeHsttb(hsttbFont);
	vpref.fPrDirty = fTrue;
}


/* %%Function:IbstXlate %%Owner:bryanl */
IbstXlate( hsttbFont, ibst )
struct STTB **hsttbFont;
int ibst;
{
	int ibstFont;
	struct FFN *pffn;

	Assert( ibst < (*hsttbFont)->ibstMac );
	pffn = (struct FFN *)PstFromSttb( hsttbFont, ibst );

	if ((ibstFont = IbstFindSzFfn( vhsttbFont, pffn )) == iNil)
		{
		CHAR rgb [cbFfnLast];

		bltbyte( pffn, rgb, cbFfnLast );
		ibstFont = IbstAddStToSttb( vhsttbFont, rgb );
		}
	else
		/* in case charset, pitch, or family changed */
		FChangeStInSttb(vhsttbFont, ibstFont, pffn);

	return ibstFont;
}



/* %%Function:HReadCbFromPrstream %%Owner:bryanl */
#ifdef OPUS_X64
CHAR **
#endif
HReadCbFromPrstream(prstream,cb)
RSTREAM *prstream;
int cb;
{
	CHAR **h;
	Assert(prstream!=NULL && prstream->osfn >= 0 && cb > 0);
	if ((h = HAllocateCb(cb)) != hNil && 
			CchReadPrstream(prstream, (CHAR FAR *)*h, cb) < 0)
		FreePh(&h);
	return h;
}


/* %%Function:CchReadPrstream %%Owner:bryanl */
int CchReadPrstream(prstream, lpb, cb)
RSTREAM *prstream;
CHAR FAR *lpb;
int cb;
{
	int cbRead;
	int cbInBuf;

	Assert(prstream!=NULL && prstream->osfn >= 0);

	cbRead = 0;
	while (cb > 0)
		{
		if (prstream->ib >= prstream->ibMac)
			{
			/* If ib whent beyond ibMac we are in deep trouble */
			Assert(prstream->ib == prstream->ibMac);

			if ((cbInBuf = CchReadDoshnd(prstream->osfn, 
					(CHAR FAR *) prstream->rgb, cbMaxRstream)) < 0)
				return cbInBuf; /* return Error */

			if (cbInBuf == 0) return cbRead; /* EOF */
			prstream->ibMac = cbInBuf;
			prstream->ib = 0;
			}

		cbInBuf = min(cb, prstream->ibMac - prstream->ib);

		bltbx((CHAR FAR *) (prstream->rgb + prstream->ib), lpb, cbInBuf);
		cbRead += cbInBuf;
		cb -= cbInBuf;
		prstream->ib += cbInBuf;
		lpb += cbInBuf;
		}
	return cbRead;
}


#ifdef PROFILE
/*  this is here so that appended native code does not appear in previous
	function in pcode profiles. */
Initwin_Last(){}
#endif /* PROFILE */

/* ADD NEW CODE *ABOVE* Initwin_Last() */
