mirror of
https://github.com/jmarshall23/msword.git
synced 2026-08-11 23:50:53 +02:00
Fixed mouse scrolling and margin issues.
This commit is contained in:
@@ -99,6 +99,10 @@ extern int vdbmgDevice;
|
||||
extern struct REB * vpreb;
|
||||
|
||||
#ifdef OPUS_X64
|
||||
static int vWin95ZoomPercent = 100;
|
||||
static int vWin95BaseDxsInch = 0;
|
||||
static int vWin95BaseDysInch = 0;
|
||||
|
||||
/* Read-only layout metrics used by the Win95 vertical ruler overlay. */
|
||||
int OpusGetWin95VerticalRulerMetrics(hwnd, pypPageTop, pypPageBottom,
|
||||
pdypTopMargin, pdypBottomMargin, pdypInch)
|
||||
@@ -124,6 +128,174 @@ int *pdypTopMargin, *pdypBottomMargin, *pdypInch;
|
||||
return fTrue;
|
||||
}
|
||||
|
||||
/* Drive Page View by pixels so wheel/trackpad input can move continuously
|
||||
through the inter-page gap instead of being reduced to scrollbar clicks. */
|
||||
int OpusScrollWin95ContinuousPages(hwnd, dypScroll)
|
||||
HWND hwnd;
|
||||
int dypScroll;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
struct WWD *pwwd;
|
||||
|
||||
if (ww < wwDocMin || ww >= wwMac || dypScroll == 0)
|
||||
return fFalse;
|
||||
pwwd = PwwdWw(ww);
|
||||
if (!pwwd->fPageView || pwwd->ipgd == ipgdNil)
|
||||
return fFalse;
|
||||
FScrollPageDyeHome(ww, dypScroll, fFalse, 0, fFalse);
|
||||
return fTrue;
|
||||
}
|
||||
|
||||
int OpusGetWin95ZoomPercent(hwnd)
|
||||
HWND hwnd;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
return ww < wwDocMin || ww >= wwMac ? 100 : vWin95ZoomPercent;
|
||||
}
|
||||
|
||||
int OpusGetWin95CurrentPageIndex(hwnd)
|
||||
HWND hwnd;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
if (ww < wwDocMin || ww >= wwMac || !PwwdWw(ww)->fPageView)
|
||||
return ipgdNil;
|
||||
return PwwdWw(ww)->ipgd;
|
||||
}
|
||||
|
||||
/* Change the screen mapping only. Page layout continues to use the original
|
||||
twip/printer measurements, while fonts, sheets, rulers, and hit testing are
|
||||
regenerated at the requested display scale. */
|
||||
int OpusAdjustWin95Zoom(hwnd, dPercent)
|
||||
HWND hwnd;
|
||||
int dPercent;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
int wwT, flmRestore, zoomNew;
|
||||
struct WWD *pwwd;
|
||||
struct DOD *pdod;
|
||||
struct FTI *pftiScreen;
|
||||
|
||||
if (ww < wwDocMin || ww >= wwMac)
|
||||
return vWin95ZoomPercent;
|
||||
zoomNew = max(25, min(300, vWin95ZoomPercent + dPercent));
|
||||
if (zoomNew == vWin95ZoomPercent)
|
||||
return zoomNew;
|
||||
if (vWin95BaseDxsInch <= 0)
|
||||
vWin95BaseDxsInch = max(1,
|
||||
NMultDiv(vfli.dxsInch, 100, vWin95ZoomPercent));
|
||||
if (vWin95BaseDysInch <= 0)
|
||||
vWin95BaseDysInch = max(1,
|
||||
NMultDiv(vfli.dysInch, 100, vWin95ZoomPercent));
|
||||
|
||||
pwwd = PwwdWw(ww);
|
||||
flmRestore = FlmDisplayFromFlags(pwwd->fDisplayAsPrint,
|
||||
pwwd->fPageView, vpref.fDraftView);
|
||||
pftiScreen = vsci.pfti;
|
||||
if (pftiScreen != NULL)
|
||||
FreeFontsPfti(pftiScreen);
|
||||
SetFlm(flmIdle);
|
||||
vWin95ZoomPercent = zoomNew;
|
||||
vfli.dxsInch = max(1,
|
||||
NMultDiv(vWin95BaseDxsInch, zoomNew, 100));
|
||||
vfli.dysInch = max(1,
|
||||
NMultDiv(vWin95BaseDysInch, zoomNew, 100));
|
||||
SetFlm(flmRestore);
|
||||
InvalFli();
|
||||
|
||||
for (wwT = wwDocMin; wwT < wwMac; ++wwT)
|
||||
if (mpwwhwwd[wwT] != hNil)
|
||||
{
|
||||
int dypOldPage, dypOldStep, dypOldOffset;
|
||||
int dypNewPage, dypNewStep, dypNewOffset, yeNew;
|
||||
pwwd = PwwdWw(wwT);
|
||||
if (!pwwd->fPageView || pwwd->ipgd == ipgdNil)
|
||||
continue;
|
||||
dypOldPage = DyOfRc(&pwwd->rcePage);
|
||||
dypOldStep = max(1, dypOldPage +
|
||||
max(8, dypGrayOutsideSci / 3));
|
||||
dypOldOffset = YeTopPage(wwT) - pwwd->rcePage.yeTop;
|
||||
pdod = PdodDoc(PmwdWw(wwT)->doc);
|
||||
dypNewPage = DysFromDya(pdod->dop.yaPage);
|
||||
dypNewStep = max(1, dypNewPage +
|
||||
max(8, dypGrayOutsideSci / 3));
|
||||
dypNewOffset = NMultDiv(dypOldOffset, dypNewStep,
|
||||
dypOldStep);
|
||||
yeNew = YeTopPage(wwT) - dypNewOffset;
|
||||
PrcSet(&pwwd->rcePage, 0, 0,
|
||||
DxsFromDxa(pwwd, pdod->dop.xaPage), dypNewPage);
|
||||
MoveRc(&pwwd->rcePage, XeLeftPage(wwT), yeNew);
|
||||
pwwd->xhScroll = pwwd->xeScroll;
|
||||
pwwd->fDirty = pwwd->fDrDirty = fTrue;
|
||||
pwwd->fBackgroundDirty = fTrue;
|
||||
TrashWw(wwT);
|
||||
}
|
||||
|
||||
if (ww == wwCur)
|
||||
selCur.fUpdateRuler = fTrue;
|
||||
RefreshPage(ww);
|
||||
return zoomNew;
|
||||
}
|
||||
|
||||
/* Pane resizing changes rcwDisp but the original Page View leaves the old
|
||||
horizontal sheet coordinate untouched. Recompute only that presentation
|
||||
coordinate so document measurements and the vertical scroll position stay
|
||||
intact. */
|
||||
int OpusRecenterWin95PageView(hwnd)
|
||||
HWND hwnd;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
int xeLeft;
|
||||
struct WWD *pwwd;
|
||||
|
||||
if (ww < wwDocMin || ww >= wwMac)
|
||||
return fFalse;
|
||||
pwwd = PwwdWw(ww);
|
||||
if (!pwwd->fPageView || pwwd->ipgd == ipgdNil)
|
||||
return fFalse;
|
||||
xeLeft = XeLeftPage(ww);
|
||||
if (pwwd->rcePage.xeLeft != xeLeft)
|
||||
{
|
||||
MoveRc(&pwwd->rcePage, xeLeft, pwwd->rcePage.yeTop);
|
||||
pwwd->xhScroll = pwwd->xeScroll;
|
||||
TrashWw(ww);
|
||||
SyncSbHor(ww);
|
||||
}
|
||||
return fTrue;
|
||||
}
|
||||
|
||||
/* Expose the physical sheet rectangle and adjacent-page availability to the
|
||||
Win95 chrome. The legacy display engine keeps one editable page live at a
|
||||
time; the chrome uses these read-only values to paint the neighboring sheet
|
||||
during a continuous-page scroll. */
|
||||
int OpusGetWin95ContinuousPageMetrics(hwnd, pxpPageLeft, pypPageTop,
|
||||
pxpPageRight, pypPageBottom, pdypPageGap, pfHasPrevious,
|
||||
pfHasNext)
|
||||
HWND hwnd;
|
||||
int *pxpPageLeft, *pypPageTop, *pxpPageRight, *pypPageBottom;
|
||||
int *pdypPageGap, *pfHasPrevious, *pfHasNext;
|
||||
{
|
||||
int ww = WwFromHwnd(hwnd);
|
||||
int ipgdMac;
|
||||
struct WWD *pwwd;
|
||||
struct DOD *pdod;
|
||||
|
||||
if (ww < wwDocMin || ww >= wwMac)
|
||||
return fFalse;
|
||||
pwwd = PwwdWw(ww);
|
||||
if (!pwwd->fPageView || pwwd->ipgd == ipgdNil)
|
||||
return fFalse;
|
||||
pdod = PdodDoc(PmwdWw(ww)->doc);
|
||||
ipgdMac = pdod->hplcpgd == hNil ? 0 : IMacPlc(pdod->hplcpgd);
|
||||
*pxpPageLeft = pwwd->rcePage.xeLeft;
|
||||
*pypPageTop = pwwd->rcePage.yeTop;
|
||||
*pxpPageRight = pwwd->rcePage.xeRight;
|
||||
*pypPageBottom = pwwd->rcePage.yeBottom;
|
||||
*pdypPageGap = max(8, dypGrayOutsideSci / 3);
|
||||
*pfHasPrevious = pwwd->ipgd > 0;
|
||||
*pfHasNext = pwwd->ipgd + 1 < ipgdMac;
|
||||
return fTrue;
|
||||
}
|
||||
|
||||
/* Commit a vertical-ruler drag through the document's existing DOP state.
|
||||
The UI passes a screen-pixel margin; preserve header/footer overlap signs
|
||||
and invalidate page layout exactly as the Page Setup path does. */
|
||||
|
||||
@@ -2054,6 +2054,7 @@ IpgdNextWw(ww, fRepag)
|
||||
int ipgd = PwwdWw(ww)->ipgd + 1;
|
||||
int doc = PmwdWw(ww)->doc;
|
||||
struct PLC **hplcpgd;
|
||||
struct PGD pgdLast;
|
||||
struct RPL rpl;
|
||||
struct LBS lbsText, lbsFtn;
|
||||
int fFormatVisiSave;
|
||||
@@ -2062,8 +2063,25 @@ IpgdNextWw(ww, fRepag)
|
||||
int flmSave = vflm;
|
||||
#endif
|
||||
Assert(PwwdWw(ww)->fPageView);
|
||||
hplcpgd = PdodDoc(doc)->hplcpgd;
|
||||
|
||||
if (ipgd >= IMacPlc(PdodDoc(doc)->hplcpgd) && fRepag)
|
||||
#ifdef OPUS_X64
|
||||
/* A valid final PGD whose sentinel already reaches cpMac is a known end
|
||||
of document. Re-running the 1989 repaginator every time a wheel event
|
||||
presses against that edge can invalidate the live page descriptors and
|
||||
briefly erase (or crash) the last page. */
|
||||
if (fRepag && ipgd >= IMacPlc(hplcpgd) &&
|
||||
IMacPlc(hplcpgd) > 0)
|
||||
{
|
||||
GetPlc(hplcpgd, IMacPlc(hplcpgd) - 1, &pgdLast);
|
||||
if (!pgdLast.fUnk &&
|
||||
CpPlc(hplcpgd, IMacPlc(hplcpgd)) >=
|
||||
CpMacDocEdit(doc))
|
||||
return ipgdNil;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ipgd >= IMacPlc(hplcpgd) && fRepag)
|
||||
{
|
||||
#ifdef MAC
|
||||
InitFliForLayout(lmPagevw, &fFormatVisiSave);
|
||||
@@ -2081,7 +2099,7 @@ IpgdNextWw(ww, fRepag)
|
||||
EndFliLayout(lmSave, WinMac(flmSave, fFormatVisiSave));
|
||||
}
|
||||
|
||||
return ipgd >= IMacPlc(PdodDoc(doc)->hplcpgd) ? ipgdNil : ipgd;
|
||||
return ipgd >= IMacPlc(hplcpgd) ? ipgdNil : ipgd;
|
||||
}
|
||||
|
||||
|
||||
@@ -2441,6 +2459,9 @@ EXPORT SetElevWw(ww)
|
||||
if (pwwd->fPageView)
|
||||
{
|
||||
int dqNextPg, dqCurPg;
|
||||
#ifdef OPUS_X64
|
||||
int yeHome, yeLastPage;
|
||||
#endif
|
||||
cpCurPg = CpFromIpgd(doc, ww, pwwd->ipgd); /* HM */
|
||||
if ((ipgd = IpgdNextWw(ww, fFalse)) == ipgdNil)
|
||||
cpNextPg = CpMacDoc(doc);
|
||||
@@ -2451,9 +2472,24 @@ EXPORT SetElevWw(ww)
|
||||
pwwd = PwwdWw(ww);
|
||||
dqCurPg = DqRatio(cpCurPg, dqMax - dqPgvwElevSpace, cpMac);
|
||||
dqNextPg = DqRatio(cpNextPg, dqMax - dqPgvwElevSpace, cpMac);
|
||||
#ifdef OPUS_X64
|
||||
yeHome = YeTopPage(ww);
|
||||
if (ipgd == ipgdNil)
|
||||
{
|
||||
yeLastPage = min(yeHome, pwwd->rcwDisp.ywBottom -
|
||||
DyOfRc(&pwwd->rcePage) - dypGrayOutsideSci);
|
||||
dyeScrollMac = max(1, yeHome - yeLastPage);
|
||||
}
|
||||
else
|
||||
dyeScrollMac = max(1, DyOfRc(&pwwd->rcePage) +
|
||||
max(8, dypGrayOutsideSci / 3));
|
||||
dyeScroll = min(dyeScrollMac,
|
||||
max(0, yeHome - pwwd->rcePage.yeTop));
|
||||
#else
|
||||
dyeScrollMac = max(1,
|
||||
DyOfRc(&pwwd->rcePage) - DyOfRc(&pwwd->rcwDisp));
|
||||
dyeScroll = min(dyeScrollMac, max(0, -pwwd->rcePage.yeTop));
|
||||
#endif
|
||||
if (dyeScrollMac > 0)
|
||||
dq = min( dqCurPg + NMultDiv(dqNextPg - dqCurPg, dyeScroll, dyeScrollMac),
|
||||
dqMax - dqPgvwElevSpace);
|
||||
|
||||
@@ -51,6 +51,15 @@ extern int wwCur;
|
||||
|
||||
extern struct DR *PdrWw();
|
||||
|
||||
#ifdef OPUS_X64
|
||||
/* Remember a completed end-of-document pagination probe. The old engine was
|
||||
written for page-at-a-time buttons and does not tolerate the same failed
|
||||
next-page repagination being requested for every wheel tick. */
|
||||
static int vrgdocWin95NoNext[wwMax];
|
||||
static int vrgipgdWin95NoNext[wwMax];
|
||||
static CP vrgcpWin95NoNext[wwMax];
|
||||
#endif
|
||||
|
||||
#ifdef WIN
|
||||
extern int vlm;
|
||||
extern int vflm;
|
||||
@@ -1052,12 +1061,126 @@ FScrollPageDyeHome(ww, dye, fHome, ncp, fNoNewPage)
|
||||
{
|
||||
struct WWD *pwwd = PwwdWw(ww);
|
||||
int dyeHome = pwwd->yeScroll - YeTopPage(ww);
|
||||
#ifndef OPUS_X64
|
||||
int w;
|
||||
BOOL fSmallPage = FSmallPage(ww, &w, &w);
|
||||
#else
|
||||
int dypPage = DyOfRc(&pwwd->rcePage);
|
||||
int dypPageGap = max(8, dypGrayOutsideSci / 3);
|
||||
int yeHome = YeTopPage(ww);
|
||||
int yeLastPage = min(yeHome,
|
||||
pwwd->rcwDisp.ywBottom - dypPage - dypGrayOutsideSci);
|
||||
int yeLimit;
|
||||
int dyeRequested;
|
||||
int dyeRemainder;
|
||||
int docScroll;
|
||||
int ipgdMacScroll;
|
||||
CP cpMacScroll;
|
||||
#endif
|
||||
|
||||
#ifdef WIN
|
||||
int ipgdNew;
|
||||
#endif
|
||||
#ifdef OPUS_X64
|
||||
/* Word 1.x normally swaps its single Page View display as soon as the
|
||||
current sheet reaches the viewport edge. Let the sheet instead travel
|
||||
one full page plus a gray inter-page gap. The Win95 chrome paints the
|
||||
adjacent sheet in that space; when it reaches the home position we hand
|
||||
the live layout to that page. */
|
||||
if (dye >= 0)
|
||||
{
|
||||
dyeRequested = dye;
|
||||
ipgdNew = IpgdNextWw(ww, fFalse);
|
||||
/* Repaginate only when the following sheet is about to become visible.
|
||||
This avoids doing page layout on every ordinary line-scroll. */
|
||||
if (ipgdNew == ipgdNil &&
|
||||
pwwd->yeScroll - dye <= yeLastPage)
|
||||
{
|
||||
docScroll = PmwdWw(ww)->doc;
|
||||
cpMacScroll = CpMacDocEdit(docScroll);
|
||||
ipgdMacScroll = IMacPlc(PdodDoc(docScroll)->hplcpgd);
|
||||
if (vrgdocWin95NoNext[ww] != docScroll ||
|
||||
vrgipgdWin95NoNext[ww] != pwwd->ipgd + 1 ||
|
||||
vrgcpWin95NoNext[ww] != cpMacScroll)
|
||||
{
|
||||
/* Once the page table already contains multiple pages, its
|
||||
active last page is authoritative. Typing/background layout
|
||||
extends that table when content grows; a wheel tick must not
|
||||
re-enter pagination on the live last-page descriptors. */
|
||||
if (ipgdMacScroll > 1 &&
|
||||
pwwd->ipgd + 1 >= ipgdMacScroll)
|
||||
ipgdNew = ipgdNil;
|
||||
else
|
||||
ipgdNew = IpgdNextWw(ww, fTrue);
|
||||
if (ipgdNew == ipgdNil)
|
||||
{
|
||||
vrgdocWin95NoNext[ww] = docScroll;
|
||||
vrgipgdWin95NoNext[ww] = pwwd->ipgd + 1;
|
||||
vrgcpWin95NoNext[ww] = cpMacScroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
yeLimit = (!fNoNewPage && ipgdNew != ipgdNil) ?
|
||||
yeHome - dypPage - dypPageGap : yeLastPage;
|
||||
if ((ncp & ncpForceYPos) == 0)
|
||||
dye = min(dye, max(0, pwwd->yeScroll - yeLimit));
|
||||
if (dyeHome > 0 && fHome)
|
||||
dye = min(dye, dyeHome);
|
||||
dyeRemainder = max(0, dyeRequested - dye);
|
||||
if (dye <= 0)
|
||||
{
|
||||
if (fNoNewPage)
|
||||
return fTrue;
|
||||
if (ipgdNew != ipgdNil)
|
||||
SetPageDisp(ww, ipgdNew, yeHome, fFalse, fFalse);
|
||||
else
|
||||
Beep();
|
||||
return fTrue;
|
||||
}
|
||||
ScrollPageDye(ww, dye);
|
||||
if (!fNoNewPage && ipgdNew != ipgdNil &&
|
||||
PwwdWw(ww)->yeScroll <= yeLimit)
|
||||
{
|
||||
SetPageDisp(ww, ipgdNew, yeHome, fFalse, fFalse);
|
||||
if (dyeRemainder > 0)
|
||||
FScrollPageDyeHome(ww, dyeRemainder, fFalse, ncp,
|
||||
fFalse);
|
||||
return fTrue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dyeRequested = -dye;
|
||||
ipgdNew = IpgdPrevWw(ww);
|
||||
yeLimit = (!fNoNewPage && ipgdNew != ipgdNil) ?
|
||||
yeHome + dypPage + dypPageGap : yeHome;
|
||||
dye = min(-dye, max(0, yeLimit - pwwd->yeScroll));
|
||||
if (dyeHome < 0 && fHome)
|
||||
dye = min(dye, -dyeHome);
|
||||
dyeRemainder = max(0, dyeRequested - dye);
|
||||
if (dye <= 0)
|
||||
{
|
||||
if (fNoNewPage)
|
||||
return fTrue;
|
||||
if (ipgdNew != ipgdNil)
|
||||
SetPageDisp(ww, ipgdNew, yeHome, fFalse, fFalse);
|
||||
else
|
||||
Beep();
|
||||
return fTrue;
|
||||
}
|
||||
ScrollPageDye(ww, -dye);
|
||||
if (!fNoNewPage && ipgdNew != ipgdNil &&
|
||||
PwwdWw(ww)->yeScroll >= yeLimit)
|
||||
{
|
||||
SetPageDisp(ww, ipgdNew, yeHome, fFalse, fFalse);
|
||||
if (dyeRemainder > 0)
|
||||
FScrollPageDyeHome(ww, -dyeRemainder, fFalse, ncp,
|
||||
fFalse);
|
||||
return fTrue;
|
||||
}
|
||||
}
|
||||
return fFalse;
|
||||
#else /* !OPUS_X64 */
|
||||
if (dye >= 0)
|
||||
{
|
||||
if ((ncp & ncpForceYPos) == 0)
|
||||
@@ -1110,6 +1233,7 @@ FScrollPageDyeHome(ww, dye, fHome, ncp, fNoNewPage)
|
||||
}
|
||||
}
|
||||
return fFalse;
|
||||
#endif /* OPUS_X64 */
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,16 +1245,20 @@ FScrollPageDyeHome(ww, dye, fHome, ncp, fNoNewPage)
|
||||
/* %%Function:ScrollPageDye %%Owner:bryanl */
|
||||
ScrollPageDye(ww, dye)
|
||||
{
|
||||
#ifndef OPUS_X64
|
||||
int w;
|
||||
#endif
|
||||
|
||||
Assert(cHpFreeze == 0);
|
||||
vfLastScroll = fTrue;
|
||||
Assert(PwwdWw(ww)->fPageView);
|
||||
#ifndef OPUS_X64
|
||||
if (FSmallPage(ww, &w, &w))
|
||||
{
|
||||
Beep();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ClearInsertLine(&selCur);
|
||||
ClearInsertLine(&selDotted);
|
||||
@@ -1275,24 +1403,50 @@ int ww, dqThumb, dqThumbOld;
|
||||
"want" to be. That is compared with the current
|
||||
scroll and, presto, we scroll */
|
||||
pwwd = PwwdWw(ww);
|
||||
#ifdef OPUS_X64
|
||||
if (ipgd == ipgdNil)
|
||||
{
|
||||
int yeHome = YeTopPage(ww);
|
||||
int yeLastPage = min(yeHome, pwwd->rcwDisp.ywBottom -
|
||||
DyOfRc(&pwwd->rcePage) - dypGrayOutsideSci);
|
||||
dyeScrollMac = max(0, yeHome - yeLastPage);
|
||||
}
|
||||
else
|
||||
dyeScrollMac = DyOfRc(&pwwd->rcePage) +
|
||||
max(8, dypGrayOutsideSci / 3);
|
||||
dyeScrollOld = min(dyeScrollMac,
|
||||
max(0, YeTopPage(ww) - pwwd->rcePage.yeTop));
|
||||
#else
|
||||
dyeScrollMac = DyOfRc(&pwwd->rcePage) - DyOfRc(&pwwd->rcwDisp);
|
||||
dyeScrollOld = max(0, -pwwd->rcePage.yeTop);
|
||||
#endif
|
||||
dqCurPage = DqRatio(cpCurPage, dqMax - dqPgvwElevSpace, cpMac);
|
||||
dqNextPage = DqRatio(cpNextPage, dqMax - dqPgvwElevSpace, cpMac);
|
||||
dyeScrollNew = NMultDiv(min(dqThumb - dqCurPage, dqNextPage - dqCurPage),
|
||||
dyeScrollMac, max(1, dqNextPage - dqCurPage));
|
||||
#ifdef OPUS_X64
|
||||
dyeScrollNew = min(dyeScrollMac, max(0, dyeScrollNew));
|
||||
#else
|
||||
dyeScrollNew = max(-YeTopPage(ww), dyeScrollNew);
|
||||
#endif
|
||||
if (dqThumb > dqThumbOld)
|
||||
{
|
||||
#ifdef OPUS_X64
|
||||
dye = dyeScrollNew - dyeScrollOld;
|
||||
#else
|
||||
dyeT = pwwd->rcePage.yeBottom + pwwd->rcwDisp.ywTop
|
||||
- pwwd->rcwDisp.ywBottom;
|
||||
dye = min(dyeT, dyeScrollNew - dyeScrollOld);
|
||||
#endif
|
||||
if (dye > 0)
|
||||
ScrollPageDye(ww, dye);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move up on the page (move text down, looking at higher portions of page) */
|
||||
#ifdef OPUS_X64
|
||||
dye = dyeScrollOld - dyeScrollNew;
|
||||
#else
|
||||
if (cpCurPage == cp0 && pwwd->rcePage.yeTop
|
||||
>= YeTopPage(ww))
|
||||
dye = -pwwd->rcePage.yeTop + dypGrayOutsideSci;
|
||||
@@ -1301,6 +1455,7 @@ int ww, dqThumb, dqThumbOld;
|
||||
dyeT = pwwd->ywMin - pwwd->rcePage.yeTop;
|
||||
dye = min(dyeT, dyeScrollOld - dyeScrollNew);
|
||||
}
|
||||
#endif
|
||||
if (dye > 0)
|
||||
ScrollPageDye(ww, -dye);
|
||||
}
|
||||
@@ -1680,7 +1835,13 @@ ScrollWwDyw(ww, dyw, ywTop)
|
||||
|
||||
/* InvalWwRc will not work because rcePage has not been offset yet,
|
||||
it is done in caller */
|
||||
#ifdef OPUS_X64
|
||||
/* DrawBlankPage and the Win95 neighbor overlay repaint the uncovered strip;
|
||||
suppress a separate background erase that otherwise flashes gray first. */
|
||||
InvalidateRect(PwwdWw(ww)->hwnd, (LPRECT)&rcwUpdate, fFalse);
|
||||
#else
|
||||
InvalidateRect(PwwdWw(ww)->hwnd, (LPRECT)&rcwUpdate, fTrue);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1734,6 +1734,25 @@ LONG lParam;
|
||||
return (LRESULT)MAKELONG((WORD)vibpProtect,
|
||||
(WORD)vibp);
|
||||
}
|
||||
case 72:
|
||||
return (LRESULT)PwwdWw(WwFromHwnd(hwnd))->ipgd;
|
||||
case 73:
|
||||
{
|
||||
int wwQuery = WwFromHwnd(hwnd);
|
||||
struct DOD *pdod = PdodDoc(PmwdWw(wwQuery)->doc);
|
||||
return (LRESULT)(pdod->hplcpgd == hNil ? 0 :
|
||||
IMacPlc(pdod->hplcpgd));
|
||||
}
|
||||
case 74:
|
||||
return (LRESULT)PwwdWw(WwFromHwnd(hwnd))->rcePage.xeLeft;
|
||||
case 75:
|
||||
return (LRESULT)PwwdWw(WwFromHwnd(hwnd))->rcePage.yeTop;
|
||||
case 76:
|
||||
return (LRESULT)PwwdWw(WwFromHwnd(hwnd))->rcePage.xeRight;
|
||||
case 77:
|
||||
return (LRESULT)PwwdWw(WwFromHwnd(hwnd))->rcePage.yeBottom;
|
||||
case 78:
|
||||
return (LRESULT)OpusGetWin95ZoomPercent(hwnd);
|
||||
}
|
||||
return (LRESULT) -1;
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,14 @@
|
||||
extern "C" int OpusGetWin95VerticalRulerMetrics(
|
||||
HWND pane, int* page_top, int* page_bottom, int* top_margin,
|
||||
int* bottom_margin, int* pixels_per_inch);
|
||||
extern "C" int OpusGetWin95ContinuousPageMetrics(
|
||||
HWND pane, int* page_left, int* page_top, int* page_right,
|
||||
int* page_bottom, int* page_gap, int* has_previous, int* has_next);
|
||||
extern "C" int OpusScrollWin95ContinuousPages(HWND pane, int pixels);
|
||||
extern "C" int OpusGetWin95ZoomPercent(HWND pane);
|
||||
extern "C" int OpusGetWin95CurrentPageIndex(HWND pane);
|
||||
extern "C" int OpusAdjustWin95Zoom(HWND pane, int percent_delta);
|
||||
extern "C" int OpusRecenterWin95PageView(HWND pane);
|
||||
extern "C" int OpusSetWin95VerticalMargin(
|
||||
HWND pane, int top_margin, int margin_pixels);
|
||||
extern "C" int OpusGetWin95HorizontalRulerMetrics(
|
||||
@@ -176,6 +184,26 @@ struct HorizontalRulerDragState {
|
||||
|
||||
HorizontalRulerDragState g_horizontal_ruler_drag{};
|
||||
|
||||
struct DocumentWheelState {
|
||||
HWND pane = nullptr;
|
||||
int scroll_remainder = 0;
|
||||
int zoom_remainder = 0;
|
||||
};
|
||||
|
||||
DocumentWheelState g_document_wheel{};
|
||||
|
||||
struct PageSnapshot {
|
||||
HWND pane = nullptr;
|
||||
int page_index = -1;
|
||||
int zoom_percent = 100;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
HBITMAP bitmap = nullptr;
|
||||
ULONGLONG last_used = 0;
|
||||
};
|
||||
|
||||
std::vector<PageSnapshot> g_page_snapshots;
|
||||
|
||||
int dpi_for_window(HWND window) {
|
||||
using GetDpiForWindowProc = UINT(WINAPI*)(HWND);
|
||||
static const auto get_dpi = reinterpret_cast<GetDpiForWindowProc>(
|
||||
@@ -1010,7 +1038,7 @@ HWND create_zoom_combo(HWND toolbar) {
|
||||
HWND combo = CreateWindowExW(
|
||||
0, L"COMBOBOX", L"",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
|
||||
CBS_DROPDOWNLIST,
|
||||
CBS_DROPDOWN | CBS_AUTOHSCROLL,
|
||||
0, 0, 10, 200, toolbar,
|
||||
reinterpret_cast<HMENU>(static_cast<UINT_PTR>(kComboZoom)),
|
||||
GetModuleHandleW(nullptr), nullptr);
|
||||
@@ -1027,6 +1055,19 @@ HWND create_zoom_combo(HWND toolbar) {
|
||||
return combo;
|
||||
}
|
||||
|
||||
void update_zoom_combo(HWND pane, int percent) {
|
||||
const HWND app = GetAncestor(pane, GA_ROOT);
|
||||
const HWND toolbar = FindWindowExW(app, nullptr, kToolbarClass, nullptr);
|
||||
ToolbarState* state = toolbar_state(toolbar);
|
||||
if (state == nullptr || state->zoom_combo == nullptr) {
|
||||
return;
|
||||
}
|
||||
const std::wstring text = std::to_wstring(percent) + L"%";
|
||||
SendMessageW(state->zoom_combo, CB_SETCURSEL,
|
||||
static_cast<WPARAM>(-1), 0);
|
||||
SetWindowTextW(state->zoom_combo, text.c_str());
|
||||
}
|
||||
|
||||
void update_toolbar_menu_checks(HWND app, const ToolbarState& state) {
|
||||
const UINT standard = MF_BYCOMMAND |
|
||||
(state.standard_visible ? MF_CHECKED : MF_UNCHECKED);
|
||||
@@ -1196,6 +1237,195 @@ void cancel_vertical_margin_drag(HWND pane) {
|
||||
redraw_vertical_ruler(pane);
|
||||
}
|
||||
|
||||
PageSnapshot* find_page_snapshot(HWND pane, int page_index, int width,
|
||||
int height, int zoom_percent) {
|
||||
for (auto& snapshot : g_page_snapshots) {
|
||||
if (snapshot.pane == pane && snapshot.page_index == page_index &&
|
||||
snapshot.width == width && snapshot.height == height &&
|
||||
snapshot.zoom_percent == zoom_percent) {
|
||||
snapshot.last_used = GetTickCount64();
|
||||
return &snapshot;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void prune_page_snapshots(HWND pane) {
|
||||
std::size_t pane_count = 0;
|
||||
for (const auto& snapshot : g_page_snapshots) {
|
||||
if (snapshot.pane == pane) {
|
||||
++pane_count;
|
||||
}
|
||||
}
|
||||
while (pane_count > 4) {
|
||||
auto oldest = g_page_snapshots.end();
|
||||
for (auto iterator = g_page_snapshots.begin();
|
||||
iterator != g_page_snapshots.end(); ++iterator) {
|
||||
if (iterator->pane == pane &&
|
||||
(oldest == g_page_snapshots.end() ||
|
||||
iterator->last_used < oldest->last_used)) {
|
||||
oldest = iterator;
|
||||
}
|
||||
}
|
||||
if (oldest == g_page_snapshots.end()) {
|
||||
break;
|
||||
}
|
||||
if (oldest->bitmap != nullptr) {
|
||||
DeleteObject(oldest->bitmap);
|
||||
}
|
||||
g_page_snapshots.erase(oldest);
|
||||
--pane_count;
|
||||
}
|
||||
}
|
||||
|
||||
void update_current_page_snapshot(HWND pane, HDC dc) {
|
||||
int page_left = 0;
|
||||
int page_top = 0;
|
||||
int page_right = 0;
|
||||
int page_bottom = 0;
|
||||
int page_gap = 0;
|
||||
int has_previous = 0;
|
||||
int has_next = 0;
|
||||
if (!OpusGetWin95ContinuousPageMetrics(
|
||||
pane, &page_left, &page_top, &page_right, &page_bottom,
|
||||
&page_gap, &has_previous, &has_next)) {
|
||||
return;
|
||||
}
|
||||
const int page_index = OpusGetWin95CurrentPageIndex(pane);
|
||||
const int zoom_percent = OpusGetWin95ZoomPercent(pane);
|
||||
const int width = page_right - page_left;
|
||||
const int height = page_bottom - page_top;
|
||||
if (page_index < 0 || width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PageSnapshot* snapshot = find_page_snapshot(
|
||||
pane, page_index, width, height, zoom_percent);
|
||||
if (snapshot == nullptr) {
|
||||
PageSnapshot created{};
|
||||
created.pane = pane;
|
||||
created.page_index = page_index;
|
||||
created.zoom_percent = zoom_percent;
|
||||
created.width = width;
|
||||
created.height = height;
|
||||
created.bitmap = CreateCompatibleBitmap(dc, width, height);
|
||||
created.last_used = GetTickCount64();
|
||||
if (created.bitmap == nullptr) {
|
||||
return;
|
||||
}
|
||||
HDC memory = CreateCompatibleDC(dc);
|
||||
HBITMAP previous = static_cast<HBITMAP>(
|
||||
SelectObject(memory, created.bitmap));
|
||||
RECT background{0, 0, width, height};
|
||||
FillRect(memory, &background,
|
||||
static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
|
||||
SelectObject(memory, previous);
|
||||
DeleteDC(memory);
|
||||
g_page_snapshots.push_back(created);
|
||||
snapshot = &g_page_snapshots.back();
|
||||
prune_page_snapshots(pane);
|
||||
snapshot = find_page_snapshot(
|
||||
pane, page_index, width, height, zoom_percent);
|
||||
}
|
||||
if (snapshot == nullptr || snapshot->bitmap == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT client{};
|
||||
RECT page{page_left, page_top, page_right, page_bottom};
|
||||
RECT visible{};
|
||||
GetClientRect(pane, &client);
|
||||
if (!IntersectRect(&visible, &page, &client)) {
|
||||
return;
|
||||
}
|
||||
HDC memory = CreateCompatibleDC(dc);
|
||||
HBITMAP previous = static_cast<HBITMAP>(
|
||||
SelectObject(memory, snapshot->bitmap));
|
||||
BitBlt(memory, visible.left - page_left, visible.top - page_top,
|
||||
visible.right - visible.left, visible.bottom - visible.top,
|
||||
dc, visible.left, visible.top, SRCCOPY);
|
||||
SelectObject(memory, previous);
|
||||
DeleteDC(memory);
|
||||
}
|
||||
|
||||
void draw_neighbor_sheet(HDC dc, const RECT& sheet, const RECT& client,
|
||||
const PageSnapshot* snapshot) {
|
||||
RECT visible{};
|
||||
if (!IntersectRect(&visible, &sheet, &client)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT shadow = sheet;
|
||||
OffsetRect(&shadow, 3, 3);
|
||||
RECT visible_shadow{};
|
||||
if (IntersectRect(&visible_shadow, &shadow, &client)) {
|
||||
HBRUSH shadow_brush = CreateSolidBrush(RGB(96, 96, 96));
|
||||
FillRect(dc, &visible_shadow, shadow_brush);
|
||||
DeleteObject(shadow_brush);
|
||||
}
|
||||
|
||||
HBRUSH page_brush = CreateSolidBrush(RGB(255, 255, 255));
|
||||
FillRect(dc, &visible, page_brush);
|
||||
DeleteObject(page_brush);
|
||||
if (snapshot != nullptr && snapshot->bitmap != nullptr) {
|
||||
HDC memory = CreateCompatibleDC(dc);
|
||||
HBITMAP previous = static_cast<HBITMAP>(
|
||||
SelectObject(memory, snapshot->bitmap));
|
||||
BitBlt(dc, visible.left, visible.top,
|
||||
visible.right - visible.left, visible.bottom - visible.top,
|
||||
memory, visible.left - sheet.left, visible.top - sheet.top,
|
||||
SRCCOPY);
|
||||
SelectObject(memory, previous);
|
||||
DeleteDC(memory);
|
||||
}
|
||||
HBRUSH border_brush = CreateSolidBrush(RGB(96, 96, 96));
|
||||
FrameRect(dc, &sheet, border_brush);
|
||||
DeleteObject(border_brush);
|
||||
}
|
||||
|
||||
void draw_continuous_page_neighbors(HWND pane, HDC dc) {
|
||||
int page_left = 0;
|
||||
int page_top = 0;
|
||||
int page_right = 0;
|
||||
int page_bottom = 0;
|
||||
int page_gap = 0;
|
||||
int has_previous = 0;
|
||||
int has_next = 0;
|
||||
if (!OpusGetWin95ContinuousPageMetrics(
|
||||
pane, &page_left, &page_top, &page_right, &page_bottom,
|
||||
&page_gap, &has_previous, &has_next)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT client{};
|
||||
GetClientRect(pane, &client);
|
||||
const int page_height = page_bottom - page_top;
|
||||
if (page_right <= page_left || page_height <= 0) {
|
||||
return;
|
||||
}
|
||||
const int page_step = page_height + page_gap;
|
||||
const int page_index = OpusGetWin95CurrentPageIndex(pane);
|
||||
const int zoom_percent = OpusGetWin95ZoomPercent(pane);
|
||||
if (has_previous) {
|
||||
RECT previous{page_left, page_top - page_step,
|
||||
page_right, page_bottom - page_step};
|
||||
draw_neighbor_sheet(
|
||||
dc, previous, client,
|
||||
find_page_snapshot(pane, page_index - 1,
|
||||
page_right - page_left, page_height,
|
||||
zoom_percent));
|
||||
}
|
||||
if (has_next) {
|
||||
RECT next{page_left, page_top + page_step,
|
||||
page_right, page_bottom + page_step};
|
||||
draw_neighbor_sheet(
|
||||
dc, next, client,
|
||||
find_page_snapshot(pane, page_index + 1,
|
||||
page_right - page_left, page_height,
|
||||
zoom_percent));
|
||||
}
|
||||
}
|
||||
|
||||
void draw_vertical_ruler(HWND pane, HDC dc) {
|
||||
RECT client{};
|
||||
GetClientRect(pane, &client);
|
||||
@@ -1756,6 +1986,41 @@ void show_document_context_menu(HWND pane, POINT screen_point) {
|
||||
LRESULT CALLBACK document_pane_proc(HWND pane, UINT message,
|
||||
WPARAM w_param, LPARAM l_param) {
|
||||
WNDPROC original = original_pane_proc(pane);
|
||||
if (message == WM_MOUSEWHEEL) {
|
||||
if (g_document_wheel.pane != pane) {
|
||||
g_document_wheel = {};
|
||||
g_document_wheel.pane = pane;
|
||||
}
|
||||
const int wheel_delta = GET_WHEEL_DELTA_WPARAM(w_param);
|
||||
if ((GET_KEYSTATE_WPARAM(w_param) & MK_CONTROL) != 0) {
|
||||
g_document_wheel.zoom_remainder += wheel_delta;
|
||||
int percent_delta = 0;
|
||||
while (g_document_wheel.zoom_remainder >= WHEEL_DELTA) {
|
||||
percent_delta += 10;
|
||||
g_document_wheel.zoom_remainder -= WHEEL_DELTA;
|
||||
}
|
||||
while (g_document_wheel.zoom_remainder <= -WHEEL_DELTA) {
|
||||
percent_delta -= 10;
|
||||
g_document_wheel.zoom_remainder += WHEEL_DELTA;
|
||||
}
|
||||
if (percent_delta != 0) {
|
||||
const int percent = OpusAdjustWin95Zoom(
|
||||
pane, percent_delta);
|
||||
update_zoom_combo(pane, percent);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int scaled_delta = g_document_wheel.scroll_remainder -
|
||||
wheel_delta * scale(pane, 48);
|
||||
const int pixels = scaled_delta / WHEEL_DELTA;
|
||||
g_document_wheel.scroll_remainder =
|
||||
scaled_delta % WHEEL_DELTA;
|
||||
if (pixels != 0 &&
|
||||
OpusScrollWin95ContinuousPages(pane, pixels)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (message == WM_LBUTTONDOWN) {
|
||||
POINT point{GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param)};
|
||||
bool top_marker = false;
|
||||
@@ -1865,11 +2130,21 @@ LRESULT CALLBACK document_pane_proc(HWND pane, UINT message,
|
||||
DefWindowProcW(pane, message, w_param, l_param);
|
||||
HDC dc = GetDC(pane);
|
||||
if (dc != nullptr) {
|
||||
update_current_page_snapshot(pane, dc);
|
||||
draw_continuous_page_neighbors(pane, dc);
|
||||
draw_vertical_ruler(pane, dc);
|
||||
ReleaseDC(pane, dc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (message == WM_SIZE) {
|
||||
const LRESULT result = original != nullptr ?
|
||||
CallWindowProcW(original, pane, message, w_param, l_param) :
|
||||
DefWindowProcW(pane, message, w_param, l_param);
|
||||
OpusRecenterWin95PageView(pane);
|
||||
InvalidateRect(pane, nullptr, TRUE);
|
||||
return result;
|
||||
}
|
||||
if (message == WM_RBUTTONDOWN) {
|
||||
SetFocus(pane);
|
||||
return 0;
|
||||
@@ -1889,6 +2164,20 @@ LRESULT CALLBACK document_pane_proc(HWND pane, UINT message,
|
||||
return 0;
|
||||
}
|
||||
if (message == WM_NCDESTROY) {
|
||||
if (g_document_wheel.pane == pane) {
|
||||
g_document_wheel = {};
|
||||
}
|
||||
for (auto iterator = g_page_snapshots.begin();
|
||||
iterator != g_page_snapshots.end();) {
|
||||
if (iterator->pane == pane) {
|
||||
if (iterator->bitmap != nullptr) {
|
||||
DeleteObject(iterator->bitmap);
|
||||
}
|
||||
iterator = g_page_snapshots.erase(iterator);
|
||||
} else {
|
||||
++iterator;
|
||||
}
|
||||
}
|
||||
RemovePropW(pane, kOriginalPaneProcProperty);
|
||||
if (original != nullptr) {
|
||||
SetWindowLongPtrW(pane, GWLP_WNDPROC,
|
||||
|
||||
Reference in New Issue
Block a user