Files
msword/src/Opus/initwin.c
T
Justin Marshall cc5a66a272 Page margin fixes.
2026-08-06 21:08:33 -07:00

3082 lines
82 KiB
C

/* 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() */