386 lines
10 KiB
C
386 lines
10 KiB
C
/************************************************************/
|
||
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
||
/************************************************************/
|
||
|
||
#define NOCLIPBOARD
|
||
#define NOGDICAPMASKS
|
||
#define NOCTLMGR
|
||
#define NOVIRTUALKEYCODES
|
||
#define NOWINMESSAGES
|
||
#define NOKEYSTATE
|
||
#define NOSYSCOMMANDS
|
||
#define NOICON
|
||
#define NOATOM
|
||
#define NOFONT
|
||
#define NOBRUSH
|
||
#define NOCLIPBOARD
|
||
#define NOCREATESTRUCT
|
||
#define NODRAWTEXT
|
||
#define NOMB
|
||
#define NOMETAFILE
|
||
#define NOOPENFILE
|
||
#define NOPEN
|
||
#define NOREGION
|
||
#define NOSOUND
|
||
#define NOWH
|
||
#define NOWNDCLASS
|
||
#define NOCOMM
|
||
#define NOFONT
|
||
#define NOBRUSH
|
||
#include <windows.h>
|
||
#include "mw.h"
|
||
#define NOUAC
|
||
#include "cmddefs.h"
|
||
#include "wwdefs.h"
|
||
#include "dispdefs.h"
|
||
#include "fmtdefs.h"
|
||
|
||
extern long ropErase;
|
||
extern struct WWD *pwwdCur;
|
||
extern struct WWD rgwwd[];
|
||
extern int wwCur;
|
||
extern int docCur;
|
||
extern typeCP cpMacCur;
|
||
extern struct FLI vfli;
|
||
|
||
int NEAR FOnScreenRect(RECT *);
|
||
|
||
|
||
/* P U T C P I N W W H Z */
|
||
PutCpInWwHz(cp)
|
||
typeCP cp;
|
||
/* Ensure that cp is in wwCur */
|
||
/* Make sure it's not off to left or right, too. */
|
||
|
||
{ /* Just check for horizontal bounding; vertical is done
|
||
by call to CpBeginLine below. */
|
||
int dxpRoom, xp, xpMin;
|
||
int dlT;
|
||
typeCP cpBegin;
|
||
|
||
UpdateWw(wwCur, false);
|
||
cpBegin = CpBeginLine(&dlT, cp);
|
||
FormatLine(docCur, cpBegin, (**(pwwdCur->hdndl))[dlT].ichCpMin, cpMacCur, flmSandMode);
|
||
/* xpMin is a dummy here */
|
||
xp = DxpDiff(0, (int)(cp - vfli.cpMin), &xpMin) + vfli.xpLeft;
|
||
xpMin = pwwdCur->xpMin;
|
||
/* we have: xp = desired position, xpMin = amount of horizontal scroll */
|
||
/* width of space in window for text */
|
||
dxpRoom = (pwwdCur->xpMac - xpSelBar);
|
||
if (xp < xpMin )
|
||
{ /* cp is left of screen */
|
||
AdjWwHoriz(max(0, xp - min(dxpRoom - 1, cxpAuto)) - xpMin);
|
||
}
|
||
else if (xp >= xpMin + dxpRoom)
|
||
{ /* cp is right of screen */
|
||
register int dxpRoomT = min(xpRightMax, xp + min(dxpRoom - 1, cxpAuto))
|
||
- dxpRoom + 1;
|
||
|
||
AdjWwHoriz(max(0, dxpRoomT) - xpMin);
|
||
}
|
||
}
|
||
|
||
|
||
/* A D J W W H O R I Z */
|
||
AdjWwHoriz(dxpScroll)
|
||
int dxpScroll;
|
||
{
|
||
/* Scroll a window horizontally */
|
||
if (dxpScroll != 0)
|
||
{
|
||
RECT rc;
|
||
|
||
/* Reset the value of the horizontal scroll bar */
|
||
SetScrollPos( pwwdCur->hHScrBar,
|
||
pwwdCur->sbHbar,
|
||
pwwdCur->xpMin + dxpScroll,
|
||
TRUE);
|
||
|
||
#ifdef ENABLE /* HideSel() */
|
||
HideSel();
|
||
#endif /* ENABLE */
|
||
|
||
ClearInsertLine();
|
||
|
||
SetRect( (LPRECT)&rc, xpSelBar, 0, pwwdCur->xpMac, pwwdCur->ypMac );
|
||
ScrollCurWw( &rc, -dxpScroll, 0 );
|
||
TrashWw(wwCur);
|
||
pwwdCur->xpMin += dxpScroll;
|
||
|
||
if (pwwdCur->fRuler)
|
||
{
|
||
UpdateRuler();
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/* Scroll specified subrectangle of current window by specified amount */
|
||
#include <stdlib.h>
|
||
ScrollCurWw( prc, dxp, dyp )
|
||
register RECT *prc;
|
||
int dxp,dyp;
|
||
{
|
||
|
||
extern int vfScrollInval;
|
||
RECT rcClear;
|
||
if (dxp && dyp)
|
||
return; /* Scroll in both dimensions is an illegal case */
|
||
|
||
if (!(dxp || dyp))
|
||
return; /* no scrolling to do */
|
||
|
||
#if 1
|
||
/**
|
||
The previous old, old code was getting flaky. (7.14.91) v-dougk
|
||
**/
|
||
if (ScrollDC(pwwdCur->hDC,dxp,dyp,(LPRECT)prc,(LPRECT)prc,NULL,&rcClear))
|
||
{
|
||
PatBlt( pwwdCur->hDC, rcClear.left, rcClear.top,
|
||
rcClear.right-rcClear.left+1, rcClear.bottom-rcClear.top+1, ropErase );
|
||
|
||
if (dxp)
|
||
vfScrollInval = FALSE;
|
||
else
|
||
vfScrollInval = (rcClear.bottom-rcClear.top+1) > abs(dyp);
|
||
|
||
if (vfScrollInval)
|
||
{
|
||
InvalidateRect(pwwdCur->wwptr,&rcClear,FALSE);
|
||
UpdateInvalid();
|
||
}
|
||
}
|
||
else
|
||
vfScrollInval = FALSE;
|
||
return;
|
||
#else
|
||
|
||
int FCheckPopupRect( HWND, LPRECT );
|
||
extern int vfScrollInval;
|
||
HDC hDC;
|
||
int dxpAbs = (dxp < 0) ? -dxp : dxp;
|
||
int dypAbs = (dyp < 0) ? -dyp : dyp;
|
||
struct RS { int left, top, cxp, cyp; }
|
||
rsSource, rsDest, rsClear;
|
||
/* Set rsSource, rsDest, rsClear == prc */
|
||
|
||
if ((rsSource.cxp = imin( prc->right, pwwdCur->xpMac ) -
|
||
(rsSource.left = imax( 0, prc->left ))) <= 0)
|
||
/* Rectangle is null or illegal in X-dimension */
|
||
return;
|
||
if ((rsSource.cyp = imin( prc->bottom, pwwdCur->ypMac ) -
|
||
(rsSource.top = imax( pwwdCur->ypMin, prc->top ))) <= 0)
|
||
/* Rectangle is null or illegal in Y-dimension */
|
||
return;
|
||
bltbyte( &rsSource, &rsDest, sizeof (struct RS ));
|
||
bltbyte( &rsSource, &rsClear, sizeof (struct RS ));
|
||
|
||
hDC = pwwdCur->hDC;
|
||
|
||
if ((dxpAbs < rsSource.cxp) && (dypAbs < rsSource.cyp))
|
||
{ /* A Real scroll, not the bogus case when we just clear exposed area */
|
||
/* NOTE: We do not bother to compute rsSource.cxp or rsSource.cyp,
|
||
as they are not needed by BitBlt or PatBlt */
|
||
|
||
/* If there are PopUp windows, use ScrollWindow to avoid getting
|
||
bogus bits from some popup. Since this is slow, only do it if there
|
||
is some popup that overlaps the scroll rect */
|
||
if ( AnyPopup() )
|
||
{
|
||
extern HANDLE hMmwModInstance;
|
||
static FARPROC lpFCheckPopupRect = (FARPROC)NULL;
|
||
|
||
/* First time through, inz ptr to thunk */
|
||
|
||
if (lpFCheckPopupRect == NULL)
|
||
lpFCheckPopupRect = MakeProcInstance( (FARPROC) FCheckPopupRect,
|
||
hMmwModInstance );
|
||
EnumWindows( lpFCheckPopupRect, (LONG) (LPRECT) prc );
|
||
}
|
||
|
||
/* Under windows 2.0, must also check for any part of the scroll
|
||
rectangle being off the screen (not possible in tiling environment).
|
||
If so, use ScrollWindow to avoid getting bogus bits from outside
|
||
the screen. */
|
||
if (!FOnScreenRect( prc ))
|
||
vfScrollInval = TRUE;
|
||
|
||
if (vfScrollInval)
|
||
{ /* vfScrollInval also tells UpdateWw that invalid region
|
||
may have changed */
|
||
|
||
extern BOOL vfEraseWw;
|
||
|
||
ScrollWindow( pwwdCur->wwptr, dxp, dyp, (LPRECT)prc, (LPRECT)prc );
|
||
vfEraseWw = TRUE;
|
||
UpdateInvalid(); /* Marks repaint area as invalid in our
|
||
structures so we don't think bits grabbed
|
||
from a popup are valid */
|
||
vfEraseWw = FALSE;
|
||
return;
|
||
}
|
||
|
||
if (dxp != 0)
|
||
rsDest.cxp -= (rsClear.cxp = dxpAbs);
|
||
else
|
||
/* dxp==dyp==0 case is caught below */
|
||
rsDest.cyp -= (rsClear.cyp = dypAbs);
|
||
|
||
if (dxp < 0)
|
||
{
|
||
rsSource.left += dxpAbs;
|
||
rsClear.left += rsDest.cxp;
|
||
}
|
||
else if (dxp > 0)
|
||
{
|
||
rsDest.left += dxpAbs;
|
||
}
|
||
else if (dyp < 0)
|
||
{
|
||
rsSource.top += dypAbs;
|
||
rsClear.top += rsDest.cyp;
|
||
}
|
||
else if (dyp > 0)
|
||
{
|
||
rsDest.top += dypAbs;
|
||
}
|
||
else
|
||
return;
|
||
|
||
BitBlt( hDC,
|
||
rsDest.left, rsDest.top,
|
||
rsDest.cxp, rsDest.cyp,
|
||
hDC,
|
||
rsSource.left, rsSource.top,
|
||
SRCCOPY );
|
||
}
|
||
|
||
|
||
#ifdef SMFONT
|
||
/* Vertical refresh will be so bindingly fast, that we do not need to erase the
|
||
old text. */
|
||
if (dxp != 0)
|
||
{
|
||
PatBlt(hDC, rsClear.left, rsClear.top, rsClear.cxp, rsClear.cyp, ropErase);
|
||
}
|
||
#else /* not SMFONT */
|
||
PatBlt( hDC, rsClear.left, rsClear.top, rsClear.cxp, rsClear.cyp, ropErase );
|
||
#endif /* SMFONT */
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
int FCheckPopupRect( hwnd, lprc )
|
||
HWND hwnd;
|
||
LPRECT lprc;
|
||
{ /* If the passed window is not a popup, return TRUE;
|
||
If the passed window is a popup, and its coordinates overlap
|
||
those of the passed rect, set vfScrollInval to TRUE and return FALSE.
|
||
Otherwise, return TRUE.
|
||
This is a window enumeration function: a return of TRUE means
|
||
continue enumerating windows, a return of FALSE means
|
||
stop the enumeration */
|
||
|
||
extern int vfScrollInval;
|
||
RECT rc;
|
||
POINT ptTopLeft, ptBottomRight;
|
||
RECT rcResult;
|
||
|
||
if ( !(GetWindowLong( hwnd, GWL_STYLE ) & WS_POPUP) )
|
||
/* Window is not a popup */
|
||
return TRUE;
|
||
|
||
/* Get popup rectangle in screen coordinates */
|
||
|
||
GetWindowRect( hwnd, (LPRECT) &rc );
|
||
|
||
/* Convert rc from screen coordinates to current document window coordinates */
|
||
|
||
ptTopLeft.x = rc.left;
|
||
ptTopLeft.y = rc.top;
|
||
ptBottomRight.x = rc.right;
|
||
ptBottomRight.y = rc.bottom;
|
||
|
||
ScreenToClient( pwwdCur->wwptr, (LPPOINT) &ptTopLeft );
|
||
ScreenToClient( pwwdCur->wwptr, (LPPOINT) &ptBottomRight );
|
||
|
||
rc.left = ptTopLeft.x;
|
||
rc.top = ptTopLeft.y;
|
||
rc.right = ptBottomRight.x;
|
||
rc.bottom = ptBottomRight.y;
|
||
|
||
IntersectRect( (LPRECT) &rcResult, (LPRECT) &rc, (LPRECT)lprc );
|
||
if ( !IsRectEmpty( (LPRECT) &rcResult ) )
|
||
{ /* Popup overlaps passed rectangle */
|
||
vfScrollInval = TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
/* S C R O L L L E F T */
|
||
ScrollLeft(dxp)
|
||
int dxp;
|
||
{ /* Scroll current window left dxp pixels */
|
||
if ((dxp = min(xpRightLim - pwwdCur->xpMin, dxp)) >0)
|
||
AdjWwHoriz(dxp);
|
||
else
|
||
_beep();
|
||
}
|
||
|
||
|
||
/* S C R O L L R I G H T */
|
||
ScrollRight(dxp)
|
||
int dxp;
|
||
{
|
||
if ((dxp = min(pwwdCur->xpMin, dxp)) > 0)
|
||
AdjWwHoriz(-dxp);
|
||
else
|
||
_beep();
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/* F O N S C R E E N R E C T
|
||
|
||
Returns TRUE iff the rectangle is entirely within the screen
|
||
boundaries.
|
||
Assumes the rectangle belongs to the current window.
|
||
|
||
*/
|
||
|
||
int NEAR
|
||
FOnScreenRect(prc)
|
||
register RECT *prc;
|
||
{
|
||
|
||
POINT ptTopLeft, ptBottomRight;
|
||
int cxScreen = GetSystemMetrics( SM_CXSCREEN );
|
||
int cyScreen = GetSystemMetrics( SM_CYSCREEN );
|
||
|
||
ptTopLeft.x = prc->left;
|
||
ptTopLeft.y = prc->top;
|
||
ptBottomRight.x = prc->right;
|
||
ptBottomRight.y = prc->bottom;
|
||
|
||
ClientToScreen( pwwdCur->wwptr, (LPPOINT) &ptTopLeft );
|
||
ClientToScreen( pwwdCur->wwptr, (LPPOINT) &ptBottomRight );
|
||
|
||
if ((ptTopLeft.x <= 0) || (ptTopLeft.y <= 0) ||
|
||
(ptBottomRight.x >= cxScreen) || (ptBottomRight.y >= cyScreen))
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|