mirror of
https://github.com/jmarshall23/msword.git
synced 2026-08-12 08:01:05 +02:00
3634 lines
88 KiB
C
3634 lines
88 KiB
C
/* W P R O C . C */
|
|
|
|
#ifdef DEBUG
|
|
/*#define SHOWAPPMSG*/
|
|
/*#define SHOWDSKMSG*/
|
|
/*#define SHOWDOCMSG*/
|
|
/*#define SHOWPNEMSG*/
|
|
#endif /* DEBUG */
|
|
|
|
#define RSHDEFS
|
|
#define NOVHGDIS
|
|
#define NOKEYSTATE
|
|
#define NOICON
|
|
#define NOBRUSH
|
|
#define NOCREATESTRUCT
|
|
#define NODRAWTEXT
|
|
#define NOMINMAX
|
|
#define NOPEN
|
|
#define NOREGION
|
|
#define NOSOUND
|
|
#define NOTEXTMETRIC
|
|
#define NOWNDCLASS
|
|
#define NOCOMM
|
|
#include "word.h"
|
|
DEBUGASSERTSZ /* WIN - bogus macro for assert string */
|
|
#include "version.h"
|
|
#include "heap.h"
|
|
#include "layout.h"
|
|
#include "file.h"
|
|
#define NOIFK
|
|
#define USEBCM
|
|
#include "cmd.h"
|
|
#include "keys.h"
|
|
#include "doc.h"
|
|
#include "disp.h"
|
|
#include "props.h"
|
|
#include "sel.h"
|
|
#include "screen.h"
|
|
#include "print.h"
|
|
#include "ch.h"
|
|
#include "format.h"
|
|
#include "status.h"
|
|
#include "wininfo.h"
|
|
#include "menu2.h"
|
|
#include "dde.h"
|
|
#include "help.h"
|
|
#include "debug.h"
|
|
#include "field.h"
|
|
#include "cmdtbl.h"
|
|
#include "fkp.h"
|
|
#include "prm.h"
|
|
#include "prompt.h"
|
|
#include "message.h"
|
|
#include "idle.h"
|
|
#include "error.h"
|
|
#include "iconbar.h"
|
|
#include "sdmdefs.h"
|
|
#include "sdmver.h"
|
|
#include "sdm.h"
|
|
#include "sdmtmpl.h"
|
|
#include "sdmparse.h"
|
|
#include "scc.h"
|
|
#include "resource.h"
|
|
#include "rareflag.h"
|
|
#include "recorder.h"
|
|
|
|
#ifdef DEBUG
|
|
#include "rerr.h"
|
|
#endif
|
|
|
|
#define WPROC
|
|
#include "core.h"
|
|
|
|
|
|
/* globals */
|
|
#ifdef DEBUG
|
|
int cHpFreeze = 0;
|
|
#endif /* DEBUG */
|
|
|
|
struct CHP vchpFetch;
|
|
struct CHP vchpStc;
|
|
struct PAP vpapStc;
|
|
struct TAP vtapStc;
|
|
struct PAP vpapFetch;
|
|
struct SEP vsepFetch;
|
|
BOOL vfFliMunged; /* returned from cachepage */
|
|
int vised;
|
|
int vipgd;
|
|
|
|
struct CA caPara;
|
|
struct CA caPage;
|
|
struct CA caSect;
|
|
struct CA caTable;
|
|
#ifdef OPUS_X64
|
|
extern struct FTI vfti;
|
|
extern char (**vhgrpchr)[];
|
|
extern int vbchrMac;
|
|
#endif
|
|
extern struct FCB **mpfnhfcb[];
|
|
extern int vfnPreload;
|
|
extern int vcPreload;
|
|
struct CA caTcxCache;
|
|
|
|
int vdocFetch;
|
|
int vdocFetchPic;
|
|
CP vcpFetch;
|
|
char HUGE *vhpchFetch;
|
|
int vccpFetch;
|
|
/* signals cpMac reached */
|
|
BOOL vfEndFetch;
|
|
|
|
CP vcpFirstTablePara;
|
|
CP vcpFirstTableCell;
|
|
|
|
/* used to avoid AdjustCp's while inserting from the keyboard */
|
|
char rgchInsert[cchInsertMax];
|
|
int ichInsert; /* Number of chars used in rgchInsert */
|
|
|
|
int fnFetch; /* last run was in this fn */
|
|
/* fc corresponding to vcpFetch. If fnLast == fnInsert, fc is an index
|
|
into rgchInsert, still corresponding to vcpFetch */
|
|
FC fcFetch;
|
|
int fcmFetch;
|
|
int prmFetch; /* prm of ipcdFetch */
|
|
|
|
int vdocPapLast = docNil;
|
|
int vfnPapLast = fnNil;
|
|
int vpnPapLast = 0;
|
|
int vbpapxPapLast = cbSector + 1;
|
|
|
|
/* number of cp's remaining in last chp run, piece, page in file */
|
|
/* following three quantities must be in order (hand-nat requirement) */
|
|
CP ccpChp, ccpPcd;
|
|
int ccpFile;
|
|
|
|
int ipcdFetch; /* index of the piece corresponding to vcpFetch */
|
|
|
|
int vstcpMapStc; /* last stcp calculated by MapStc */
|
|
|
|
char rgchCaps[ichCapsMax];
|
|
|
|
int vfAwfulNoise;
|
|
int vssc; /* secondary selection (move, copy, copy looks) mode */
|
|
int vfInitializing = TRUE;
|
|
int vwwSelect;
|
|
/* means idle should normalize to the selection and then reset the flag */
|
|
BOOL vfSeeSel;
|
|
|
|
/* flags are set fTrue when prefix key is encountered. Thus, the next
|
|
keystroke is interpreted as part of a 2 key sequence. */
|
|
int vgrpfKeyPrefix;
|
|
int vxwCursor; /* preferred column for up-down cursor movement */
|
|
int flashID = 0; /* timer ID for flashing before we put up a messagebox when we are not the active app */
|
|
MSG vmsgLast; /* last message received */
|
|
HANDLE vhSysMenu; /* handle to system (toaster) menu */
|
|
HWND vhwndApp; /* handle to parent ww (created in
|
|
interface module) */
|
|
HWND vhwndStartup; /* handle to start up monologue */
|
|
HANDLE vhInstance; /* handle to memory module instance */
|
|
|
|
HMENU vhMenu; /* handle to current top level menu */
|
|
HMENU vhMenuLongFull; /* full menu*/
|
|
int viMenu = -2; /* current menu number */
|
|
|
|
CHAR *vpDlgBuf; /* pointer to buffer for dialog boxes */
|
|
|
|
BOOL vfSingleApp; /* if true, running with runtime windows */
|
|
|
|
HBRUSH vhbrWhite; /* various brushes used for pattern fills */
|
|
HBRUSH vhbrBlack;
|
|
HBRUSH vhbrGray;
|
|
HBRUSH vhbrLtGray;
|
|
HBRUSH vhbrDkGray;
|
|
|
|
/* bitmaps used for drawing vertical and horizontal lines */
|
|
HBITMAP vhbmPatVert;
|
|
HBITMAP vhbmPatHorz;
|
|
|
|
|
|
int vfFocus = FALSE; /* Whether we have the input focus */
|
|
int vfMouseExist = fFalse; /* fTrue if mouse hardware is installed */
|
|
int vfInLongOperation = fFalse; /* fTrue if we are still in a long operation
|
|
so that the cursor should stay hourglass */
|
|
int vfDeactByOtherApp=fFalse; /* We were deactivated by another app */
|
|
|
|
HWND vhwndSizeBox; /* handle to the size box */
|
|
HWND vhwndMsgBoxParent; /* current parent to use for message boxes */
|
|
HWND vhwndDeskTop; /* handle to desktop window, area that contains doc windows */
|
|
|
|
#ifdef DEBUG
|
|
int **vhgdis = hNil;
|
|
#endif /* DEBUG */
|
|
|
|
int vgrpfKeyBoardState = 0; /* current keyboard state */
|
|
|
|
BOOL vfOvertypeMode = fFalse;
|
|
BOOL vfExtendSel = fFalse; /* true if extend to next typed character and survive in search and goto */
|
|
BOOL vfBlockSel = fFalse; /* true if in block selection state */
|
|
|
|
BOOL vfDoubleClick = FALSE; /* whether click is double click */
|
|
BOOL vfRightClick = FALSE; /* whether click is right button */
|
|
HCURSOR vhcHourGlass; /* handle to hour glass cursor */
|
|
HCURSOR vhcIBeam; /* handle to i-beam cursor */
|
|
HCURSOR vhcArrow; /* handle to arrow cursor */
|
|
HCURSOR vhcBarCur; /* handle to back arrow cursor */
|
|
HCURSOR vhcSplit; /* handle to split cursor */
|
|
HCURSOR vhcStyWnd; /* handle to style name window cursor */
|
|
HCURSOR vhcRecorder;
|
|
HCURSOR vhcHelp; /* handle to ? cursor for help */
|
|
HCURSOR vhcOtlCross;
|
|
HCURSOR vhcOtlHorz;
|
|
HCURSOR vhcOtlVert;
|
|
HCURSOR vhcColumn;
|
|
HCURSOR vhcPrvwCross = NULL;
|
|
HICON vhiWord; /* winword icon */
|
|
|
|
/* This is how we tell if NewCurWw is being called as a result of
|
|
returning from a message box mamong other things (we disable
|
|
coming back from a messagebox or dialog if we were in a message box
|
|
too. They can nest, e.g., at ExitWindows time bz
|
|
*/
|
|
int vcInMessageBox = 0;
|
|
|
|
/* USAGE: caAdjust is a temporary CA which can be used by anyone if they
|
|
want a caTemp that will be adjusted whenever AdjustCp is called. The
|
|
only constraint is that you must call AcquireCaAdjust() before using
|
|
it and ReleaseCaAdjust() when you're done, to ensure that noone else
|
|
is using it at the time. Actually these are macros that will go away
|
|
when DEBUG is undefined, but we should catch these conflicts now.
|
|
*/
|
|
struct CA caAdjust = {
|
|
0, 0, docNil };
|
|
|
|
|
|
struct CA caAdjustL = {
|
|
cp0, cp0, docNil };
|
|
|
|
|
|
#ifdef DEBUG
|
|
int cCaAdjust = 0;
|
|
int cCaAdjustL = 0;
|
|
#endif
|
|
|
|
|
|
#ifdef RSH
|
|
|
|
#ifdef NOASM
|
|
NATIVE IScanLprgw( int far *, WORD, int ); /* DECLARATION ONLY */
|
|
#endif /* NOASM */
|
|
|
|
/* this table is used to record sys commands (SC_) in the research version */
|
|
csconst int rgscRsh[] =
|
|
{
|
|
SC_SIZE,
|
|
SC_MOVE,
|
|
SC_MINIMIZE,
|
|
SC_MAXIMIZE,
|
|
SC_NEXTWINDOW,
|
|
SC_PREVWINDOW,
|
|
SC_CLOSE,
|
|
SC_VSCROLL,
|
|
SC_HSCROLL,
|
|
SC_MOUSEMENU,
|
|
SC_KEYMENU,
|
|
SC_RESTORE
|
|
};
|
|
#define iscMax sizeof(rgscRsh)/sizeof(int)
|
|
|
|
/* this table is used to record interesting messages (WM_) in the research version */
|
|
csconst int rgwmRsh[] =
|
|
{
|
|
WM_QUERYENDSESSION,
|
|
WM_ENDSESSION,
|
|
WM_ACTIVATEAPP,
|
|
WM_NCLBUTTONDOWN,
|
|
WM_NCRBUTTONDOWN,
|
|
WM_NCLBUTTONDBLCLK,
|
|
WM_NCRBUTTONDBLCLK,
|
|
WM_LBUTTONDOWN,
|
|
WM_RBUTTONDOWN,
|
|
WM_LBUTTONDBLCLK,
|
|
WM_RBUTTONDBLCLK,
|
|
WM_CLOSE,
|
|
WM_VSCROLL,
|
|
WM_HSCROLL
|
|
};
|
|
#define iwmMax sizeof(rgwmRsh)/sizeof(int)
|
|
|
|
#endif /* RSH */
|
|
|
|
extern int vpisPrompt;
|
|
extern int flashID;
|
|
extern ENV *penvMem;
|
|
extern BOOL vfDdeIdle;
|
|
extern BOOL vfRecording;
|
|
extern BOOL vfRecordNext;
|
|
extern CMR **vhcmr;
|
|
extern FARPROC vlppFWHChain;
|
|
extern int vfInitializing;
|
|
extern struct MWD **hmwdCur;
|
|
extern int mwCur;
|
|
extern int mwMac; /* mac of child window */
|
|
extern int wwMac;
|
|
extern HMENU vhMenuNoMwd;
|
|
extern int vfLargeFrameEMS;
|
|
extern HMENU vhMenuShort;
|
|
extern HMENU vhMenuWithMwd;
|
|
extern struct MWD **mpmwhmwd[];
|
|
extern struct SCI vsci;
|
|
extern struct PRI vpri;
|
|
extern struct FLI vfli;
|
|
extern struct PREF vpref;
|
|
extern CHAR szApp[];
|
|
extern HANDLE vhInstance;
|
|
extern HWND vhwndApp; /* handle to parent's window */
|
|
extern HWND vhwndDeskTop;
|
|
extern HWND vhwndPrompt;
|
|
extern HWND vhwndPromptHidden;
|
|
extern HWND vhwndRibbon;
|
|
extern HWND vhwndCBT;
|
|
extern int vcxtHelp; /* help context id */
|
|
extern BOOL vfHelp; /* whether we're in Help Mode */
|
|
extern long vcmsecHelp;
|
|
#ifdef OPUS_X64
|
|
extern WPARAM vwParamHelp;
|
|
extern LPARAM vlParamHelp;
|
|
#else
|
|
extern WORD vwParamHelp;
|
|
extern LONG vlParamHelp;
|
|
#endif
|
|
extern HCURSOR vhcHourGlass;
|
|
extern HCURSOR vhcIBeam;
|
|
extern HCURSOR vhcArrow;
|
|
extern HCURSOR vhcBarCur;
|
|
extern HCURSOR vhcRecorder;
|
|
extern HCURSOR vhcHelp;
|
|
extern HCURSOR vhcStyWnd;
|
|
extern HMENU vhMenu;
|
|
extern HWND vhwndAppModalFocus;
|
|
extern HWND vhwndStatLine;
|
|
extern BOOL vfExtendSel;
|
|
extern struct STTB **vhsttbOpen;
|
|
extern BOOL vfBlockSel;
|
|
extern MSG vmsgLast;
|
|
extern struct WWD **mpwwhwwd[];
|
|
extern struct WWD **hwwdCur;
|
|
extern int mwCreate;
|
|
extern BOOL vfInLongOperation;
|
|
extern int wwCur;
|
|
extern struct SEL selCur;
|
|
extern struct SEL selDotted;
|
|
extern int vfDeactByOtherApp;
|
|
extern HWND vhwndMsgBoxParent;
|
|
extern struct PPR **vhpprPRPrompt;
|
|
extern int vlm;
|
|
extern int vssc;
|
|
extern struct MERR vmerr;
|
|
extern int vfFocus;
|
|
extern BOOL vfDoubleClick;
|
|
extern BOOL vfRightClick;
|
|
extern int vfSysMenu;
|
|
extern MUD ** vhmudUser;
|
|
extern MUD ** vhmudBase;
|
|
extern KMP ** vhkmpUser;
|
|
extern KMP ** hkmpCur;
|
|
extern KMP ** hkmpBase;
|
|
extern CP vcpFetch;
|
|
extern int vfSeeSel;
|
|
extern int vcConseqScroll;
|
|
extern int sbScroll;
|
|
extern int sbScrollLast;
|
|
extern IDF vidf;
|
|
extern int cLongOpCount;
|
|
extern int vfMouseExist;
|
|
extern BOOL fElActive;
|
|
extern struct RF vrf;
|
|
extern BOOL vfInCommit;
|
|
extern int cbMemChunk;
|
|
extern struct BPTB vbptbExt;
|
|
#ifdef OPUS_X64
|
|
extern int vibp;
|
|
extern int vibpProtect;
|
|
#endif
|
|
extern int vgrfMenuKeysAreDirty;
|
|
extern BOOL vfEmptyMenu;
|
|
|
|
|
|
BOOL vfChildSysMenu = fFalse;
|
|
BOOL fRecordMove=fFalse;
|
|
BOOL fRecordSize=fFalse;
|
|
BOOL fCdlScrollSet=fFalse;
|
|
|
|
struct MERR vmerr;
|
|
|
|
|
|
extern BOOL vfRestPmtOnInput;
|
|
extern long vusecTimeoutPrompt;
|
|
extern int vcchStatLinePrompt;
|
|
extern int docCur;
|
|
extern struct DRF *vpdrfHead;
|
|
extern struct DRF *vpdrfHeadUnused;
|
|
extern int vfNoInval;
|
|
|
|
void MwdVertScroll( int, WORD, int );
|
|
void MwdHorzScroll( int, WORD, int );
|
|
void WwPaneMouse( int, unsigned, WORD, POINT );
|
|
#ifdef OPUS_X64
|
|
LRESULT LMenuChar(HWND, WPARAM, LPARAM);
|
|
void DrawMenuHelp(HMENU, UINT_PTR, int);
|
|
void SaveMenuHelpContext(WPARAM, LPARAM, int);
|
|
|
|
/*
|
|
* Opus used the sign bit of a Win16 WORD-sized int to distinguish its
|
|
* command ids from the SC_* values in WM_SYSCOMMAND. A Win64 int is 32
|
|
* bits, so casting WPARAM to int makes every SC_* value positive and causes
|
|
* Word to swallow window move/size/close commands as application commands.
|
|
*/
|
|
#define FOpusCommandWParam(wParam) ((short) LOWORD(wParam) >= 0)
|
|
#define BcmFromWParam(wParam) ((WORD) LOWORD(wParam))
|
|
#define WM_OPUS_X64_QUERY_SELECTION (WM_APP + 0x351)
|
|
#else
|
|
LONG LMenuChar(HWND, WORD, LONG);
|
|
#define FOpusCommandWParam(wParam) ((int) (wParam) >= 0)
|
|
#define BcmFromWParam(wParam) (wParam)
|
|
#endif
|
|
|
|
|
|
#ifdef DEBUG
|
|
ENV *penvBase;
|
|
BYTE fCoverWasActive;
|
|
#endif /* DEBUG */
|
|
|
|
#ifdef HYBRID
|
|
BOOL vfShowSwapping;
|
|
#endif /* HYBRID */
|
|
|
|
/************************************************************************/
|
|
/* WinMain -- Windows' equivalent of "main()" in standard C */
|
|
/************************************************************************/
|
|
|
|
/* %%Function:WinMain %%Owner:peterj */
|
|
#ifdef OPUS_X64
|
|
EXPORT int PASCAL OpusOriginalWinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
|
|
#else
|
|
EXPORT int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
|
|
#endif
|
|
HANDLE hInstance, hPrevInstance;
|
|
LPSTR lpszCmdLine;
|
|
int cmdShow;
|
|
{
|
|
int wMsg;
|
|
#ifdef DEBUG
|
|
ENV env;
|
|
extern BYTE fCoverActive;
|
|
#endif /* DEBUG */
|
|
#ifdef HYBRID
|
|
extern BYTE fCoverActive;
|
|
#endif
|
|
|
|
InitApploader();
|
|
#ifdef DEBUG
|
|
FInitCover(0);
|
|
fCoverWasActive = fCoverActive;
|
|
fCoverActive = fFalse;
|
|
#endif
|
|
#ifdef HYBRID
|
|
FInitCover(0);
|
|
fCoverActive &= GetProfileInt(szApp, SzShared("HybridfCoverActive"), 0);
|
|
#endif
|
|
|
|
/* Initialize our huge pointer info
|
|
** IMPORTANT FInitSegTable before GlobalMemInit, else GlobalMemInit may
|
|
cause our code being moved and WINDOW does not know that our segment
|
|
table has to be updated.
|
|
*/
|
|
if (!FInitSegTable( sbMax ))
|
|
{
|
|
ReportSz("FinitSegTable failure");
|
|
return fFalse; /* Could not initialize; exit the program */
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/* initialize SetJmp/DoJmp for out of memory errors */
|
|
penvBase = &env;
|
|
if (SetJmp (penvMem = penvBase))
|
|
{
|
|
Assert (fFalse);
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
#ifdef HYBRID
|
|
vfShowSwapping = GetProfileInt((LPSTR)szApp,
|
|
(LPSTR)SzFrameKey("HybridShowSwapping",HybridShowSwapping), 0);
|
|
if (vfShowSwapping) InstallInt3FHandler();
|
|
#endif /* HYBRID */
|
|
|
|
/* initialize structures, create initial windows, etc. */
|
|
|
|
if (!FInitWinInfo( hInstance, hPrevInstance, lpszCmdLine, cmdShow ))
|
|
{
|
|
CleanUpForExit();
|
|
return fFalse; /* Could not initialize; exit the program */
|
|
}
|
|
|
|
|
|
for (;;)
|
|
{
|
|
BOOL fHaveMsg = fFalse;
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
extern BOOL vfAllocGuaranteed, vfInCmd, vfInDebug;
|
|
extern int vnErrorLevel;
|
|
Assert(vfAllocGuaranteed == 0);
|
|
vfAllocGuaranteed = 0;
|
|
Assert(vfInCmd == 0);
|
|
vfInCmd = 0;
|
|
Assert(vfInDebug == 0);
|
|
vfInDebug = 0;
|
|
vnErrorLevel = 0;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
if (cLongOpCount > 0)
|
|
EndLongOp(fTrue);
|
|
|
|
while (!fHaveMsg)
|
|
/* wait for a message */
|
|
{
|
|
TopOfMainLoop();
|
|
|
|
/* iconbar dialog uses its own message loop */
|
|
if (vidf.fIBDlgMode)
|
|
{
|
|
Assert (!vidf.fDead);
|
|
IBDlgLoop();
|
|
}
|
|
/* idle if there are not messages ready */
|
|
else if (PeekMessage((LPMSG)&vmsgLast, NULL, NULL, NULL, PM_REMOVE))
|
|
/* we have a message */
|
|
fHaveMsg = fTrue;
|
|
|
|
else
|
|
{
|
|
BOOL fYield = fFalse;
|
|
if (!vfDeactByOtherApp && !vidf.fNotLive)
|
|
/* Neither an icon nor a dying ember -- perform background
|
|
tasks like screen update, showing selection, etc. */
|
|
fYield = !FIdle(); /* true if interrupted */
|
|
/* perform background DDE processes, if any (esp when deact, icon or dead) */
|
|
else if (vfDdeIdle)
|
|
DoDdeIdle ();
|
|
else
|
|
WaitMessage();
|
|
|
|
if (vmerr.mat == matFont || vmerr.mat == matDisp)
|
|
FlushPendingAlerts();
|
|
vmerr.mat = matNil;/* don't report errors in bkgnd processes */
|
|
vmerr.fHadMemAlert = fFalse;/* in case we already did */
|
|
|
|
if (fYield)
|
|
Yield();
|
|
}
|
|
}
|
|
|
|
if ((wMsg = vmsgLast.message) == WM_QUIT)
|
|
{
|
|
QuitExit();
|
|
Assert( fFalse );
|
|
}
|
|
|
|
/* If the prompt line wants to be cleared on input, vfRestPmtOnInput is
|
|
set. */
|
|
if (vfRestPmtOnInput && ((wMsg == WM_SYSCOMMAND)||
|
|
(wMsg == WM_KEYDOWN) ||
|
|
(wMsg == WM_LBUTTONDOWN) || (wMsg == WM_RBUTTONDOWN)
|
|
|| (wMsg == WM_COMMAND)))
|
|
{
|
|
BOOL fMsgForPrompt = vmsgLast.hwnd == vhwndPrompt;
|
|
RestorePrompt();
|
|
|
|
/* if the message was destined for the prompt and the prompt was
|
|
destroyed by RestorePrompt, don't try to send it on! */
|
|
fHaveMsg = !fMsgForPrompt || vhwndPrompt != NULL;
|
|
}
|
|
|
|
if (fHaveMsg)
|
|
{
|
|
/* keyboard processing */
|
|
if (!FIsKeyMessage((LPMSG) &vmsgLast))
|
|
{
|
|
/* messages not fully processed */
|
|
DispatchMessage((LPMSG)&vmsgLast);
|
|
}
|
|
|
|
if (vfChildSysMenu)
|
|
{
|
|
Assert(!vfSysMenu);
|
|
if (hwwdCur != hNil)
|
|
{
|
|
SendMessage((*hwwdCur)->hwnd, WM_SYSCOMMAND,
|
|
SC_KEYMENU, (DWORD) '-');
|
|
}
|
|
vfChildSysMenu = fFalse;
|
|
}
|
|
}
|
|
|
|
/* This means we got a WM_CBTTERM from CBT and waited to clean up
|
|
until they are no longer on our stack (since we free their
|
|
library as part of our cleanup) */
|
|
if (vrf.fMustStopCBT && !vfDeactByOtherApp)
|
|
{
|
|
StopCBT();
|
|
vrf.fMustStopCBT = fFalse;
|
|
}
|
|
|
|
} /* for (;;) */
|
|
Assert( fFalse );
|
|
}
|
|
|
|
|
|
/* performes standard actions between all commands */
|
|
/* %%Function:TopOfMainLoop %%Owner:peterj */
|
|
TopOfMainLoop()
|
|
{
|
|
int ww;
|
|
|
|
Assert (vfNoInval == 0);
|
|
vfNoInval = 0;
|
|
Assert (vpdrfHead == NULL);
|
|
vpdrfHead = NULL;
|
|
Assert (vpdrfHeadUnused == NULL);
|
|
Debug(vpdrfHeadUnused = NULL);
|
|
|
|
if (vidf.fDead)
|
|
return;
|
|
|
|
if (vmerr.fKillRulRib) /* take down before messages appear */
|
|
EndIbdlg();
|
|
|
|
if (vmerr.mat != matNil && !vidf.fNotLive)
|
|
FlushPendingAlerts();
|
|
|
|
/* if set, we should have had a mat set, so Flush... should have cleared this. bz */
|
|
Assert (vmerr.fHadMemAlert == fFalse || vidf.fNotLive);
|
|
|
|
vmerr.fHadMemAlert = fFalse;
|
|
vmerr.fErrorAlert = fFalse;
|
|
vmerr.fDiskAlert = fFalse;
|
|
vmerr.fDiskWriteErr = fFalse;
|
|
vmerr.fFmtFailed = fFalse;
|
|
vmerr.fCompressFailed = fFalse;
|
|
|
|
/* some document has overflown size we are capable of saving */
|
|
if (vmerr.fWarnDocTooBig)
|
|
{
|
|
ErrorEid(eidDocTooBigToSave, "WinMain");
|
|
vmerr.fWarnDocTooBig = fFalse;
|
|
}
|
|
|
|
/* if a nestable progress report was left active, deactivate it */
|
|
if (vhpprPRPrompt)
|
|
StopProgressReport(hNil, pdcRestore);
|
|
|
|
/* make sure no AbortChecks were left active */
|
|
Assert(vpisPrompt == pisNormal);
|
|
vpisPrompt = pisNormal;
|
|
|
|
|
|
/* check for no-dr case which will want to bag windows out of PageView */
|
|
if (vmerr.fNoDrs)
|
|
UpdateAllWws(fFalse);
|
|
|
|
Assert(cHpFreeze==0);
|
|
if (vmerr.hrgwEmerg3 == 0)
|
|
vmerr.hrgwEmerg3 = HAllocateCw(cwEmerg3);
|
|
if (vmerr.hrgwEmerg2 == 0)
|
|
vmerr.hrgwEmerg2 = HAllocateCw(cwEmerg2);
|
|
if (vmerr.hrgwEmerg1 == 0)
|
|
vmerr.hrgwEmerg1 = HAllocateCw(cwEmerg1);
|
|
vmerr.mat = matNil; /* Do not report errors from above allocations */
|
|
|
|
/* if we're in a memory emergency, pop all ww's out of page view */
|
|
if (vmerr.hrgwEmerg1 ==0 || vmerr.hrgwEmerg2 == 0 || vmerr.hrgwEmerg3 == 0)
|
|
{
|
|
for (ww = wwDocMin; ww < wwMac; ww++)
|
|
if (mpwwhwwd[ww] != hNil && PwwdWw(ww)->fPageView)
|
|
{
|
|
if (ww == wwCur)
|
|
/* go through FExecCmd so that special modes get terminated.
|
|
Undo, repeat, recording are also taken care of. FLegalBcm
|
|
will allow PageView if current window is already in page view */
|
|
FExecCmd(bcmPageView);
|
|
else
|
|
CmdPageViewOff(ww);
|
|
}
|
|
}
|
|
for (ww = wwDocMin; ww < wwMac; ww++)
|
|
{
|
|
struct WWD *pwwd;
|
|
if (mpwwhwwd[ww] !=hNil && (pwwd = PwwdWw(ww))->fOutline &&
|
|
PdodDoc(PmwdWw(ww)->doc)->hplcpad == hNil)
|
|
{
|
|
/* For various reasons, we do not restore
|
|
rulers in this case. */
|
|
pwwd->fHadRuler = fFalse;
|
|
FToggleOutline(ww);
|
|
}
|
|
}
|
|
|
|
/* from printer change message */
|
|
if (vrf.fCkPgMarg)
|
|
{
|
|
SetFlm( flmRepaginate );
|
|
FCheckPageAndMargins(selCur.doc, fTrue, fFalse, NULL);
|
|
vrf.fCkPgMarg = fFalse;
|
|
}
|
|
|
|
/* handle postponed system messages (from print, pictures) */
|
|
if (vpri.wmm)
|
|
CheckEnvPending();
|
|
|
|
/* close any files on floppies so we are not hosed if the user
|
|
removes/changes floppies */
|
|
CloseEveryFn(fFalse);
|
|
}
|
|
|
|
|
|
/* FInitWinInfo - initialise the world, this routine simply calls two
|
|
* other initialisation routines making sure their code modules get
|
|
* swapped out after use. It is reason for being (rather than have the
|
|
* code in line in WinMain, is to declare the command line buffers shared
|
|
* between FInitPart1 and FInitPart2.
|
|
*/
|
|
/* %%Function:FInitWinInfo %%Owner:peterj */
|
|
int FInitWinInfo( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
|
|
HANDLE hInstance, hPrevInstance;
|
|
LPSTR lpszCmdLine;
|
|
int cmdShow;
|
|
{
|
|
int ipchArgMac;
|
|
BOOL fOpenUntitled = fTrue;
|
|
BOOL fTutorial = fFalse;
|
|
CHAR rgchCmdLine [ichMaxCmdLine+1];
|
|
CHAR *rgpchArg [ipchArgMax];
|
|
extern int far pascal initwin_q();
|
|
extern int far pascal init2_q();
|
|
|
|
if (!FInitPart1( hInstance, hPrevInstance, lpszCmdLine,
|
|
rgchCmdLine, rgpchArg, &ipchArgMac, &fOpenUntitled, &fTutorial))
|
|
return fFalse;
|
|
|
|
/* get it out of memory */
|
|
#ifndef OPUS_X64
|
|
GlobalDiscard(GetCodeHandle((FARPROC)initwin_q));
|
|
#endif
|
|
|
|
if (!FInitPart2(cmdShow, rgchCmdLine, rgpchArg, ipchArgMac, fOpenUntitled, fTutorial))
|
|
return fFalse;
|
|
|
|
/* get it out of memory */
|
|
#ifndef OPUS_X64
|
|
GlobalDiscard(GetCodeHandle((FARPROC)init2_q));
|
|
#endif
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* NOTE: Messages bound for this WndProc are filtered in wprocn.asm */
|
|
|
|
/* %%Function:AppWndProc %%Owner:peterj */
|
|
#ifdef OPUS_X64
|
|
LRESULT CALLBACK AppWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
long EXPORT FAR PASCAL AppWndProc(hwnd, message, wParam, lParam)
|
|
HWND hwnd;
|
|
unsigned message;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
#endif
|
|
{
|
|
static int fEnteredIdle=fTrue;
|
|
static HMENU hMenu;
|
|
#ifdef OPUS_X64
|
|
static UINT_PTR bcm;
|
|
#else
|
|
static int bcm;
|
|
#endif
|
|
static int mf;
|
|
int cxt;
|
|
|
|
#ifdef OPUS_X64
|
|
LRESULT AppWndProcRare(HWND, UINT, WPARAM, LPARAM);
|
|
LRESULT AppWndProcAct(HWND, UINT, WPARAM, LPARAM);
|
|
#else
|
|
long AppWndProcRare();
|
|
long AppWndProcAct();
|
|
#endif
|
|
|
|
struct RC rc;
|
|
|
|
#ifdef SHOWAPPMSG
|
|
ShowMsg ("ap", hwnd, message, wParam, lParam);
|
|
#endif /* SHOWAPPMSG */
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log message */
|
|
{
|
|
int iwm = IScanLprgw((int far *)rgwmRsh,message,iwmMax);
|
|
if (iwm >= 0 && iwm < iwmMax)
|
|
LogUa(uaAppMessage+iwm);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
switch (message)
|
|
{
|
|
default:
|
|
return AppWndProcRare( hwnd, message, wParam,lParam );
|
|
|
|
case WM_ACTIVATE:
|
|
case WM_ACTIVATEAPP:
|
|
return AppWndProcAct( hwnd, message, wParam,lParam );
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
/* this keeps us from beeping unnecessarly when the application
|
|
is reactivated by a mouse click if a window is app modal */
|
|
if (vhwndAppModalFocus != hNil && vfDeactByOtherApp)
|
|
return (LONG) MA_ACTIVATEANDEAT;
|
|
else
|
|
goto LDefProc;
|
|
|
|
case WM_COMMAND:
|
|
/* Ignore command messages posted while in a message box (this
|
|
can happen when our app is activated by clicking on an icon
|
|
bar button while a message box is waiting to come up). BAC */
|
|
if (vcInMessageBox)
|
|
return 0L;
|
|
|
|
/* CBT hook must be the first thing we do under WM_COMMAND */
|
|
|
|
if (vhwndCBT && !SendMessage(vhwndCBT, WM_CBTSEMEV, smvCommand,
|
|
MAKELONG(CxtFromBcm(BcmFromWParam(wParam)), 0 /* from menu */)))
|
|
{
|
|
return (0L);
|
|
}
|
|
|
|
/* CBT returned TRUE; do normal handling */
|
|
|
|
EnsureFocusInPane();
|
|
|
|
SetOurKeyState(); /* we don't get a key-up for Alt! */
|
|
/* dyadic stuff handled at command level now */
|
|
|
|
RestorePrompt();
|
|
|
|
if (BcmFromWParam(wParam) == bcmNil) /* menu empty */
|
|
return (0L);
|
|
|
|
Assert(FOpusCommandWParam(wParam));
|
|
vcxtHelp = cxtNil;
|
|
FExecCmd(BcmFromWParam(wParam));
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log command */
|
|
{
|
|
int isc = IScanLprgw((int far *)rgscRsh,wParam,iscMax);
|
|
if (isc >= 0 && isc < iscMax)
|
|
LogUa(uaAppCommand+isc);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
if (vfHelp || vhwndCBT)
|
|
cxt = CxtAppSysMenu(wParam);
|
|
|
|
/* Must notify CBT before processing the message */
|
|
/* undocumented Windows fact: wParam & 0x000F is non-zero if
|
|
WM_SYSCOMMAND was generated from clicking in title bar or
|
|
sizing borders, and zero otherwise */
|
|
if (vhwndCBT && (!(wParam & 0x000F) || wParam == bcmControlRun))
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case SC_MOVE:
|
|
case SC_SIZE:
|
|
case SC_MAXIMIZE:
|
|
case SC_MINIMIZE:
|
|
case SC_RESTORE:
|
|
case SC_CLOSE:
|
|
case bcmControlRun:
|
|
#ifdef DEBUG
|
|
if (wParam == bcmControlRun)
|
|
Assert(cxt == CxtFromBcm(bcmControlRun));
|
|
#endif
|
|
if (!SendMessage(vhwndCBT, WM_CBTSEMEV, smvCommand,
|
|
MAKELONG(cxt, 0 /* from menu */)))
|
|
{
|
|
return (0L);
|
|
}
|
|
break;
|
|
|
|
#ifdef INEFFICIENT
|
|
case SC_NEXTWINDOW:
|
|
case SC_PREVWINDOW:
|
|
case SC_VSCROLL:
|
|
case SC_HSCROLL:
|
|
case SC_MOUSEMENU:
|
|
case SC_KEYMENU:
|
|
case SC_ARRANGE:
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (vfHelp)
|
|
{
|
|
if (cxt == cxtNil)
|
|
goto LDefProc; /* pressed Alt, or clicked to drop down a menu */
|
|
|
|
GetHelp(cxt);
|
|
return fTrue;
|
|
}
|
|
else
|
|
{
|
|
Profile(vpfi == pfiMenu ? StartProf(30) : 0);
|
|
EnsureFocusInPane();
|
|
vcxtHelp = cxtNil;
|
|
if (FOpusCommandWParam(wParam))
|
|
{
|
|
CmdExecBcmKc(BcmFromWParam(wParam), kcNil);
|
|
}
|
|
else
|
|
{
|
|
if (vfRecording)
|
|
RecordAppSysCmd(wParam);
|
|
switch (wParam & 0xfff0)
|
|
{
|
|
case SC_MOVE:
|
|
fRecordMove = fTrue;
|
|
break;
|
|
case SC_SIZE:
|
|
fRecordMove = fTrue;
|
|
fRecordSize = fTrue;
|
|
break;
|
|
}
|
|
goto LDefProc;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
/* setup the pull down menu before being drawn */
|
|
/* wParam is the popup menu handle */
|
|
/* LOWORD(lParam) = index of popup in main menu */
|
|
/* HIWORD(lParam) = 1 if system menu, 0 if application main menu */
|
|
EndLongOp(fTrue /* fAll */);
|
|
if (HIWORD(lParam) == 0)
|
|
{ /* we care for the application main menu only */
|
|
/* for the zorn menu in the menu bar HIWORD(lParam) is still 0 */
|
|
SetAppMenu((HMENU) wParam, lParam);
|
|
}
|
|
|
|
/* Turn on the cursor so we can see where it is */
|
|
if (!selCur.fOn && selCur.fIns)
|
|
{
|
|
/* Bug Fix BL 9/13/88: be sure window is up to date first */
|
|
UpdateWw( selCur.ww, fFalse /*fAbortOK*/ );
|
|
ToggleSel( &selCur, selCur.cpFirst, selCur.cpFirst );
|
|
selCur.fHidden = fFalse;
|
|
}
|
|
break;
|
|
|
|
case WM_MENUCHAR:
|
|
{
|
|
LONG lRet = LMenuChar(hwnd, wParam, lParam);
|
|
if (lRet != 0)
|
|
return lRet;
|
|
}
|
|
|
|
LDefProc:
|
|
return(DefWindowProc(hwnd, message, wParam, lParam));
|
|
|
|
case WM_SETCURSOR:
|
|
if (vfHelp | vfInLongOperation)
|
|
{
|
|
OurSetCursor(NULL); /* will set according to the vf's */
|
|
return fTrue;
|
|
}
|
|
goto LDefProc;
|
|
|
|
case WM_MENUSELECT:
|
|
SaveMenuHelpContext(wParam, lParam, cxtAppMenuSelect);
|
|
|
|
if (vhwndStatLine)
|
|
{
|
|
#ifdef OPUS_X64
|
|
hMenu = (HMENU) lParam;
|
|
mf = HIWORD(wParam);
|
|
bcm = (mf & MF_POPUP) && hMenu != NULL ?
|
|
(UINT_PTR) GetSubMenu(hMenu, LOWORD(wParam)) :
|
|
(UINT_PTR) LOWORD(wParam);
|
|
#else
|
|
hMenu = HIWORD(lParam);
|
|
bcm = wParam;
|
|
mf = LOWORD(lParam );
|
|
#endif
|
|
if (hMenu == 0 && fEnteredIdle)
|
|
DrawMenuHelp(hMenu, bcm, mf);
|
|
fEnteredIdle = fFalse;
|
|
|
|
if (!vwParamHelp && !vlParamHelp && !vcxtHelp) /* exit menu */
|
|
RestorePrompt();
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
/* received when no window has the input focus */
|
|
if (wParam == VK_F1 && !vfControlKey && !vfOptionKey)
|
|
{
|
|
if (vfShiftKey)
|
|
CmdHelpContext(NULL);
|
|
else
|
|
CmdHelp(NULL);
|
|
break;
|
|
}
|
|
goto LDefProc;
|
|
|
|
case WM_ENTERIDLE:
|
|
/* received from Windows code when idle in menu or dialog.
|
|
Now is the time to really paint status line menu help
|
|
NOTE: we don't use windows dialogs, bug libraries we call may
|
|
(esp. conv-wrd.dll).
|
|
wParam==MSGF_MENU indicates idle in menu, we should put up menuhelp
|
|
*/
|
|
Profile( vpfi == pfiMenu ? StopProf() : 0 );
|
|
|
|
Assert(wParam == MSGF_MENU || wParam == MSGF_DIALOGBOX); /* documentation said so */
|
|
if (wParam == MSGF_MENU && !fEnteredIdle && vhwndStatLine)
|
|
{
|
|
fEnteredIdle = fTrue;
|
|
DrawMenuHelp(hMenu, bcm, mf);
|
|
}
|
|
#ifdef DCORELOAD
|
|
CommSz(SzShared("."));
|
|
#endif /* DCORELOAD */
|
|
FAbortNewestCmg(cmgDlgNew, fTrue, fTrue);
|
|
break;
|
|
|
|
}
|
|
|
|
/* A window proc should always return something */
|
|
return(0L);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NOTE: Messages bound for this WndProc are filtered in wprocn.asm */
|
|
|
|
/* %%Function:MwdWndProc %%Owner:peterj */
|
|
#ifdef OPUS_X64
|
|
LRESULT CALLBACK MwdWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
long EXPORT FAR PASCAL MwdWndProc(hwnd, message, wParam, lParam)
|
|
HWND hwnd;
|
|
unsigned message;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
#endif
|
|
{
|
|
extern int mwCreate;
|
|
static int fEnteredIdle=fTrue;
|
|
static HMENU hMenu;
|
|
#ifdef OPUS_X64
|
|
static UINT_PTR bcm;
|
|
#else
|
|
static int bcm;
|
|
#endif
|
|
static int mf;
|
|
#ifdef OPUS_X64
|
|
LRESULT MwdWndProcRare(HWND, UINT, WPARAM, LPARAM);
|
|
#else
|
|
long MwdWndProcRare();
|
|
#endif
|
|
int ww;
|
|
PAINTSTRUCT ps;
|
|
|
|
#ifdef SHOWDOCMSG
|
|
ShowMsg ("dc", hwnd, message, wParam, lParam);
|
|
#endif /* SHOWDOCMSG */
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log message */
|
|
{
|
|
int iwm = IScanLprgw((int far *)rgwmRsh,message,iwmMax);
|
|
if (iwm >= 0 && iwm < iwmMax)
|
|
LogUa(uaMwdMessage+iwm);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
switch (message)
|
|
{
|
|
default:
|
|
return MwdWndProcRare( hwnd, message, wParam,lParam );
|
|
|
|
case WM_VSCROLL:
|
|
case WM_HSCROLL:
|
|
/* Vertical/Horizontal scroll bar input. wParam contains the
|
|
** scroll code. For the thumb movement codes, the low
|
|
** word of lParam contain the new scroll position.
|
|
** Possible values for wParam are: SB_LINEUP, SB_LINEDOWN,
|
|
** SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION, SB_THUMBTRACK
|
|
** Hiword of lParam contains the window handle of the
|
|
** scroll bar. */
|
|
EnsureFocusInPane();
|
|
Assert(hwwdCur);
|
|
#ifdef RSH
|
|
SetUatMode(uamNavigation);
|
|
StopUatTimer();
|
|
#endif /* RSH */
|
|
#ifdef OPUS_X64
|
|
{
|
|
WORD code = LOWORD(wParam);
|
|
int dqThumb = HIWORD(wParam);
|
|
HWND hwndScroll = (HWND) lParam;
|
|
|
|
if (message == WM_HSCROLL)
|
|
MwdHorzScroll(wwCur, code, dqThumb);
|
|
else
|
|
MwdVertScroll(((*hwwdCur)->hwndVScroll == hwndScroll) ?
|
|
wwCur : WwOther(wwCur), code, dqThumb);
|
|
if (vfRecording)
|
|
RecordScroll(message, code, dqThumb);
|
|
}
|
|
#else
|
|
if (message == WM_HSCROLL)
|
|
MwdHorzScroll( wwCur, wParam, (int)lParam);
|
|
else
|
|
MwdVertScroll(((*hwwdCur)->hwndVScroll == HIWORD(lParam)) ?
|
|
wwCur : WwOther(wwCur), wParam, (int)lParam);
|
|
if (vfRecording)
|
|
RecordScroll(message, wParam, LOWORD(lParam));
|
|
#endif
|
|
break;
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
{
|
|
int iRet =
|
|
#ifdef OPUS_X64
|
|
MA_ACTIVATE;
|
|
#else
|
|
0;
|
|
#endif
|
|
|
|
if (vhwndAppModalFocus != hNil)
|
|
if (!vfDeactByOtherApp)
|
|
return (LONG) MA_NOACTIVATE;
|
|
else
|
|
goto DefaultProc;
|
|
|
|
if (hmwdCur != hNil && (*hmwdCur)->hwnd != hwnd)
|
|
{
|
|
switch (LOWORD(lParam))
|
|
{
|
|
/* We eat HTCLIENT, HTSYSMENU, and HTMENU */
|
|
/* NOTE: HTSIZE, HTHSCROLL, and HTVSCROLL have no affect
|
|
because our scroll bars and size box are in our client
|
|
area and are therefore not considered by Windows to be
|
|
"real" scroll bars and size boxes. (BAC) */
|
|
|
|
case HTREDUCE:
|
|
case HTZOOM:
|
|
case HTCAPTION:
|
|
case HTSIZE:
|
|
case HTHSCROLL:
|
|
case HTVSCROLL:
|
|
case HTLEFT:
|
|
case HTRIGHT:
|
|
case HTTOP:
|
|
case HTTOPLEFT:
|
|
case HTTOPRIGHT:
|
|
case HTBOTTOM:
|
|
case HTBOTTOMLEFT:
|
|
case HTBOTTOMRIGHT:
|
|
iRet = MA_NOACTIVATE;
|
|
break;
|
|
|
|
case HTCLIENT:
|
|
NewCurWw( PmwdMw(MwFromHwndMw(hwnd))->wwActive, fFalse /*fDoNotSelect*/);
|
|
/* fall through */
|
|
default:
|
|
#ifdef OPUS_X64
|
|
/* Modern USER can activate and deliver this click without the
|
|
* Win16 re-entrancy workaround. Eating it makes the first click
|
|
* after switching documents disappear. */
|
|
iRet = MA_ACTIVATE;
|
|
#else
|
|
iRet = MA_ACTIVATEANDEAT;
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
return(iRet);
|
|
}
|
|
|
|
case WM_CHILDACTIVATE:
|
|
NewCurWw( PmwdMw(MwFromHwndMw(hwnd))->wwActive, fFalse /*fDoNotSelect*/);
|
|
break;
|
|
|
|
case WM_MENUCHAR:
|
|
{
|
|
LONG lRet = LMenuChar(hwnd, wParam, lParam);
|
|
if (lRet == 0)
|
|
goto DefaultProc;
|
|
else
|
|
return lRet;
|
|
}
|
|
|
|
case WM_SYSCOMMAND:
|
|
if (vfSysMenu)
|
|
/* don't really want to be here */
|
|
{
|
|
SendMessage(vhwndApp, message, wParam, lParam);
|
|
return fTrue;
|
|
}
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log command */
|
|
{
|
|
int isc = IScanLprgw((int far *)rgscRsh,wParam,iscMax);
|
|
if (isc >= 0 && isc < iscMax)
|
|
LogUa(uaMwdCommand+isc);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
if (vhwndCBT)
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case bcmRestoreWnd:
|
|
/* should get this here if doc window maximized;
|
|
would come through AppWndProc */
|
|
Assert (fFalse);
|
|
/* fall thru just in case */
|
|
|
|
case bcmMoveWnd:
|
|
case bcmSizeWnd:
|
|
case bcmZoomWnd:
|
|
case bcmSplit:
|
|
case bcmCloseWnd:
|
|
if (!SendMessage(vhwndCBT, WM_CBTSEMEV, smvCommand,
|
|
MAKELONG(CxtFromBcm(wParam), 0 /* from menu */)))
|
|
{
|
|
return (0L);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (vfHelp)
|
|
{
|
|
int cxt;
|
|
|
|
if ((cxt = CxtDocSysMenu(wParam)) == cxtNil)
|
|
goto DefaultProc; /* Probably clicked to drop down sys menu */
|
|
|
|
GetHelp(cxt);
|
|
return fTrue;
|
|
}
|
|
|
|
EnsureFocusInPane();
|
|
|
|
if (FOpusCommandWParam(wParam))
|
|
return CmdExecBcmKc(BcmFromWParam(wParam), kcNil) == cmdOK;
|
|
|
|
switch (wParam & 0xfff0)
|
|
{
|
|
case SC_MAXIMIZE:
|
|
fRecordMove = fFalse;
|
|
fRecordSize = fFalse;
|
|
CmdExecBcmKc(bcmZoomWnd, kcNil);
|
|
return fTrue;
|
|
|
|
case SC_MINIMIZE: /* not allowed! */
|
|
return fFalse;
|
|
|
|
case SC_SIZE:
|
|
if (vpref.fZoomMwd) /* not allowed if maximized! */
|
|
return fFalse;
|
|
fRecordMove = fTrue;
|
|
fRecordSize = fTrue;
|
|
break;
|
|
case SC_MOVE:
|
|
if (vpref.fZoomMwd) /* not allowed if maximized! */
|
|
return fFalse;
|
|
fRecordMove = fTrue;
|
|
}
|
|
if (vfRecording)
|
|
RecordDocSysCmd(wParam);
|
|
goto DefaultProc;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
lParam |= 0x10000; /* Windows lies the first time! */
|
|
vgrfMenuKeysAreDirty = 0xffff;/* force update of accelerator keys */
|
|
SetAppMenu((HMENU) wParam, lParam);
|
|
break;
|
|
|
|
case WM_MENUSELECT:
|
|
SaveMenuHelpContext(wParam, lParam, cxtDocMenuSelect);
|
|
|
|
if (vhwndStatLine)
|
|
{
|
|
#ifdef OPUS_X64
|
|
hMenu = (HMENU) lParam;
|
|
mf = HIWORD(wParam);
|
|
bcm = (mf & MF_POPUP) && hMenu != NULL ?
|
|
(UINT_PTR) GetSubMenu(hMenu, LOWORD(wParam)) :
|
|
(UINT_PTR) LOWORD(wParam);
|
|
#else
|
|
hMenu = HIWORD(lParam);
|
|
bcm = wParam;
|
|
mf = LOWORD(lParam );
|
|
#endif
|
|
if (hMenu == 0 && fEnteredIdle)
|
|
DrawMenuHelp(hMenu, bcm, mf);
|
|
fEnteredIdle = fFalse;
|
|
|
|
if (!vwParamHelp && !vlParamHelp && !vcxtHelp) /* exit menu */
|
|
RestorePrompt();
|
|
}
|
|
break;
|
|
|
|
case WM_ENTERIDLE:
|
|
/* received from Windows code when idle in menu or dialog.
|
|
Now is the time to really paint status line menu help
|
|
NOTE: we don't use windows dialogs, bug libraries we call may
|
|
(esp. conv-wrd.dll).
|
|
wParam==MSGF_MENU indicates idle in menu, we should put up menuhelp
|
|
*/
|
|
|
|
Assert(wParam == MSGF_MENU || wParam == MSGF_DIALOGBOX); /* documentation said so */
|
|
if (wParam == MSGF_MENU && !fEnteredIdle && vhwndStatLine)
|
|
{
|
|
fEnteredIdle = fTrue;
|
|
DrawMenuHelp(hMenu, bcm, mf);
|
|
}
|
|
#ifdef DCORELOAD
|
|
CommSz(SzShared("."));
|
|
#endif /* DCORELOAD */
|
|
FAbortNewestCmg(cmgDlgNew, fTrue, fTrue);
|
|
break;
|
|
|
|
}
|
|
|
|
/* A window proc should always return something */
|
|
return(0L);
|
|
|
|
DefaultProc: /* All messages not processed come here. */
|
|
return (DefWindowProc(hwnd, message, wParam, lParam));
|
|
}
|
|
|
|
|
|
/* S A V E M E N U H E L P C O N T E X T - */
|
|
/* Since we do not want to compute the help context every time the
|
|
user pulls down a menu, we will just save the wParam and lParam.
|
|
If the user hits F1, and vcxtHelp has not yet been set to something
|
|
else, we can compute the context from these saved values.
|
|
*/
|
|
/* %%Function:SaveMenuHelpContext %%Owner:rosiep */
|
|
#ifdef OPUS_X64
|
|
void SaveMenuHelpContext(WPARAM wParam, LPARAM lParam, int cxt)
|
|
#else
|
|
SaveMenuHelpContext(wParam,lParam,cxt)
|
|
WORD wParam;
|
|
LONG lParam;
|
|
int cxt;
|
|
#endif
|
|
{
|
|
Assert(cxt == cxtAppMenuSelect || cxt == cxtDocMenuSelect);
|
|
|
|
/* if we're exiting Menu Mode, no more help context */
|
|
#ifdef OPUS_X64
|
|
if (lParam == 0 && HIWORD(wParam) == 0xffff)
|
|
#else
|
|
if (HIWORD(lParam) == 0 || wParam == 0)
|
|
#endif
|
|
{
|
|
vwParamHelp = 0;
|
|
vlParamHelp = 0;
|
|
vcxtHelp = cxtNil;
|
|
}
|
|
else
|
|
{
|
|
vwParamHelp = wParam;
|
|
vlParamHelp = lParam;
|
|
vcxtHelp = cxt;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifdef REFERENCE /* most of these are now in UpdateWindowWw */
|
|
/* U P D A T E I N V A L I D W W */
|
|
/* Find out what Windows considers to be the invalid range of
|
|
the passed window. Mark it invalid in WWD & blank the area on the screen */
|
|
|
|
/* %%Function:UpdateInvalidWw %%Owner:NOTUSED */
|
|
UpdateInvalidWw(ww)
|
|
int ww;
|
|
{
|
|
struct RC rc, rcwAboveYwMin;
|
|
struct WWD **hwwd;
|
|
int ypTop;
|
|
|
|
/* First, get the update rect for the parent. This will do necessary background
|
|
erasure and border validation, the returned rectangle is ignored.
|
|
Test for wwCur assures we only do this once per UpdateWindows */
|
|
|
|
if (ww == wwCur)
|
|
GetUpdateRect( vhwndApp, (LPRECT) &rc, fTrue /* fErase */ );
|
|
|
|
if ((hwwd = mpwwhwwd [ww]) == hNil || (*hwwd)->wk == wkClipboard)
|
|
return;
|
|
|
|
/* Now, do the same for the document window, except that this time we use the
|
|
rect to update the invalid band stored in the WWD structure */
|
|
|
|
Assert( (*hwwd)->hwnd != NULL );
|
|
GetUpdateRect( (*hwwd)->hwnd, (LPRECT) &rc, fTrue /* fErase */);
|
|
|
|
if (FSectRc( PrcSet( &rcwAboveYwMin, 0, 0,
|
|
(*hwwd)->xwMac, (*hwwd)->ywMin ),
|
|
&rc, &rcwAboveYwMin ))
|
|
PatBltRc( (*hwwd)->hdc, &rcwAboveYwMin, vsci.ropErase );
|
|
|
|
if (vidf.fDead)
|
|
{
|
|
/* If we are in the process of shutting down, we DONT want to repaint,
|
|
but we DO want to erase the bkgrnd and validate the border */
|
|
PatBltRc( (*hwwd)->hdc, &rc, vsci.ropErase );
|
|
return;
|
|
}
|
|
|
|
/* draw portion of style name window border that extends above ypMin */
|
|
/* This is the only drawing/invalidation that we have to do in this area */
|
|
if ((*hwwd)->xwSelBar)
|
|
PaintStyStub( ww, &rc );
|
|
rc.ypTop = max( (*hwwd)->ywMin, rc.ypTop );
|
|
|
|
if (rc.ypTop < rc.ypBottom)
|
|
InvalWwRc(ww, &rc );
|
|
|
|
/* Since we have found out the invalid rect, and marked it invalid
|
|
in our structures, we don't want to hear about it again,
|
|
so we tell windows that we have made everything valid */
|
|
|
|
ValidateRect( (*hwwd)->hwnd, (LPRECT) NULL );
|
|
}
|
|
|
|
|
|
#endif /* REFERENCE */
|
|
|
|
|
|
|
|
/* NOTE: Messages bound for this WndProc are filtered in wprocn.asm */
|
|
|
|
/* %%Function:WwPaneWndProc %%Owner:peterj */
|
|
#ifdef OPUS_X64
|
|
LRESULT CALLBACK WwPaneWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
long EXPORT FAR PASCAL WwPaneWndProc(hwnd, message, wParam, lParam)
|
|
HWND hwnd;
|
|
unsigned message;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
#endif
|
|
{
|
|
int ww;
|
|
struct RC rc;
|
|
#ifdef OPUS_X64
|
|
LRESULT RareWwPaneWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
#else
|
|
long RareWwPaneWndProc();
|
|
#endif
|
|
|
|
#ifdef SHOWPNEMSG
|
|
ShowMsg ("pn", hwnd, message, wParam, lParam);
|
|
#endif /* SHOWPNEMSG */
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log message */
|
|
{
|
|
int iwm = IScanLprgw((int far *)rgwmRsh,message,iwmMax);
|
|
if (iwm >= 0 && iwm < iwmMax)
|
|
LogUa(uaWwdMessage+iwm);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
switch (message)
|
|
{
|
|
default:
|
|
return RareWwPaneWndProc( hwnd, message, wParam,lParam );
|
|
|
|
#ifdef OPUS_X64
|
|
case WM_OPUS_X64_QUERY_SELECTION:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case 0: return (LRESULT) selCur.cpFirst;
|
|
case 1: return (LRESULT) selCur.cpLim;
|
|
case 2: return (LRESULT) selCur.fIns;
|
|
case 3: return (LRESULT) selCur.sty;
|
|
case 4: return (LRESULT) selCur.xw;
|
|
case 5: return (LRESULT) vfDoubleClick;
|
|
case 6: return (LRESULT) selCur.sk;
|
|
case 7: return (LRESULT) selCur.yw;
|
|
case 8: return (LRESULT) selCur.dyp;
|
|
case 9: return (LRESULT) selCur.fOn;
|
|
case 10: return (LRESULT) selCur.fHidden;
|
|
case 11: return (LRESULT) selCur.xpFirst;
|
|
case 12: return (LRESULT) selCur.xpLim;
|
|
case 13: return (LRESULT) vfli.cpMin;
|
|
case 14: return (LRESULT) vfli.cpMac;
|
|
case 15: return (LRESULT) vfli.xpLeft;
|
|
case 16: return (LRESULT) vfli.xpRight;
|
|
case 17: return (LRESULT) vfli.ichMac;
|
|
case 18: return (LRESULT) vfli.rgdxp[0];
|
|
case 19: return (LRESULT) vfli.rgdxp[
|
|
vfli.ichMac == 0 ? 0 : vfli.ichMac - 1];
|
|
case 24: return (LRESULT) sizeof(struct CHR);
|
|
case 25: return (LRESULT) sizeof(struct CHRT);
|
|
case 26: return (LRESULT) sizeof(struct CHRV);
|
|
case 27: return (LRESULT) sizeof(struct CHRF);
|
|
case 28: return (LRESULT) sizeof(struct CHRDF);
|
|
case 29: return (LRESULT) sizeof(struct CHRFG);
|
|
case 30:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return (LRESULT) IMacPlc(pdr->hplcedl);
|
|
}
|
|
case 31:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return (LRESULT) CpPlc(pdr->hplcedl, (int) lParam);
|
|
}
|
|
case 32:
|
|
case 33:
|
|
case 34:
|
|
case 35:
|
|
{
|
|
struct EDL edl;
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
GetPlc(pdr->hplcedl, (int) lParam, &edl);
|
|
if (LOWORD(wParam) == 32) return (LRESULT) edl.ypTop;
|
|
if (LOWORD(wParam) == 33) return (LRESULT) edl.dyp;
|
|
if (LOWORD(wParam) == 34) return (LRESULT) edl.dcp;
|
|
return (LRESULT) edl.fDirty;
|
|
}
|
|
case 36:
|
|
case 37:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return LOWORD(wParam) == 36 ?
|
|
(LRESULT) pdr->cpFirst : (LRESULT) pdr->cpLim;
|
|
}
|
|
case 38: return (LRESULT) sizeof(struct EDL);
|
|
case 39:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return (LRESULT) pdr->fDirty;
|
|
}
|
|
case 40:
|
|
return (LRESULT) PwwdWw(WwFromHwnd(hwnd))->fDirty;
|
|
case 41: return (LRESULT) CpMacDocEdit(selCur.doc);
|
|
case 42:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return (LRESULT) pdr->dyl;
|
|
}
|
|
case 43:
|
|
return (LRESULT) DyOfRc(&PwwdWw(WwFromHwnd(hwnd))->rcwDisp);
|
|
case 44:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
return (LRESULT) pdr->dxl;
|
|
}
|
|
case 45:
|
|
return (LRESULT) DxOfRc(&PwwdWw(WwFromHwnd(hwnd))->rcwDisp);
|
|
case 46: return (LRESULT) CpMacDoc(selCur.doc);
|
|
case 47:
|
|
case 48:
|
|
{
|
|
struct EDL edl;
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
GetPlc(pdr->hplcedl, (int) lParam, &edl);
|
|
return LOWORD(wParam) == 47 ?
|
|
(LRESULT) edl.dlk : (LRESULT) edl.fEnd;
|
|
}
|
|
case 49: return (LRESULT) selCur.chp.ftc;
|
|
case 50: return (LRESULT) selCur.chp.hps;
|
|
case 51:
|
|
case 52:
|
|
{
|
|
CP cp = (CP) lParam;
|
|
if (cp < cp0 || cp >= CpMacDocEdit(selCur.doc))
|
|
return (LRESULT) -1;
|
|
FetchCp(selCur.doc, cp, fcmProps);
|
|
return LOWORD(wParam) == 51 ?
|
|
(LRESULT) vchpFetch.ftc : (LRESULT) vchpFetch.hps;
|
|
}
|
|
case 53:
|
|
return (LRESULT) IbstFontFromFtcDoc(selCur.chp.ftc,
|
|
selCur.doc);
|
|
case 54:
|
|
{
|
|
union FCID fcid;
|
|
fcid.lFcid = 0L;
|
|
fcid.ibstFont = (int)lParam;
|
|
return (LRESULT) fcid.ibstFont;
|
|
}
|
|
case 58:
|
|
return (LRESULT) sizeof(union FCID);
|
|
case 55:
|
|
case 56:
|
|
case 57:
|
|
InvalFli();
|
|
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
|
|
if (LOWORD(wParam) == 55)
|
|
return (LRESULT) vfli.dypLine;
|
|
if (LOWORD(wParam) == 56)
|
|
return (LRESULT) vfti.fcid.hps;
|
|
return (LRESULT) (vfti.dypAscent + vfti.dypDescent);
|
|
case 59:
|
|
case 60:
|
|
case 61:
|
|
case 62:
|
|
{
|
|
int bchr = 0;
|
|
int cchp = 0;
|
|
int hpsChpMax = 0;
|
|
int hpsFcidMax = 0;
|
|
int ichMax = 0;
|
|
InvalFli();
|
|
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
|
|
while (bchr < vbchrMac)
|
|
{
|
|
struct CHR *pchr =
|
|
(struct CHR *)&(**vhgrpchr)[bchr];
|
|
int cb = CbFromChrm(pchr->chrm);
|
|
if (cb <= 0 || cb > vbchrMac - bchr)
|
|
break;
|
|
if (pchr->chrm == chrmChp)
|
|
{
|
|
++cchp;
|
|
hpsChpMax = max(hpsChpMax,
|
|
(int)pchr->chp.hps);
|
|
hpsFcidMax = max(hpsFcidMax,
|
|
(int)pchr->fcid.hps);
|
|
ichMax = max(ichMax,
|
|
(int)(unsigned char)pchr->ich);
|
|
}
|
|
bchr += cb;
|
|
}
|
|
if (LOWORD(wParam) == 59) return (LRESULT) hpsChpMax;
|
|
if (LOWORD(wParam) == 60) return (LRESULT) hpsFcidMax;
|
|
if (LOWORD(wParam) == 61) return (LRESULT) cchp;
|
|
return (LRESULT) ichMax;
|
|
}
|
|
case 63:
|
|
InvalFli();
|
|
FormatLine(selCur.ww, selCur.doc, cp0);
|
|
if ((int)lParam < 0 || (int)lParam >= vfli.ichMac)
|
|
return (LRESULT) -1;
|
|
return (LRESULT) vfli.rgdxp[(int)lParam];
|
|
case 64:
|
|
case 65:
|
|
case 66:
|
|
case 67:
|
|
{
|
|
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
|
|
CP cp = CpPlc(pdr->hplcedl, 0);
|
|
InvalFli();
|
|
FormatLineDr(selCur.ww, cp, pdr);
|
|
if (LOWORD(wParam) == 64)
|
|
{
|
|
if ((int)lParam < 0 || (int)lParam >= vfli.ichMac)
|
|
return (LRESULT) -1;
|
|
return (LRESULT) vfli.rgdxp[(int)lParam];
|
|
}
|
|
if (LOWORD(wParam) == 65) return (LRESULT) vfli.dxsInch;
|
|
if (LOWORD(wParam) == 66) return (LRESULT) vfli.dxuInch;
|
|
return (LRESULT) vfti.dxpInch;
|
|
}
|
|
case 68:
|
|
{
|
|
int ich = (int)HIWORD(wParam);
|
|
InvalFli();
|
|
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
|
|
if (ich < 0 || ich >= vfli.ichMac)
|
|
return (LRESULT)-1;
|
|
return (LRESULT)(unsigned char)vfli.rgch[ich];
|
|
}
|
|
case 69:
|
|
{
|
|
CP cp = (CP)lParam;
|
|
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
|
|
return (LRESULT)-1;
|
|
FetchCp(selCur.doc, cp, fcmChars);
|
|
if (vccpFetch <= 0 || vhpchFetch == NULL)
|
|
return (LRESULT)-1;
|
|
return (LRESULT)(unsigned char)*vhpchFetch;
|
|
}
|
|
case 70:
|
|
{
|
|
CP cp = (CP)lParam;
|
|
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
|
|
return (LRESULT)-1;
|
|
FetchCp(selCur.doc, cp,
|
|
fcmChars + fcmProps + fcmParseCaps);
|
|
if (vccpFetch <= 0 || vhpchFetch == NULL)
|
|
return (LRESULT)-1;
|
|
return (LRESULT)(unsigned char)*vhpchFetch;
|
|
}
|
|
case 71:
|
|
{
|
|
CP cp = (CP)lParam;
|
|
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
|
|
return (LRESULT)-1;
|
|
FetchCp(selCur.doc, cp,
|
|
fcmChars + fcmProps + fcmParseCaps);
|
|
return (LRESULT)MAKELONG((WORD)vibpProtect,
|
|
(WORD)vibp);
|
|
}
|
|
}
|
|
return (LRESULT) -1;
|
|
#endif
|
|
|
|
case WM_SETFOCUS:
|
|
/* The window is getting the focus. wParam contains the window
|
|
** handle of the window that previously had the focus. */
|
|
WwPaneGetFocus(hwnd, (HWND)wParam);
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
/* The window is losing the focus. wParam contains the window
|
|
** handle of the window about to get the focus, or NULL. */
|
|
if (vidf.fDead)
|
|
break;
|
|
Debug(vdbs.fShakeHeap ? ShakeHeap() : 0);
|
|
WwPaneLoseFocus(hwnd, (HWND)wParam);
|
|
break;
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
{ /* reset the wwActivePane of its parent */
|
|
int fSscClick = fFalse;
|
|
|
|
if ((vhwndAppModalFocus != hNil) && !vfHelp)
|
|
if (!vfDeactByOtherApp)
|
|
return (LONG) MA_NOACTIVATE;
|
|
else
|
|
goto DefaultProc;
|
|
|
|
if (vfHelp || (GetMessageTime() < vcmsecHelp))
|
|
return(fTrue);
|
|
|
|
if (GetFocus() != hwnd)
|
|
{
|
|
int ww = WwFromHwnd(hwnd);
|
|
|
|
/* we want to gain focus */
|
|
if (HIWORD(lParam) == WM_RBUTTONDOWN)
|
|
vfRightClick = fTrue;
|
|
|
|
if (fSscClick = FSscClick())
|
|
{
|
|
int eid = eidInvalidSelection;
|
|
|
|
/* Note: Ssc click will do a quickmove/copy
|
|
unless selCur.fIns or in dyadic mode or a few
|
|
other cases. In those cases cancel the operation.
|
|
Better to do it now before we change the activation.
|
|
*/
|
|
if ( FOutlineEmpty(ww, fFalse) ||
|
|
(eid = EidMouseAction()) != eidNil )
|
|
{
|
|
ErrorEid(eid, "WwPaneWndProc");
|
|
return (LONG) MA_NOACTIVATE;
|
|
}
|
|
else
|
|
{
|
|
/* a value which is not sscNil. This will keep
|
|
NewCurWw from changing selCur.
|
|
*/
|
|
vssc = sscMouse;
|
|
}
|
|
}
|
|
|
|
/* Kludge Alert! Windows has a re-entrancy problem with MA_ACTIVATEANDEAT
|
|
such that we cannot call PeekMessage while nested in a WM_MOUSEACTIVATE
|
|
message to which we plan to return MA_ACTIVATEANDEAT. If we do, the
|
|
message will stay on the queue. NewCurWw can cause FMsgPresent to be
|
|
called indirectly. rp - 1/4/89
|
|
|
|
Dyadic copy formatting, which does some extra NewCurWw calls had a similar
|
|
problem with the MOUSEACTIVATE message not getting cleared. Setting the
|
|
flag so FMsgPresent will return solved the problem, though I am not sure
|
|
why, since the details are a little different that Rosie describes in
|
|
Opus bug 5810. bz 4-27-89
|
|
|
|
Moved setting of flag, now counter, to NewCurWw itself bz 5/10/89 */
|
|
|
|
NewCurWw(ww, fFalse /*fDoNotSelect*/);
|
|
if (fSscClick)
|
|
{
|
|
|
|
/* leave vssc as sscMouse so PselActive will use selDotted */
|
|
return(MA_ACTIVATE); /* cause click msg to do dyadic move */
|
|
}
|
|
else
|
|
{
|
|
#ifdef OPUS_X64
|
|
/* The Win16 eat-on-activate workaround makes the next
|
|
* physical click look like a double-click on modern USER.
|
|
* Let the activating click position the caret immediately. */
|
|
return(MA_ACTIVATE);
|
|
#else
|
|
return(MA_ACTIVATEANDEAT);
|
|
#endif
|
|
}
|
|
}
|
|
DefaultProc: /* All messages not processed come here. */
|
|
return (DefWindowProc(hwnd, message, wParam, lParam));
|
|
}
|
|
|
|
case WM_MENUCHAR:
|
|
{
|
|
LONG lRet = LMenuChar(hwnd, wParam, lParam);
|
|
if (lRet != 0)
|
|
return lRet;
|
|
goto DefaultProc;
|
|
}
|
|
|
|
case WM_SYSCOMMAND:
|
|
if ((wParam & 0xfff0) == SC_KEYMENU)
|
|
{
|
|
if (vfSysMenu || LOWORD(lParam != '-'))
|
|
return SendMessage(vhwndApp, message, wParam, lParam);
|
|
else if (vlm == lmPreview)
|
|
/* prevent Menu From Nowhere from popping up over the
|
|
Preview window */
|
|
return (0L);
|
|
}
|
|
|
|
#ifdef RSH
|
|
/* BLOCK - log command */
|
|
{
|
|
int isc = IScanLprgw((int far *)rgscRsh,wParam,iscMax);
|
|
if (isc >= 0 && isc < iscMax)
|
|
LogUa(uaMwdCommand+isc);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
goto DefaultProc;
|
|
|
|
case WM_PAINT:
|
|
/* Time for the window to draw itself. */
|
|
UpdateWindowWw(WwFromHwnd(hwnd));
|
|
break;
|
|
|
|
/* For each of following mouse window messages, wParam contains
|
|
** bits indicating whether or not various virtual keys are down,
|
|
** and lParam is a POINT containing the mouse coordinates. The
|
|
** keydown bits of wParam are: MK_LBUTTON (set if Left Button is
|
|
** down); MK_RBUTTON (set if Right Button is down); MK_SHIFT (set
|
|
** if Shift Key is down); MK_ALTERNATE (set if Alt Key is down);
|
|
** and MK_CONTROL (set if Control Key is down). */
|
|
|
|
case WM_SETCURSOR:
|
|
return 0L;
|
|
case WM_MOUSEMOVE:
|
|
ForceCursorChange(hwnd, &lParam, vidf.fInIdle/*fExact*/);
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONDBLCLK:
|
|
case WM_RBUTTONDOWN:
|
|
|
|
#ifdef RSH
|
|
{
|
|
int w = 0;
|
|
if (GetKeyState(VK_SHIFT) < 0) w |= 1;
|
|
if (GetKeyState(VK_MENU) < 0) w |= 2;
|
|
if (GetKeyState(VK_CONTROL) < 0) w |= 4;
|
|
LogUa(uaKeyState + w);
|
|
}
|
|
#endif /* RSH */
|
|
|
|
ww = WwFromHwnd( hwnd );
|
|
Assert( ww != wwNil );
|
|
WwPaneMouse(ww, message, wParam, MAKEPOINT(lParam));
|
|
|
|
}
|
|
/* A window proc should always return something */
|
|
return(0L);
|
|
}
|
|
|
|
|
|
/* %%Function:WwPaneMouse %%Owner:peterj */
|
|
void WwPaneMouse(ww, message, wParam, pt)
|
|
int ww;
|
|
unsigned message;
|
|
WORD wParam;
|
|
POINT pt;
|
|
{
|
|
BOOL fShift;
|
|
BOOL fInStyleName = fFalse;
|
|
|
|
if ((ww != wwCur) && !vfHelp)
|
|
return;
|
|
|
|
if (vfRecording)
|
|
{
|
|
#ifdef OPUS_X64
|
|
MessageBeep(MB_OK);
|
|
#else
|
|
Beep();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
Assert( message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ||
|
|
message == WM_LBUTTONDBLCLK );
|
|
vfDoubleClick = (message == WM_LBUTTONDBLCLK);
|
|
vfRightClick = (message == WM_RBUTTONDOWN);
|
|
|
|
Assert(hwwdCur != hNil);
|
|
|
|
if (vfDoubleClick && (GetMessageTime() < vcmsecHelp))
|
|
return;
|
|
|
|
/* styname area? */
|
|
if ((*hwwdCur)->xwSelBar > 0)
|
|
{
|
|
/* styname border? */
|
|
if (pt.x <= ((*hwwdCur)->xwSelBar + (vsci.dxpBorder << 1)))
|
|
if (vfHelp)
|
|
{
|
|
GetHelp(cxtStyleArea);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
fInStyleName = fTrue;
|
|
if (FXpNearStyWndBorder(pt.x, hwwdCur))
|
|
{
|
|
if (!vhwndCBT || SendMessage(vhwndCBT, WM_CBTSEMEV,
|
|
smvTrackStyWnd, 0L))
|
|
{
|
|
TrackStyWndCursor(pt);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
fShift = vgrpfKeyBoardState & wKbsShiftMask;
|
|
|
|
if (vfHelp)
|
|
{
|
|
GetHelp(CxtFromWwPt(ww, pt));
|
|
return;
|
|
}
|
|
|
|
/* the fCommand parameter for Mac is used as fControl in Win */
|
|
DoContentHit( pt, fShift, fFalse /* fOption */, vfControlKey /* fCommand */ );
|
|
|
|
if (!vfBlockSel && vfDoubleClick && fInStyleName)
|
|
{
|
|
if (!vhwndCBT || SendMessage(vhwndCBT, WM_CBTSEMEV, smvCommand,
|
|
MAKELONG(CxtFromBcm(bcmApplyStyleDlg), 2 /* dbl click */)))
|
|
{
|
|
CmdExecBcmKc(bcmApplyStyleDlg, kcNil);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/* %%Function:ClearAbortKeyState %%Owner:peterj */
|
|
ClearAbortKeyState()
|
|
{
|
|
GetAsyncKeyState(VK_ESCAPE);
|
|
GetAsyncKeyState(VK_CANCEL);
|
|
GetAsyncKeyState(VK_MENU);
|
|
}
|
|
|
|
|
|
/* SetOurKeyState
|
|
This function is called when ever there is likely to have been
|
|
a change in the state of the keyboard. This function updates
|
|
vgrpfKeyBoardState which contains the state of:
|
|
|
|
Keys:
|
|
Shift Key wKbsShiftMask
|
|
Control Key wKbsControlMask
|
|
Alt/Option/menu Key wKbsOptionMask
|
|
Capslock key wKbsCapsLckMask
|
|
|
|
Note that Extend Mode and Block Selection are not purely toggle key
|
|
because it could be turned off by switching windows or executing
|
|
certain commands.
|
|
*/
|
|
|
|
|
|
|
|
/* %%Function:SetOurKeyState %%Owner:peterj */
|
|
void SetOurKeyState()
|
|
{
|
|
#ifdef INTL
|
|
extern int vwWinVersion, vkRightBracket;
|
|
#endif /* INTL */
|
|
extern int vgrpfKeyBoardState;
|
|
int grpfT = vgrpfKeyBoardState;
|
|
|
|
vgrpfKeyBoardState = (GetKeyState(VK_SHIFT) < 0) ? wKbsShiftMask : 0;
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_MENU) < 0) ? wKbsOptionMask : 0;
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_CONTROL)<0) ? wKbsControlMask : 0;
|
|
|
|
#ifdef CAPSLOCKSFIX /* for intl only */
|
|
/* localized pre-Win3.0 keyboards don't toggle the caps-lock key! */
|
|
/* We detect localalized keyboards by looking at the vk for the ']'. */
|
|
/* Only for German and French (defined CAPSLOCKSFIX) */
|
|
if (vwWinVersion < 0x300 && vkRightBracket >= 0x600)
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_CAPITAL) < 0) ? wKbsCapsLckMask : 0;
|
|
else
|
|
#endif /* CAPSLOCKSFIX */
|
|
|
|
/* VK_CAPITAL is a toggle key, hence we check if it's toggled, not
|
|
if it's down */
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_CAPITAL) & 1) ? wKbsCapsLckMask : 0;
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_NUMLOCK) & 1) ? wKbsNumLckMask : 0;
|
|
|
|
if (vhwndStatLine != NULL &&
|
|
(grpfT & (wKbsCapsLckMask + wKbsNumLckMask)) !=
|
|
(vgrpfKeyBoardState & (wKbsCapsLckMask + wKbsNumLckMask)))
|
|
{
|
|
UpdateStatusLine(usoToggles);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* %%Function:FXpNearStyWndBorder %%Owner:peterj */
|
|
FXpNearStyWndBorder(xp, hwwd)
|
|
int xp;
|
|
struct WWD **hwwd;
|
|
{
|
|
int xpStyWndBorder = (*hwwd)->xwSelBar;
|
|
|
|
return( xp <= xpStyWndBorder &&
|
|
xp >= xpStyWndBorder - (vsci.dxpBorder << 1));
|
|
}
|
|
|
|
|
|
|
|
/* F W H K E Y */
|
|
/* Note: wParam is no longer used.
|
|
wCode, if >= 0 will be one of the MSGF_* codes, otherwise
|
|
we MUST pass it on to DefHookProc.
|
|
HC_'s no longer exist (except internally)
|
|
The Windows people are very confused about this too, and it took
|
|
me a while to figure it out with Bob Gunderson.
|
|
*/
|
|
|
|
/* %%Function:FWHKey %%Owner:peterj */
|
|
EXPORT long FAR PASCAL FWHKey(wCode, wParam, lpmsg)
|
|
int wCode, wParam;
|
|
LPMSG lpmsg;
|
|
{
|
|
int wm;
|
|
|
|
if (lpmsg != 0L && (wm = lpmsg->message) == WM_QUIT)
|
|
{
|
|
bltbx(lpmsg, (LPMSG)&vmsgLast, sizeof(MSG));
|
|
QuitExit();
|
|
Assert(fFalse);
|
|
}
|
|
|
|
switch (wCode)
|
|
{
|
|
case MSGF_DIALOGBOX:
|
|
Assert (lpmsg != 0L);
|
|
SetOurKeyState(); /* we don't get a key-up for Alt */
|
|
/* We will get this for non-SDM (printer driver) dialog boxes */
|
|
if (wm == WM_KEYDOWN && lpmsg->wParam == VK_F1
|
|
&& !vfControlKey && !vfOptionKey)
|
|
{
|
|
GetHelp(vcxtHelp);
|
|
}
|
|
break;
|
|
|
|
case MSGF_MESSAGEBOX:
|
|
Assert (lpmsg != 0L);
|
|
|
|
/* GetCapture will return NULL in a message box unless a
|
|
key is held down, in which case we don't want to process
|
|
a second key. Excel does this trick, which is where I
|
|
got it. This is to fix a bug where we'd crash if you
|
|
pressed a key to dismiss the message box and then
|
|
pressed F1 while the first key was still down. (rp)
|
|
*/
|
|
if (GetCapture())
|
|
break;
|
|
#ifdef DEBUG
|
|
if (!FCheckToggleKeyMessage(lpmsg) &&
|
|
wm == WM_KEYDOWN &&
|
|
FProcessDbgKey(KcModified(lpmsg->wParam)))
|
|
/* special debugging key processing */
|
|
return fTrue;
|
|
#endif /* DEBUG */
|
|
|
|
/* FALL THROUGH */
|
|
|
|
case MSGF_MENU:
|
|
Assert (lpmsg != 0L);
|
|
/** This code will call the help application if the user
|
|
* selects something from a menu with the keyboard. Mouse
|
|
* selection is handled elsewhere (in the wndproc). **/
|
|
SetOurKeyState();
|
|
|
|
/** return immediately if it's not the right message **/
|
|
if (wm != WM_KEYDOWN && wm != WM_SYSKEYDOWN)
|
|
break;
|
|
|
|
if (vfEmptyMenu && lpmsg->wParam == VK_UP)
|
|
return fTrue;
|
|
|
|
|
|
/** Two possible cases: (1) the user selects something from
|
|
* a menu, then presses F1. (2) The user is already in help
|
|
* mode, selects something from a menu, presses return. **/
|
|
if ((lpmsg->wParam == VK_F1 && !vfControlKey && !vfOptionKey)
|
|
|| (lpmsg->wParam == kcReturn && vfHelp))
|
|
{
|
|
CmdHelp(NULL);
|
|
return fTrue;
|
|
}
|
|
} /* end of switch (wCode) */
|
|
|
|
return DefHookProc(wCode, wParam, lpmsg, (FARPROC FAR *) &vlppFWHChain);
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef NOTUSED
|
|
/* %%Function:ChFromKc %%Owner:NOTUSED */
|
|
ChFromKc(kc)
|
|
int kc;
|
|
{
|
|
CHAR ch;
|
|
|
|
switch (kc)
|
|
{
|
|
case kcPageBreak:
|
|
ch = chSect;
|
|
break;
|
|
case kcColumnBreak:
|
|
ch = chColumnBreak;
|
|
break;
|
|
case kcNonBreakSpace:
|
|
ch = chNonBreakSpace;
|
|
break;
|
|
case kcNonReqHyphen:
|
|
ch = chNonReqHyphen;
|
|
break;
|
|
case kcNonBreakHyphen:
|
|
ch = chNonBreakHyphen;
|
|
break;
|
|
case kcNewLine:
|
|
ch = chCRJ;
|
|
break;
|
|
default:
|
|
ch = kc;
|
|
}
|
|
return (ch);
|
|
}
|
|
|
|
|
|
#endif /* NOTUSED */
|
|
|
|
|
|
|
|
|
|
|
|
/* F C H E C K T O G G L E K E Y M E S S A G E */
|
|
/* If the passed message is an up- or down- transition of a
|
|
keyboard toggle key (e.g. shift), update our global flags & return
|
|
fTrue; if not, return fFalse */
|
|
/* %%Function:FCheckToggleKeyMessage %%Owner:peterj */
|
|
FCheckToggleKeyMessage(lpmsg)
|
|
LPMSG lpmsg;
|
|
{
|
|
switch (lpmsg->message)
|
|
{
|
|
case WM_SYSKEYDOWN: /* we'll get WM_SYSKEY messages if no
|
|
window has the focus */
|
|
case WM_SYSKEYUP:
|
|
case WM_KEYDOWN:
|
|
case WM_KEYUP:
|
|
switch (lpmsg->wParam)
|
|
{
|
|
case VK_NUMLOCK:
|
|
case VK_CAPITAL:
|
|
case VK_CONTROL:
|
|
case VK_SHIFT:
|
|
/* FUTURE: SetOurKeyState will not work in win3 if the msg
|
|
is just peeked at and not removed. We had to add calls
|
|
to do that in the callers, and should remove this call
|
|
once we agree it is safe bz
|
|
*/
|
|
|
|
|
|
/* case VK_MENU:*/
|
|
SetOurKeyState();
|
|
return fTrue;
|
|
/* Following returns fFalse iff Alt key is down */
|
|
/* return !(lpmsg->lParam & 0x20000000);*/
|
|
}
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/* S p e c i a l S e l M o d e E n d */
|
|
/* cancel special selection modes. Check globals to avoid bringing
|
|
in code in the very common case when this routine has nothing to do. */
|
|
|
|
/* %%Function:SpecialSelModeEnd %%Owner:peterj */
|
|
SpecialSelModeEnd()
|
|
{
|
|
extern int vfBlockSel;
|
|
extern int vfExtendSel;
|
|
extern int vssc;
|
|
|
|
if (vfBlockSel)
|
|
BlockModeEnd();
|
|
if (vfExtendSel)
|
|
ExtendSelEnd();
|
|
if (vssc != sscNil)
|
|
CancelDyadic();
|
|
}
|
|
|
|
|
|
/* O U R S E T C U R S O R */
|
|
/* %%Function:OurSetCursor %%Owner:peterj */
|
|
EXPORT PASCAL OurSetCursor(hc)
|
|
HCURSOR hc;
|
|
{
|
|
if (vfHelp)
|
|
hc = vhcHelp;
|
|
else if (vfInLongOperation)
|
|
hc = vhcHourGlass;
|
|
|
|
if (!vfMouseExist && hc != vhcHourGlass)
|
|
hc = NULL;
|
|
|
|
#ifdef DEBUG
|
|
else
|
|
Assert (hc != NULL || vhcHourGlass == NULL);
|
|
#endif /* DEBUG */
|
|
|
|
SetCursor(hc);
|
|
}
|
|
|
|
|
|
|
|
/* these are here for swap-tuning purposes */
|
|
|
|
/* RestorePrompt
|
|
Remove the currently displayed prompt. If there is some other prompt that
|
|
should be displayed (based on the programs global mode) display that
|
|
prompt.
|
|
*/
|
|
|
|
/* %%Function:RestorePrompt %%Owner:peterj */
|
|
RestorePrompt ()
|
|
|
|
{
|
|
#ifdef RSH
|
|
StopSubTimer(uasMenu);
|
|
#endif /* RSH */
|
|
|
|
/* the following code should check the state of the program and assign to
|
|
pmt the new prompt to display. */
|
|
|
|
vfRestPmtOnInput = fFalse;
|
|
vusecTimeoutPrompt = 0;
|
|
|
|
if (vssc != sscNil)
|
|
SetPromptVssc();
|
|
else
|
|
{
|
|
if (vcchStatLinePrompt)
|
|
DisplayStatLinePrompt(pdcRestore);
|
|
}
|
|
if (vhwndPrompt != NULL)
|
|
HidePromptWindow();
|
|
if (vhwndStatLine)
|
|
UpdateWindow(vhwndStatLine);
|
|
else
|
|
UpdateWindow(vhwndDeskTop);
|
|
}
|
|
|
|
|
|
/* %%Function:HidePromptWindow %%Owner:peterj */
|
|
HidePromptWindow()
|
|
{
|
|
Assert(vhpprPRPrompt == hNil);
|
|
/* don't really destroy, just hide! */
|
|
SetWindowPos(vhwndPrompt, NULL, 0,0,0,0,
|
|
SWP_HIDEWINDOW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOMOVE);
|
|
Assert(vhwndPromptHidden == vhwndPrompt);
|
|
vhwndPrompt = NULL;
|
|
}
|
|
|
|
|
|
/* SetPromptRestore
|
|
Set the "restore prompt" information according to pdc.
|
|
*/
|
|
|
|
/* %%Function:SetPromptRestore %%Owner:peterj */
|
|
SetPromptRestore (pdc)
|
|
int pdc;
|
|
|
|
{
|
|
|
|
vusecTimeoutPrompt = 0;
|
|
vfRestPmtOnInput = fFalse;
|
|
if (pdc & pdcmRestore)
|
|
{
|
|
RestorePrompt();
|
|
return;
|
|
}
|
|
if (pdc & pdcmRestOnInput)
|
|
/* restore on input */
|
|
vfRestPmtOnInput = fTrue;
|
|
if (pdc & pdcmTimeout)
|
|
/* restore on timeout */
|
|
{
|
|
vusecTimeoutPrompt = GetTickCount() + usecPromptTimeout;
|
|
if (!vusecTimeoutPrompt)
|
|
vusecTimeoutPrompt++;
|
|
}
|
|
/* else: don't restore */
|
|
}
|
|
|
|
|
|
/* E n s u r e F o c u s I n P a n e */
|
|
/* This is called by the recipients of some messages which may arrive
|
|
while the user is in a ribbon or ruler combo box. It moves the
|
|
focus back to the pane, closing the combo, if necessary */
|
|
|
|
/* %%Function:EnsureFocusInPane %%Owner:peterj */
|
|
EnsureFocusInPane()
|
|
{
|
|
HWND hwnd;
|
|
|
|
if (!vfDeactByOtherApp && wwCur != wwNil &&
|
|
(hwnd = PwwdWw(wwCur)->hwnd) != GetFocus())
|
|
{
|
|
if (vidf.fIBDlgMode)
|
|
TermCurIBDlg(fFalse); /* escapes without doing action */
|
|
SetFocus(hwnd);
|
|
}
|
|
}
|
|
|
|
|
|
/* F I S K E Y M E S S A G E */
|
|
/* General key message handler. Pass messages to this and it will return
|
|
fTrue if it dealt with it, fFalse otherwise. This function knows about
|
|
insert mode. */
|
|
/* %%Function:FIsKeyMessage %%Owner:peterj */
|
|
BOOL FIsKeyMessage(lpmsg)
|
|
LPMSG lpmsg;
|
|
{
|
|
extern BOOL vfInsertMode;
|
|
extern KME vkme;
|
|
|
|
#ifdef COMING_SOON_TO_A_WORD_PROCESSOR_NEAR_YOU
|
|
/* and when is does, this flag should be part of vrf for
|
|
efficient DS usage */
|
|
static BOOL fIconBarPending = fFalse;
|
|
#endif
|
|
int wm, kc;
|
|
|
|
wm = lpmsg->message;
|
|
kc = lpmsg->wParam; /* key code or char */
|
|
|
|
|
|
#ifdef COMING_SOON_TO_A_WORD_PROCESSOR_NEAR_YOU
|
|
|
|
/* This is currently commented out due to the fact that Windows seems to
|
|
have a bug where they do not tell us when keys are released always... */
|
|
|
|
|
|
ShowMsg("KM", lpmsg->hwnd, wm, kc, lpmsg->lParam);
|
|
CommSz(SzShared("\r\n"));
|
|
|
|
/* Deal with Alt+Shift for IconBarMode */
|
|
/*CommSzNum(SzShared("f is "), fIconBarPending);*/
|
|
/* What it does: start icon bar mode when Alt and Shift are pressed
|
|
and released.
|
|
|
|
How it works: fIconBarPending is set whenever both the Alt and
|
|
Shift keys are down and reset when any other key is pressed.
|
|
When both the Alt and Shift keys have been released,
|
|
fIconBarPending is checked. If it is set, IconBarMode is
|
|
entered. */
|
|
|
|
if (wm == WM_KEYDOWN || wm == WM_SYSKEYDOWN)
|
|
{
|
|
fIconBarPending = ((kc == VK_MENU || kc == VK_SHIFT) &&
|
|
(GetKeyState(VK_MENU) & 0x8000) &&
|
|
(GetKeyState(VK_SHIFT) & 0x8000));
|
|
/*CommSzNum(SzShared("set f to "), fIconBarPending);*/
|
|
}
|
|
else if (fIconBarPending && (!(GetKeyState(VK_MENU) & 0x8000) &&
|
|
!(GetKeyState(VK_SHIFT) & 0x8000)))
|
|
{
|
|
CommSz(SzShared("Chaining...\r\n"));
|
|
ChainCmd(bcmIconBarMode);
|
|
fIconBarPending = fFalse;
|
|
}
|
|
#endif /* COMING_SOON___ */
|
|
|
|
|
|
|
|
/* FUTURE: TRASH THIS!!! (BAC) */
|
|
if (FCheckToggleKeyMessage(lpmsg))
|
|
goto LTranslate;
|
|
|
|
|
|
switch (wm)
|
|
{
|
|
case WM_CHAR:
|
|
/* this must come first! */
|
|
if (vhwndCBT && !SendMessage(vhwndCBT, WM_CBTSEMEV,
|
|
smvWmChar, MAKELONG(kc, 0)))
|
|
{
|
|
/* if CBT doesn't like it, kill it */
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
return fTrue;
|
|
}
|
|
|
|
if (vlm == lmPreview)
|
|
return fTrue;
|
|
if (vfInsertMode)
|
|
{
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
/* indicate we have a char to insert */
|
|
lpmsg->wParam |= 0x8000;
|
|
return fTrue;
|
|
}
|
|
|
|
LInsert:
|
|
if (hwwdCur != hNil && lpmsg->hwnd == (*hwwdCur)->hwnd)
|
|
{
|
|
if (vfExtendSel) /* catch the extend to alpha case */
|
|
{
|
|
if (kc != kcBackSpace)
|
|
{
|
|
ExtendSelToCh(kc);
|
|
return fTrue;
|
|
}
|
|
else
|
|
{
|
|
/* terminate Extend Mode before going into the insert code */
|
|
/* cannot simply add these keys as terminate mode keys in the keymap
|
|
because we still want the backspace and delete to be performed */
|
|
ExtendSelEnd();
|
|
}
|
|
}
|
|
|
|
/* don't allow typing with 2nd sel active */
|
|
if (vssc != sscNil)
|
|
#ifdef OPUS_X64
|
|
MessageBeep(MB_OK);
|
|
#else
|
|
Beep();
|
|
#endif
|
|
else
|
|
InsertLoopCh(kc, bcmNil);
|
|
|
|
return fTrue;
|
|
}
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
if (kc == VK_MENU)
|
|
{
|
|
if (vfInsertMode)
|
|
return fFalse;
|
|
goto LTranslate;
|
|
}
|
|
|
|
case WM_KEYDOWN:
|
|
/* Get Alt key state from message, as vfOptionKey cannot
|
|
be trusted. */
|
|
if ((lpmsg->lParam & 0x20000000) != 0)
|
|
{
|
|
vgrpfKeyBoardState |= wKbsOptionMask;
|
|
if ((uns)(kc - VK_F1) <= (VK_F2 - VK_F1))
|
|
kc += 10; /* assumes VK_Fn's are contiguous */
|
|
}
|
|
else
|
|
{
|
|
vgrpfKeyBoardState &= ~wKbsOptionMask;
|
|
}
|
|
|
|
/* Get current Ctrl key state; OurGetKeyState cannot be trusted
|
|
(sez bradch(rp)) */
|
|
vgrpfKeyBoardState |= (GetKeyState(VK_CONTROL)<0) ? wKbsControlMask : 0;
|
|
|
|
/* FUTURE: cursor keys will be in keymap someday... */
|
|
/* but because they're not, need to special case preview */
|
|
if (vlm != lmPreview && FCursKey(kc, !vfInsertMode /*fDoIt*/ ))
|
|
return !vfInsertMode;
|
|
|
|
|
|
kc = KcModified(kc); /* Apply Shift, Ctrl, etc. */
|
|
|
|
if (vfInsertMode)
|
|
{
|
|
extern KME * PkmeOfKcInChain();
|
|
KME * pkme;
|
|
|
|
#ifdef DEBUG /* special debug key processing */
|
|
if (FProcessDbgKey(kc))
|
|
{
|
|
/* message has been dealt with, throw away! */
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
return fTrue;
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
if ((pkme = PkmeOfKcInChain(kc)) == 0)
|
|
{
|
|
/* key not in table, try to translate */
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
/* Ctrl+ keys are not translated so we do
|
|
not have to deal with the CHAR message. */
|
|
#ifdef INTL
|
|
if (!TranslateMessage(lpmsg)) /* no beep on Ctrl+Alt */
|
|
#else
|
|
if ((FCtrlKc(kc) && !FAltKc(kc)) || !TranslateMessage(lpmsg))
|
|
#endif
|
|
#ifdef OPUS_X64
|
|
MessageBeep(MB_OK);
|
|
#else
|
|
Beep();
|
|
#endif
|
|
}
|
|
else if (pkme->kt == ktInsert)
|
|
{
|
|
/* key is special insert type */
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
/* indicate we have a char to insert */
|
|
lpmsg->wParam = pkme->ch | 0x8000;
|
|
}
|
|
else
|
|
{
|
|
/* command key not handled yet, tell
|
|
insert loop to stop */
|
|
return fFalse;
|
|
}
|
|
}
|
|
else /* !vfInsertMode */
|
|
{
|
|
if (!FExecKc(kc) && vkme.kt == ktInsert)
|
|
{
|
|
kc = vkme.ch;
|
|
goto LInsert;
|
|
}
|
|
}
|
|
|
|
return fTrue;
|
|
|
|
/* FUTURE: trash this when SetOurKeyState() is trashed (BAC) */
|
|
case WM_MOUSEMOVE:
|
|
if (vfInsertMode)
|
|
return fFalse;
|
|
|
|
/* Windows doesn't give us the shift KEYUP message if
|
|
mouse button is down!! */
|
|
SetOurKeyState();
|
|
/* FALL THROUGH */
|
|
|
|
case WM_SYSKEYUP:
|
|
case WM_KEYUP:
|
|
LTranslate:
|
|
if (vfInsertMode)
|
|
GetMessage(lpmsg, NULL, 0, 0);
|
|
|
|
|
|
SetOurKeyState(); /* must be done after msg removed for win3 */
|
|
TranslateMessage(lpmsg);
|
|
DispatchMessage(lpmsg);
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
/********************** CODE LRU MANIPULATIONS *************************/
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
#define cparaStrip (55*64)
|
|
|
|
/* sizes to request/get back */
|
|
csconst int mpsascpara[sasMin+1] =
|
|
{
|
|
/*sas, swap area >= */
|
|
/*0*/ 210*64, /* what we really want */
|
|
/*1*/ 175*64, /* enough for SDM */
|
|
/*2*/ 150*64, /* acceptable (won't load SDM) */
|
|
/*3*/ 128*64, /* lowest "good" amount - get warning & lose fonts below here */
|
|
/*4*/ 115*64,
|
|
/*5*/ 100*64,
|
|
/*6*/ 90*64,
|
|
/*7*/ 60*64,
|
|
/*8*/ cparaStrip
|
|
}; /* number of elements MUST equal mpsaseid in init2.c! */
|
|
|
|
|
|
int vsasCur = sasMin;
|
|
int vcShrinkSwapArea = 0;
|
|
int vfNoCoreLoad;
|
|
int vcparaReserve;
|
|
|
|
/* REVIEW ship(pj): do i really want this to stay around? */
|
|
int vcparaMaxReqLast = 0;
|
|
int vcparaRequestLast = 0;
|
|
int vcparaSwapLast = 0;
|
|
|
|
/* O U R S E T S A S */
|
|
/* Set Opus's SwapAreaSize according to sas */
|
|
/* %%Function:OurSetSas %%Owner:peterj */
|
|
EXPORT OurSetSas(sas)
|
|
int sas;
|
|
{
|
|
int cparaSwap;
|
|
|
|
Assert(sas >= 0 && sas <= sasMin);
|
|
|
|
if (vfNoCoreLoad Debug(|| vdbs.fNoCoreLoad))
|
|
{
|
|
vsasCur = sasMin;
|
|
return;
|
|
}
|
|
|
|
if (vcShrinkSwapArea != 0)
|
|
/* someome is counting on the fact that we are using min swap area */
|
|
sas = sasMin;
|
|
|
|
/* block - compute amount to ask for */
|
|
{
|
|
int cparaMaxReq = CpMin(SetSwapAreaSize(0) + (GlobalCompact(0)/16)
|
|
- vcparaReserve, 0x00007fffL);
|
|
int cparaRequest = min(mpsascpara[sas], max(cparaStrip, cparaMaxReq));
|
|
Assert(vfLargeFrameEMS == 0 || vfLargeFrameEMS == 1);
|
|
cparaSwap = SetSwapAreaSize(cparaRequest);
|
|
|
|
/* for use by AppInfo$() */
|
|
vcparaMaxReqLast = cparaMaxReq;
|
|
vcparaRequestLast = cparaRequest;
|
|
vcparaSwapLast = cparaSwap;
|
|
|
|
#ifdef DCORELOAD
|
|
CommSzNum(SzShared("sas = "), sas);
|
|
CommSzNum(SzShared("cparaRequest = "), cparaRequest);
|
|
CommSzNum(SzShared("cparaSwap = "), cparaSwap);
|
|
#endif /* DCORELOAD */
|
|
}
|
|
|
|
/* given how much swap area we now have, what can we do with it? */
|
|
for (vsasCur = sas; vsasCur < sasMin; vsasCur++)
|
|
{
|
|
if (mpsascpara[vsasCur] <= cparaSwap)
|
|
break;
|
|
}
|
|
|
|
#ifdef DCORELOAD
|
|
CommSzNum (SzShared("\t\tvsasCur = "), vsasCur);
|
|
CommSzNum (SzShared("\t\tSwap Area Available (K)= "), cparaSwap/64);
|
|
#endif /* DCORELOAD */
|
|
}
|
|
|
|
|
|
/* C O R E N E W E S T */
|
|
/* Makes newest (or loads) the Opus core. Also loads portions of Windows
|
|
needed for our "core" functionality. Pays some attention to how much
|
|
memory is available when loading. Interruptable when loading.
|
|
*/
|
|
/* %%Function:CoreNewest %%Owner:peterj */
|
|
CoreNewest(fLoad)
|
|
BOOL fLoad;
|
|
{
|
|
int ihcd;
|
|
extern int vsasCur;
|
|
|
|
if (hmwdCur == hNil || vfDeactByOtherApp)
|
|
return;
|
|
|
|
#ifdef DCORELOAD
|
|
if (fLoad)
|
|
CommSz(SzShared(" {"));
|
|
#endif /* DCORELOAD */
|
|
|
|
/* SDM - all (just Newest it) */
|
|
if (FAbortNewestCmg(cmgCoreSdmAll, fFalse, fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* windows code for scroll bars */
|
|
if ((vpref.fHorzScrollBar || vpref.fVertScrollBar) &&
|
|
FAbortNewestCmg(cmgCoreWinScroll, (fLoad && vsasCur <= 2), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* windows core */
|
|
if (FAbortNewestCmg(cmgCoreWindows, (fLoad && vsasCur <= 2), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* optional core */
|
|
if (vpref.fBkgrndPag &&
|
|
FAbortNewestCmg(cmgCoreLayout, (fLoad && vsasCur <= 3), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
if ((vhwndRibbon || (hmwdCur != hNil && (*hmwdCur)->hwndRuler != NULL))
|
|
&& FAbortNewestCmg(cmgCoreRibbon, (fLoad && vsasCur <= 4), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
if (vhwndStatLine &&
|
|
FAbortNewestCmg(cmgCoreStatline, (fLoad && vsasCur <= 4), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* SDM - startup portion */
|
|
if (FAbortNewestCmg(cmgDlgNew, (fLoad && vsasCur <= 1), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* semi optional portion of core */
|
|
if (FAbortNewestCmg(cmgCore1, (fLoad && vsasCur <= 5), fTrue))
|
|
goto LDone;
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* not really optional core */
|
|
FAbortNewestCmg(cmgCore2, (fLoad && vsasCur <= 6), fTrue);
|
|
|
|
if (FMsgPresent(mtyIdle))
|
|
goto LDone;
|
|
|
|
/* not really optional core */
|
|
FAbortNewestCmg(cmgCore3, (fLoad && vsasCur <= 7), fTrue);
|
|
|
|
LDone:
|
|
;
|
|
|
|
#ifdef DCORELOAD
|
|
if (fLoad)
|
|
{
|
|
static int cLoad = 0;
|
|
CommSz(SzShared("} "));
|
|
if (!(++cLoad & 15))
|
|
CommSz(SzShared("\r\n"));
|
|
}
|
|
#endif /* DCORELOAD */
|
|
|
|
}
|
|
|
|
|
|
/* F A B O R T N E W E S T C M G */
|
|
/* Makes Code Module Group identified by cmg newest. If fLoad will force
|
|
them to be loaded. May be interrupted if fAbortOk. Returns fTrue if
|
|
interrupted, otherwise fFalse.
|
|
See core.h for structures etc.
|
|
*/
|
|
/* %%Function:FAbortNewestCmg %%Owner:peterj */
|
|
FAbortNewestCmg (cmg, fLoad, fAbortOk)
|
|
int cmg;
|
|
BOOL fLoad, fAbortOk;
|
|
{
|
|
HANDLE hcd;
|
|
int iihcd = 0;
|
|
int ihcd;
|
|
|
|
#ifdef HYBRID
|
|
if (vfShowSwapping)
|
|
return fFalse;
|
|
#endif /* HYBRID */
|
|
#ifdef DEBUG
|
|
if (vdbs.fNoCoreLoad)
|
|
return fFalse;
|
|
#endif /* DEBUG */
|
|
|
|
if (vfNoCoreLoad || vhwndCBT != NULL)
|
|
return fFalse;
|
|
|
|
/* so we don't kick them out on their way in! */
|
|
if (fLoad && FAbortNewestCmg(cmg, fFalse, fAbortOk))
|
|
return fTrue;
|
|
|
|
while ((ihcd = mpcmgrgihcd [cmg][iihcd++]) != ihcdEnd)
|
|
{
|
|
MSG msg;
|
|
if (fAbortOk &&
|
|
PeekMessage(&msg, NULL, NULL, NULL, PM_NOYIELD|PM_NOREMOVE))
|
|
{
|
|
#ifdef DCORELOAD
|
|
CommSz(SzShared("FAbortNewestCmg aborted\r\n"));
|
|
#endif /* DCORELOAD */
|
|
return fTrue;
|
|
}
|
|
|
|
if (fLoad || (hcd = rghcdModules [ihcd]) == NULL)
|
|
{
|
|
StartUMeas (umGetCodeHandle);
|
|
hcd = rghcdModules[ihcd] = GetCodeHandle(mpihcdpfnModules[ihcd]);
|
|
StopUMeas (umGetCodeHandle);
|
|
}
|
|
StartUMeas (umGlobalLru);
|
|
GlobalLruNewest (hcd);
|
|
StopUMeas (umGlobalLru);
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/* O L D E S T C M G */
|
|
/* makes modules in cmg oldest.
|
|
*/
|
|
/* %%Function:OldestCmg %%Owner:peterj */
|
|
OldestCmg (cmg)
|
|
int cmg;
|
|
{
|
|
int iihcd = 0;
|
|
int ihcd;
|
|
HANDLE hcd;
|
|
|
|
while ((ihcd = mpcmgrgihcd [cmg][iihcd++]) != ihcdEnd)
|
|
{
|
|
if ((hcd = rghcdModules[ihcd]) == NULL)
|
|
continue;
|
|
StartUMeas (umGlobalLru);
|
|
GlobalLruOldest (hcd);
|
|
StopUMeas (umGlobalLru);
|
|
}
|
|
}
|
|
|
|
|
|
/* G E T N E X T H C D */
|
|
/* Finds the next NULL entry in rghcdModules and obtains the module handle
|
|
for it.
|
|
*/
|
|
/* %%Function:GetNextHcd %%Owner:peterj */
|
|
GetNextHcd()
|
|
{
|
|
int ihcd;
|
|
for (ihcd = 0; ihcd < ihcdQuietlyLoadMax; ihcd++)
|
|
{
|
|
if (rghcdModules[ihcd] == NULL)
|
|
{
|
|
rghcdModules[ihcd] = GetCodeHandle(mpihcdpfnModules[ihcd]);
|
|
Assert(rghcdModules[ihcd] != NULL);
|
|
break;
|
|
}
|
|
}
|
|
#ifdef DCORELOAD
|
|
if (ihcd == ihcdQuietlyLoadMax)
|
|
{
|
|
static int fReported = fFalse;
|
|
if (!fReported)
|
|
CommSz(SzShared("All desired handles in rghcd obtained\r\n"));
|
|
fReported = fTrue;
|
|
}
|
|
#endif /* DCORELOAD */
|
|
}
|
|
|
|
|
|
/*
|
|
Return true if the window is not visible */
|
|
/* %%Function:FWindowHidden %%Owner:peterj */
|
|
FWindowHidden(ww)
|
|
int ww;
|
|
{
|
|
|
|
Assert(ww);
|
|
return !IsWindowVisible(PwwdWw(ww)->hwnd);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG /* debug routines that we would like to be in the core */
|
|
|
|
/* D u m m y */
|
|
/* A Do-nothing function useful for breakpointing in the middle of
|
|
long routines */
|
|
|
|
/* %%Function:Dummy %%Owner:peterj */
|
|
Dummy()
|
|
{
|
|
}
|
|
|
|
|
|
/* %%Function:NatDummy %%Owner:peterj */
|
|
NATIVE NatDummy() /* WINIGNORE - DEBUG only */
|
|
{
|
|
}
|
|
|
|
|
|
ARG_RAREEVENTS RareEvent[RareEventMax];
|
|
|
|
/* F R A R E P R O C */
|
|
/* this procedure returns true if the selected rare event has
|
|
occured the selected number of times
|
|
wEventNumber identifier of event
|
|
wRepetitions current repetition count
|
|
wRepetitionsMac stop repetition count
|
|
fOn count on/off flag
|
|
These variables will be typically set from the debugger or other debug
|
|
routines.
|
|
*/
|
|
/* %%Function:FRareProc %%Owner:peterj */
|
|
NATIVE FRareProc(n) /* WINIGNORE - DEBUG only */
|
|
int n;
|
|
{
|
|
int i;
|
|
int fRetVal;
|
|
|
|
fRetVal = fFalse;
|
|
|
|
for (i=0; i < RareEventMax; i++)
|
|
{
|
|
if (RareEvent[i].fOn && (RareEvent[i].wEventNumber == n))
|
|
if (RareEvent[i].wRepetitions < RareEvent[i].wRepetitionsMac)
|
|
if (++RareEvent[i].wRepetitions == RareEvent[i].wRepetitionsMac)
|
|
fRetVal = fTrue;
|
|
}
|
|
|
|
return(fRetVal);
|
|
}
|
|
|
|
|
|
/* %%Function:FRareNULL %%Owner:peterj */
|
|
NATIVE FRareNULL(re,w) /* WINIGNORE - DEBUG only */
|
|
int re;
|
|
int w;
|
|
{
|
|
int i;
|
|
int fRetVal;
|
|
|
|
fRetVal = w;
|
|
if (!fRetVal)
|
|
return NULL;
|
|
|
|
for (i=0; i < RareEventMax; i++)
|
|
{
|
|
if (RareEvent[i].fOn && (RareEvent[i].wEventNumber == re))
|
|
if (RareEvent[i].wRepetitions < RareEvent[i].wRepetitionsMac)
|
|
if (++RareEvent[i].wRepetitions == RareEvent[i].wRepetitionsMac)
|
|
fRetVal = NULL;
|
|
}
|
|
|
|
return(fRetVal);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A s s e r t H S z L n */
|
|
/* If H is not a valid, nonfree handle, report an Assertion failure
|
|
in file szFile, line line */
|
|
|
|
/* %%Function:AssertHSzLn %%Owner:peterj */
|
|
AssertHSzLn( h, szFile, line )
|
|
VOID **h;
|
|
CHAR szFile[];
|
|
int line;
|
|
{
|
|
struct DRF *pdrfList;
|
|
extern struct SCC vsccAbove;
|
|
|
|
for (pdrfList = vpdrfHead; pdrfList != NULL; pdrfList = pdrfList->pdrfNext)
|
|
if (pdrfList->dr.hplcedl == h)
|
|
{
|
|
if (!(*((struct PLC **)h))->fExtBase)
|
|
break;
|
|
Assert (pdrfList->dr.hplcedl == &pdrfList->pplcedl);
|
|
Assert (pdrfList->pplcedl == &pdrfList->dr.plcedl);
|
|
return;
|
|
}
|
|
|
|
if (!FCheckHandle (sbDds, h))
|
|
{
|
|
if (!(h == vsccAbove.hplcedl || *h == &vsccAbove))
|
|
AssertProc(szFile, line );
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
/* %%Function:ForceCursorChange %%Owner:peterj */
|
|
ForceCursorChange(hwnd, ppt, fExact)
|
|
HWND hwnd;
|
|
struct PT * ppt;
|
|
BOOL fExact;
|
|
{
|
|
HCURSOR hc = NULL;
|
|
struct WWD *pwwd;
|
|
BOOL fOtlEmpty;
|
|
extern struct SEL selCur;
|
|
extern int vfInLongOperation;
|
|
extern int mwCur;
|
|
extern HWND vhwndPgPrvw;
|
|
extern struct WWD **mpwwhwwd[];
|
|
extern HCURSOR vhcArrow, vhcRecorder, vhcIBeam, vhcBarCur,
|
|
vhcHelp, vhcStyWnd, vhcOtlCross, vhcColumn;
|
|
extern BOOL vfHelp, vfRecording;
|
|
extern struct WWD **hwwdCur;
|
|
|
|
vidf.fCorrectCursor = fFalse;
|
|
|
|
if (vfHelp)
|
|
hc = vhcHelp;
|
|
else if (vfInLongOperation)
|
|
hc = vhcHourGlass;
|
|
else if (hwnd == NULL || vhwndPgPrvw != NULL)
|
|
hc = vhcArrow;
|
|
else if (vfRecording)
|
|
hc = vhcRecorder;
|
|
if (hc != NULL)
|
|
goto lblSet;
|
|
|
|
hc = vhcArrow;
|
|
if (hwwdCur != hNil && hwnd == (pwwd = *hwwdCur)->hwnd)
|
|
{
|
|
int ww = wwCur;
|
|
int xw = ppt->xw;
|
|
int dxp = vsci.dxpBorder << 1;
|
|
|
|
Assert(ww != wwNil);
|
|
Assert(wwCur == GetWindowWord(hwnd, IDWWW));
|
|
Assert(mwCur == pwwd->mw);
|
|
|
|
if (pwwd->xwSelBar && xw < pwwd->xwSelBar + dxp)
|
|
{
|
|
Assert(!pwwd->fPageView);
|
|
if (xw <= pwwd->xwSelBar &&
|
|
xw >= pwwd->xwSelBar - dxp /* fNearSty */)
|
|
{
|
|
if (vhcStyWnd == NULL && !FAssureIrcds(ircdsStyWnd))
|
|
hc = vhcArrow;
|
|
else
|
|
hc = vhcStyWnd;
|
|
}
|
|
else
|
|
hc = vhcBarCur;
|
|
}
|
|
else if (ppt->yw >= pwwd->ywMin)
|
|
{
|
|
if (fExact)
|
|
{
|
|
int idr;
|
|
int dl;
|
|
struct PLDR **hpldr;
|
|
struct PT ptT;
|
|
struct SPT spt;
|
|
|
|
ptT = *ppt;
|
|
if ((fOtlEmpty = FOutlineEmpty(ww, fFalse)) ||
|
|
(dl = DlWherePt(ww, &ptT, &hpldr, &idr, &spt, fTrue, fTrue))
|
|
== dlNil)
|
|
goto lblSet;
|
|
if (spt.fWholeColumn)
|
|
hc = vhcColumn;
|
|
else if (spt.fSelBar)
|
|
{
|
|
hc = vhcBarCur;
|
|
dl = DlWherePt(ww, &ptT, &hpldr, &idr, &spt, fFalse, fFalse);
|
|
if ((*hwwdCur)->fOutline && !fOtlEmpty && dl != dlNil &&
|
|
FXwInBullet(ww, dl, ppt->xw))
|
|
{
|
|
int yp, ywBottom;
|
|
struct EDL edl;
|
|
GetPlc(PdrGalley(PwwdWw(ww))->hplcedl, dl, &edl);
|
|
yp = edl.ypTop + edl.dyp;
|
|
|
|
ywBottom = YwFromYp(((edl.hpldr != hNil) ?
|
|
edl.hpldr : HwwdWw(ww)), 0, yp);
|
|
if (ppt->yw <= ywBottom)
|
|
hc = vhcOtlCross;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hc = (selCur.fGraphics ? vhcArrow : vhcIBeam);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vidf.fCorrectCursor = fTrue;
|
|
hc = vhcIBeam;
|
|
}
|
|
}
|
|
}
|
|
|
|
lblSet:
|
|
SetCursor( hc );
|
|
}
|
|
|
|
|
|
/* L M E N U C H A R */
|
|
/*
|
|
Handle WM_MENUCHAR messages. Returns 0 if message should be
|
|
passed to DefWindowProc(). Non-0 return values should be returned
|
|
by the window proc receiving the message.
|
|
*/
|
|
/* %%Function:LMenuChar %%Owner:peterj */
|
|
#ifdef OPUS_X64
|
|
LRESULT LMenuChar(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
LONG LMenuChar(hwnd, wParam, lParam)
|
|
HWND hwnd;
|
|
WORD wParam;
|
|
LONG lParam;
|
|
#endif
|
|
{
|
|
if (vhwndAppModalFocus != NULL)
|
|
return MAKELONG(0, 1);
|
|
|
|
#ifdef OPUS_X64
|
|
if (LOWORD(wParam) == '-' && !(HIWORD(wParam) & MF_POPUP) &&
|
|
hwwdCur != hNil)
|
|
#else
|
|
if (wParam == '-' && !(LOWORD(lParam) & MF_POPUP) && hwwdCur != hNil)
|
|
#endif
|
|
{
|
|
if (vfSysMenu)
|
|
{
|
|
if (hwnd == vhwndApp)
|
|
return MAKELONG(0,2);
|
|
|
|
PostMessage(vhwndApp, WM_MENUCHAR, wParam, lParam);
|
|
return MAKELONG(0, 1);
|
|
}
|
|
|
|
if (hwnd == vhwndApp)
|
|
{
|
|
vfChildSysMenu = fTrue;
|
|
return MAKELONG(0, 1);
|
|
}
|
|
|
|
return MAKELONG(0, 2);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* I N H I B I T R E C O R D E R */
|
|
/*
|
|
Called to inhibit or allow recording operation for the subsequent
|
|
actions. Inhibits when fInhibit is true. The state of both vfRecording
|
|
and vfRecordNext are saved in *pwsave, so the saved value should not
|
|
used by any other function. The saved value will either be 0 if
|
|
neither flag was on, 1 if vfRecording if on, or 2 if both flags are on.
|
|
Note that vfRecordNext cannot be on if vfRecording is not on, so we can
|
|
simply add the flags to give a numerical value of 0, 1, or 2.
|
|
/*
|
|
|
|
/* %%Function:InhibitRecorder %%Owner:tonykr */
|
|
InhibitRecorder(pwSav, fInhibit)
|
|
BOOL *pwSav, fInhibit;
|
|
{
|
|
Assert(fTrue == 1 && fFalse == 0);
|
|
Assert(vfRecording == fTrue || vfRecording == fFalse);
|
|
Assert(vfRecordNext == fTrue || vfRecordNext == fFalse);
|
|
Assert((2 == 2) == 1);
|
|
|
|
if (fInhibit)
|
|
{
|
|
*pwSav = vfRecording + vfRecordNext;
|
|
Assert(*pwSav != 1 || !vfRecordNext);
|
|
vfRecording = fFalse;
|
|
vfRecordNext = fFalse;
|
|
}
|
|
else
|
|
{
|
|
if (vhcmr == hNil && !vfRecordNext && *pwSav != 2)
|
|
{
|
|
vfRecording = fFalse;
|
|
vfRecordNext = fFalse;
|
|
}
|
|
else
|
|
{
|
|
vfRecordNext = ((*pwSav == 2 || vfRecordNext) && vhcmr == hNil);
|
|
vfRecording = (*pwSav != 0 || vfRecording);
|
|
}
|
|
selCur.fUpdateStatLine = fTrue; /* force a stat line update in Idle */
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
extern struct PLSBHI ** vhplsbhi;
|
|
BOOL vfBogusHeapState = fFalse;
|
|
|
|
/* R E P O R T H E A P */
|
|
/* %%Function:ReportHeapSz %%Owner:peterj */
|
|
ReportHeapSz (sz, cbDiff)
|
|
CHAR *sz;
|
|
int cbDiff;
|
|
{
|
|
static uns cbHeapLast = 0;
|
|
static uns cbTotalLast = 0;
|
|
static long cbFarLast = 0L;
|
|
|
|
if (vfBogusHeapState)
|
|
return;
|
|
|
|
{
|
|
uns cbHeap = CbAvailHeap(sbDds);
|
|
uns dcbDS = cbMaxSbDds - CbSizeSb(sbDds);
|
|
uns cbTotal = cbHeap + dcbDS;
|
|
long cbFarUsed=MemUsed(1)-CbSizeSb(sbDds);
|
|
long cbFarAvail=LcbUnusedEmm();
|
|
long cbEmmUsed=MemUsed(2)-((long)vbptbExt.ibpMax*cbSector)-cbFarAvail;
|
|
long dcbFar;
|
|
long cbEmm = smtMemory==smtLIM ? CbFreeEmm() : 0L;
|
|
CHAR rgch [100], *pch = rgch;
|
|
|
|
dcbFar = cbFarUsed + cbEmmUsed - cbFarLast;
|
|
|
|
if (abs(cbHeap-cbHeapLast)>=cbDiff || abs(cbTotal-cbTotalLast)>=cbDiff
|
|
|| dcbFar >= cbDiff || -dcbFar >= cbDiff)
|
|
{
|
|
SetBytes(rgch, ' ', 100);
|
|
CchPchToPpch(sz, &pch);
|
|
pch = max (pch, rgch+13);
|
|
CchPchToPpch(SzShared(" local="), &pch);
|
|
CchUnsToPpch(cbHeap, &pch);
|
|
*pch++ = '+';
|
|
CchUnsToPpch(dcbDS, &pch);
|
|
*pch++ = '=';
|
|
*pch++ = ' ';
|
|
CchUnsToPpch(cbTotal, &pch);
|
|
pch = max (pch, rgch+33);
|
|
CchPchToPpch(SzShared(" farUsed="), &pch);
|
|
CchLongToPpch(cbFarUsed, &pch);
|
|
if (smtMemory==smtLIM)
|
|
{
|
|
*pch++='+';
|
|
CchLongToPpch(cbEmmUsed, &pch);
|
|
}
|
|
if (smtMemory==smtLIM)
|
|
{
|
|
pch = max (pch, rgch+59);
|
|
CchPchToPpch(SzShared(" emm="), &pch);
|
|
CchLongToPpch(cbEmm, &pch);
|
|
*pch++='+';
|
|
CchLongToPpch(cbFarAvail, &pch);
|
|
}
|
|
*pch++ = '\r';
|
|
*pch++ = '\n';
|
|
*pch = 0;
|
|
CommSz(rgch);
|
|
cbHeapLast = cbHeap;
|
|
cbTotalLast = cbTotal;
|
|
cbFarLast = cbFarUsed+cbEmmUsed;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL vfAllocGuaranteed; /* alloc should succeed unconditionally */
|
|
BOOL vfInDebug; /* in debug code, don't force failures */
|
|
|
|
|
|
/* R E P O R T F A I L C A L L S */
|
|
/* %%Function:ReportFailCalls %%Owner:peterj */
|
|
ReportFailCalls()
|
|
{
|
|
if (vdbs.cWinCalls || vdbs.cLmemCalls)
|
|
{
|
|
CHAR rgch[cchMaxSz], *pch = rgch;
|
|
CchPchToPpch(SzShared("\r\nMem calls = "), &pch);
|
|
CchUnsToPpch(vdbs.cLmemCalls, &pch);
|
|
CchPchToPpch(SzShared(" Win calls = "), &pch);
|
|
CchUnsToPpch(vdbs.cWinCalls, &pch);
|
|
*pch++ = '\r';
|
|
*pch++ = '\n';
|
|
*pch = 0;
|
|
CommSz(rgch);
|
|
vdbs.cLmemCalls = 0;
|
|
vdbs.cWinCalls = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* F F A I L L M E M O P U S */
|
|
/* Return fTrue to cause lmem allocation to fail, fFalse to allow them to
|
|
succeed.
|
|
*/
|
|
/* %%Function:FFailLmemOpus %%Owner:peterj */
|
|
EXPORT FFailLmemOpus (merr, sb, cbNew, cRetry)
|
|
WORD merr;
|
|
SB sb;
|
|
WORD cbNew;
|
|
WORD cRetry;
|
|
{
|
|
extern BOOL vfInitializing;
|
|
extern BOOL vfInCmd;
|
|
|
|
if (vfBogusHeapState)
|
|
return fFalse;
|
|
|
|
if (!vfInitializing)
|
|
{
|
|
#ifdef DLMEM
|
|
int rgw [5];
|
|
rgw[0] = merr;
|
|
rgw[1] = sb;
|
|
rgw[2] = cbNew;
|
|
rgw[3] = CbSizeSb(sb);
|
|
rgw[4] = CbAvailHeap(sb);
|
|
CommSzRgNum(SzShared("FFailLmemOpus (merr,sb,cbNew,cbSb,cbAvail): "), rgw, 5);
|
|
#endif /* DLMEM */
|
|
|
|
if (vdbs.fReportHeap)
|
|
ReportHeapSz(SzShared("memory usage."), 200);
|
|
}
|
|
|
|
Assert (vdbs.cLmemSucceed >= 0 && vdbs.cLmemFail >= 0);
|
|
Assert (cHpFreeze == 0 || sb != sbDds);
|
|
|
|
if (vfAllocGuaranteed || vfInDebug)
|
|
return fFalse;
|
|
|
|
Assert(!vfInCommit);
|
|
|
|
if (vdbs.fOutsideCmd || vfInCmd)
|
|
{
|
|
if (vdbs.fHeapAct)
|
|
CommSz(SzShared("h"));
|
|
vdbs.cLmemCalls++;
|
|
if (vdbs.cLmemSucceed)
|
|
{
|
|
if (vdbs.fHeapAct)
|
|
CommSz(SzShared("s "));
|
|
vdbs.cLmemSucceed--;
|
|
return fFalse;
|
|
}
|
|
if (vdbs.cLmemFail)
|
|
{
|
|
if (vdbs.fHeapAct)
|
|
CommSz(SzShared("f "));
|
|
vdbs.cLmemFail--;
|
|
if (vdbs.fBreakOnFail)
|
|
DebugBreak(1);
|
|
if (sb == sbDds)
|
|
FreePh(&vmerr.hrgwEmerg1);
|
|
return fTrue;
|
|
}
|
|
if (vdbs.fHeapAct)
|
|
CommSz(SzShared(" "));
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
/* %%Function:CkFarHeaps %%Owner:peterj */
|
|
CkFarHeaps()
|
|
{
|
|
struct SBHI *psbhi = PInPl(vhplsbhi, 0);
|
|
struct SBHI *psbhiMac = psbhi + (*vhplsbhi)->isbhiMac;
|
|
VOID **ppv;
|
|
int ch;
|
|
|
|
while (psbhi < psbhiMac)
|
|
{
|
|
if (psbhi->fHasHeap)
|
|
{
|
|
CheckHeap(psbhi->sb);
|
|
if (vdbs.fShakeHeap)
|
|
ShakeHeapSb(psbhi->sb);
|
|
ch = 0;
|
|
ppv = NULL;
|
|
for (;;)
|
|
if ((ppv = PpvWalkHeap(psbhi->sb, ppv)) == NULL)
|
|
break;
|
|
else
|
|
ch++;
|
|
Assert(ch == psbhi->ch);
|
|
}
|
|
else
|
|
{
|
|
Assert(CbSizeSb(psbhi->sb) > cbMinBig-dcbBigSmall);
|
|
Assert(psbhi->ch == 1);
|
|
Assert(!psbhi->fHasFixed);
|
|
}
|
|
/* other checks */
|
|
Assert(psbhi->ch || psbhi->fHasFixed);
|
|
psbhi++;
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
/* %%Function:SbMgrError %%Owner:peterj */
|
|
SbMgrError(sberr, sb)
|
|
int sberr;
|
|
SB sb;
|
|
{
|
|
extern BOOL fElActive;
|
|
|
|
IdPromptBoxSz(SzShared("SB Manager interface error"),MB_TROUBLE);
|
|
|
|
if (fElActive)
|
|
{
|
|
FlagRtError(rerrInternalError);
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
int vfMsg=fFalse; /* tell caller whether msg arrived */
|
|
|
|
/* F S t i l l D o w n R e p l a y */
|
|
/* %%Function:FStillDownReplay %%Owner:peterj */
|
|
FStillDownReplay( ppt, fRightButton )
|
|
struct PT *ppt;
|
|
BOOL fRightButton;
|
|
{ /* This is roughly equivalent to a Mac routine that returns whether
|
|
the mouse button is down. We look for one mouse message from our
|
|
window's queue, and return FALSE if it is a BUTTONUP. We return the
|
|
point at which the mouse event occurred through a pointer. If no
|
|
message occurred, we return whether the left button is down
|
|
and do not store into the pointer
|
|
|
|
Note that we specifically do not return the state of the right button;
|
|
our right button processing is handled at the top of DoContentHit, and
|
|
we don't want to deal with dragging that button in this loop. (bz).
|
|
*/
|
|
MSG msg;
|
|
|
|
/* Since re-entrancy can move the heap sometimes, shake it */
|
|
|
|
Debug(vdbs.fShakeHeap ? ShakeHeap() : 0);
|
|
|
|
if ( (vfMsg = PeekMessage( (LPMSG)&msg, (HWND)NULL, NULL, NULL, TRUE )) )
|
|
{
|
|
switch (msg.message)
|
|
{
|
|
default:
|
|
TranslateMessage( (LPMSG)&msg );
|
|
DispatchMessage( (LPMSG)&msg );
|
|
break;
|
|
|
|
case WM_RBUTTONUP:
|
|
case WM_LBUTTONUP:
|
|
if (fRightButton != (msg.message == WM_RBUTTONUP))
|
|
break;
|
|
|
|
ppt->xp = MAKEPOINT( msg.lParam ).x;
|
|
ppt->yp = MAKEPOINT( msg.lParam ).y;
|
|
return fFalse;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
case WM_MOUSEMOVE:
|
|
/* A Mouse Move, Mouse Down, or Mouse Up is waiting */
|
|
ppt->xp = MAKEPOINT(msg.lParam).x;
|
|
ppt->yp = MAKEPOINT(msg.lParam).y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef OPUS_X64
|
|
/*
|
|
* The Win16 loop could rely on GetKeyState's queue snapshot while nested
|
|
* inside the button-down dispatch. On modern Windows that snapshot can
|
|
* lag the physical/SENDINPUT transition and prematurely end a drag before
|
|
* the corresponding button-up reaches this replay loop.
|
|
*/
|
|
return ((GetAsyncKeyState(fRightButton ? VK_RBUTTON : VK_LBUTTON) &
|
|
0x8000) != 0);
|
|
#else
|
|
return (GetKeyState( fRightButton ? VK_RBUTTON : VK_LBUTTON ) < 0);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* %%Function:CloseEveryFn %%Owner:peterj */
|
|
CloseEveryFn( fHardToo )
|
|
{ /* Close all files we have open. Close only files on removable media
|
|
if fHardToo is FALSE; ALL files if fHardToo is TRUE */
|
|
extern int fnMac;
|
|
int fn;
|
|
struct FCB **hfcb;
|
|
|
|
for ( fn = 0; fn < fnMac; fn++ )
|
|
if ((hfcb = mpfnhfcb [fn]) != NULL)
|
|
{
|
|
struct FCB *pfcb = *hfcb;
|
|
int osfn = pfcb->osfn;
|
|
|
|
if (osfn != osfnNil)
|
|
{
|
|
if (fHardToo || !pfcb->ofh.fFixedDisk)
|
|
{
|
|
/* Close may fail if windows already closed the file for us, but that's OK */
|
|
FCloseDoshnd( osfn );
|
|
pfcb->osfn = osfnNil;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* E N A B L E P R E L O A D */
|
|
/* Make subsequent accesses to fn load large chunks.
|
|
Does not guarantee that preloading will be done for fn (if a
|
|
preload is already in progress, this one is ignored).
|
|
*/
|
|
/* %%Function:EnablePreload %%Owner:peterj */
|
|
EnablePreload(fn)
|
|
int fn;
|
|
{
|
|
if (!vcPreload++)
|
|
{
|
|
Assert(vfnPreload == fnNil);
|
|
vfnPreload = fn;
|
|
}
|
|
}
|
|
|
|
|
|
/* %%Function:DisablePreload %%Owner:peterj */
|
|
DisablePreload()
|
|
{
|
|
if (--vcPreload == 0)
|
|
vfnPreload = fnNil;
|
|
Assert(vcPreload >= 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PROFILE
|
|
/* P C O D E S T A R T P R O F I L E R */
|
|
/* %%Function:PcodeStartProfiler %%Owner:peterj */
|
|
PcodeStartProfiler()
|
|
{
|
|
}
|
|
|
|
|
|
/* P C O D E S T O P P R O F I L E R */
|
|
/* %%Function:PcodeStopProfiler %%Owner:peterj */
|
|
PcodeStopProfiler()
|
|
{
|
|
}
|
|
|
|
|
|
#endif /* PROFILE */
|
|
|
|
|
|
#ifdef PROFILE
|
|
/* this is here so that appended native code does not appear in previous
|
|
function in pcode profiles. */
|
|
Wproc_Last(){}
|
|
#endif /* PROFILE */
|
|
|
|
/* ADD NEW CODE *ABOVE* Wproc_Last() */
|