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