1575 lines
48 KiB
C
1575 lines
48 KiB
C
/************************************************************/
|
||
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
||
/************************************************************/
|
||
|
||
/* disp.c -- MW display routines */
|
||
|
||
#define NOKEYSTATE
|
||
#define NOSYSCOMMANDS
|
||
#define NOSHOWWINDOW
|
||
//#define NOATOM
|
||
#define NOCLIPBOARD
|
||
#define NOGDICAPMASKS
|
||
#define NOCTLMGR
|
||
#define NOWINSTYLES
|
||
//#define NOVIRTUALKEYCODES
|
||
#define NOSYSMETRICS
|
||
#define NOMENUS
|
||
#define NOSOUND
|
||
#define NOCOMM
|
||
#define NOOPENFILE
|
||
#define NOWH
|
||
#define NOWINOFFSETS
|
||
#define NOMETAFILE
|
||
#define NOMB
|
||
#define NODRAWTEXT
|
||
#include <windows.h>
|
||
|
||
#define NOUAC
|
||
#include "mw.h"
|
||
#include "debug.h"
|
||
#include "cmddefs.h"
|
||
#include "dispdefs.h"
|
||
#include "wwdefs.h"
|
||
#define NOKCCODES /* Removes all kc code defines */
|
||
#include "ch.h"
|
||
#include "docdefs.h"
|
||
#include "fmtdefs.h"
|
||
#include "propdefs.h"
|
||
#include "macro.h"
|
||
#include "printdef.h"
|
||
#include "fontdefs.h"
|
||
#if defined(OLE)
|
||
#include "obj.h"
|
||
#endif
|
||
#ifdef DBCS
|
||
#include "dbcs.h"
|
||
#endif
|
||
|
||
#ifdef CASHMERE /* No VisiMode in WinMemo */
|
||
extern int vfVisiMode;
|
||
#endif /* CASHMERE */
|
||
|
||
extern int vcchBlted;
|
||
extern int vidxpInsertCache;
|
||
extern int vdlIns;
|
||
extern int vfInsLast;
|
||
extern struct PAP vpapAbs;
|
||
extern struct SEP vsepAbs;
|
||
extern int rgval[];
|
||
extern struct DOD (**hpdocdod)[];
|
||
extern typeCP cpMacCur;
|
||
extern int vfSelHidden;
|
||
extern struct WWD rgwwd[];
|
||
extern int wwCur, wwMac;
|
||
extern struct FLI vfli;
|
||
extern struct SEL selCur;
|
||
extern struct WWD *pwwdCur;
|
||
extern int docCur;
|
||
extern struct CHP (**vhgchpFormat)[];
|
||
extern int vichpFormat;
|
||
extern typeCP cpMinCur;
|
||
extern typeCP cpMinDocument;
|
||
extern int vfInsertOn;
|
||
extern int vfTextBltValid;
|
||
extern typeCP vcpFirstParaCache;
|
||
extern typeCP vcpLimParaCache;
|
||
extern unsigned vpgn;
|
||
extern struct SEP vsepAbs;
|
||
extern CHAR stBuf[];
|
||
extern typeCP CpEdge();
|
||
extern typeCP CpMacText();
|
||
extern int vdocPageCache;
|
||
extern int vfPictSel;
|
||
extern int vfAwfulNoise;
|
||
extern int vfSkipNextBlink;
|
||
extern int dypMax;
|
||
extern HDC vhMDC;
|
||
extern HWND vhWndPageInfo;
|
||
extern struct FMI vfmiScreen;
|
||
extern int docScrap;
|
||
extern long rgbBkgrnd;
|
||
extern long ropErase;
|
||
extern BOOL vfMonochrome;
|
||
extern int dxpbmMDC;
|
||
extern int dypbmMDC;
|
||
extern HBITMAP hbmNull;
|
||
extern int vfOutOfMemory;
|
||
extern int vfSeeSel;
|
||
extern int vfInsEnd; /* Is insert point at end-of-line? */
|
||
extern int vipgd;
|
||
extern typeCP vcpMinPageCache;
|
||
extern typeCP vcpMacPageCache;
|
||
/* actual position of the cursor line */
|
||
extern int vxpCursLine;
|
||
extern int vypCursLine;
|
||
|
||
extern int vdypCursLine;
|
||
extern int vfScrollInval; /* means scroll did not take and UpdateWw must be repeated */
|
||
extern BOOL vfDead;
|
||
extern HRGN vhrgnClip;
|
||
|
||
|
||
/* G L O B A L S
|
||
int dlsMac = 0;*/
|
||
#ifdef DBCS
|
||
int donteat = 0; /* propagate not to eat message */
|
||
#endif
|
||
|
||
|
||
/* D I S P L A Y F L I */
|
||
/* Display formatted line in window ww at line dl */
|
||
|
||
|
||
DisplayFli(ww, dl, fDontDisplay)
|
||
int ww;
|
||
int dl;
|
||
int fDontDisplay; /* True if we set up dl info but don't display */
|
||
{
|
||
#ifdef KOREA // jinwoo: 92, 9, 28
|
||
/* process Subscript separatedly from descent */
|
||
#ifdef NODESC
|
||
extern int isSubs;
|
||
#endif
|
||
#endif
|
||
typeCP dcp;
|
||
typeCP dcpMac;
|
||
struct WWD *pwwd = &rgwwd[ww];
|
||
HDC hDC = pwwd->hDC;
|
||
int xp; /* Current xp to write text */
|
||
int yp; /* Current yp to write text */
|
||
int xpMin = pwwd->xpMin; /* Minimum xp in window */
|
||
int xpMac = pwwd->xpMac; /* Maximum xp in window */
|
||
int ypLine; /* Screen yp for current line */
|
||
int dxp; /* Width of current run */
|
||
int dyp; /* Line height */
|
||
int dxpExtra; /* Width of pad for each space */
|
||
typeCP cpMin;
|
||
typeCP cpMac;
|
||
int xpSel; /* xp of the start of the selection */
|
||
int dxpSel = 0; /* Width of the selection. */
|
||
CHAR chMark = '\0'; /* style character */
|
||
struct CHP *pchp;
|
||
BOOL fTabsKludge = (vfli.ichLastTab >= 0);
|
||
BOOL fInsertOn = FALSE;
|
||
int cBreakRun; /* break characters in run (no relation to Dick or Jane) */
|
||
|
||
#ifdef SMFONT
|
||
RECT rcOpaque;
|
||
#endif /* SMFONT */
|
||
|
||
#ifdef DDISP
|
||
CommSzNumNum(" DisplayFli: dl/fDontDisplay ", dl, fDontDisplay);
|
||
#endif
|
||
Assert(ww >= 0 && ww < wwMax);
|
||
#ifdef SMFONT
|
||
Assert(!fDontDisplay || vfli.fGraphics)
|
||
#endif /* SMFONT */
|
||
Scribble(5,'D');
|
||
|
||
/* Fill up EDL and set some useful locals */
|
||
{
|
||
register struct EDL *pedl = &(**pwwd->hdndl)[dl];
|
||
|
||
if (dl == vdlIns)
|
||
{
|
||
/* Overwriting chars blted during fast insert; reset blt count */
|
||
vcchBlted = 0;
|
||
vidxpInsertCache = -1;
|
||
}
|
||
|
||
pedl->xpLeft = vfli.xpLeft;
|
||
pedl->xpMac = vfli.xpReal;
|
||
cpMin = pedl->cpMin = vfli.cpMin;
|
||
pedl->dcpMac = (cpMac = vfli.cpMac) - cpMin;
|
||
dyp = pedl->dyp = vfli.dypLine;
|
||
pedl->ichCpMin = vfli.ichCpMin;
|
||
pedl->dcpDepend = (cpMin == cpMac) ? 0xff : vfli.dcpDepend;
|
||
pedl->fValid = TRUE;
|
||
pedl->fGraphics = vfli.fGraphics;
|
||
pedl->fSplat = vfli.fSplat;
|
||
|
||
/* The position of current line equals the position of the previous line
|
||
+ height of this line. */
|
||
#ifdef SMFONT
|
||
pedl->yp = rcOpaque.bottom = dyp + (ypLine = rcOpaque.top = (dl == 0 ?
|
||
pwwd->ypMin : (pedl - 1)->yp));
|
||
#else /* not SMFONT */
|
||
pedl->yp = dyp + (ypLine = (dl == 0 ? pwwd->ypMin :
|
||
(pedl - 1)->yp));
|
||
#endif /* SMFONT */
|
||
|
||
if (pedl->fIchCpIncr = (vfli.ichCpMac != 0))
|
||
{
|
||
/* Look at final text column */
|
||
++cpMac;
|
||
|
||
/* Since this is true, we can compress pedl->ichCpMac to 1 bit. */
|
||
Assert(vfli.ichCpMac == pedl->ichCpMin + 1);
|
||
}
|
||
}
|
||
|
||
if (vfli.doc == docNil)
|
||
{
|
||
/* This is the space beyond the end mark. */
|
||
PatBlt(hDC, 0, ypLine, xpMac, dyp, ropErase);
|
||
goto Finished;
|
||
}
|
||
|
||
/* Is there a character in the "style bar"? */
|
||
if (cpMin != cpMac)
|
||
{
|
||
|
||
#ifdef CASHMERE
|
||
/* This line is not completely empty (not after the end mark); check for
|
||
painting marks on the style bar. */
|
||
if (cpMin == vcpFirstParaCache && vpapAbs.rhc != 0)
|
||
{
|
||
/* This is a running-head. */
|
||
chMark = chStatRH;
|
||
}
|
||
else if ((**hpdocdod)[vfli.doc].hpgtb != 0)
|
||
#else /* not CASHMERE */
|
||
if (vpapAbs.rhc == 0 && (**hpdocdod)[vfli.doc].hpgtb != 0)
|
||
#endif /* CASHMERE */
|
||
|
||
{
|
||
if (vdocPageCache != vfli.doc || cpMac > vcpMacPageCache || cpMac <=
|
||
vcpMinPageCache)
|
||
{
|
||
CachePage(vfli.doc, cpMac - 1);
|
||
}
|
||
|
||
/* We are now guaranteed that cpMac is within the cached page. */
|
||
if (cpMin <= vcpMinPageCache && (!vfli.fGraphics || vfli.ichCpMin ==
|
||
0))
|
||
{
|
||
/* This is the first line of new page; show page mark. */
|
||
chMark = chStatPage;
|
||
}
|
||
}
|
||
}
|
||
|
||
#ifdef SMFONT
|
||
#ifdef DDISP
|
||
/* black out this line to test how efficiently/correctly we
|
||
overwrite pixels from previously-resident lines of text */
|
||
PatBlt(hDC, 0, ypLine, xpMac, dyp, BLACKNESS);
|
||
{ long int i; for (i=0; i < 500000; i++) ; }
|
||
#endif
|
||
|
||
/* Calculate dcpMac now, so we might be able to know how much to erase. */
|
||
dcpMac = vfli.fSplat ? vfli.ichMac : vfli.ichReal;
|
||
|
||
/* Erase any character that might be in the style bar. */
|
||
dxp = xpSelBar + 1;
|
||
if (!vfli.fGraphics)
|
||
{
|
||
dxp = xpMac; // clear the whole line
|
||
}
|
||
PatBlt(hDC, 0, ypLine, dxp, dyp, ropErase);
|
||
|
||
/* If this is graphics then go draw any characters in the style bar. */
|
||
if (vfli.fGraphics)
|
||
{
|
||
goto DrawMark;
|
||
}
|
||
|
||
/* If there are no "real" characters on this line then we can skip alot of
|
||
this. */
|
||
if (dcpMac == 0)
|
||
{
|
||
goto EndLine2;
|
||
}
|
||
#else /* not SMFONT */
|
||
if (vfli.fGraphics || fDontDisplay)
|
||
{
|
||
/* Erase any character that might be in the style bar. */
|
||
PatBlt(hDC, 0, ypLine, xpSelBar, dyp, ropErase);
|
||
goto DrawMark;
|
||
}
|
||
#endif /* SMFONT */
|
||
|
||
ValidateMemoryDC();
|
||
if (vhMDC == NULL)
|
||
{
|
||
Error:
|
||
/* Notify the user that an error has occured and simply erase this line.
|
||
*/
|
||
WinFailure();
|
||
PatBlt(hDC, xpSelBar, ypLine, xpMac - xpSelBar, dyp, ropErase);
|
||
goto Finished;
|
||
}
|
||
|
||
#ifndef SMFONT
|
||
/* Create a new bitmap for the memory DC if the current bitmap is not big
|
||
enough. */
|
||
if (xpMac > dxpbmMDC || dyp > dypbmMDC)
|
||
{
|
||
HBITMAP hbm;
|
||
|
||
/* If there is an old bitmap, then delete it. */
|
||
if (dxpbmMDC != 0 || dypbmMDC != 0)
|
||
{
|
||
DeleteObject(SelectObject(vhMDC, hbmNull));
|
||
}
|
||
|
||
/* Create the new bitmap and select it in. */
|
||
if ((hbm = CreateBitmap(dxpbmMDC = xpMac, dypbmMDC = dyp, 1, 1,
|
||
(LPSTR)NULL)) == NULL)
|
||
{
|
||
/* There should be a graceful way to recover if the bitmap is ever
|
||
NULL (e.g we don't have enough memory for it). */
|
||
dxpbmMDC = dypbmMDC = 0;
|
||
goto Error;
|
||
}
|
||
SelectObject(vhMDC, hbm);
|
||
}
|
||
|
||
/* Erase the are of the bitmap we are going to use. */
|
||
PatBlt(vhMDC, xpSelBar, 0, xpMac, dyp, vfMonochrome ? ropErase : WHITENESS);
|
||
#endif /* not SMFONT */
|
||
|
||
/* Initialize some of the variables we'll need. */
|
||
pchp = &(**vhgchpFormat)[0];
|
||
#ifdef SMFONT
|
||
xp = rcOpaque.left = rcOpaque.right = vfli.xpLeft + xpSelBar - xpMin + 1;
|
||
#else /* not SMFONT */
|
||
dcpMac = vfli.fSplat ? vfli.ichMac : vfli.ichReal;
|
||
xp = vfli.xpLeft + xpSelBar - xpMin + 1;
|
||
#endif /* SMFONT */
|
||
dxpExtra = fTabsKludge ? 0 : vfli.dxpExtra;
|
||
|
||
#ifdef SMFONT
|
||
/* If we are horizontally scrolled, then set the clip area to the area
|
||
outside of the selection bar. */
|
||
if (xpMin != 0)
|
||
{
|
||
IntersectClipRect(hDC, xpSelBar, rcOpaque.top, xpMac, rcOpaque.bottom);
|
||
}
|
||
#endif /* SMFONT */
|
||
|
||
for (dcp = 0; dcp < dcpMac; pchp++)
|
||
{
|
||
/* For all runs do: */
|
||
int ichFirst; /* First character in the current run */
|
||
int cchRun; /* Number of characters in the current run */
|
||
|
||
dcp = ichFirst = pchp->ichRun;
|
||
dcp += pchp->cchRun;
|
||
if (dcp > dcpMac)
|
||
{
|
||
dcp = dcpMac;
|
||
}
|
||
cchRun = dcp - ichFirst;
|
||
|
||
/* Compute dxp = sum of width of characters in current run (formerly
|
||
DxaFromIcpDcp). */
|
||
{
|
||
register int *pdxp;
|
||
register int cchT = cchRun;
|
||
PCH pch = vfli.rgch + ichFirst;
|
||
|
||
dxp = cBreakRun = 0;
|
||
pdxp = &vfli.rgdxp[ichFirst];
|
||
while (cchT-- > 0)
|
||
{
|
||
dxp += *pdxp++;
|
||
if (*pch++ == chSpace)
|
||
++cBreakRun;
|
||
}
|
||
#ifdef DDISP
|
||
CommSzNum(" dxp=",dxp);
|
||
#endif
|
||
}
|
||
|
||
if (dxp > 0)
|
||
{
|
||
int cchDone;
|
||
PCH pch = &vfli.rgch[ichFirst];
|
||
|
||
#ifdef KOREA //920525 KDLEE; jinwoo: 92, 9, 28
|
||
#ifdef NODESC
|
||
TEXTMETRIC tm;
|
||
#endif
|
||
#endif //KOREA
|
||
LoadFont(vfli.doc, pchp, mdFontScreen);
|
||
#ifdef KOREA //KDLEE 920525; jinwoo: 92, 9, 28
|
||
#ifdef NODESC
|
||
GetTextMetrics (vhMDC, (LPTEXTMETRIC)&tm);
|
||
|
||
if (tm.tmCharSet==HANGEUL_CHARSET)
|
||
yp = dyp - (vfli.dypBase/3) -((pchp->hpsPos != 0 ? (pchp->hpsPos <
|
||
hpsNegMin ? ypSubSuper : -ypSubSuper) : 0)) -
|
||
vfmiScreen.dypBaseline - (isSubs ? ypSubSuper : 0);
|
||
else
|
||
yp = (dyp - (vfli.dypBase + (pchp->hpsPos != 0 ? (pchp->hpsPos <
|
||
hpsNegMin ? ypSubSuper : -ypSubSuper) : 0))) -
|
||
vfmiScreen.dypBaseline - (isSubs ? ypSubSuper : 0);
|
||
#else /* NODESC */
|
||
yp = (dyp - (vfli.dypBase + (pchp->hpsPos != 0 ? (pchp->hpsPos <
|
||
hpsNegMin ? ypSubSuper : -ypSubSuper) : 0))) -
|
||
vfmiScreen.dypBaseline;
|
||
#endif /* NODESC */
|
||
#else /* KOREA */
|
||
|
||
yp = (dyp - (vfli.dypBase + (pchp->hpsPos != 0 ? (pchp->hpsPos <
|
||
hpsNegMin ? ypSubSuper : -ypSubSuper) : 0))) -
|
||
vfmiScreen.dypBaseline;
|
||
#endif // KOREA jinwoo: 92, 9, 28
|
||
|
||
|
||
/* Note: tabs and other special characters are guaranteed to come at
|
||
the start of a run. */
|
||
SetTextJustification(vhMDC, dxpExtra * cBreakRun, cBreakRun);
|
||
#ifdef SMFONT
|
||
SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun);
|
||
#endif /* SMFONT */
|
||
cchDone = 0;
|
||
while (cchDone < cchRun)
|
||
{
|
||
int cch;
|
||
|
||
/* Does the wide-space zone begin in this run? */
|
||
if (vfli.fAdjSpace && (vfli.ichFirstWide < ichFirst + cchRun) &&
|
||
(ichFirst + cchDone <= vfli.ichFirstWide))
|
||
{
|
||
int cchDoneT = cchDone;
|
||
|
||
/* Is this the beginning of the wide-space zone? */
|
||
if (ichFirst + cchDone == vfli.ichFirstWide)
|
||
{
|
||
/* Reset the width of the spaces. */
|
||
SetTextJustification(vhMDC, ++dxpExtra * cBreakRun, cBreakRun);
|
||
#ifdef SMFONT
|
||
SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun);
|
||
#endif /* SMFONT */
|
||
cch = cchRun - cchDone;
|
||
cchDone = cchRun;
|
||
}
|
||
else
|
||
{
|
||
cchDone = cch = vfli.ichFirstWide - ichFirst;
|
||
}
|
||
|
||
/* This run is cut short because of a wide space, so we need
|
||
to calculate a new width. */
|
||
{
|
||
register int *pdxp;
|
||
register int cchT = cch;
|
||
PCH pch = &vfli.rgch[ichFirst + cchDoneT];
|
||
|
||
dxp = 0;
|
||
pdxp = &vfli.rgdxp[ichFirst + cchDoneT];
|
||
while (cchT-- > 0)
|
||
{
|
||
dxp += *pdxp++;
|
||
if (*pch++ == chSpace)
|
||
++cBreakRun;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cchDone = cch = cchRun;
|
||
}
|
||
|
||
while (cch > 0)
|
||
{
|
||
switch (*pch)
|
||
{
|
||
CHAR ch;
|
||
int dxpT;
|
||
|
||
case chTab:
|
||
|
||
#ifdef CASHMERE
|
||
/* chLeader contains tab leader character (see
|
||
FormatLine) */
|
||
if ((ch = pchp->chLeader) != chSpace)
|
||
{
|
||
int cxpTab;
|
||
CHAR rgch[32];
|
||
int dxpLeader = CharWidth(ch);
|
||
int xpT = xp;
|
||
int iLevelT = SaveDC(vhMDC);
|
||
|
||
SetBytes(&rgch[0], ch, 32);
|
||
dxpT = vfli.rgdxp[ichFirst];
|
||
cxpTab = ((dxpT + dxpLeader - 1) / dxpLeader + 31)
|
||
>> 5;
|
||
|
||
xp += dxpT;
|
||
|
||
while (cxpTab-- > 0)
|
||
{
|
||
TextOut(vhMDC, xpT, yp, (LPSTR)rgch, 32);
|
||
xpT += dxpLeader << 5;
|
||
}
|
||
RestoreDC(vhMDC, iLevelT);
|
||
}
|
||
else
|
||
#endif /* CASHMERE */
|
||
|
||
{
|
||
#ifdef SMFONT
|
||
/* Expand the opaque rectangle to include the tab.
|
||
*/
|
||
rcOpaque.right += vfli.rgdxp[ichFirst];
|
||
#endif /* SMFONT */
|
||
xp += vfli.rgdxp[ichFirst];
|
||
}
|
||
|
||
if (fTabsKludge && ichFirst >= vfli.ichLastTab)
|
||
{
|
||
SetTextJustification(vhMDC, (dxpExtra =
|
||
vfli.dxpExtra) * cBreakRun, cBreakRun);
|
||
#ifdef SMFONT
|
||
SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun);
|
||
#endif /* SMFONT */
|
||
fTabsKludge = FALSE;
|
||
}
|
||
dxp -= vfli.rgdxp[ichFirst];
|
||
pch++;
|
||
cch--;
|
||
goto EndLoop;
|
||
|
||
#ifdef CASHMERE
|
||
case schPage:
|
||
if (!pchp->fSpecial)
|
||
{
|
||
goto EndLoop;
|
||
}
|
||
stBuf[0] = CchExpPgn(&stBuf[1], vpgn, vsepAbs.nfcPgn,
|
||
flmSandMode, ichMaxLine);
|
||
goto DrawSpecial;
|
||
|
||
case schFootnote:
|
||
if (!pchp->fSpecial)
|
||
{
|
||
goto EndLoop;
|
||
}
|
||
stBuf[0] = CchExpFtn(&stBuf[1], cpMin + ichFirst,
|
||
flmSandMode, ichMaxLine);
|
||
DrawSpecial:
|
||
#else /* not CASHMERE */
|
||
case schPage:
|
||
case schFootnote:
|
||
if (!pchp->fSpecial)
|
||
{
|
||
goto EndLoop;
|
||
}
|
||
stBuf[0] = *pch == schPage && (wwdCurrentDoc.fEditHeader
|
||
|| wwdCurrentDoc.fEditFooter) ? CchExpPgn(&stBuf[1],
|
||
vpgn, 0, flmSandMode, ichMaxLine) :
|
||
CchExpUnknown(&stBuf[1], flmSandMode, ichMaxLine);
|
||
#endif /* not CASHMERE */
|
||
|
||
#ifdef SMFONT
|
||
/* Calculate the opaque rectangle. */
|
||
rcOpaque.right += vfli.rgdxp[ichFirst] +
|
||
vfmiScreen.dxpOverhang;
|
||
|
||
TextOut(hDC, xp, ypLine+yp, &stBuf[1], stBuf[0]);
|
||
#else /* not SMFONT */
|
||
TextOut(vhMDC, xp, yp, (LPSTR)&stBuf[1], stBuf[0]);
|
||
#endif /* SMFONT */
|
||
break;
|
||
|
||
default:
|
||
goto EndLoop;
|
||
}
|
||
|
||
dxp -= vfli.rgdxp[ichFirst];
|
||
#ifdef SMFONT
|
||
/* End the line if no more will fit into the window. */
|
||
if ((xp += vfli.rgdxp[ichFirst++]) >= xpMac) {
|
||
goto EndLine;
|
||
}
|
||
rcOpaque.left = (rcOpaque.right = xp) +
|
||
vfmiScreen.dxpOverhang;
|
||
#else /* not SMFONT */
|
||
xp += vfli.rgdxp[ichFirst++];
|
||
#endif /* SMFONT */
|
||
pch++;
|
||
cch--;
|
||
}
|
||
EndLoop:
|
||
|
||
#ifdef SMFONT
|
||
if (cch == 0)
|
||
{
|
||
Assert(dxp == 0);
|
||
}
|
||
else
|
||
{
|
||
/* Calculate the opaque rectangle. */
|
||
rcOpaque.right += dxp + vfmiScreen.dxpOverhang;
|
||
|
||
#if 0
|
||
{
|
||
char msg[180];
|
||
wsprintf(msg,"putting out %d characters\n\r",cch);
|
||
OutputDebugString(msg);
|
||
}
|
||
#endif
|
||
/* Output cch characters starting at pch */
|
||
TextOut(hDC, xp, ypLine+yp, pch, cch);
|
||
|
||
/* End the line if no more will fit into the window. */
|
||
if ((xp += dxp) >= xpMac)
|
||
{
|
||
goto EndLine;
|
||
}
|
||
rcOpaque.left = (rcOpaque.right = xp) +
|
||
vfmiScreen.dxpOverhang;
|
||
pch += cch;
|
||
}
|
||
#else /* not SMFONT */
|
||
/* Output cch characters starting at pch */
|
||
TextOut(vhMDC, xp, yp, (LPSTR)pch, cch);
|
||
xp += dxp;
|
||
pch += cch;
|
||
#endif /* SMFONT */
|
||
} /* end while (cchDone<cchRun) */
|
||
} /* end if (dxp>0) */
|
||
} /* end for dcp=0..dcpMac */
|
||
|
||
#ifdef SMFONT
|
||
EndLine:
|
||
/* Restore the clip region if need be. */
|
||
if (xpMin != 0)
|
||
{
|
||
SelectClipRgn(hDC, NULL);
|
||
}
|
||
EndLine2:
|
||
#endif /* SMFONT */
|
||
|
||
#ifdef CASHMERE
|
||
if (vfVisiMode)
|
||
{
|
||
AddVisiSpaces(ww, &(**pwwd->hdndl)[dl], vfli.dypBase, vfli.dypAfter +
|
||
vfli.dypFont);
|
||
}
|
||
#endif /* CASHMERE */
|
||
|
||
vfTextBltValid = FALSE;
|
||
|
||
if ((ww == wwCur) && (pwwd->doc != docScrap) && !vfSelHidden &&
|
||
(selCur.cpLim >= cpMin))
|
||
{
|
||
if (selCur.cpFirst <= cpMac)
|
||
{
|
||
/* Show selection */
|
||
int xpFirst;
|
||
int xpLim;
|
||
|
||
#ifdef ENABLE
|
||
if (vfli.fSplatNext && selCur.cpFirst == selCur.cpLim &&
|
||
selCur.cpFirst == cpMac)
|
||
{
|
||
vfInsEnd = TRUE;
|
||
ClearInsertLine();
|
||
}
|
||
vfInsertOn = FALSE;
|
||
#endif /* ENABLE */
|
||
|
||
if (selCur.cpFirst <= cpMin && selCur.cpLim >= cpMac)
|
||
{
|
||
xpFirst = vfli.xpLeft;
|
||
xpLim = vfli.xpReal;
|
||
}
|
||
else if (selCur.cpFirst < cpMac || (selCur.cpLim == cpMac &&
|
||
vfInsEnd))
|
||
{
|
||
typeCP cpBegin = CpMax(cpMin, selCur.cpFirst);
|
||
typeCP cpEnd = CpMin(cpMac, selCur.cpLim);
|
||
|
||
dxp = DxpDiff((int)(cpBegin - cpMin), (int)(cpEnd - cpBegin),
|
||
&xpFirst);
|
||
xpLim = min(xpMin + vfli.xpReal, xpFirst + dxp);
|
||
}
|
||
else
|
||
{
|
||
goto DidntHighlight;
|
||
}
|
||
|
||
xpSel = xpSelBar + max(xpFirst - xpMin, 0);
|
||
if (xpLim > xpFirst)
|
||
{
|
||
/* Set highlighting at desired screen position. */
|
||
dxpSel = max(xpLim - max(xpFirst, xpMin), 0);
|
||
}
|
||
else if (selCur.cpFirst == selCur.cpLim && ((selCur.cpLim != cpMac)
|
||
^ vfInsEnd))
|
||
{
|
||
vfInsertOn = FALSE; /* Because we redisplayed insert pt line */
|
||
|
||
#ifdef CASHMERE
|
||
vdypCursLine = min(vfli.dypFont, vfli.dypLine - vfli.dypAfter);
|
||
vypCursLine = ypLine + dyp - vfli.dypAfter;
|
||
#else /* not CASHMERE */
|
||
vdypCursLine = vfli.dypFont;
|
||
vypCursLine = ypLine + dyp;
|
||
#endif /* not CASHMERE */
|
||
|
||
vxpCursLine = xpSel;
|
||
|
||
/* Start blinking in a while */
|
||
vfSkipNextBlink = TRUE;
|
||
|
||
fInsertOn = xpFirst >= xpMin;
|
||
}
|
||
|
||
DidntHighlight:;
|
||
}
|
||
}
|
||
|
||
#ifdef SMFONT
|
||
/* Invert the selection */
|
||
if (dxpSel != 0) {
|
||
PatBlt(hDC, xpSel, ypLine, dxpSel, dyp, DSTINVERT);
|
||
}
|
||
#else /* not SMFONT */
|
||
/* Blt the line of text onto the screen. */
|
||
PatBlt(vhMDC, 0, 0, xpSelBar, dyp, vfMonochrome ? ropErase : WHITENESS);
|
||
if (dxpSel == 0)
|
||
{
|
||
BitBlt(hDC, 0, ypLine, xpMac, dyp, vhMDC, 0, 0, SRCCOPY);
|
||
}
|
||
else
|
||
{
|
||
BitBlt(hDC, 0, ypLine, xpSel, dyp, vhMDC, 0, 0, SRCCOPY);
|
||
BitBlt(hDC, xpSel, ypLine, dxpSel, dyp, vhMDC, xpSel, 0, NOTSRCCOPY);
|
||
xpSel += dxpSel;
|
||
BitBlt(hDC, xpSel, ypLine, xpMac - xpSel, dyp, vhMDC, xpSel, 0,
|
||
SRCCOPY);
|
||
}
|
||
#endif /* SMFONT */
|
||
|
||
/* Draw the insertion bar if necessary. */
|
||
if (fInsertOn)
|
||
{
|
||
DrawInsertLine();
|
||
}
|
||
|
||
DrawMark:
|
||
/* Draw the character in the style bar if necessary. */
|
||
if (chMark != '\0')
|
||
{
|
||
#ifdef SYSENDMARK
|
||
struct CHP chpT;
|
||
extern struct CHP vchpNormal;
|
||
|
||
blt(&vchpNormal, &chpT, cwCHP);
|
||
chpT.ftc = ftcSystem;
|
||
chpT.ftcXtra = 0;
|
||
chpT.hps = hpsDefault;
|
||
|
||
/* Draw the style character in the standard font. */
|
||
LoadFont(vfli.doc, &chpT, mdFontScreen);
|
||
|
||
TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline,
|
||
(LPSTR)&chMark, 1);
|
||
#else /* ifdef SYSENDMARK */
|
||
/* Draw the style character in the standard font. */
|
||
LoadFont(vfli.doc, NULL, mdFontScreen);
|
||
TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline,
|
||
(LPSTR)&chMark, 1);
|
||
#endif /* if-else-def SYSENDMARK */
|
||
}
|
||
|
||
if (vfli.fGraphics)
|
||
{
|
||
DisplayGraphics(ww, dl, fDontDisplay);
|
||
}
|
||
|
||
Finished:
|
||
Scribble(5,' ');
|
||
}
|
||
|
||
|
||
/* D X P D I F F */
|
||
DxpDiff(dcpFirst, dcp, pdxpFirst)
|
||
int dcpFirst;
|
||
int dcp;
|
||
int *pdxpFirst;
|
||
{
|
||
#if 1
|
||
register int *pdxp = &vfli.rgdxp[0];
|
||
register int cch;
|
||
int dxp = vfli.xpLeft;
|
||
#ifdef ENABLE /* Not used */
|
||
int ichLim = dcpFirst + dcp;
|
||
#endif
|
||
|
||
|
||
if (dcp > vfli.ichMac - dcpFirst)
|
||
{ /* This should not be, but is when we have a CR */
|
||
//Assert( dcpFirst < vfli.ichMac );
|
||
dcp = vfli.ichMac - dcpFirst;
|
||
}
|
||
|
||
for (cch = 0; cch < dcpFirst; ++cch)
|
||
{
|
||
dxp += *pdxp++;
|
||
}
|
||
*pdxpFirst = dxp;
|
||
dxp = 0;
|
||
for (cch = 0; cch < dcp; ++cch)
|
||
{
|
||
dxp += *pdxp++;
|
||
}
|
||
return dxp;
|
||
#else
|
||
|
||
int dxp;
|
||
if (dcp > vfli.ichMac - dcpFirst)
|
||
{ /* This should not be, but is when we have a CR */
|
||
Assert( dcpFirst < vfli.ichMac );
|
||
dcp = vfli.ichMac - dcpFirst;
|
||
}
|
||
|
||
/* first get space up to first character */
|
||
*pdxpFirst = LOWORD(GetTextExtent(hDC,vfli.rgch,dcpFirst)) + vfli.xpLeft;
|
||
|
||
/* now get space between first and first+dcp */
|
||
dxp = LOWORD(GetTextExtent(hDC,vfli.rgch+dcpFirst,dcp));
|
||
return dxp;
|
||
#endif
|
||
}
|
||
|
||
|
||
UpdateDisplay(fAbortOK)
|
||
int fAbortOK;
|
||
{
|
||
int ww;
|
||
|
||
if (wwMac <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
#ifdef CASHMERE
|
||
for (ww = 0; ww < wwMac; ww++)
|
||
if ( rgwwd[ww].doc != docScrap )
|
||
{
|
||
UpdateWw(ww, fAbortOK);
|
||
if (rgwwd[ww].fDirty || vfOutOfMemory)
|
||
{
|
||
return; /* update has been interrupted */
|
||
}
|
||
}
|
||
#else /* not CASHMERE */
|
||
UpdateWw(wwDocument, fAbortOK);
|
||
if (wwdCurrentDoc.fDirty || vfOutOfMemory)
|
||
{
|
||
/* Update has been interrupted */
|
||
return;
|
||
}
|
||
#endif /* not CASHMERE */
|
||
|
||
if (wwdCurrentDoc.fRuler)
|
||
{
|
||
UpdateRuler();
|
||
}
|
||
}
|
||
|
||
|
||
/* U P D A T E W W */
|
||
UpdateWw(ww, fAbortOK)
|
||
int ww, fAbortOK;
|
||
{ /* Redisplay ww as necessary */
|
||
extern int vfWholePictInvalid;
|
||
register struct WWD *pwwd = &rgwwd[ww];
|
||
int dlMac;
|
||
int dlOld, dlNew;
|
||
int doc;
|
||
int ichCp;
|
||
struct EDL *pedlNew;
|
||
register struct EDL *pedl;
|
||
struct EDL (**hdndl)[]=pwwd->hdndl;
|
||
int dypDiff;
|
||
int ypTop;
|
||
int ypFirstInval;
|
||
int dr;
|
||
int fLastNotShown;
|
||
typeCP cp, cpMacWw;
|
||
|
||
if (!pwwd->fDirty)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (!((**hpdocdod)[pwwd->doc].fDisplayable))
|
||
return;
|
||
|
||
if (fAbortOK && FImportantMsgPresent())
|
||
return;
|
||
|
||
#if 0 // how to get first and last cp's in invalid rect?
|
||
#if defined(OLE)
|
||
/*
|
||
Load visible objects. Do it now rather than in DisplayGraphics()
|
||
because here it has less chance of disrupting the state variables
|
||
upon which UpdateWw depends.
|
||
*/
|
||
ObjEnumInRange(docCur,cpMinCur,cpMacCur,ObjLoadObjectInDoc);
|
||
#endif
|
||
#endif
|
||
|
||
dlMac = pwwd->dlMac;
|
||
ypTop = pwwd->ypMin;
|
||
|
||
Assert( ww >= 0 && ww < wwMax );
|
||
vfli.doc = docNil; /* An aid to Fast Insert */
|
||
|
||
UpdateInvalid(); /* InvalBand for what Windows considers to be invalid */
|
||
ypFirstInval = pwwd->ypFirstInval;
|
||
|
||
#ifndef CASHMERE
|
||
Assert( ww == wwCur ); /* A MEMO-only assumption */
|
||
#endif /* CASHMERE */
|
||
|
||
Scribble(5, 'U');
|
||
|
||
ValidateMemoryDC(); /* to do any update, we need a good memory DC */
|
||
if (vhMDC == NULL)
|
||
{
|
||
WinFailure();
|
||
return;
|
||
}
|
||
|
||
doc = pwwd->doc;
|
||
vfli.doc = docNil;
|
||
|
||
if (pwwd->fCpBad)
|
||
{
|
||
/* cp first displayed has not been blessed */
|
||
|
||
#ifdef CASHMERE /* Must do this if ww != wwCur assertion is FALSE */
|
||
int wwT = wwCur;
|
||
if (ww != wwCur && wwCur >= 0)
|
||
/* CtrBackTrs cache is only good for wwCur. Treat != case */
|
||
{
|
||
if (pwwdCur->fDirty) /* Do wwCur first, saving cache */
|
||
UpdateWw(wwCur, fAbortOK);
|
||
|
||
if (fAbortOK && FImportantMsgPresent())
|
||
return;
|
||
|
||
ChangeWw(ww, false);
|
||
CtrBackDypCtr( 0, 0 ); /* Validate pwwdCur->cpFirst */
|
||
ChangeWw(wwT, false);
|
||
}
|
||
else
|
||
#endif /* CASHMERE */
|
||
|
||
{
|
||
if (fAbortOK && FImportantMsgPresent())
|
||
return;
|
||
|
||
CtrBackDypCtr( 0, 0 ); /* Validate pwwdCur->cpFirst */
|
||
}
|
||
}
|
||
|
||
/* check for cpMin accessible in this ww */
|
||
RestartUpdate:
|
||
vfWholePictInvalid = fTrue; /* Tells DisplayGraphics to
|
||
abandon accumulated partial pict rect */
|
||
fLastNotShown = fFalse;
|
||
cp = CpMax(pwwd->cpMin, pwwd->cpFirst);
|
||
cpMacWw = pwwd->cpMac;
|
||
ichCp = pwwd->ichCpFirst;
|
||
|
||
/* Note test for dlNew==0 that guarantees that there will be at least
|
||
one dl -- this was added for WRITE because we do not have
|
||
the ability to enforce a minimum window size */
|
||
|
||
for (dlNew = dlOld = 0; ypTop < pwwd->ypMac || (dlNew == 0) ; dlNew++)
|
||
/* we have: cp, ichCP: pints to text desired on the coming line dlNew
|
||
ypTop: desired position for top of dlNew -1
|
||
dlOld: next line to be considered for re-use
|
||
*/
|
||
/* check for having to extend dndl array */
|
||
{
|
||
if (dlNew >= (int)pwwd->dlMax)
|
||
{
|
||
/* extend the array with uninitialized dl's, increment max, break if no space.
|
||
We assume that dlMac(Old) was <= dlMax, so the dl's will not be looked at
|
||
but used only to store new lines */
|
||
#define ddlIncr 5
|
||
|
||
if (!FChngSizeH(hdndl, (pwwd->dlMax + ddlIncr) * cwEDL, fFalse))
|
||
break;
|
||
pwwd->dlMax += ddlIncr;
|
||
}
|
||
/* discard unusable dl's */
|
||
for (; dlOld < dlMac; dlOld++)
|
||
{ /* Set dlOld and pedl to the next good dl */
|
||
int ypTopOld, ypOld;
|
||
|
||
/* Re-entrant Heap Movement */
|
||
if (fAbortOK && !fLastNotShown && FImportantMsgPresent())
|
||
goto RetInval;
|
||
|
||
pedl = &(**hdndl)[dlOld];
|
||
ypOld = pedl->yp;
|
||
|
||
/* loop if: invalid, passed over in cp space, passed over in dl space,
|
||
passed over in yp space,
|
||
in invalid band, passed over in ich space */
|
||
if (!pedl->fValid || dlOld < dlNew || pedl->cpMin < cp
|
||
|| (ypTopOld = (ypOld - pedl->dyp)) < ypTop
|
||
|| (ypOld >= ypFirstInval && ypTopOld <= pwwd->ypLastInval)
|
||
|| (pedl->cpMin == cp && pedl->ichCpMin < ichCp))
|
||
continue;
|
||
/* now we have dlOld, an acceptable if not necessarily useful dl.
|
||
now compute dlNew either from scratch or by re-using dlOld. To be
|
||
re-useable, dlOld must have right cp/ichCp pair, plus be totally on screen
|
||
or, if it is a partial line, it must stay still or move down - not up */
|
||
if (pedl->cpMin == cp && pedl->ichCpMin == ichCp &&
|
||
(ypOld <= pwwd->ypMac || ypTopOld <= ypTop))
|
||
{
|
||
/* Re-use this dl */
|
||
int yp = ypTop;
|
||
if (fLastNotShown)
|
||
{
|
||
/* HEAP MOVEMENT */
|
||
DisplayFli(ww, dlNew - 1, fLastNotShown = fFalse);
|
||
pedl = &(**hdndl)[dlOld];
|
||
}
|
||
|
||
cp = pedl->cpMin + pedl->dcpMac;
|
||
ichCp = pedl->fIchCpIncr ? pedl->ichCpMin + 1 : 0;
|
||
ypTop += pedl->dyp;
|
||
if (dlOld != dlNew || ypTopOld != yp)
|
||
{
|
||
DypScroll(ww, dlOld, dlNew - dlOld, yp);
|
||
if (vfScrollInval)
|
||
{
|
||
/* There was a popup; invalid region might have changed */
|
||
/* fLastNotShown test is for interrupting picture display */
|
||
/* before we've really displayed it */
|
||
|
||
(**hdndl) [dlOld].fValid = fFalse;
|
||
goto Restart1;
|
||
}
|
||
dlMac += dlNew - dlOld;
|
||
}
|
||
dlOld = dlNew + 1;
|
||
goto NextDlNew;
|
||
}
|
||
break;
|
||
}
|
||
/* cpMin > cp, the line is not anywhere so it will have to be formatted
|
||
from scratch */
|
||
|
||
if (fAbortOK && !fLastNotShown && FImportantMsgPresent())
|
||
goto RetInval;
|
||
|
||
FormatLine(doc, cp, ichCp, cpMacWw, flmSandMode); /* Creates vfli */
|
||
|
||
if (vfOutOfMemory)
|
||
goto RetInval;
|
||
|
||
ichCp = vfli.ichCpMac;
|
||
cp = vfli.cpMac;
|
||
/* advance invalid band so that update can resume after an interruption */
|
||
pwwd->ypFirstInval = (ypTop += vfli.dypLine);
|
||
pedl = &(**hdndl)[dlOld];
|
||
if (dlOld < dlMac && pedl->cpMin == cp && pedl->ichCpMin == ichCp)
|
||
{
|
||
int dlT = dlOld;
|
||
|
||
/* line at dlOld is a valid, existing line that will abutt the line just about
|
||
to be displayed. */
|
||
if (dlOld == dlNew && pedl->yp - pedl->dyp <= ypTop)
|
||
/* the line about to be overwritten will be re-used in the next loop.
|
||
Hence, it is worthwhile to save this line and its dl */
|
||
DypScroll(ww, dlOld++, 1, ypTop);
|
||
else
|
||
/* Move the next line to its abutting position. We know that it has not yet been
|
||
overwritten (yp, dlOld all > than ypTop, dlNew) */
|
||
DypScroll(ww, dlOld, 0, ypTop);
|
||
|
||
if (vfScrollInval)
|
||
{
|
||
/* There was a popup; invalid region might have changed */
|
||
/* fLastNotShown test is for interrupting picture display */
|
||
/* before we've really displayed it */
|
||
|
||
(**hdndl) [dlT].fValid = fFalse;
|
||
Restart1:
|
||
if (fLastNotShown)
|
||
{
|
||
pwwd->ypFirstInval = pwwd->ypMin;
|
||
}
|
||
|
||
ypFirstInval = pwwd->ypFirstInval;
|
||
ypTop = pwwd->ypMin;
|
||
goto RestartUpdate;
|
||
}
|
||
}
|
||
|
||
/* true in 3rd param means put off picture redisplay till later */
|
||
/* condition: graphics & not last in picture & not last in y space and
|
||
not in front of a invalid or valid transition in the picture */
|
||
DisplayFli(ww, dlNew, fLastNotShown =
|
||
(vfli.fGraphics && vfli.ichCpMac!=0 && ypTop < pwwd->ypMac));
|
||
NextDlNew:;
|
||
}
|
||
Break1:
|
||
pwwd->dlMac = dlNew;
|
||
|
||
#ifdef CASHMERE
|
||
/* condition is here to avoid swapping */
|
||
if (pwwd->fSplit && rgwwd[pwwd->ww].fFtn)
|
||
CalcFtnLimits(pwwd);
|
||
#endif /* CASHMERE */
|
||
|
||
SetCurWwVScrollPos(); /* Set Scroll bar position */
|
||
vfTextBltValid = false;
|
||
|
||
/* reset invalid indications */
|
||
pwwd->fDirty = false;
|
||
pwwd->ypFirstInval = ypMaxAll;
|
||
pwwd->ypLastInval = 0; /* so that max in InvalBand will work */
|
||
Scribble(5, ' ');
|
||
goto Validate;
|
||
|
||
/* Before returning from an interrupt, invalidate lines that were overwritten
|
||
within the present update. */
|
||
RetInval:
|
||
Scribble(5, ' ');
|
||
for (; dlOld < dlMac; dlOld++)
|
||
{
|
||
pedl = &(**hdndl)[dlOld];
|
||
if ((pedl->yp - pedl->dyp) < ypTop)
|
||
pedl->fValid = fFalse;
|
||
else
|
||
break;
|
||
}
|
||
Validate: ;
|
||
|
||
#ifdef ENABLE /* We will let UpdateInvalid handle this in case
|
||
further invalidation occurred during the update */
|
||
|
||
{ /* Tell Windows that the part we updated is valid */
|
||
RECT rc;
|
||
|
||
rc.left = 0;
|
||
rc.top = pwwd->ypMin;
|
||
rc.right = pwwd->xpMac;
|
||
rc.bottom = imin( pwwd->ypMac, ypTop );
|
||
ValidateRect( pwwd->wwptr, (LPRECT)&rc );
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
|
||
/* D Y P S C R O L L */
|
||
DypScroll(ww, dlFirst, ddl, ypTo)
|
||
int ww, dlFirst, ddl, ypTo;
|
||
{
|
||
/* Scroll dl's in a window, from dlFirst to end, down ddl lines (or up -ddl).
|
||
Bitmap is moved from top of dlFirst to ypTo. The yp's of the dl's are updated.
|
||
Returns the amount scrolled. (positive means down). */
|
||
|
||
register struct WWD *pwwd = &rgwwd[ww];
|
||
int dlMac;
|
||
int dlT;
|
||
int ypFrom;
|
||
int dypChange;
|
||
int cdlBelow;
|
||
struct EDL *pedl;
|
||
struct EDL *pedlT;
|
||
|
||
/* Do not call procedures while dndl is loaded up to avoid heap movement */
|
||
struct EDL *dndl = &(**(pwwd->hdndl))[0];
|
||
|
||
Assert( ww >= 0 && ww < wwMax );
|
||
|
||
vfScrollInval = fFalse;
|
||
|
||
/* Number of dl's below (and including) the first one to be scrolled */
|
||
cdlBelow = pwwd->dlMac - dlFirst;
|
||
pwwd->dlMac = min(pwwd->dlMac + ddl, pwwd->dlMax);
|
||
cdlBelow = max(0, min(cdlBelow, pwwd->dlMac - ddl - dlFirst));
|
||
|
||
pedlT = &dndl[dlFirst];
|
||
ypFrom = pedlT->yp - pedlT->dyp;
|
||
|
||
/* Length of area to be moved */
|
||
dypChange = ypTo - ypFrom;
|
||
|
||
if (cdlBelow > 0)
|
||
{
|
||
int dlTo = dlFirst + ddl;
|
||
int ypMac = pwwd->ypMac;
|
||
|
||
pedlT = &dndl[dlTo];
|
||
if (ddl != 0)
|
||
{
|
||
blt(&dndl[dlFirst], pedlT, cwEDL * cdlBelow);
|
||
}
|
||
|
||
for (dlT = dlTo; dlT < pwwd->dlMac; ++dlT, ++pedlT)
|
||
{
|
||
if (dypChange < 0 && pedlT->yp > ypMac)
|
||
{
|
||
/* Invalidate dl's that are pulled in from the ozone below ypMac
|
||
*/
|
||
pedlT->fValid = fFalse;
|
||
}
|
||
else
|
||
{
|
||
pedlT->yp += dypChange;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (dypChange != 0)
|
||
{
|
||
RECT rc;
|
||
|
||
SetRect( (LPRECT)&rc, 0, min(ypFrom, ypTo),
|
||
pwwd->xpMac, pwwd->ypMac );
|
||
Assert( ww == wwCur ); /* A MEMO-only assumption */
|
||
ScrollCurWw( &rc, 0, dypChange );
|
||
}
|
||
|
||
return dypChange;
|
||
}
|
||
|
||
|
||
|
||
|
||
FImportantMsgPresent()
|
||
{
|
||
/* If the next message is important enough to interrupt a screen update, we
|
||
return TRUE; if it can wait, we return FALSE */
|
||
|
||
BOOL fToggledKey;
|
||
extern MSG vmsgLast;
|
||
|
||
#ifdef DEBUG
|
||
unsigned wHeapVal = *(pLocalHeap + 1);
|
||
|
||
Assert( wHeapVal == 0 ); /* Heap should not be frozen */
|
||
#endif
|
||
|
||
#ifdef DBCS
|
||
if( donteat )
|
||
return TRUE;
|
||
#endif
|
||
|
||
while (PeekMessage((LPMSG) &vmsgLast, NULL, NULL, NULL, PM_NOREMOVE))
|
||
{
|
||
|
||
if (((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL)))
|
||
{
|
||
if (vmsgLast.wParam == VK_CONTROL)
|
||
{
|
||
GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL);
|
||
SetShiftFlags();
|
||
}
|
||
return TRUE;
|
||
}
|
||
/* Filter uninteresting or easily handled events */
|
||
else if (fToggledKey = FCheckToggleKeyMessage(&vmsgLast) ||
|
||
(vmsgLast.message == WM_KEYUP && vmsgLast.hwnd == wwdCurrentDoc.wwptr))
|
||
{
|
||
|
||
/* This is so the Windows keyboard interface mechanism will see toggle
|
||
key and key-up transitions */
|
||
GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL);
|
||
#ifdef WIN30
|
||
/* PeekMessage has been changed in Win 3.0 so that GetKeyState()
|
||
called from FCheckToggleKeyMessage() is really only valid if
|
||
you've done a PeekMessage(...,PM_REMOVE) or GetMessage() first.
|
||
That is, while the FCheckToggleKeyMessage() call might succeed
|
||
above, it will NOT have set the vfShiftKey/vfCommandKey flags
|
||
correctly -- so we do it here ..pault */
|
||
if (fToggledKey)
|
||
FCheckToggleKeyMessage(&vmsgLast);
|
||
#endif
|
||
if (vmsgLast.hwnd != wwdCurrentDoc.wwptr)
|
||
{
|
||
/* Just in case a modeless dialog's window proc cares */
|
||
TranslateMessage((LPMSG)&vmsgLast);
|
||
DispatchMessage((LPMSG)&vmsgLast);
|
||
}
|
||
#ifdef DBCS
|
||
#ifdef KOREA /* 90.12.23 by sangl */ // jinwoo: 92, 9, 28
|
||
if (vmsgLast.message == WM_CHAR || vmsgLast.message == WM_KEYDOWN
|
||
|| vmsgLast.message == WM_INTERIM) {
|
||
#else /* KOREA */
|
||
if (vmsgLast.message == WM_CHAR || vmsgLast.message == WM_KEYDOWN ) {
|
||
#endif //KOREA 920525 KDLEE; jinwoo: 92, 9, 28
|
||
donteat = TRUE;
|
||
return( TRUE );
|
||
} /* else Ok, you are KEYUP message. do normal */
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
switch (vmsgLast.message)
|
||
{
|
||
case WM_MOUSEMOVE:
|
||
/* Process mouse move messages immediately; they are not really
|
||
important. NOTE: This assumes that we have not captured all mouse
|
||
events; in which case, they are important. */
|
||
DispatchMessage((LPMSG)&vmsgLast);
|
||
|
||
case WM_TIMER:
|
||
case WM_SYSTIMER:
|
||
/* Remove timer and mouse move messages from the queue. */
|
||
GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL);
|
||
break;
|
||
|
||
default:
|
||
Assert( *(pLocalHeap+1) == 0 ); /* Heap should still not be frozen */
|
||
return (TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
Assert( *(pLocalHeap + 1) == 0 ); /* Heap should still not be frozen */
|
||
return (FALSE);
|
||
}
|
||
|
||
|
||
/* C P B E G I N L I N E */
|
||
typeCP CpBeginLine(pdl, cp)
|
||
int *pdl;
|
||
typeCP cp;
|
||
{ /* return the cp and dl containing cp */
|
||
int dlMin, dlLim;
|
||
typeCP cpGuess;
|
||
struct EDL *dndl;
|
||
|
||
do
|
||
{
|
||
UpdateWw(wwCur, false);
|
||
PutCpInWwVert(cp); /* Ensure cp on screen */
|
||
} while (pwwdCur->fDirty && !vfOutOfMemory);
|
||
|
||
dndl = &(**(pwwdCur->hdndl))[0];
|
||
dlMin = 0;
|
||
dlLim = pwwdCur->dlMac;
|
||
while (dlMin + 1 < dlLim)
|
||
{ /* Binary search the ww */
|
||
int dlGuess = (dlMin + dlLim) >> 1;
|
||
struct EDL *pedl = &dndl[dlGuess];
|
||
if ((cpGuess = pedl->cpMin) <= cp && (cpGuess != cp || pedl->ichCpMin == 0))
|
||
{ /* guess is low or right */
|
||
dlMin = dlGuess;
|
||
if (cp == cpGuess && pedl->cpMin + pedl->dcpMac != cp)
|
||
break; /* Got it right */
|
||
}
|
||
else /* Guess is high */
|
||
dlLim = dlGuess;
|
||
}
|
||
*pdl = dlMin;
|
||
return dndl[dlMin].cpMin;
|
||
}
|
||
|
||
|
||
|
||
|
||
/* T O G G L E S E L */
|
||
ToggleSel(cpFirst, cpLim, fOn)
|
||
typeCP cpFirst, cpLim; /* selection bounds */
|
||
int fOn;
|
||
{ /* Flip selection highlighting on and off */
|
||
extern int vfPMS;
|
||
struct EDL *pedl;
|
||
int dlT;
|
||
int xpMin;
|
||
int dxpRoom;
|
||
int xpFirst;
|
||
int xpLim;
|
||
int fInsertPoint = (cpFirst == cpLim);
|
||
|
||
if (vfSelHidden || cpFirst > cpLim || cpLim < /*cp0*/ cpMinCur || vfDead)
|
||
return;
|
||
|
||
if ( vfPictSel && vfPMS &&
|
||
(CachePara( docCur, cpFirst ), vpapAbs.fGraphics) &&
|
||
(vcpLimParaCache == cpLim) )
|
||
{ /* Don't show inversion if we're moving or sizing a picture */
|
||
return;
|
||
}
|
||
|
||
dxpRoom = pwwdCur->xpMac - xpSelBar;
|
||
xpMin = pwwdCur->xpMin;
|
||
|
||
for (dlT = 0; dlT < pwwdCur->dlMac; dlT++)
|
||
{
|
||
typeCP cpMin, cpMac; /* line bounds */
|
||
pedl = &(**(pwwdCur->hdndl))[dlT];
|
||
if (!pedl->fValid)
|
||
continue;
|
||
cpMin = pedl->cpMin;
|
||
if (cpMin > cpLim || cpMin > cpMacCur || (cpMin == cpLim && cpLim != cpFirst))
|
||
break;
|
||
cpMac = cpMin + pedl->dcpMac;
|
||
if (cpFirst <= cpMin && cpLim >= cpMac)
|
||
{
|
||
/* entire line is highlighted */
|
||
xpFirst = pedl->xpLeft;
|
||
if (pedl->fGraphics && cpLim == cpMac && cpMin == cpMac)
|
||
/* Special kludge for graphics paras */
|
||
xpLim = xpFirst;
|
||
else
|
||
xpLim = pedl->xpMac;
|
||
}
|
||
else if (fInsertPoint && cpFirst == cpMac && vfInsEnd)
|
||
{ /* Special kludge for an insert point at the end of a line */
|
||
xpLim = xpFirst = pedl->xpMac;
|
||
}
|
||
else if (cpFirst < cpMac)
|
||
{
|
||
/* Bite the bullet */
|
||
int dxp;
|
||
typeCP cpBegin = CpMax(cpMin, cpFirst);
|
||
typeCP cpEnd = CpMin(cpMac, cpLim);
|
||
|
||
FormatLine(docCur, cpMin, pedl->ichCpMin, cpMacCur, flmSandMode);
|
||
dxp = DxpDiff((int) (cpBegin - cpMin),
|
||
(int) (cpEnd - cpBegin), &xpFirst);
|
||
xpLim = xpFirst + dxp;
|
||
/* reload pedl because procedures were called */
|
||
pedl = &(**(pwwdCur->hdndl))[dlT];
|
||
}
|
||
else
|
||
continue;
|
||
/* now we have: pedl valid, xpFirst, xpLast describe highlight */
|
||
/* xpFirst = max(xpFirst, xpMin); */
|
||
xpLim = min(xpLim, xpMin + pedl->xpMac);
|
||
if (xpLim > xpFirst)
|
||
{
|
||
if (xpLim > xpMin)
|
||
{
|
||
RECT rc;
|
||
rc.top = pedl->yp - pedl->dyp;
|
||
rc.left = xpSelBar + max(xpFirst - xpMin, 0);
|
||
rc.bottom = pedl->yp;
|
||
rc.right = xpSelBar + xpLim - xpMin;
|
||
InvertRect( wwdCurrentDoc.hDC, (LPRECT)&rc);
|
||
}
|
||
}
|
||
/* ToggleSel modified 7/28/85 -- added explicit check for fInsertPoint, since
|
||
the xpLim == xpFirst test sometimes succeeded bogusly when a selection
|
||
was extended backwards. BL */
|
||
else if (fInsertPoint && (xpLim == xpFirst)) /* Insertion point */
|
||
{
|
||
/* vfli should usually be cached already, so will be fast. */
|
||
int yp = pedl->yp;
|
||
FormatLine(docCur, cpMin, pedl->ichCpMin, cpMacCur, flmSandMode);
|
||
if (fOn ^ vfInsertOn)
|
||
{
|
||
if (!vfInsertOn)
|
||
{
|
||
vxpCursLine = xpSelBar + xpFirst - xpMin;
|
||
vypCursLine = yp - vfli.dypAfter;
|
||
vdypCursLine = min(vfli.dypFont, vfli.dypLine - vfli.dypAfter);
|
||
|
||
/* Start blinking in a while */
|
||
vfSkipNextBlink = TRUE;
|
||
}
|
||
DrawInsertLine();
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/* T R A S H W W */
|
||
TrashWw(ww)
|
||
{ /* Invalidate all dl's in ww */
|
||
Assert( ww >= 0 && ww < wwMax );
|
||
InvalBand(&rgwwd[ww], 0, ypMaxAll);
|
||
}
|
||
|
||
|
||
|
||
|
||
/* I N V A L B A N D */
|
||
/* invalidate the band ypFirst, ypLast inclusive */
|
||
InvalBand(pwwd, ypFirst, ypLast)
|
||
struct WWD *pwwd; int ypFirst, ypLast;
|
||
{
|
||
/* this covers some peculiar rects received from update event after a
|
||
window resize by 1 pixel. CS */
|
||
if (ypLast < 0 || ypFirst == ypLast) return;
|
||
|
||
pwwd->fDirty = true;
|
||
pwwd->ypFirstInval = min(pwwd->ypFirstInval, ypFirst);
|
||
pwwd->ypLastInval = max(ypLast, pwwd->ypLastInval);
|
||
}
|
||
|
||
|
||
|
||
|
||
/* T R A S H A L L W W S */
|
||
TrashAllWws()
|
||
{ /* trash them all */
|
||
int ww;
|
||
|
||
#ifdef CASHMERE
|
||
for (ww = 0; ww < wwMac; ++ww)
|
||
TrashWw(ww);
|
||
#else
|
||
TrashWw( wwDocument );
|
||
#endif
|
||
vfli.doc = docNil; /* Mark vfli invalid */
|
||
}
|
||
|
||
|
||
/* T U R N O F F S E L */
|
||
TurnOffSel()
|
||
{ /* Remove sel highlighting from screen */
|
||
/* HideSel has no effect */
|
||
if (!vfSelHidden)
|
||
{
|
||
ToggleSel(selCur.cpFirst, selCur.cpLim, false);
|
||
vfSelHidden = true;
|
||
}
|
||
}
|
||
|
||
|
||
/* D R A W I N S E R T L I N E */
|
||
DrawInsertLine()
|
||
{ /* Draw (in Xor mode) a vertical bar at screen position v*CursLine */
|
||
/* Toggles both the display and the vfInsertOn flag */
|
||
/* Adjustments in cursor draw must be reflected in DisplayFli, above */
|
||
|
||
/* Last-minute correction for a bug: assure that the insert line
|
||
does not extend above ypMin */
|
||
if (!vfInsertOn && vdypCursLine > vypCursLine - wwdCurrentDoc.ypMin)
|
||
vdypCursLine = vypCursLine - wwdCurrentDoc.ypMin;
|
||
|
||
/* Tell GDI to invert the caret line */
|
||
PatBlt( wwdCurrentDoc.hDC, vxpCursLine, vypCursLine - vdypCursLine,
|
||
2, vdypCursLine , DSTINVERT );
|
||
vfInsertOn = 1 - vfInsertOn;
|
||
}
|
||
|
||
|
||
|
||
|
||
/* C L E A R I N S E R T L I N E */
|
||
ClearInsertLine()
|
||
{
|
||
if ( vfInsertOn) DrawInsertLine();
|
||
}
|
||
|