mirror of
https://github.com/jmarshall23/msword.git
synced 2026-08-11 23:50:53 +02:00
2526 lines
48 KiB
C
2526 lines
48 KiB
C
/* C O M M A N D 2 . C */
|
|
/* Command processing code */
|
|
|
|
|
|
#define RSHDEFS
|
|
#define OEMRESOURCE /* So we get OBM_CLOSE from qwindows.h */
|
|
#include "word.h"
|
|
DEBUGASSERTSZ /* WIN - bogus macro for assert string */
|
|
#include "heap.h"
|
|
#include "debug.h"
|
|
#include "menu2.h"
|
|
#include "disp.h"
|
|
#include "doc.h"
|
|
#define NOEXTERN
|
|
#include "cmdtbl.h"
|
|
#include "ch.h"
|
|
#include "field.h"
|
|
#include "print.h"
|
|
#include "props.h"
|
|
#include "sel.h"
|
|
#include "keys.h"
|
|
#include "recorder.h"
|
|
#include "screen.h"
|
|
#include "status.h"
|
|
#include "el.h"
|
|
#include "sdmtmpl.h"
|
|
#include "layout.h"
|
|
#include "preview.h"
|
|
#include "macrocmd.h"
|
|
#define RULER
|
|
#define REPEAT
|
|
#include "ruler.h"
|
|
#include "fontwin.h"
|
|
#include "help.h"
|
|
#include "idd.h"
|
|
#include "tmc.h"
|
|
#include "rareflag.h"
|
|
|
|
#define MPATMST
|
|
#include "automcr.h"
|
|
|
|
#define VERBFIRST
|
|
|
|
#define USEBCM
|
|
#include "cmd.h"
|
|
|
|
#include "runmacro.hs"
|
|
#include "runmacro.sdm"
|
|
|
|
/* G L O B A L S */
|
|
struct UAB vuab;
|
|
struct AAB vaab;
|
|
HPSYT vhpsyt = hpNil;
|
|
KMP ** hkmpCur;
|
|
KMP ** hkmpBase;
|
|
CMB vcmb;
|
|
FARPROC vlppFWHChain;
|
|
FARPROC lppFWHKey;
|
|
struct STTB ** hsttbMenu;
|
|
MUD ** vhmudBase;
|
|
MUD ** vhmudUser;
|
|
KMP ** vhkmpUser;
|
|
|
|
|
|
|
|
/* E X T E R N A L S */
|
|
extern BOOL vfExtendSel;
|
|
extern BOOL vfBlockSel;
|
|
extern BOOL vfRecording;
|
|
extern BOOL vfElFunc;
|
|
extern int vcElParams;
|
|
extern HPSYT vhpsyt;
|
|
extern struct SEL selCur;
|
|
extern HWND vhwndStatLine;
|
|
extern int docGlobalDot;
|
|
extern BOOL vfInsertMode;
|
|
extern struct AAB vaab;
|
|
extern struct WWD ** hwwdCur;
|
|
extern int vlm;
|
|
extern RRF rrf;
|
|
extern PVS vpvs;
|
|
extern BOOL vfRecordNext;
|
|
extern BOOL vfSingleApp;
|
|
extern BOOL vfFileCacheDirty;
|
|
extern BOOL vfWndCacheDirty;
|
|
extern CHAR szNone[];
|
|
extern int vssc;
|
|
extern struct CA caPara;
|
|
extern BOOL vfSearchRepl;
|
|
extern BOOL vfDefineStyle;
|
|
extern HANDLE vhInstance;
|
|
extern int vfLastCursor;
|
|
extern int vcConseqScroll;
|
|
extern int sbScroll;
|
|
extern int sbScrollLast;
|
|
|
|
/* L O C A L F U N C T I O N S */
|
|
|
|
BCM BcmOfSt();
|
|
NATIVE uns WHash(); /* DECLARATION ONLY */
|
|
ELG ElgFromDoc();
|
|
HPSY HpsyFromBcmElg();
|
|
PFN PfnFromBsy();
|
|
CMD CmdExecBcmKc();
|
|
CMD CmdExecCmb();
|
|
|
|
|
|
extern struct STTB **hsttbMenu;
|
|
extern struct SCI vsci;
|
|
extern KMP ** hkmpCur;
|
|
extern int mwCur;
|
|
extern HWND vhwndRibbon;
|
|
extern HWND vhwndStatLine;
|
|
extern HWND vhwndCBT;
|
|
extern struct STTB ** vhsttbOpen;
|
|
extern struct STTB ** vhsttbWnd;
|
|
extern struct PRI vpri;
|
|
extern struct MERR vmerr;
|
|
extern int cfLink;
|
|
extern int cfRTF;
|
|
extern struct SAB vsab;
|
|
extern struct UAB vuab;
|
|
extern struct PREF vpref;
|
|
extern HANDLE vhMenuLongFull;
|
|
extern HMENU vhMenu;
|
|
extern int viMenu;
|
|
extern HWND vhwndApp;
|
|
extern struct MWD ** mpmwhmwd [];
|
|
extern struct WWD ** mpwwhwwd [];
|
|
extern int wwCur;
|
|
extern BOOL vfRecording;
|
|
extern struct MWD ** hmwdCur;
|
|
extern MES ** vhmes;
|
|
extern KME vkme;
|
|
extern struct PAP vpapFetch;
|
|
|
|
extern int vgrfMenuCmdsAreDirty;
|
|
extern int vgrfMenuKeysAreDirty;
|
|
extern int docDotMudCur;
|
|
extern int vkcPrev;
|
|
extern int vfSysMenu;
|
|
extern BCM vbcmFetch;
|
|
extern CHAR vrgchsyFetch[];
|
|
|
|
|
|
KME * PkmeFromKc();
|
|
KME * PkmeOfKcInChain();
|
|
|
|
SY * PsyGetSyOfBsy();
|
|
|
|
#ifdef NOASM
|
|
NATIVE IScanLprgw( int far *, WORD, int ); /* DECLARATION ONLY */
|
|
#endif /* NOASM */
|
|
|
|
extern HBITMAP hbmpSystem; /* System menu bitmap */
|
|
|
|
#define FWInWloWhi(w, wLo, wHi) ((uns) ((w) - (wLo)) <= (wHi) - (wLo))
|
|
|
|
#define CatCsSt(csstFrom, stTo) \
|
|
(bltbx((csstFrom) + 1, (char far *) ((stTo) + 1 + (stTo)[0]), \
|
|
(csstFrom)[0]), \
|
|
(stTo)[0] += *(csstFrom))
|
|
|
|
|
|
/* C B H P S Y */
|
|
/* %%Function:CbHpsy %%Owner:bradch */
|
|
CbHpsy(hpsy)
|
|
HPSY hpsy;
|
|
{
|
|
int cb = CbLpsy(LpLockHp(hpsy));
|
|
UnlockHp(hpsy);
|
|
return cb;
|
|
}
|
|
|
|
|
|
/* %%Function:CbLpsy %%Owner:bradch */
|
|
CbLpsy(lpsy)
|
|
SY FAR *lpsy;
|
|
{
|
|
int cb;
|
|
|
|
if ((cb = lpsy->stName[0]) == 0)
|
|
cb += sizeof (uns); /* for back pointer */
|
|
|
|
cb += cbSY;
|
|
|
|
switch (lpsy->mct)
|
|
{
|
|
case mctSdm:
|
|
cb += 2 * sizeof (uns); /* for cabi and ieldi */
|
|
break;
|
|
|
|
case mctCmd:
|
|
break;
|
|
|
|
case mctEl:
|
|
cb += lpsy->cagdMax * cbAGD;
|
|
break;
|
|
|
|
case mctMacro:
|
|
case mctGlobalMacro:
|
|
/* break; */;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (cb > cbMaxSy)
|
|
/* %%Function:MessageBox %%Owner:bradch */
|
|
MessageBox(vhwndApp, lpsy->stName+1,
|
|
(LPSTR) SzShared("CbLpsy: Bad sy!"), MB_OK|MB_SYSTEMMODAL);
|
|
#endif
|
|
Assert(cb <= cbMaxSy);
|
|
|
|
return cb;
|
|
}
|
|
|
|
|
|
/* P S Y G E T S Y F R O M B S Y */
|
|
/* %%Function:PsyGetSyOfBsy %%Owner:bradch */
|
|
SY * PsyGetSyOfBsy(psy, bsy)
|
|
CHAR * psy;
|
|
uns bsy;
|
|
{
|
|
HPSY hpsy;
|
|
hpsy = vhpsyt->grpsy + bsy;
|
|
bltbh(hpsy, (CHAR HUGE *)psy, CbHpsy(hpsy));
|
|
return psy;
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
int vfInCmd = fFalse;
|
|
#endif
|
|
|
|
/* F E X E C K C */
|
|
/* %%Function:FExecKc %%Owner:bradch */
|
|
BOOL FExecKc(kc)
|
|
int kc;
|
|
{
|
|
KME * pkme;
|
|
BOOL fTranslated;
|
|
|
|
#ifdef DKEYMAP
|
|
CommSzNum(SzShared("FExecKc: "), kc);
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
if (FProcessDbgKey (kc))
|
|
return fTrue;
|
|
#endif /* DEBUG */
|
|
|
|
if ((pkme = PkmeFromKc(kc, &fTranslated)) == 0)
|
|
{
|
|
vkme.kt = ktNil;
|
|
return fTranslated;
|
|
}
|
|
|
|
vkme = *pkme;
|
|
|
|
#ifdef DKEYMAP
|
|
CommSzNum(SzShared("kc: "), vkme.kc);
|
|
CommSzNum(SzShared("kt: "), vkme.kt);
|
|
CommSzNum(SzShared("w: "), vkme.w);
|
|
#endif
|
|
|
|
switch (pkme->kt)
|
|
{
|
|
case ktFunc: /* actual C function */
|
|
Debug( vfInCmd++ );
|
|
(*pkme->pfn)();
|
|
Debug( vfInCmd-- );
|
|
return fTrue;
|
|
|
|
case ktMacro: /* something in the command table */
|
|
FetchCm(pkme->bcm);
|
|
if (vbcmFetch == bsyNil) /* Deleted or renamed macro */
|
|
goto LBeep;
|
|
|
|
|
|
/* if CBT installed, must send this message before we
|
|
process the key, so they can mask it out if they want to */
|
|
|
|
if (vhwndCBT && !SendMessage(vhwndCBT, WM_CBTSEMEV,
|
|
smvCommand, MAKELONG(CxtFromBcm(pkme->bcm), 1 /* from keyboard */)))
|
|
return fTrue; /* yes it was processed */
|
|
|
|
/* CBT returned true; do normal handling */
|
|
|
|
|
|
switch (pkme->bcm)
|
|
{
|
|
case bcmTraceMacro:
|
|
case bcmStepMacro:
|
|
case bcmContinueMacro:
|
|
case bcmAnimateMacro:
|
|
PostMessage(vhwndApp, WM_COMMAND, pkme->bcm, 0L);
|
|
return fTrue;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
CMD cmd;
|
|
|
|
cmd = CmdExecBcmKc(pkme->bcm, kc);
|
|
return cmd == cmdOK;
|
|
}
|
|
|
|
#else
|
|
return CmdExecBcmKc(pkme->bcm, kc) == cmdOK;
|
|
#endif
|
|
|
|
case ktBeep: /* just beep */
|
|
LBeep:
|
|
Beep();
|
|
/* FALL THROUGH */
|
|
|
|
case ktIgnore: /* totally ignore (rare) */
|
|
return fTrue;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/* F P R O C E S S K E Y */
|
|
/* This function handles all non-insert type keys. Returns true iff
|
|
key was handled */
|
|
/* %%Function:FProcessKey %%Owner:bradch */
|
|
BOOL FProcessKey(kc)
|
|
int kc;
|
|
{
|
|
#ifdef DKEYMAP
|
|
CommSzNum(SzShared("FProcessKey: "), kc);
|
|
#endif /* DKEYMAP */
|
|
|
|
/* Check for cursor movement key */
|
|
|
|
if (FCursKey(kc, fTrue /* fDoIt */))
|
|
return fTrue;
|
|
|
|
return (FExecKc(KcModified(kc)));
|
|
}
|
|
|
|
|
|
|
|
/* P K M E F R O M K C */
|
|
/* Searches the current keymap chain for the given kc. fDoIt indicates
|
|
whether this kc is supposed to be acted upon as opposed to just looked
|
|
up. fDoIt is only false in insert the loop so that keys may be checked
|
|
for whether or not they abort the insert loop. */
|
|
/* %%Function:PkmeFromKc %%Owner:bradch */
|
|
KME * PkmeFromKc(kc, pfTranslated)
|
|
int kc;
|
|
BOOL * pfTranslated;
|
|
{
|
|
KMP ** hkmp, * pkmp;
|
|
int ikme, kt;
|
|
BOOL fStopHere;
|
|
|
|
*pfTranslated = fFalse;
|
|
hkmp = hkmpCur;
|
|
while (hkmp != hNil)
|
|
{
|
|
pkmp = *hkmp;
|
|
if (FSearchKmp(hkmp, kc, &ikme))
|
|
return &pkmp->rgkme[ikme]; /* FOUND! */
|
|
|
|
if (pkmp->fTranslate && !(FCtrlKc(kc) && !FAltKc(kc)))
|
|
{
|
|
extern MSG vmsgLast;
|
|
/* NOTE: assumes last message was WM_KEYDOWN */
|
|
if (TranslateMessage((LPMSG) &vmsgLast))
|
|
{
|
|
/* TRANSLATED! Ignore key message, we'll
|
|
get a CHAR message rsn... */
|
|
DispatchMessage((LPMSG) &vmsgLast);
|
|
*pfTranslated = fTrue;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (pkmp->fBeep)
|
|
Beep();
|
|
|
|
fStopHere = pkmp->fStopHere;
|
|
|
|
if (pkmp->fModal)
|
|
{
|
|
EndKeyMode();
|
|
hkmp = hkmpCur;
|
|
}
|
|
else
|
|
hkmp = pkmp->hkmpNext;
|
|
|
|
if (fStopHere)
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* F S E A R C H K M P */
|
|
/* Binary search a keymap for a given kc. Sets *pikme to where kc is
|
|
found (returns fTrue), or where it would be (returns fFalse). */
|
|
/* %%Function:FSearchKmp %%Owner:bradch */
|
|
FSearchKmp(hkmp, kcSearch, pikme)
|
|
KMP ** hkmp;
|
|
int kcSearch;
|
|
int * pikme;
|
|
{
|
|
KMP * pkmp;
|
|
KME * rgkme;
|
|
int iMin, iLim, iGuess, kc;
|
|
|
|
pkmp = *hkmp;
|
|
rgkme = &pkmp->rgkme[0];
|
|
iMin = 0;
|
|
iLim = pkmp->ikmeMac;
|
|
if (iLim > 0 && kcSearch >= rgkme[0].kc)
|
|
{{ /* NATIVE - loop in FSearchKmp */
|
|
while (iMin < iLim)
|
|
{
|
|
iGuess = (iMin + iLim) >> 1;
|
|
if ((kc = rgkme[iGuess].kc) == kcSearch)
|
|
{{ /* !NATIVE - FSearchKmp */
|
|
*pikme = iGuess;
|
|
return fTrue;
|
|
}}
|
|
if (kc < kcSearch)
|
|
iMin = iGuess + 1;
|
|
else
|
|
iLim = iGuess;
|
|
}
|
|
}}
|
|
*pikme = iMin;
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/* P K M E O F K C I N C H A I N */
|
|
/* %%Function:PkmeOfKcInChain %%Owner:bradch */
|
|
KME * PkmeOfKcInChain(kc)
|
|
int kc;
|
|
{
|
|
KMP ** hkmp, * pkmp;
|
|
int ikme;
|
|
|
|
for (hkmp = hkmpCur; hkmp != hNil; hkmp = pkmp->hkmpNext)
|
|
{
|
|
pkmp = *hkmp;
|
|
if (FSearchKmp(hkmp, kc, &ikme))
|
|
{
|
|
return &pkmp->rgkme[ikme];
|
|
}
|
|
|
|
if (pkmp->fStopHere || pkmp->fTranslate || pkmp->fModal)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (KME *) 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ***************************** */
|
|
|
|
|
|
/* %%Function:FetchCm %%Owner:bradch */
|
|
FetchCm(bcm)
|
|
BCM bcm;
|
|
{
|
|
FetchCm2(bcm, cmmNormal);
|
|
}
|
|
|
|
|
|
int cmmCache;
|
|
|
|
/* %%Function:FetchCm2 %%Owner:bradch */
|
|
FetchCm2(bcm, cmm)
|
|
BCM bcm;
|
|
{
|
|
HPSY hpsy;
|
|
|
|
if (bcm == vbcmFetch && cmm == cmmCache)
|
|
return;
|
|
|
|
cmmCache = cmm;
|
|
|
|
vbcmFetch = bcm;
|
|
|
|
/* FUTURE: is it worth it to cache the whole symbol? */
|
|
if ((hpsy = HpsyFromBcmElg(vhpsyt, bcm,
|
|
ElgFromDoc(selCur.doc), cmm)) != NULL)
|
|
{
|
|
bltbh(hpsy, (HPSY) vrgchsyFetch, CbHpsy(hpsy));
|
|
vbcmFetch = (uns) ((char *) hpsy - vhpsyt->grpsy);
|
|
}
|
|
else
|
|
{
|
|
vbcmFetch = bcmNil;
|
|
}
|
|
}
|
|
|
|
|
|
/* %%Function:FetchSy %%Owner:bradch */
|
|
FetchSy(bsy)
|
|
uns bsy;
|
|
{
|
|
HPSY hpsy;
|
|
|
|
if (bsy == vbcmFetch && cmmCache == 0)
|
|
return;
|
|
|
|
cmmCache = 0;
|
|
/* FUTURE: is it worth it to cache the whole symbol? */
|
|
hpsy = (HPSY)(vhpsyt->grpsy + bsy);
|
|
bltbh(hpsy, (HPSY) vrgchsyFetch, CbHpsy(hpsy));
|
|
vbcmFetch = bsy;
|
|
}
|
|
|
|
|
|
/* F E X E C C M D */
|
|
/* This one is about to bite the big one... */
|
|
/* %%Function:FExecCmd %%Owner:bradch */
|
|
BOOL FExecCmd(bcm)
|
|
BCM bcm;
|
|
{
|
|
return CmdExecBcmKc(bcm, kcNil) == cmdOK;
|
|
}
|
|
|
|
|
|
/* %%Function:FInitCmb %%Owner:bradch */
|
|
FInitCmb(pcmb, bcm, hcab, cmm)
|
|
CMB * pcmb;
|
|
BCM bcm;
|
|
HCAB hcab;
|
|
int cmm;
|
|
{
|
|
|
|
|
|
|
|
#ifdef NOTYET
|
|
if (bcm == bcmRepeat)
|
|
{
|
|
if ((bcm = vaab.bcm) == bcmNil)
|
|
{
|
|
/* Nothing to repeat! */
|
|
Beep();
|
|
return fFalse;
|
|
}
|
|
hcab = vaab.hcab;
|
|
}
|
|
#endif
|
|
|
|
/* init SDM if we haven't already */
|
|
if (!vmerr.fSdmInit && !FAssureSdmInit())
|
|
goto ErrRet;
|
|
|
|
FetchCm2(bcm, cmm);
|
|
|
|
if (hcab == hNil && vpsyFetch->mct == mctSdm)
|
|
{
|
|
if ((hcab = HcabAlloc((WORD) CabiFromPsy(vpsyFetch))) == hNil)
|
|
{
|
|
ErrRet:
|
|
pcmb->hcab = hNil;
|
|
return fFalse;
|
|
}
|
|
NinchCab(hcab);
|
|
}
|
|
|
|
pcmb->hcab = hcab;
|
|
pcmb->bcm = bcm;
|
|
pcmb->kc = kcNil;
|
|
pcmb->pv = (void *) 0;
|
|
pcmb->cmm = cmm;
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
extern BOOL FRecordCab();
|
|
|
|
|
|
/* C M D E X E C B C M */
|
|
/* Use this to just call a command from another command. This does NOT
|
|
set up undo or repeat and is NOT recorded. */
|
|
/* %%Function:CmdExecBcm %%Owner:bradch */
|
|
CMD CmdExecBcm(bcm, hcab)
|
|
BCM bcm;
|
|
HCAB hcab;
|
|
{
|
|
CMD cmd;
|
|
CMB cmb;
|
|
|
|
if (!FInitCmb(&cmb, bcm, hcab, cmmNormal))
|
|
return cmdNoMemory;
|
|
|
|
cmd = CmdExecCmb(&cmb);
|
|
|
|
if (cmb.hcab != hNil)
|
|
FreeCab(cmb.hcab);
|
|
|
|
return cmd;
|
|
}
|
|
|
|
|
|
/* C M D E X E C B C M K C */
|
|
/* This one deals with keys, menus, and icons... (kc == kcNil means this
|
|
was invoked from a menu or icon). This takes care of undo, repeat, and
|
|
recording. */
|
|
/* %%Function:CmdExecBcmKc %%Owner:bradch */
|
|
CMD CmdExecBcmKc(bcm, kc)
|
|
BCM bcm;
|
|
int kc;
|
|
{
|
|
CMD cmd;
|
|
CMB cmb;
|
|
#ifdef FLASHMENU
|
|
BOOL fHilited;
|
|
#endif
|
|
BOOL fRepeatable = fFalse;
|
|
|
|
#ifdef DEBUG
|
|
if (bcm == imiDebugFailures)
|
|
vfAllocGuaranteed++;
|
|
#endif /* DEBUG */
|
|
|
|
if (!FInitCmb(&cmb, bcm, hNil, cmmNormal))
|
|
{
|
|
if (bcm == imiSaveAs)
|
|
DoEmergSave(selCur.doc);
|
|
#ifdef NOTUSED
|
|
/* cmdError and cmdNoMemory are the same value. Old code: */
|
|
return bcm == bcmRepeat ? cmdError : cmdNoMemory;
|
|
#endif /* NOTUSED */
|
|
cmd = cmdError;
|
|
goto LRet;
|
|
}
|
|
|
|
#ifdef FLASHMENU
|
|
fHilited = fFalse;
|
|
if (kc != kcNil)
|
|
{
|
|
fHilited = HiliteMenuItem(vhwndApp, vhMenu, bcm,
|
|
MF_HILITE | MF_BYCOMMAND);
|
|
}
|
|
#endif
|
|
|
|
cmb.kc = kc;
|
|
|
|
PrepAgainBcm(bcm);
|
|
|
|
switch (cmd = CmdExecCmb(&cmb))
|
|
{
|
|
default:
|
|
/* q: (bac) Do we really want to trash again
|
|
if the user cancells?
|
|
a: (bz) yes, because we set bcm to bcmNil at the start, so
|
|
the old repeat was already lost, and anything set should
|
|
be disposed of, since we cancelled. We could save away
|
|
the vaab and its handle data and restore if we cancel, but
|
|
it's probably not worth it if noone complains
|
|
*/
|
|
/* in case something within the cancelled command set the
|
|
again stuff (e.g. Ctrl+B in the Replace dialog) */
|
|
/* [rp] except for Search and Goto because they NEVER touch
|
|
the again state as they use FindNext for repeating */
|
|
if (vaab.bcm != bcmNil && bcm != bcmSearch && bcm != bcmGoto)
|
|
SetAgain(bcmNil);
|
|
break;
|
|
|
|
case cmdOK:
|
|
/* Record action if applicable */
|
|
if (vfRecording && bcm != bcmRecordNext)
|
|
{
|
|
/* NOTE: cmb.bcm is used because some commands change
|
|
it for the sake of the recorder (exp. Save when
|
|
it really does a SaveAs) */
|
|
GenStatement(cmb.bcm);
|
|
}
|
|
|
|
/* Setup repeat command stuff */
|
|
/* note: this says that we assume anyone who set done a
|
|
set again explicitly knew what they were doing, so we
|
|
leave it. bz
|
|
*/
|
|
if (vaab.bcm == bcmNil && FRepeatableBcm(bcm) &&
|
|
!FSpecialBcmInDialog(bcm))
|
|
{
|
|
SetAgainCab(bcm, cmb.hcab);
|
|
fRepeatable = fTrue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* End RecordNextCommand iff:
|
|
* a) vfRecordNext is true, and
|
|
* b) we did not just finish executing RecordNextCommand, and
|
|
* c) the command we just finished was recordable, and
|
|
* d) we did not just finish executing a MacroRun that in turn
|
|
* executed RecordNextCommand
|
|
*/
|
|
if (vfRecordNext && bcm != bcmRecordNext &&
|
|
(FRecordableBcm(bcm) || bcm == bcmRepeat))
|
|
{
|
|
char stName [cchMaxMacroName + 1];
|
|
|
|
Assert(vfRecording);
|
|
if (bcm == imiMacro)
|
|
{
|
|
/* We did a MacroRun, check that we didn't run RecordNextCommand */
|
|
GetCabSt(cmb.hcab, stName, cchMaxMacroName + 1,
|
|
Iag(CABRUNMACRO, hszName));
|
|
if (BcmOfSt(stName) != bcmRecordNext)
|
|
goto EndRecordNext;
|
|
}
|
|
else
|
|
{
|
|
EndRecordNext:
|
|
EndSdmTranscription();
|
|
vfRecording = vfRecordNext = fFalse;
|
|
}
|
|
|
|
/* Blow away Undo and Repeat, since we have inserted text, and they
|
|
* may no longer be valid */
|
|
SetUndoNil();
|
|
InvalAgain();
|
|
}
|
|
|
|
vkcPrev = cmb.kc;
|
|
|
|
#ifdef DEBUG
|
|
if (bcm == imiDebugFailures)
|
|
vfAllocGuaranteed--;
|
|
#endif /* DEBUG */
|
|
|
|
#ifdef FLASHMENU
|
|
if (fHilited)
|
|
{
|
|
HiliteMenuItem(vhwndApp, vhMenu, bcm,
|
|
MF_UNHILITE | MF_BYCOMMAND);
|
|
}
|
|
#endif
|
|
|
|
LRet:
|
|
if (!fRepeatable && cmb.hcab != hNil)
|
|
FreeCab(cmb.hcab);
|
|
return cmd;
|
|
}
|
|
|
|
|
|
/* C M D E X E C C M B */
|
|
/* The lowest level... The hcab must be set up if the command needs one! */
|
|
/* %%Function:CmdExecCmb %%Owner:bradch */
|
|
CMD CmdExecCmb(pcmb)
|
|
CMB * pcmb;
|
|
{
|
|
extern int vfInCmd;
|
|
extern BOOL vfHelp;
|
|
extern struct DBS vdbs;
|
|
|
|
CMD cmd = cmdOK;
|
|
BCM bcm = pcmb->bcm;
|
|
|
|
FetchCm2(pcmb->bcm, pcmb->cmm);
|
|
|
|
Assert(bcm != bcmNil);
|
|
Assert(selCur.doc == docNil || (hwwdCur != hNil && hmwdCur != hNil));
|
|
/* attempt to ensure no asynchronous command executions */
|
|
Assert (!vfInsertMode);
|
|
|
|
#ifdef RSH
|
|
SetUatMode(uamCommand);
|
|
#endif /* RSH */
|
|
|
|
/* Check for legality of executing this cmd given the current state */
|
|
if (!FLegalBcm(bcm))
|
|
{
|
|
Beep();
|
|
return cmdError;
|
|
}
|
|
|
|
if (vfHelp) /* Help mode: don't actually execute the cmd */
|
|
{
|
|
if (bcm == bcmCancel)
|
|
CancelContextHelp();
|
|
else
|
|
{
|
|
#ifdef RSH
|
|
LogUa(uaCxtHelp);
|
|
#endif /* RSH */
|
|
GetHelp(CxtFromBcm(bcm));
|
|
}
|
|
return cmdOK;
|
|
}
|
|
|
|
FetchCm2(bcm, pcmb->cmm);
|
|
if (vbcmFetch == bcmNil)
|
|
{
|
|
return cmdError;
|
|
}
|
|
|
|
vfElFunc = fFalse;
|
|
vcElParams = 0;
|
|
|
|
PrepExecBcm(bcm);
|
|
ClearAbortKeyState();
|
|
|
|
switch (vpsyFetch->mct)
|
|
{
|
|
default:
|
|
Beep(); /* most likely a deleted macro */
|
|
return cmdError;
|
|
|
|
case mctSdm:
|
|
case mctCmd:
|
|
|
|
#ifdef RSH
|
|
LogUa(uaBcmFollows);
|
|
LogUa(bcm);
|
|
#endif /* RSH */
|
|
|
|
{
|
|
#ifdef BRADCH
|
|
if (vfRecordNext)
|
|
pcmb->fAction = fFalse;
|
|
#endif
|
|
{
|
|
#ifdef DEBUG
|
|
int hEatCmd = hNil;
|
|
if (vdbs.cbHeapWantedCmd)
|
|
SetHeapSize(vdbs.cbHeapWantedCmd, &hEatCmd);
|
|
#endif
|
|
/* Don't want to call CMD for non-dialog commands
|
|
if action flag is not set because they all
|
|
ignore it. */
|
|
if (vpsyFetch->mct == mctSdm)
|
|
{
|
|
Debug( vfInCmd++ );
|
|
cmd = (*vpsyFetch->pfnCmd)(pcmb);
|
|
Debug( vfInCmd-- );
|
|
}
|
|
else
|
|
{
|
|
Debug( vfInCmd++ );
|
|
cmd = pcmb->fAction ? (*vpsyFetch->pfnCmd)(pcmb) : cmdOK;
|
|
Debug( vfInCmd-- );
|
|
}
|
|
#ifdef DEBUG
|
|
if (hEatCmd)
|
|
FreeH(hEatCmd);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
|
|
case mctMacro:
|
|
case mctGlobalMacro:
|
|
#ifdef RSH
|
|
LogUa(uaTempMacro+(vpsyFetch->mct==mctGlobalMacro));
|
|
#endif /* RSH */
|
|
cmd = CmdExecMacroDotImcr(vpsyFetch->docDot, vpsyFetch->imcr);
|
|
if (vmerr.fCBTMacroMemErr)
|
|
{
|
|
Assert(vhwndCBT);
|
|
SendMessage(vhwndCBT, WM_CBTTERM, vhInstance,
|
|
MAKELONG(0, ctrOutOfMemory));
|
|
vmerr.fCBTMacroMemErr = fFalse;
|
|
vmerr.fSentCBTMemErr = fTrue;
|
|
}
|
|
} /* end switch */
|
|
|
|
/* Force command failure if we ran out of memory or had disk problem */
|
|
if (vmerr.fMemFail || vmerr.fDiskFail)
|
|
cmd = cmdError;
|
|
|
|
/* Force a status line update */
|
|
if (vhwndStatLine != NULL)
|
|
{
|
|
selCur.fUpdateStatLine = fTrue;
|
|
}
|
|
|
|
if (vaab.bcm != bcmRRFormat)
|
|
{
|
|
ClearRrf();
|
|
}
|
|
|
|
if (bcm == bcmRecordNext && cmd == cmdOK)
|
|
SaveCabs(FRecordCab, fFalse);
|
|
|
|
#ifdef RSH
|
|
if (cmd != cmdOK)
|
|
LogUa(uaCancelOrError);
|
|
#endif /* RSH */
|
|
return cmd;
|
|
}
|
|
|
|
|
|
/* H P S Y F R O M B C M E L G */
|
|
/* Given a BCM and ELG (docDot), find the symbol for the command to
|
|
execute. This is the function that handles distinguishing between
|
|
commands, global macros, and local macros that have the same name. */
|
|
|
|
/* The first symbol in a bcm chain will always refer to the "most global"
|
|
entry (i.e. built-in before global, global before doc-type). */
|
|
|
|
/* %%Function:HpsyFromBcmElg %%Owner:bradch */
|
|
HPSY HpsyFromBcmElg(hpsyt, bcm, elg, cmm)
|
|
HPSYT hpsyt;
|
|
BCM bcm;
|
|
ELG elg;
|
|
{
|
|
uns bsy;
|
|
HPSY hpsy;
|
|
HPSY hpsyRet;
|
|
|
|
bsy = bcm;
|
|
|
|
hpsyRet = hpNil;
|
|
|
|
hpsy = (CHAR HUGE *) hpsyt->grpsy + bsy;
|
|
|
|
while (bsy != bsyNil)
|
|
{
|
|
switch (hpsy->mct)
|
|
{
|
|
/* NOTE: Global macros will be selected over commands automaticaly because
|
|
the commands are listed in the command table first. If it is
|
|
decided that the user cannot replace global commands with a macro,
|
|
this still will not need to change, only adding a macro will. */
|
|
|
|
case mctSdm:
|
|
case mctCmd:
|
|
if (cmm & cmmBuiltIn)
|
|
return hpsy;
|
|
/* FALL THROUGH */
|
|
|
|
case mctGlobalMacro:
|
|
if (cmm & cmmSuper)
|
|
return hpsy;
|
|
hpsyRet = hpsy; /* Built-in command or global macro found */
|
|
break;
|
|
|
|
case mctMacro:
|
|
if (hpsy->docDot == elg)
|
|
return hpsy; /* Local macro found */
|
|
break;
|
|
}
|
|
|
|
if ((bsy = hpsy->bsyNext) == bsyNil)
|
|
break;
|
|
|
|
hpsy = (HPSY) (hpsyt->grpsy + bsy);
|
|
|
|
if (hpsy->stName[0] != 0)
|
|
break; /* end of same-name chain */
|
|
}
|
|
return hpsyRet;
|
|
}
|
|
|
|
|
|
/* E L G D O C */
|
|
/* %%Function:ElgFromDoc %%Owner:bradch */
|
|
ELG ElgFromDoc(doc)
|
|
int doc;
|
|
{
|
|
doc = DocDotMother(doc);
|
|
return ((doc == docNil) ? docGlobalDot : doc);
|
|
}
|
|
|
|
|
|
/* P F N F R O M B S Y */
|
|
/* %%Function:PfnFromBsy %%Owner:bradch */
|
|
PFN PfnFromBsy(bsy)
|
|
int bsy;
|
|
{
|
|
HPSY hpsy;
|
|
PFN pfn;
|
|
|
|
Assert(bsy != bsyNil);
|
|
Assert(vhpsyt != hpNil);
|
|
|
|
/* BLOCK */
|
|
{
|
|
hpsy = (HPSY) (vhpsyt->grpsy + bsy);
|
|
#ifdef DEBUG
|
|
{
|
|
MCT mct = hpsy->mct;
|
|
/* NOTE: if this assertion fails, and you Ignore it, Opus WILL crash! */
|
|
Assert(mct == mctCmd || mct == mctSdm || mct == mctEl);
|
|
}
|
|
#endif
|
|
pfn = hpsy->pfnEl;
|
|
}
|
|
|
|
return pfn;
|
|
}
|
|
|
|
|
|
/* made native for optimizing macro tokenization */
|
|
/* %%Function:BcmOrBsyOfSt %%Owner:bradch */
|
|
NATIVE BcmOrBsyOfSt(st, docDot, fBsy)
|
|
CHAR * st;
|
|
{
|
|
CHAR * pch;
|
|
CHAR FAR * lpch;
|
|
int cch;
|
|
SY FAR * lpsy;
|
|
SYT FAR *lpsyt;
|
|
uns bcm;
|
|
|
|
if (st[0] == 0)
|
|
return bsyNil;
|
|
|
|
Assert(vhpsyt != hpNil);
|
|
|
|
/* note: using long pointers for speed */
|
|
lpsyt = LpLockHp(vhpsyt);
|
|
|
|
/* BLOCK */
|
|
{
|
|
CHAR FAR * lpgrpsy;
|
|
|
|
lpgrpsy = lpsyt->grpsy;
|
|
|
|
for (bcm = lpsyt->mpwbsy[WHash(st)]; bcm != bcmNil;
|
|
bcm = lpsy->bsyNext)
|
|
{
|
|
lpsy = (SY FAR *)(lpgrpsy + bcm);
|
|
|
|
pch = st;
|
|
lpch = lpsy->stName;
|
|
cch = *pch++;
|
|
if (cch != *lpch++)
|
|
continue;
|
|
|
|
while (cch-- > 0)
|
|
{
|
|
if (ChUpperLookup(*pch++) != ChUpperLookup(*lpch++))
|
|
break;
|
|
}
|
|
|
|
if (cch < 0) /* matched */
|
|
break;
|
|
}
|
|
}
|
|
|
|
UnlockHp(vhpsyt);
|
|
|
|
if (fBsy)
|
|
{
|
|
HPSY hpsy;
|
|
|
|
if ((hpsy = HpsyFromBcmElg(vhpsyt, bcm, docDot, 0)) != 0)
|
|
bcm = (CHAR huge *) hpsy - (CHAR huge *) vhpsyt->grpsy;
|
|
/* bcm now contains a bsy */
|
|
}
|
|
|
|
return bcm;
|
|
}
|
|
|
|
|
|
/* B C M O F S T */
|
|
/* %%Function:BcmOfSt %%Owner:bradch */
|
|
BCM BcmOfSt(st)
|
|
CHAR * st;
|
|
{
|
|
return BcmOrBsyOfSt(st, docNil, fFalse);
|
|
}
|
|
|
|
|
|
/* B S Y O F S T */
|
|
/* %%Function:BsyOfStDocDot %%Owner:bradch */
|
|
uns BsyOfStDocDot(st, docDot)
|
|
CHAR * st;
|
|
int docDot;
|
|
{
|
|
return BcmOrBsyOfSt(st, docDot, fTrue);
|
|
}
|
|
|
|
|
|
/* W H A S H */
|
|
/* Return hash code for given string. NOTE: case insensitive */
|
|
/* %%Function:WHash %%Owner:bradch */
|
|
NATIVE uns WHash(st)
|
|
CHAR * st;
|
|
{
|
|
uns wHash, cch;
|
|
|
|
wHash = 0;
|
|
cch = *st++;
|
|
while (cch--)
|
|
wHash = ((wHash << 5) + (wHash >> 11) + ChUpperLookup(*st++));
|
|
wHash = ((wHash & 0x7fff) % wHashMax);
|
|
|
|
return wHash;
|
|
}
|
|
|
|
|
|
/* %%Function:BsyElOfSt %%Owner:bradch */
|
|
BsyElOfSt(st)
|
|
CHAR * st;
|
|
{
|
|
return BsyElOfBcm(BcmOfSt(st));
|
|
}
|
|
|
|
|
|
/* made native for optimizing macro tokenization */
|
|
/* %%Function:BsyElOfBcm %%Owner:bradch */
|
|
NATIVE BsyElOfBcm(bcm)
|
|
BCM bcm;
|
|
{
|
|
CHAR * pch;
|
|
CHAR FAR * lpch;
|
|
int cch;
|
|
SYT FAR *lpsyt;
|
|
SY FAR *lpsy;
|
|
uns bsy;
|
|
|
|
Assert(vhpsyt != hpNil);
|
|
|
|
if (bcm == bsyNil)
|
|
return bsyNil;
|
|
|
|
/* using long pointers instead of huge pointers for speed */
|
|
lpsyt = LpLockHp(vhpsyt);
|
|
|
|
/* BLOCK */
|
|
{
|
|
CHAR FAR * lpgrpsy;
|
|
|
|
lpgrpsy = lpsyt->grpsy;
|
|
|
|
bsy = bcm;
|
|
lpsy = (SY FAR *) (lpgrpsy + bsy);
|
|
for (;;)
|
|
{
|
|
if (FElMct(lpsy->mct))
|
|
{
|
|
bcm = bsy;
|
|
goto LDone;
|
|
}
|
|
|
|
if (lpsy->mct == mctCmd || lpsy->mct == mctSdm)
|
|
{
|
|
bcm = bsy;
|
|
}
|
|
|
|
if ((bsy = lpsy->bsyNext) == bsyNil)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lpsy = (SY FAR *) (lpgrpsy + bsy);
|
|
if (lpsy->stName[0] != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
LDone:
|
|
UnlockHp(vhpsyt);
|
|
|
|
return bcm;
|
|
}
|
|
|
|
|
|
|
|
/* K C M O D I F I E D */
|
|
/* Given a kc, apply the shift, ctrl, and alt modifier bits as apropriate. */
|
|
/* FUTURE: should put vfFooKeys in propper bits so this can be an OR. */
|
|
/* %%Function:KcModified %%Owner:bradch */
|
|
int KcModified(kc)
|
|
int kc;
|
|
{
|
|
if (vfOptionKey)
|
|
/* we don't allow Alt-F11 thru Alt-F16 because you
|
|
can't get them on the old-style AT keyboard */
|
|
if ((uns)(kc - VK_F11) > (VK_F16 - VK_F11))
|
|
kc = KcAlt(kc);
|
|
|
|
if (vfShiftKey)
|
|
kc = KcShift(kc);
|
|
|
|
if (vfControlKey)
|
|
kc = KcCtrl(kc);
|
|
|
|
return kc;
|
|
}
|
|
|
|
|
|
/* FUTURE: Temporary until cursor keys are in keymap */
|
|
csconst int rgkcCursor [] =
|
|
{
|
|
kcNextPara,
|
|
kcPrevPara,
|
|
kcWordRight,
|
|
kcWordLeft,
|
|
kcWordRightAlt,
|
|
kcWordLeftAlt,
|
|
kcEndLine,
|
|
kcBeginLine,
|
|
kcRight,
|
|
kcLeft,
|
|
kcTopScreen,
|
|
kcEndScreen,
|
|
kcDown,
|
|
kcUp,
|
|
kcPageDown,
|
|
kcPageUp,
|
|
kcEndDoc,
|
|
kcTopDoc,
|
|
kcClear
|
|
};
|
|
|
|
|
|
#define ikcCursorMax (sizeof (rgkcCursor)/ sizeof (int))
|
|
|
|
|
|
/* F C U R S K E Y */
|
|
/* Check if a kc is a cursor key and optionaly execute the key's function */
|
|
/* %%Function:FCursKey %%Owner:bradch */
|
|
FCursKey(kc, fDoIt)
|
|
int kc;
|
|
BOOL fDoIt;
|
|
{
|
|
extern BOOL vfBlockSel;
|
|
int ikc;
|
|
|
|
if (wwCur == wwNil)
|
|
return fFalse;
|
|
|
|
SetOurKeyState();
|
|
kc |= vgrpfKeyBoardState & (wKbsControlMask | wKbsOptionMask);
|
|
|
|
/* ignore control key if block selection */
|
|
if (vfBlockSel)
|
|
kc &= ~wKbsControlMask;
|
|
|
|
/* search to avoid bringing in curskeys.c */
|
|
if (IScanLprgw( (int far *)rgkcCursor, kc, ikcCursorMax ) != iNil)
|
|
{
|
|
BOOL fRet;
|
|
|
|
#ifdef RSH
|
|
if (!vfInsertMode)
|
|
{
|
|
if (vfShiftKey || vfExtendSel)
|
|
LogUa(uaCursExtend+IScanLprgw((int far *)rgkcCursor,kc,ikcCursorMax));
|
|
else
|
|
LogUa(uaCursor+IScanLprgw((int far *)rgkcCursor,kc,ikcCursorMax));
|
|
SetUatMode(uamNavigation);
|
|
StopUatTimer();
|
|
}
|
|
#endif /* RSH */
|
|
|
|
fRet = FKeyCmdLeftRight(kc, fDoIt) ||
|
|
FKeyCmdUpDown(kc, fDoIt) || kc == kcClear;
|
|
vkcPrev = kc;
|
|
return fRet;
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
|
|
/* F K E Y C M D L E F T R I G H T */
|
|
/* Move or drag selection in left or right directions */
|
|
/* %%Function:FKeyCmdLeftRight %%Owner:bradch */
|
|
FKeyCmdLeftRight(kc, fDoIt)
|
|
int kc;
|
|
BOOL fDoIt;
|
|
{
|
|
|
|
BOOL fFwdKey = fFalse;
|
|
BOOL fExtend = (vfShiftKey || vfExtendSel);
|
|
int sty;
|
|
|
|
switch ( kc )
|
|
{
|
|
case kcNextPara:
|
|
fFwdKey = fTrue;
|
|
|
|
case kcPrevPara:
|
|
sty = styPara;
|
|
break;
|
|
|
|
case kcWordRightAlt:
|
|
if (vfShiftKey) /* Avoid interference w/outline key*/
|
|
return fFalse;
|
|
/* FALL THROUGH */
|
|
case kcWordRight:
|
|
fFwdKey = fTrue;
|
|
sty = styWord;
|
|
break;
|
|
case kcWordLeftAlt:
|
|
if (vfShiftKey) /* Avoid interference w/outline key*/
|
|
return fFalse;
|
|
/* FALL THROUGH */
|
|
case kcWordLeft:
|
|
sty = styWord;
|
|
break;
|
|
|
|
case kcEndLine:
|
|
fFwdKey = fTrue;
|
|
|
|
case kcBeginLine:
|
|
sty = styLineEnd;
|
|
break;
|
|
|
|
case kcRight:
|
|
fFwdKey = fTrue;
|
|
|
|
case kcLeft:
|
|
/* 2202 fix: incorrect dragging in outline mode (peterdur) */
|
|
/* If dragging and a para is selected, do a para move instead */
|
|
if ((*hwwdCur)->fOutline && (vfShiftKey || vfExtendSel)
|
|
&& (selCur.sty == styPara))
|
|
sty = styPara;
|
|
else
|
|
sty = styChar;
|
|
break;
|
|
|
|
default:
|
|
return fFalse;
|
|
}
|
|
|
|
if (fDoIt)
|
|
{
|
|
ClearInsertLine(PselActive());
|
|
if (vfBlockSel)
|
|
CursBlockLeftRight(sty, fFwdKey ? 1 : -1, fFalse/*ignored*/);
|
|
else
|
|
CursLeftRight(sty, fFwdKey ? 1 : -1, fExtend);
|
|
|
|
vfLastCursor = fFalse;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* F K E Y C M D U P D O W N */
|
|
/* Check if kc is a vertical cursor mover. If it is, then if fDoIt, do the
|
|
movement and return fTrue. If it is not, return fFalse.
|
|
*/
|
|
/* %%Function:FKeyCmdUpDown %%Owner:bradch */
|
|
FKeyCmdUpDown(kc, fDoIt)
|
|
int kc;
|
|
{
|
|
struct SEL *psel;
|
|
int sty, dSty;
|
|
BOOL fFwdKey = fFalse;
|
|
extern int vkcPrev;
|
|
BOOL fDragOutline = fFalse;
|
|
|
|
/* Reset the scroll counts, if not consecutive scroll up or down. */
|
|
if (kc != vkcPrev)
|
|
{
|
|
vcConseqScroll = 0;
|
|
sbScroll = sbScrollLast = SB_NIL;
|
|
}
|
|
switch (kc)
|
|
{
|
|
case kcDown:
|
|
fFwdKey = fTrue;
|
|
/* FALL THRU */
|
|
|
|
case kcUp:
|
|
/* 2202 fix: incorrect dragging in outline mode (peterdur) */
|
|
/* If dragging and a para is selected, do a para move instead */
|
|
if ((*hwwdCur)->fOutline && (vfShiftKey || vfExtendSel)
|
|
&& (selCur.sty == styPara))
|
|
fDragOutline = fTrue;
|
|
sty = styLine;
|
|
break;
|
|
|
|
case kcPageDown:
|
|
fFwdKey = fTrue;
|
|
/* FALL THRU */
|
|
|
|
case kcPageUp:
|
|
sty = styScreen;
|
|
break;
|
|
|
|
case kcEndDoc:
|
|
fFwdKey = fTrue;
|
|
/* FALL THRU */
|
|
|
|
case kcTopDoc:
|
|
sty = styDoc;
|
|
break;
|
|
|
|
case kcEndScreen:
|
|
fFwdKey = fTrue;
|
|
|
|
case kcTopScreen:
|
|
sty = styScreenEnd;
|
|
break;
|
|
|
|
default:
|
|
return fFalse;
|
|
}
|
|
|
|
if (fDoIt)
|
|
{
|
|
Profile(vpfi == pfiPgUp ? StartProf(5) : 0);
|
|
dSty = 1;
|
|
ClearInsertLine((psel = PselActive()));
|
|
if (vfBlockSel)
|
|
CursBlockUpDown(sty,
|
|
fFwdKey ? dSty : -dSty, fTrue /* fDrag */);
|
|
else
|
|
{
|
|
EnsureSelInWw(fTrue, psel);
|
|
if (fDragOutline)
|
|
CursLeftRight(styPara, fFwdKey ? dSty : -dSty, fTrue);
|
|
else
|
|
CursUpDown(sty, fFwdKey ? dSty : -dSty,
|
|
(vfShiftKey || vfExtendSel)/* fDrag */);
|
|
}
|
|
Profile(vpfi == pfiPgUp ? StopProf() : 0);
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
/* F P R O C E S S D B G K E Y */
|
|
/* Handle special debugging keys. Here they get handled in dialogs,
|
|
message boxes and during normal operation.
|
|
*/
|
|
|
|
/* %%Function:FProcessDbgKey %%Owner:bradch */
|
|
FProcessDbgKey (kc)
|
|
int kc;
|
|
{
|
|
switch (kc)
|
|
{
|
|
case kcPrintScr:
|
|
SlapWnd();
|
|
case kcSysState:
|
|
DumpState ();
|
|
return fTrue;
|
|
case kcStackTrace:
|
|
DoStackTrace (NULL);
|
|
return fTrue;
|
|
case kcExitWin1:
|
|
case kcExitWin2:
|
|
OurExitWindows(); /* does not return */
|
|
|
|
#ifdef PCJ
|
|
case KcAlt(KcCtrl('1')):
|
|
PCJDbg1 ();
|
|
return fTrue;
|
|
case KcAlt(KcCtrl('2')):
|
|
PCJDbg2 ();
|
|
return fTrue;
|
|
case KcAlt(KcCtrl('3')):
|
|
PCJDbg3 ();
|
|
return fTrue;
|
|
#endif /* PCJ */
|
|
|
|
}
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
/* F R U N M A C R O */
|
|
/* %%Function:FRunMacro %%Owner:bradch */
|
|
FRunMacro(stName)
|
|
char * stName;
|
|
{
|
|
extern CMB vcmb;
|
|
BCM bcm;
|
|
|
|
#ifdef DCMDTBL
|
|
CommSz(SzShared("FRunMacro: "));
|
|
CommStNL(stName);
|
|
#endif
|
|
|
|
if ((bcm = BcmOfSt(stName)) == bcmNil)
|
|
return fFalse;
|
|
|
|
vcmb.kc = kcNil;
|
|
vcmb.bcm = bcm;
|
|
vcmb.fDefaults = fTrue;
|
|
vcmb.fAction = fTrue;
|
|
vcmb.fDialog = fTrue;
|
|
|
|
return FExecCmd(bcm);
|
|
}
|
|
|
|
|
|
csconst int rgbcm[] =
|
|
{
|
|
/* This file is generated by MKCMD */
|
|
#include "rgbcm.h"
|
|
};
|
|
|
|
|
|
#define ibcmNil -1
|
|
#define ibcmMac (sizeof(rgbcm) / sizeof(int))
|
|
|
|
/* I B C M F R O M B C M */
|
|
/* ibcm's are the invariant id numbers used for help contexts and
|
|
semantic events in CBT */
|
|
/* made native for macro optimization */
|
|
/* %%Function:IbcmFromBcm %%Owner:bradch */
|
|
NATIVE IbcmFromBcm(bcm)
|
|
int bcm;
|
|
{
|
|
return IScanLprgw( (int far *)rgbcm, bcm, ibcmMac );
|
|
}
|
|
|
|
|
|
/* %%Function:CxtFromBcm %%Owner:bradch */
|
|
CxtFromBcm(bcm)
|
|
BCM bcm;
|
|
{
|
|
int ibcm;
|
|
HPSY hpsy;
|
|
uns bsyNext;
|
|
uns bsyI;
|
|
|
|
if (bcm >= bcmMacStd)
|
|
return cxtUserDefined;
|
|
|
|
hpsy = (SY HUGE *) (vhpsyt->grpsy + bcm);
|
|
bsyNext = hpsy->bsyNext;
|
|
|
|
for (ibcm = 0; ibcm < ibcmMac; ibcm++)
|
|
{
|
|
bsyI = rgbcm[ibcm];
|
|
if (bcm == bsyI || bsyI != bsyNil && bsyNext == bsyI &&
|
|
((SY HUGE *) (vhpsyt->grpsy + bsyI))->stName[0] == '\0')
|
|
return ibcm;
|
|
}
|
|
|
|
return ibcmNil;
|
|
}
|
|
|
|
|
|
/* B C M F R O M I B C M */
|
|
/* %%Function:BcmFromIbcm %%Owner:bradch */
|
|
BcmFromIbcm(ibcm)
|
|
int ibcm;
|
|
{
|
|
Assert (ibcm < ibcmMac);
|
|
|
|
return rgbcm[ibcm];
|
|
}
|
|
|
|
|
|
|
|
/* %%Function:ClearRrf %%Owner:bradch */
|
|
ClearRrf()
|
|
{
|
|
if (rrf.hgrpprl != hNil)
|
|
{
|
|
FreePh(&rrf.hgrpprl);
|
|
}
|
|
SetBytes(&rrf, '\0', sizeof(RRF));
|
|
rrf.doc = selCur.doc;
|
|
rrf.ftc = ftcNil;
|
|
/*
|
|
rrf.stc = stcNil;
|
|
*/
|
|
}
|
|
|
|
|
|
/* %%Function:FRepeatableBcm %%Owner:bradch */
|
|
FRepeatableBcm(bcm)
|
|
BCM bcm;
|
|
{
|
|
if ((int)bcm >= 0)
|
|
{
|
|
FetchCm(bcm);
|
|
return vpsyFetch->fRepeatable;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* F S P E C I A L B C M I N D I A L O G */
|
|
/* Returns true if this is one of the bcm's of formatting keys while
|
|
in a dialog. These should not touch the again state. */
|
|
|
|
/* %%Function:FSpecialBcmInDialog %%Owner:bradch */
|
|
FSpecialBcmInDialog(bcm)
|
|
{
|
|
return (vfSearchRepl && bcm != imiSearch && bcm != imiReplace ||
|
|
vfDefineStyle && bcm != bcmStyles);
|
|
}
|
|
|
|
|
|
/* %%Function:FNeedsDocBcm %%Owner:bradch */
|
|
FNeedsDocBcm(bcm)
|
|
int bcm;
|
|
{
|
|
if (bcm >= 0)
|
|
{
|
|
FetchCm(bcm);
|
|
return vpsyFetch->fNeedsDoc;
|
|
}
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* S E T A G A I N */
|
|
|
|
/* %%Function:SetAgain %%Owner:bradch */
|
|
SetAgain(bcm)
|
|
int bcm;
|
|
{
|
|
extern struct AAB vaab;
|
|
|
|
if (!FRepeatableBcm(bcm))
|
|
{
|
|
bcm = bcmNil;
|
|
}
|
|
|
|
vaab.bcm = bcm;
|
|
|
|
/* free up grpprl in vaab if bcmFormatting is not the action repeated */
|
|
if (vaab.hgrpprl != hNil && vaab.bcm != bcmFormatting)
|
|
{
|
|
FreePh(&vaab.hgrpprl);
|
|
vaab.cbGrpprl = 0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/* S E T A G A I N C P */
|
|
/* Sets vaab with cp info */
|
|
/* %%Function:SetAgainCp %%Owner:bradch */
|
|
SetAgainCp(doc, cpFirst, cpLow, cpLim)
|
|
int doc;
|
|
CP cpFirst, cpLow, cpLim;
|
|
{
|
|
extern struct AAB vaab;
|
|
|
|
/* if copylooks, the space occupied by these cp's is a handle
|
|
that should be freed. Hopefully, this routine is aways called
|
|
AFTER SetAgain so that will already be taken care of. bz
|
|
*/
|
|
Assert (vaab.bcm != bcmCopyLooks);
|
|
vaab.doc = doc;
|
|
vaab.cpFirst = cpFirst;
|
|
vaab.cpLow = cpLow;
|
|
vaab.cpLim = cpLim;
|
|
}
|
|
|
|
|
|
/* S E T A G A I N C A B */
|
|
/* %%Function:SetAgainCab %%Owner:bradch */
|
|
SetAgainCab(bcm, hcab)
|
|
BCM bcm;
|
|
void ** hcab;
|
|
{
|
|
extern struct AAB vaab;
|
|
|
|
if (vaab.hcab != hNil && vaab.hcab != hcab)
|
|
FreeCab(vaab.hcab);
|
|
|
|
SetAgain(bcm);
|
|
vaab.hcab = hcab;
|
|
}
|
|
|
|
|
|
/* %%Function:InvalAgain %%Owner:bradch */
|
|
InvalAgain()
|
|
{
|
|
SetAgain(bcmNil);
|
|
vaab.acc = accNil;
|
|
vaab.asc = ascNil;
|
|
vaab.doc = docNil;
|
|
}
|
|
|
|
|
|
/* %%Function:TestInvalAgain %%Owner:bradch */
|
|
TestInvalAgain()
|
|
{
|
|
/* kill all commands which act on the document and hence can get smashed by
|
|
changed doc. possible overkills in the process. */
|
|
|
|
if (vaab.bcm != bcmNil && FNeedsDocBcm(vaab.bcm))
|
|
InvalAgain();
|
|
}
|
|
|
|
|
|
/* %%Function:ClearRibbonRrf %%Owner:bradch */
|
|
ClearRibbonRrf()
|
|
{
|
|
rrf.fBold = rrf.fItalic = rrf.fSCaps = fFalse;
|
|
rrf.kul = rrf.iSuperSub = 0;
|
|
rrf.ftc = ftcNil;
|
|
rrf.hps = 0;
|
|
rrf.fRibbon = fFalse;
|
|
rrf.fDirty = /*(rrf.stc != stcNil) ||*/ (rrf.hgrpprl != hNil);
|
|
rrf.fTouched = fTrue;
|
|
}
|
|
|
|
|
|
/* %%Function:ClearRulerRrf %%Owner:bradch */
|
|
ClearRulerRrf()
|
|
{
|
|
/*
|
|
rrf.stc = stcNil;
|
|
*/
|
|
if (rrf.hgrpprl != hNil)
|
|
{
|
|
FreePh(&rrf.hgrpprl);
|
|
rrf.hgrpprl = hNil;
|
|
rrf.cbGrpprl = 0;
|
|
}
|
|
rrf.fRibbon = fTrue;
|
|
rrf.fDirty = rrf.fBold || rrf.fItalic || rrf.fSCaps ||
|
|
(rrf.kul != 0) || (rrf.iSuperSub != iSSNormal) ||
|
|
(rrf.ftc != ftcNil) || (rrf.hps != 0);
|
|
rrf.fTouched = fTrue;
|
|
}
|
|
|
|
|
|
/* F S E T A G A I N G R P P R L */
|
|
/* Sets the Grpprl in the again structure */
|
|
/* %%Function:FSetAgainGrpprl %%Owner:bradch */
|
|
FSetAgainGrpprl(grpprl, cb, bcm)
|
|
char *grpprl;
|
|
int cb;
|
|
int bcm;
|
|
{
|
|
|
|
|
|
if (vaab.hgrpprl != hNil)
|
|
FreeH(vaab.hgrpprl);
|
|
if (cb > cbMaxAgainGrpprl || (vaab.hgrpprl = HAllocateCw(CwFromCch(cb))) == hNil)
|
|
{
|
|
/* return value set up for whoever cares if repeat set up ok */
|
|
/* note that if allocation fails,repeat will do nothing */
|
|
vaab.cbGrpprl = 0;
|
|
return fFalse;
|
|
}
|
|
|
|
bltb(grpprl, *vaab.hgrpprl, cb);
|
|
vaab.cbGrpprl = cb;
|
|
SetAgain (bcm);
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* F P R I N T E R O K */
|
|
/* Check if the printer and the port are valid */
|
|
/* If we have never actually tried to get a printer DC
|
|
(DisplayAsPrint and background repag and status line are off)
|
|
this routine may return fTrue because it doesn't know any better
|
|
and finding out is too expensive (because it would entail
|
|
trying to get a printer DC) */
|
|
|
|
/* %%Function:FPrinterOK %%Owner:bradch */
|
|
BOOL FPrinterOK()
|
|
{
|
|
return !vmerr.fPrintEmerg && vpri.hszPrinter != NULL &&
|
|
FNeNcSz(*vpri.hszPrPort, szNone);
|
|
}
|
|
|
|
|
|
/* F S C R A P F U L L */
|
|
/* Return fTrue iff the clipboard contains something we can use */
|
|
/* %%Function:FScrapFull %%Owner:bradch */
|
|
FScrapFull(fPasteLink)
|
|
BOOL fPasteLink;
|
|
{
|
|
BOOL f = fFalse;
|
|
|
|
if (vsab.fOwnClipboard)
|
|
{
|
|
return !fPasteLink && (CpMacDocEdit(docScrap) > cp0);
|
|
}
|
|
|
|
if (OpenClipboard(vhwndApp) != 0)
|
|
{
|
|
int fmt = 0;
|
|
|
|
while ((fmt = EnumClipboardFormats(fmt)) != 0)
|
|
{
|
|
if ((fPasteLink && fmt == cfLink)
|
|
|| (!fPasteLink && (fmt == cfRTF ||
|
|
fmt == CF_UNICODETEXT ||
|
|
fmt == CF_TEXT ||
|
|
fmt == CF_BITMAP ||
|
|
fmt == CF_METAFILEPICT)))
|
|
{
|
|
f = fTrue;
|
|
break;
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
|
|
/* F H A S G L S Y S */
|
|
/* %%Function:FHasGlsys %%Owner:bradch */
|
|
FHasGlsys(doc)
|
|
int doc;
|
|
{
|
|
Assert(doc == docNil || PdodDoc(doc)->fDot);
|
|
if (doc == docNil || (doc = PdodDoc(doc)->docGlsy) == docNil)
|
|
return fFalse;
|
|
else
|
|
return (*PdodDoc(doc)->hsttbGlsy)->ibstMac > 0;
|
|
}
|
|
|
|
|
|
/* %%Function:FHasRefs %%Owner:bradch */
|
|
FHasRefs(doc, edcDrp)
|
|
int doc;
|
|
int edcDrp;
|
|
{
|
|
struct DOD *pdod;
|
|
struct DRP *pdrp;
|
|
|
|
if (doc != docNil && (pdod = PdodDoc(doc))->fMother)
|
|
{
|
|
pdrp = ((int *)pdod + edcDrp);
|
|
if (pdrp->doc != docNil && pdrp->hplcRef != hNil &&
|
|
PdodDoc(pdrp->doc)->hplcfnd != hNil)
|
|
{
|
|
return fTrue;
|
|
}
|
|
}
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
/* F W H O L E R O W S P S E L */
|
|
/* Returns true if the selection covers all of the rows */
|
|
/* %%Function:FWholeRowsPsel %%Owner:bradch */
|
|
FWholeRowsPsel(psel)
|
|
struct SEL *psel;
|
|
{
|
|
|
|
if (!psel->fTable)
|
|
return fFalse;
|
|
else if (psel->sk == skRows)
|
|
return fTrue;
|
|
else if (psel->itcFirst == 0 && psel->itcLim >= ItcMacPca(&psel->ca))
|
|
return fTrue;
|
|
|
|
return fFalse;
|
|
|
|
}
|
|
|
|
|
|
/* F T A B L E I N P C A */
|
|
/* Returns true if there is a table anywhere in the ca */
|
|
/* %%Function:FTableInPca %%Owner:bradch */
|
|
FTableInPca(pca)
|
|
struct CA *pca;
|
|
{
|
|
CP cpCur;
|
|
int doc = pca->doc;
|
|
CP cpLim = pca->cpLim;
|
|
|
|
cpCur = pca->cpFirst;
|
|
if (cpLim == cpCur)
|
|
cpLim++;
|
|
|
|
while (cpCur < cpLim)
|
|
{
|
|
CachePara(doc,cpCur);
|
|
if (FInTableDocCp(doc, cpCur))
|
|
return fTrue;
|
|
cpCur = caPara.cpLim;
|
|
}
|
|
|
|
return fFalse;
|
|
|
|
}
|
|
|
|
|
|
/* F T T P P S E L */
|
|
/* Determine whether selection is the end of row paragraph */
|
|
/* %%Function:FTtpPsel %%Owner:bradch */
|
|
BOOL FTtpPsel(psel)
|
|
struct SEL *psel;
|
|
{
|
|
extern struct TAP vtapFetch;
|
|
extern struct CA caTap;
|
|
|
|
struct CA caSel;
|
|
CP cp;
|
|
|
|
if (psel->fIns)
|
|
{
|
|
CachePara(psel->doc, psel->cpFirst);
|
|
return (vpapFetch.fTtp);
|
|
}
|
|
else if (psel->fTable)
|
|
{
|
|
CpFirstTap(psel->doc, psel->cpFirst);
|
|
return (psel->itcFirst == vtapFetch.itcMac);
|
|
}
|
|
|
|
return fFalse;
|
|
}
|
|
|
|
|
|
|
|
/* %%Function:FLegalBcm %%Owner:bradch */
|
|
FLegalBcm(bcm)
|
|
BCM bcm;
|
|
{
|
|
struct SEL *psel = PselActive();
|
|
struct DOD *pdod = psel->doc != docNil ? PdodDoc(psel->doc) : NULL;
|
|
|
|
if (bcm == imiRepeat)
|
|
bcm = vaab.bcm;
|
|
|
|
if (bcm == bcmNil)
|
|
return fFalse;
|
|
|
|
/* This takes care of menu caches, etc. */
|
|
/* legal except when in Preview */
|
|
if ((int) bcm < 0 && vlm == lmPreview)
|
|
return fFalse;
|
|
|
|
if ((int)bcm >= 0)
|
|
{
|
|
FetchCm(bcm);
|
|
|
|
#ifdef DEBUG
|
|
if (psel->doc != docNil)
|
|
AssertH(hwwdCur);
|
|
#endif
|
|
|
|
/* REVIEW cslbug: broken up because of native bug */
|
|
if ((bcm == bcmRibbon && vhmes != hNil) ||
|
|
(vpsyFetch->fNeedsDoc && psel->doc == docNil) ||
|
|
(!vpsyFetch->fPreviewMode && vlm == lmPreview))
|
|
{
|
|
return fFalse;
|
|
}
|
|
|
|
if (psel->doc != docNil)
|
|
{
|
|
if ((vpsyFetch->fMomLock && PdodMother(psel->doc)->fLockForEdit) ||
|
|
(vpsyFetch->fLockedMode && pdod->fLockForEdit))
|
|
{
|
|
switch (bcm)
|
|
{
|
|
case bcmExpand:
|
|
case bcmCollapse:
|
|
case bcmShowToLevel1:
|
|
case bcmShowToLevel2:
|
|
case bcmShowToLevel3:
|
|
case bcmShowToLevel4:
|
|
case bcmShowToLevel5:
|
|
case bcmShowToLevel6:
|
|
case bcmShowToLevel7:
|
|
case bcmShowToLevel8:
|
|
case bcmShowToLevel9:
|
|
case bcmExpandAll:
|
|
case bcmToggleEllip:
|
|
break;
|
|
default:
|
|
return fFalse;
|
|
}
|
|
}
|
|
if (vpsyFetch->fFootnoteMode && pdod->fFtn)
|
|
return fFalse;
|
|
|
|
|
|
if ((vpsyFetch->fHeaderMode && (pdod->fHdr || pdod->fDispHdr)) ||
|
|
(vpsyFetch->fAnnotateMode && pdod->fAtn) ||
|
|
(vpsyFetch->fOutlineMode && (*hwwdCur)->wk == wkOutline) ||
|
|
(vpsyFetch->fMacroMode && (*hwwdCur)->wk == wkMacro))
|
|
{
|
|
return fFalse;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (psel->doc != docNil)
|
|
{
|
|
if ( (PdodDoc(psel->doc)->fFtn || PdodDoc(psel->doc)->fAtn))
|
|
{
|
|
/* are we pasting into a footnote/annot subdoc outside the
|
|
range of any entry? In the autodelete with selection case
|
|
this is checked in CmdAutoDelete (eventually) but for non-
|
|
autodelete or ins pt, we need this check. Note that in the
|
|
non autodelete case, we use an ins pt. This prevents bogus
|
|
rejections when the selection would not let us paste because it
|
|
spans footnotes, but it would be ok as an ins pt.
|
|
*/
|
|
switch (bcm)
|
|
{
|
|
case bcmInsTable: /* insert table ignores autodelete */
|
|
if (!FCheckRefDoc(psel->doc, psel->cpFirst, psel->cpFirst, fFalse/*fReportErr*/))
|
|
return fFalse;
|
|
break;
|
|
case bcmInsFieldChars:
|
|
case bcmPaste:
|
|
case bcmPasteLink:
|
|
case bcmHdrPage:
|
|
case bcmHdrDate:
|
|
case bcmHdrTime:
|
|
case bcmInsPic:
|
|
case bcmInsFile:
|
|
case bcmInsField:
|
|
if ((psel->fIns || !vpref.fAutoDelete) &&
|
|
!FCheckRefDoc(psel->doc, psel->cpFirst, psel->cpFirst, fFalse/*fReportErr*/))
|
|
{
|
|
return fFalse;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (bcm)
|
|
{
|
|
case bcmRuler:
|
|
if ((*hwwdCur)->fOutline)
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiFieldCodes:
|
|
if (hwwdCur == hNil || (*hwwdCur)->grpfvisi.fvisiShowAll)
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiUndo:
|
|
if (vuab.uac == uacNil || vuab.bcm == bcmNil)
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmMoveWnd:
|
|
case bcmSizeWnd:
|
|
case bcmZoomWnd:
|
|
if (vpref.fZoomMwd)
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmRestoreWnd:
|
|
if (!vpref.fZoomMwd)
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmSplit:
|
|
if (hmwdCur == hNil || !(*hmwdCur)->fCanSplit)
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiPrint:
|
|
case imiPrintPreview:
|
|
/* grayed if no printer */
|
|
if (!FPrinterOK())
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiCalculate:
|
|
case imiDelCut:
|
|
case imiCopy:
|
|
/* grayed if empty selection */
|
|
if (psel->fIns)
|
|
return fFalse;
|
|
break;
|
|
|
|
/* listed here, I think, are all bcm's which cause something
|
|
to be inserted into the document (RP) */
|
|
case bcmPaste:
|
|
if (!FScrapFull(fFalse))
|
|
return fFalse;
|
|
/* FALL THROUGH */
|
|
|
|
case bcmTyping:
|
|
case bcmInsBreak:
|
|
case imiInsPicture:
|
|
case imiInsFile:
|
|
case bcmIndexEntry:
|
|
case bcmIndex:
|
|
case imiTOC:
|
|
case imiInsPageBreak:
|
|
case bcmHdrPage:
|
|
case bcmHdrDate:
|
|
case bcmHdrTime:
|
|
case bcmUnspike:
|
|
case imiRenumParas:
|
|
case bcmInsFootnote:
|
|
case imiSort:
|
|
|
|
/* REVIEW bradch (rp): Are all the checks for fLockForEdit in FLegalBcm
|
|
necessary with the LockMode bit in the command table? There are a
|
|
couple more below in this routine. If they aren't, we should make sure
|
|
all the bcm's we're checking specifically in here have the *L in
|
|
opuscmd.cmd before removing this code, but once we do it will save us
|
|
a bunch of code.
|
|
*/
|
|
|
|
if (psel->doc == docNil || PdodDoc(psel->doc)->fLockForEdit)
|
|
return fFalse;
|
|
if (bcm == imiSort) /* fttp check not enough for sort */
|
|
break;
|
|
if (bcm == bcmPaste && vsab.fTable)
|
|
break; /* fTtp check not necessary if pasting cells */
|
|
/* FALL THROUGH */
|
|
|
|
case bcmInsAnnotation:
|
|
|
|
if (FTtpPsel(psel))
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmInsColumnBreak:
|
|
pdod = PdodDoc(psel->doc);
|
|
if (!FSelWithinTable(psel) && ((*hwwdCur)->wk == wkOutline ||
|
|
pdod->fShort))
|
|
{
|
|
return fFalse;
|
|
}
|
|
break;
|
|
|
|
case imiPasteLink:
|
|
if (!FScrapFull(fTrue) || FTtpPsel(psel))
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiGlossary:
|
|
if (FTtpPsel(psel))
|
|
return fFalse;
|
|
|
|
if ((psel->fTable ? !FWholeRowsPsel(psel) :
|
|
(psel->sk & skNotGlsy)) &&
|
|
!FHasGlsys(docGlobalDot) &&
|
|
!FHasGlsys(DocDotMother(psel->doc)))
|
|
{
|
|
return fFalse;
|
|
}
|
|
break;
|
|
|
|
case imiViewFootnote:
|
|
case imiViewAnnotation:
|
|
if (!FHasRefs(DocMother(psel->doc),
|
|
bcm == imiViewFootnote ? edcDrpFtn : edcDrpAtn))
|
|
{
|
|
return fFalse;
|
|
}
|
|
break;
|
|
|
|
case imiInsField:
|
|
case bcmInsFieldChars:
|
|
if (psel->doc == docNil ||
|
|
PdodDoc(psel->doc)->fLockForEdit ||
|
|
(psel->sk != skIns && psel->sk != skSel) ||
|
|
psel->fTable || FTtpPsel(psel))
|
|
{
|
|
return fFalse;
|
|
}
|
|
break;
|
|
|
|
case bcmInsBookmark:
|
|
if (psel->fTable && !FWholeRowsPsel(psel))
|
|
return fFalse;
|
|
if (psel->sk == skBlock)
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmHdrLinkPrev:
|
|
return FCanLinkPrev(wwCur);
|
|
|
|
case imiReplace:
|
|
case imiHyphenate:
|
|
case imiRevMarking:
|
|
case imiSpelling:
|
|
case bcmSpellSelection:
|
|
case bcmChangeCase:
|
|
LNoBlock:
|
|
if (psel->fBlock)
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiInsTable:
|
|
if (psel->fWithinCell || FTableInPca(&psel->ca))
|
|
return fFalse;
|
|
goto LNoBlock;
|
|
|
|
case bcmTableToText:
|
|
if (!FWholeRowsPsel(psel))
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmFormatTable:
|
|
if (!psel->fWithinCell && !psel->fTable)
|
|
return fFalse;
|
|
|
|
if (FTtpPsel(psel))
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiEditTable:
|
|
case bcmNextCell:
|
|
case bcmPrevCell:
|
|
if (!psel->fWithinCell && !psel->fTable)
|
|
return fFalse;
|
|
|
|
break;
|
|
|
|
case bcmTopColumn:
|
|
case bcmSelectTable:
|
|
if (!FInTableDocCp(psel->doc, psel->cpFirst))
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmBottomColumn:
|
|
if (!FInTableDocCp(psel->doc, psel->cpLim))
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiPosition:
|
|
if (vlm == lmPreview && (vpvs.iobj - iobjMinAbs < 0))
|
|
return fFalse;
|
|
break;
|
|
|
|
case imiPicture:
|
|
if (!psel->fGraphics)
|
|
return fFalse;
|
|
break;
|
|
|
|
case bcmRecorder:
|
|
case bcmEditMacro:
|
|
case bcmChangeKeys:
|
|
case bcmAssignToMenu:
|
|
if (PdodDoc(docGlobalDot)->fLockForEdit &&
|
|
FDisableTemplate(psel->doc))
|
|
{
|
|
return fFalse;
|
|
}
|
|
break;
|
|
|
|
case bcmExpand:
|
|
case bcmCollapse:
|
|
case bcmShowToLevel1:
|
|
case bcmShowToLevel2:
|
|
case bcmShowToLevel3:
|
|
case bcmShowToLevel4:
|
|
case bcmShowToLevel5:
|
|
case bcmShowToLevel6:
|
|
case bcmShowToLevel7:
|
|
case bcmShowToLevel8:
|
|
case bcmShowToLevel9:
|
|
case bcmExpandAll:
|
|
case bcmToggleEllip:
|
|
if (!(*hwwdCur)->fOutline)
|
|
return fFalse;
|
|
break;
|
|
}
|
|
|
|
/* check for in extremis (extremely low memory or no scratch file
|
|
space left) -- just let them save or shutdown */
|
|
Assert(cHpFreeze==0);
|
|
if (vmerr.fDiskEmerg ||
|
|
(vmerr.hrgwEmerg3 == hNil &&
|
|
(vmerr.hrgwEmerg3 = HAllocateCw(cwEmerg3)) == hNil) ||
|
|
(vmerr.hrgwEmerg2 == hNil &&
|
|
(vmerr.hrgwEmerg2 = HAllocateCw(cwEmerg2)) == hNil) ||
|
|
(vmerr.hrgwEmerg1 == hNil &&
|
|
(vmerr.hrgwEmerg1 = HAllocateCw(cwEmerg1)) == hNil))
|
|
{
|
|
vmerr.mat = matNil; /* Do not report errors from above allocations */
|
|
switch (bcm)
|
|
{
|
|
case bcmOK:
|
|
case bcmCancel:
|
|
case bcmMenuMode:
|
|
case bcmSaveDot:
|
|
case bcmSave:
|
|
case bcmExit:
|
|
case imiSaveAs:
|
|
case imiFileClose:
|
|
case imiSaveAll:
|
|
case bcmCloseWnd:
|
|
case bcmNextMwd:
|
|
case bcmPrevMwd:
|
|
case bcmWndCache:
|
|
#ifdef DEBUG
|
|
case imiDebugFailures:
|
|
case imiDbgMemory:
|
|
case bcmEatMemory:
|
|
case bcmFreeMemory:
|
|
#endif /* DEBUG */
|
|
return fTrue;
|
|
case bcmPageView:
|
|
Assert(wwCur != wwNil);
|
|
/* allow pageview to be turned off can improve low memory situation */
|
|
return (PwwdWw(wwCur)->fPageView);
|
|
default:
|
|
return (bcm >= imiWnd1 && bcm <= imiWnd9);
|
|
}
|
|
}
|
|
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
|
|
/* Prepare for execution of the given command by terminating
|
|
any appropriate modes we might be in. It is assumed that the
|
|
command has been fetched. */
|
|
/* %%Function:PrepExecBcm %%Owner:bradch */
|
|
PrepExecBcm(bcm)
|
|
int bcm;
|
|
{
|
|
/* We do not just fetch the commands here because when EL calls
|
|
this, it uses FetchSy() instead of FetchCm(). */
|
|
|
|
/* bcmHelp is a special case - we do NOT want to cancel block
|
|
mode or extend selection mode if the user calls help. */
|
|
if (vfBlockSel && !vpsyFetch->fBlockMode && bcm != bcmHelp)
|
|
BlockModeEnd();
|
|
|
|
if (vfExtendSel && !vpsyFetch->fExtendMode && bcm != bcmHelp)
|
|
ExtendSelEnd();
|
|
|
|
if (vssc != sscNil)
|
|
switch (bcm)
|
|
{
|
|
extern int vfAwfulNoise;
|
|
|
|
case bcmCancel:
|
|
vfAwfulNoise = fTrue; /* prevent beep in this case */
|
|
/* fall thru intentional */
|
|
default:
|
|
if (vpsyFetch->mct != mctEl || !vpsyFetch->fDyadic)
|
|
CancelDyadic();
|
|
break;
|
|
|
|
case bcmTraceMacro:
|
|
case bcmStepMacro:
|
|
case bcmContinueMacro:
|
|
case bcmAnimateMacro:
|
|
case bcmOK:
|
|
case bcmOtherPane:
|
|
case bcmPgvNextPage:
|
|
case bcmPgvPrevPage:
|
|
case bcmNextMwd:
|
|
case bcmPrevMwd:
|
|
case bcmNextCell:
|
|
case bcmPrevCell:
|
|
case bcmBeginRow:
|
|
case bcmEndRow:
|
|
case bcmTopColumn:
|
|
case bcmBottomColumn:
|
|
|
|
/* bobz bcmGoto would be nice, but it is hardcoded for selCur,
|
|
and we would have to change it all all its called routines to
|
|
use PSelActive().
|
|
*/
|
|
case imiWnd1:
|
|
case imiWnd2:
|
|
case imiWnd3:
|
|
case imiWnd4:
|
|
case imiWnd5:
|
|
case imiWnd6:
|
|
case imiWnd7:
|
|
case imiWnd8:
|
|
case imiWnd9:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
PrepAgainBcm(bcm)
|
|
int bcm;
|
|
{
|
|
if (bcm != bcmRepeat)
|
|
{
|
|
if (FRepeatableBcm(bcm))
|
|
{
|
|
if (!FSpecialBcmInDialog(bcm))
|
|
SetAgain(bcmNil);
|
|
}
|
|
else if (FNeedsDocBcm(bcm))
|
|
{
|
|
/* for a non-repeatable command, blow away repeat of some
|
|
fragile commands, like dyad move/copy and insert text bz
|
|
This may be overkill, but easier that checking every
|
|
non-repeatable command. We can safely ignore those non-
|
|
repeatables that don't require a doc, since they won't
|
|
change anything. bz [bc]
|
|
*/
|
|
switch (bcm)
|
|
{
|
|
case bcmGoto:
|
|
case bcmSearch:
|
|
case bcmNextCell:
|
|
case bcmPrevCell:
|
|
case bcmBeginRow:
|
|
case bcmEndRow:
|
|
case bcmTopColumn:
|
|
case bcmBottomColumn:
|
|
case imiWnd1:
|
|
case imiWnd2:
|
|
case imiWnd3:
|
|
case imiWnd4:
|
|
case imiWnd5:
|
|
case imiWnd6:
|
|
case imiWnd7:
|
|
case imiWnd8:
|
|
case imiWnd9:
|
|
case bcmFindNext:
|
|
case bcmNextField:
|
|
case bcmPreviousField:
|
|
case bcmNextMwd:
|
|
case bcmPrevMwd:
|
|
case bcmOtherPane:
|
|
case bcmPgvPrevPage:
|
|
case bcmPgvNextPage:
|
|
case bcmNextDr:
|
|
case bcmPrevDr:
|
|
case bcmArrangeWnd:
|
|
case bcmSplit:
|
|
case bcmSizeWnd:
|
|
case bcmMoveWnd:
|
|
case bcmZoomWnd:
|
|
case bcmRestoreWnd:
|
|
case bcmShowAll:
|
|
case bcmSelectAll:
|
|
case bcmExtendSel:
|
|
case bcmShrinkExtend:
|
|
break;
|
|
|
|
default:
|
|
TestInvalAgain();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* C M D R U N A T M O N D O C */
|
|
/* %%Function:CmdRunAtmOnDoc %%Owner:bradch */
|
|
CmdRunAtmOnDoc(atm, doc)
|
|
uns atm;
|
|
{
|
|
extern BOOL vfDisableAutoMacros;
|
|
extern HPSY HpsyFromBcmElg();
|
|
extern HWND vhwndStartup;
|
|
extern HPSYT vhpsyt;
|
|
extern int mwCur;
|
|
BCM bcm;
|
|
char stAtm [ichMaxAtm];
|
|
|
|
Assert(atm < atmMax);
|
|
|
|
#ifdef OPUS_X64
|
|
/* Never execute document/template macros merely because a file opened,
|
|
closed, or Word started. See the secure default in elmisc.c. */
|
|
return cmdOK;
|
|
#endif
|
|
|
|
/* Skip auto macro if shift key is down */
|
|
if (vfDisableAutoMacros || (GetAsyncKeyState(VK_SHIFT) & 0x8000))
|
|
return cmdOK;
|
|
|
|
|
|
/* Figure out name of macro */
|
|
CopyCsSt(stAuto, stAtm);
|
|
CatCsSt(mpatmst[atm], stAtm);
|
|
|
|
|
|
/* See if macro exists for this doc */
|
|
if ((bcm = BcmOfSt(stAtm)) == bcmNil ||
|
|
HpsyFromBcmElg(vhpsyt, bcm, ElgFromDoc(doc), 0) == hpNil)
|
|
return cmdOK;
|
|
|
|
|
|
/* Kill the copyright box if necessary... */
|
|
if (atm == atmExec && vhwndStartup != NULL)
|
|
EndStartup();
|
|
|
|
|
|
/* Make the document current so the macro can run on it */
|
|
if (selCur.doc != doc)
|
|
{
|
|
Assert(doc != docNil);
|
|
if (PdodDoc(doc)->wwDisp == wwNil)
|
|
return cmdOK;
|
|
SetMw(PwwdWw(PdodDoc(doc)->wwDisp)->mw);
|
|
}
|
|
|
|
|
|
/* Finally, run the macro */
|
|
return CmdExecBcmKc(bcm, kcNil);
|
|
}
|
|
|
|
|
|
|