windows-nt/Source/XPSP1/NT/base/mvdm/wow16/write/scrollhz.c
2020-09-26 16:20:57 +08:00

386 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/************************************************************/
/* 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;
}