|
|
/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/
/* curskeys.c-- cursor key movement subroutines */ /* Oct 4, 1984, KJS */
#define NOGDICAPMASKS
#define NOWINMESSAGES
#define NOWINSTYLES
#define NOCLIPBOARD
#define NOCTLMGR
#define NOSYSMETRICS
#define NOATOM
#define NOSYSCOMMANDS
#define NOCOMM
#define NOSOUND
#define NOMENUS
#define NOGDI
#define NOPEN
#define NOBRUSH
#define NOFONT
#define NOWNDCLASS
#include <windows.h>
#include "mw.h"
#define NOUAC
#include "cmddefs.h"
#include "dispdefs.h"
#include "wwdefs.h"
#include "ch.h"
#include "docdefs.h"
#include "editdefs.h"
#include "propdefs.h"
#include "debug.h"
#include "fmtdefs.h"
#include "printdef.h"
struct DOD (**hpdocdod)[]; extern typeCP cpMinCur; extern typeCP cpMacCur; extern struct PAP vpapAbs; extern int vfSeeSel; extern int vfShiftKey; extern struct FLI vfli; extern struct SEL selCur; extern int wwCur; extern struct WWD rgwwd[]; extern struct WWD *pwwdCur; /* Current window descriptor */ extern int docCur; extern typeCP vcpSelect; extern int vfSelAtPara; extern int vfLastCursor; extern int vfMakeInsEnd; extern CHAR *vpchFetch;
int vfSeeEdgeSel=FALSE; /* Whether Idle() should show edge of selection
even if selection is partially visible */
/* Absolute x-position to try to achieve on up-down motions;
used in this module only */ int vxpCursor;
MoveLeftRight( kc ) int kc; { /* Move or drag selection in left or right directions */ extern int vfInsEnd; typeCP CpEdge();
extern int vfGotoKeyMode; extern int xpRightLim; int fDrag = vfShiftKey ; int fFwdKey = FALSE; int fForward = selCur.fForward; int sty; typeCP cp;
MSG msg;
PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE);
vfGotoKeyMode |= (GetKeyState( kcGoto & ~wKcCommandMask) < 0);
switch( kc ) { int dl; int xp; int xpJunk;
default: Assert( FALSE ); return; case kcNextPara: fFwdKey = TRUE; case kcPrevPara: sty = styPara; break; case kcWordRight: fFwdKey = TRUE; case kcWordLeft: sty = styWord; break; case kcEndLine: if (vfGotoKeyMode) { MoveUpDown( kcEndDoc ); return; } xp = xpRightLim; goto GoDlXp;
case kcBeginLine: if (vfGotoKeyMode) { MoveUpDown( kcTopDoc ); return; } xp = xpSelBar - wwdCurrentDoc.xpMin; GoDlXp:
if (CpBeginLine( &dl, CpEdge() ) == selCur.cpFirst && selCur.cpFirst > cpMinCur && vfInsEnd ) { CpBeginLine( &dl, selCur.cpFirst - 1); } vcpSelect = cpNil; vfSelAtPara = false; SelectDlXp( dl, xp, styChar, fDrag ); goto SeeSel; case kcRight: fFwdKey = TRUE; case kcLeft: sty = (vfGotoKeyMode) ? stySent : styChar; break; }
/* Find cp to start extension from */ if (selCur.cpLim == selCur.cpFirst || fDrag) cp = fForward ? selCur.cpLim : selCur.cpFirst; else cp = fFwdKey ? selCur.cpLim - 1 : selCur.cpFirst + 1;
/* Catch attempts to run off the document start or end */
if (fFwdKey) { if (cp == cpMacCur) { _beep(); return; } } else if (cp == cpMinCur) { _beep(); return; }
if (fFwdKey) { if (cp >= cpMacCur) /* If at end, stay at end. */ cp = cpMacCur; else { cp = CpLimSty( cp, sty ); } } else { if (cp > cpMinCur) /* So we go back to the PREVIOUS sty unit */ cp--; cp = CpFirstSty( cp, sty ); }
if (fDrag) { /* Drag selection edge to new bound. */ /* If selection flips, keep one sty unit selected EXCEPT if it's styChar;
when dragging by char, the selection can become an insertion point */
ChangeSel( cp, sty == styChar ? styNil : sty ); } else { Select(cp, cp); if (!fFwdKey) selCur.fForward = false; }
SeeSel:
vfSeeSel = true; /* Tell Idle to scroll the selection into view */ vfSeeEdgeSel = true; /* And the edge of it even if it's already partly visible */ return; }
/* M O V E U P D O W N */ MoveUpDown(kc) int kc; { /* Move the selection in direction of kc, in up or down directions */
/* Our goal with up-and-down motions is to keep (if applicable) an */ /* absolute x-position to which the cursor tends to go if there is */ /* text on the line at that position. We set this position (vxpCursor) */ /* when we process the first up/down key, and hang onto it thereafter */ /* A global flag, vfLastCursor, tells us whether we should use the */ /* last calculated setting of vxpCursor or generate a new one. vxpCursor */ /* is set below and cleared in Select() and AlphaMode() */
extern int vfGotoKeyMode; int fDrag = vfShiftKey; int dl; typeCP cpT; struct EDL (**hdndl)[] = wwdCurrentDoc.hdndl; register struct EDL *pedl; int dipgd; int xpNow;
MSG msg;
PeekMessage(&msg, (HWND)NULL, NULL, NULL, PM_NOREMOVE);
vfGotoKeyMode |= (GetKeyState( kcGoto & ~wKcCommandMask) < 0);
/* Compute dl, vxpCursor for selection starting point */
switch (kc) { default: Assert( FALSE ); break; case kcUp: if (vfGotoKeyMode) { /* GOTO-UP is Prev Para */ MoveLeftRight( kcPrevPara ); return; } case kcPageUp: case kcUpScrollLock: case kcTopScreen: case kcTopDoc: cpT = selCur.fForward && fDrag ? selCur.cpLim : selCur.cpFirst; break; case kcDown: if (vfGotoKeyMode) { /* GOTO-DOWN is Next Para */ MoveLeftRight( kcNextPara ); return; } case kcPageDown: case kcDownScrollLock: case kcEndScreen: case kcEndDoc: cpT = selCur.fForward || !fDrag ? selCur.cpLim : selCur.cpFirst; break; }
CpToDlXp( cpT, &dl, (vfLastCursor) ? &xpNow : &vxpCursor );
/* HACK: If the guy is dragging up/down and is on the first/last line of
the doc but not right at the start/end of the doc, extend him to the start/end of the doc */
if (fDrag && !vfGotoKeyMode) { switch (kc) { case kcUp: /* Special fix for dragging upward: if we are seeking up to a position
that is equivalent in cp space to where we are now, force a decrement of the source dl so we really go up a line */
if (vfLastCursor && xpNow <= xpSelBar && vxpCursor > xpSelBar && cpT > cpMinCur) { CpToDlXp( CpFirstSty( cpT - 1, styChar), &dl, &xpNow ); } case kcPageUp: case kcUpScrollLock: if (wwdCurrentDoc.cpFirst == cpMinCur && cpT > cpMinCur) if (dl == 0 || kc == kcPageUp) { MoveUpDown( kcTopDoc ); return; } break; case kcPageDown: case kcDown: case kcDownScrollLock: { typeCP cpLimDl;
pedl = &(**hdndl) [dl]; cpLimDl = pedl->cpMin + pedl->dcpMac; if (cpLimDl >= cpMacCur && cpT >= pedl->cpMin && cpT < cpMacCur) { MoveUpDown( kcEndDoc ); return; } break; } } }
/* Do the cursor movement, scrolling if necessary */ switch (kc) { case kcPageUp: if (vfGotoKeyMode) { /* Go to previous printed page */ extern int vipgd; extern int rgval[]; struct PGTB **hpgtb; int ipgd;
dipgd = -1;
CachePage( docCur, selCur.cpFirst ); if (vipgd != iNil) { hpgtb = (**hpdocdod) [docCur].hpgtb; if ((**hpgtb).rgpgd [vipgd].cpMin != selCur.cpFirst) /* Not at page start; go there first */ dipgd++; }
GoPage: CachePage( docCur, selCur.cpFirst ); /*validate vipgd*/ hpgtb = (**hpdocdod)[docCur].hpgtb; if ((vipgd == iNil) || ((ipgd = vipgd + dipgd) < 0) || (ipgd >= (**hpgtb).cpgd)) { /*Whole doc on one page || run off either end*/ _beep(); } else { rgval [0] = (**hpgtb).rgpgd[ipgd].pgn; CmdJumpPage(); /* rgval [0] is a parm to CmdJumpPage */ } return; } ScrollUpDypWw(); break; case kcPageDown: if (vfGotoKeyMode) { /* Go to next printed page */ dipgd = 1; goto GoPage; }
/* Special case for extending selection one page down from the
top line of the ww -- extend to the NEXT line so we don't end up without any part of the selection on the screen */
ScrollDownCtr( 100 ); /* 100 > tr's in a page */ vcpSelect = cpNil; vfSelAtPara = false; SelectDlXp( dl, (**hdndl)[dl].fGraphics ? 0 : vxpCursor, styChar, fDrag ); if (fDrag && (dl == 0) && selCur.cpLim == wwdCurrentDoc.cpFirst) { MoveUpDown( kcDown ); } goto DontSelect;
case kcUpScrollLock: case kcUp: UpdateWw(wwCur, false);
pedl = &(**hdndl) [dl];
if ( fDrag && (selCur.fForward ? selCur.cpLim : selCur.cpFirst) == pedl->cpMin && pedl->cpMin > cpMinCur) { /* Up into picture == left */ CachePara( docCur, pedl->cpMin - 1 ); if (vpapAbs.fGraphics) { MoveLeftRight( kcLeft ); return; } }
if ((pedl->cpMin == cpMinCur) && (pedl->ichCpMin == 0)) { /* At beginning of doc or area */ int xpT;
_beep(); CpToDlXp(cpMinCur, &dl, &xpT); goto DoSelect; } else if ( (dl == 0) || (kc == kcUpScrollLock) ) { /* At top of screen OR keep posn */ ScrollUpCtr( 1 ); UpdateWw(wwCur, false); } else { --dl; } break;
case kcDownScrollLock: case kcDown: UpdateWw(wwCur, false); pedl = &(**hdndl)[dl]; { int xpT; typeCP cp;
cp = pedl->cpMin + pedl->dcpMac;
if (selCur.cpFirst < selCur.cpLim && selCur.fForward && pedl->cpMin == selCur.cpLim && cp < cpMacCur && (!fDrag || ((vxpCursor > pedl->xpLeft + xpSelBar) && (pedl->dcpMac > ccpEol)))) { /* In this case, it thinks we are at the start of the
next line; incrementing/scrolling is unnecessary */ goto DoSelect; }
if (pedl->fGraphics) { /* Special for pictures */ MoveLeftRight( kcRight );
if (!fDrag) { extern struct PAP vpapAbs;
CachePara( docCur, selCur.cpFirst ); if (vpapAbs.fGraphics) { vfShiftKey = TRUE; MoveLeftRight( kcRight ); SetShiftFlags(); } } goto DontSelect; }
if (cp > cpMacCur) { if (selCur.cpLim == selCur.cpFirst || selCur.cpLim == cpMacCur) /* test is because CpToDlXp cannot account for
selection extending to end of next-to-last line */ _beep(); CpToDlXp(cpMacCur, &dl, &xpT); goto DoSelect; } if ( (dl >= wwdCurrentDoc.dlMac - 2) || (kc == kcDownScrollLock) ) { /* within one line of window end */ ScrollDownCtr( 1 ); UpdateWw(wwCur, false); } else dl++; } break;
case kcTopScreen: dl = 0; break; case kcEndScreen: dl = wwdCurrentDoc.dlMac - 1; if ( dl > 0 && (**wwdCurrentDoc.hdndl) [dl].yp >= wwdCurrentDoc.ypMac) { /* Back up if last (and not only) dl is partially clipped */ dl--; } break; case kcTopDoc: CpToDlXp(cpMinCur, &dl, &vxpCursor); break; case kcEndDoc: CpToDlXp(cpMacCur, &dl, &vxpCursor); break;
default: return; }
DoSelect: /* select at/to position vxpCursor on line dl */ vcpSelect = cpNil; vfSelAtPara = false; SelectDlXp( dl, (**hdndl)[dl].fGraphics ? 0 : vxpCursor, styChar, fDrag ); DontSelect: vfLastCursor = true; /* don't recalc vxpCursor next time */ }
/* C P T O D L X P */ CpToDlXp(cp, pdl, pxp) typeCP cp; int *pdl, *pxp; { /* Transform cp into cursor coordinates */ extern int vfInsEnd; typeCP cpBegin; int dcp; int xp;
if (!vfInsEnd) PutCpInWwHz(cp);
cpBegin = CpBeginLine(pdl, cp); ClearInsertLine(); if ( (cp == selCur.cpFirst) && (cp == selCur.cpLim) && vfInsEnd && cp > cpMinCur) { /* cp indicates we are at line beginning, but we are really
kludged at the end of the previous line */ CpToDlXp( cp - 1, pdl, pxp ); PutCpInWwHz( cp - 1 ); return; }
dcp = (int) (cp - cpBegin); FormatLine(docCur, cpBegin, 0, cpMacCur, flmSandMode); xp = DxpDiff(0, dcp, &xp) + vfli.xpLeft; *pxp = xp + (xpSelBar - wwdCurrentDoc.xpMin); }
|