799 lines
24 KiB
C
799 lines
24 KiB
C
|
/************************************************************/
|
|||
|
|
|||
|
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
|||
|
/************************************************************/
|
|||
|
|
|||
|
/* picture.c -- MW format and display routines for pictures */
|
|||
|
|
|||
|
//#define NOGDICAPMASKS
|
|||
|
#define NOWINMESSAGES
|
|||
|
#define NOVIRTUALKEYCODES
|
|||
|
#define NOWINSTYLES
|
|||
|
#define NOCLIPBOARD
|
|||
|
#define NOCTLMGR
|
|||
|
#define NOSYSMETRICS
|
|||
|
#define NOMENUS
|
|||
|
#define NOICON
|
|||
|
#define NOKEYSTATE
|
|||
|
//#define NOATOM
|
|||
|
#define NOCREATESTRUCT
|
|||
|
#define NODRAWTEXT
|
|||
|
#define NOFONT
|
|||
|
#define NOMB
|
|||
|
#define NOMENUS
|
|||
|
#define NOOPENFILE
|
|||
|
#define NOREGION
|
|||
|
#define NOSCROLL
|
|||
|
#define NOSOUND
|
|||
|
#define NOWH
|
|||
|
#define NOWINOFFSETS
|
|||
|
#define NOWNDCLASS
|
|||
|
#define NOCOMM
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
#include "mw.h"
|
|||
|
#define NOKCCODES
|
|||
|
#include "ch.h"
|
|||
|
#include "docdefs.h"
|
|||
|
#include "fmtdefs.h"
|
|||
|
#include "dispdefs.h"
|
|||
|
#include "cmddefs.h"
|
|||
|
#include "propdefs.h"
|
|||
|
#include "stcdefs.h"
|
|||
|
#include "wwdefs.h"
|
|||
|
#include "filedefs.h"
|
|||
|
#include "editdefs.h"
|
|||
|
/* #include "str.h" */
|
|||
|
#include "prmdefs.h"
|
|||
|
/* #include "fkpdefs.h" */
|
|||
|
/* #include "macro.h" */
|
|||
|
#include "winddefs.h"
|
|||
|
#if defined(OLE)
|
|||
|
#include "obj.h"
|
|||
|
#endif
|
|||
|
|
|||
|
extern typeCP cpMacCur;
|
|||
|
extern int docCur;
|
|||
|
extern int vfSelHidden;
|
|||
|
extern struct WWD rgwwd[];
|
|||
|
extern int wwCur;
|
|||
|
extern int wwMac;
|
|||
|
extern struct FLI vfli;
|
|||
|
extern struct SEL selCur;
|
|||
|
extern struct WWD *pwwdCur;
|
|||
|
extern struct PAP vpapCache;
|
|||
|
extern typeCP vcpFirstParaCache;
|
|||
|
extern typeCP vcpLimParaCache;
|
|||
|
extern int vfPictSel;
|
|||
|
extern struct PAP vpapAbs;
|
|||
|
extern struct SEP vsepAbs;
|
|||
|
extern struct SEP vsepPage;
|
|||
|
extern struct DOD (**hpdocdod)[];
|
|||
|
extern unsigned cwHeapFree;
|
|||
|
extern int vfInsertOn;
|
|||
|
extern int vfPMS;
|
|||
|
extern int dxpLogInch;
|
|||
|
extern int dypLogInch;
|
|||
|
extern int dxaPrPage;
|
|||
|
extern int dyaPrPage;
|
|||
|
extern int dxpPrPage;
|
|||
|
extern int dypPrPage;
|
|||
|
extern HBRUSH hbrBkgrnd;
|
|||
|
extern long ropErase;
|
|||
|
extern int vdocBitmapCache;
|
|||
|
extern typeCP vcpBitmapCache;
|
|||
|
extern HBITMAP vhbmBitmapCache;
|
|||
|
extern BOOL vfBMBitmapCache;
|
|||
|
extern HCURSOR vhcIBeam;
|
|||
|
extern BOOL vfMonochrome;
|
|||
|
|
|||
|
|
|||
|
/* Used in this module only */
|
|||
|
#ifdef DEBUG
|
|||
|
#define STATIC static
|
|||
|
#else
|
|||
|
#define STATIC
|
|||
|
#endif
|
|||
|
|
|||
|
STATIC RECT rcPictInvalid; /* Rectangle (in window coords) that needs refresh */
|
|||
|
int vfWholePictInvalid = TRUE;
|
|||
|
|
|||
|
|
|||
|
FreeBitmapCache()
|
|||
|
{
|
|||
|
vdocBitmapCache = docNil;
|
|||
|
if (vhbmBitmapCache != NULL)
|
|||
|
{
|
|||
|
DeleteObject( vhbmBitmapCache );
|
|||
|
vhbmBitmapCache = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
MarkInvalidDlPict( ww, dlPict )
|
|||
|
int ww;
|
|||
|
int dlPict;
|
|||
|
{ /* Mark the passed dl (presumed to be part of a picture) as requiring
|
|||
|
eventual update, when DisplayGraphics is called */
|
|||
|
|
|||
|
register struct WWD *pwwd = &rgwwd [ww];
|
|||
|
struct EDL (**hdndl)[] = pwwd->hdndl;
|
|||
|
struct EDL *pedl = &(**hdndl)[ dlPict ];
|
|||
|
RECT rcDl;
|
|||
|
|
|||
|
SetRect( (LPRECT) &rcDl, 0, pedl->yp - pedl->dyp,
|
|||
|
pwwd->xpMac, pedl->yp );
|
|||
|
|
|||
|
if (vfWholePictInvalid)
|
|||
|
{
|
|||
|
CopyRect( (LPRECT) &rcPictInvalid, (LPRECT) &rcDl );
|
|||
|
vfWholePictInvalid = FALSE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
RECT rcT;
|
|||
|
|
|||
|
rcT = rcPictInvalid; /* Necessary? i.e. can UnionRect handle
|
|||
|
source == destination */
|
|||
|
UnionRect( (LPRECT) &rcPictInvalid, (LPRECT) &rcT, (LPRECT) &rcDl );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DisplayGraphics( ww, dl, fDontDisplay )
|
|||
|
int ww;
|
|||
|
int dl;
|
|||
|
int fDontDisplay;
|
|||
|
{ /* Display a line of graphics info */
|
|||
|
struct WWD *pwwd = &rgwwd[ww];
|
|||
|
struct EDL *pedl;
|
|||
|
typeCP cpPictStart;
|
|||
|
typeCP cp;
|
|||
|
typeCP cpMac = (**hpdocdod)[vfli.doc].cpMac;
|
|||
|
struct PICINFOX picInfo;
|
|||
|
RECT rcEnclose;
|
|||
|
RECT rcPict;
|
|||
|
HANDLE hBits=NULL;
|
|||
|
HDC hMDC=NULL;
|
|||
|
HDC hMDCCache=NULL;
|
|||
|
HANDLE hbm=NULL;
|
|||
|
HDC hDC=pwwd->hDC;
|
|||
|
int cchRun;
|
|||
|
unsigned long cbPict=0;
|
|||
|
int dxpOrig; /* Size of picture in the original */
|
|||
|
int dypOrig;
|
|||
|
int dxpDisplay; /* Size of picture as we want to show it */
|
|||
|
int dypDisplay;
|
|||
|
int fBitmap;
|
|||
|
int ilevel=0;
|
|||
|
|
|||
|
/* THIS ROUTINE COULD USE SOME GDI-CALL ERROR CHECKING! ..pault */
|
|||
|
|
|||
|
int fDrew=false;
|
|||
|
|
|||
|
/* In the case of monochrome devices, this raster op will map white in
|
|||
|
the bitmap to the background color and black to the foreground color. */
|
|||
|
#define ropMonoBm 0x00990066
|
|||
|
|
|||
|
Assert( dl >= 0 && dl < pwwd->dlMax );
|
|||
|
|
|||
|
MarkInvalidDlPict( ww, dl );
|
|||
|
|
|||
|
if (fDontDisplay)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Diag(CommSz("DisplayGraphics: \n\r"));
|
|||
|
|
|||
|
FreezeHp();
|
|||
|
pedl = &(**(pwwd->hdndl))[dl];
|
|||
|
cpPictStart=pedl->cpMin;
|
|||
|
|
|||
|
GetPicInfo( cpPictStart, cpMac, vfli.doc, &picInfo );
|
|||
|
|
|||
|
/* Compute desired display size of picture (in device pixels) */
|
|||
|
|
|||
|
ComputePictRect( &rcPict, &picInfo, pedl, ww );
|
|||
|
dxpDisplay = rcPict.right - rcPict.left;
|
|||
|
dypDisplay = rcPict.bottom - rcPict.top;
|
|||
|
|
|||
|
/* Compute original size of picture (in device pixels) */
|
|||
|
/* MM_ANISOTROPIC and MM_ISOTROPIC pictures have no original size */
|
|||
|
|
|||
|
switch ( picInfo.mfp.mm ) {
|
|||
|
case MM_ISOTROPIC:
|
|||
|
case MM_ANISOTROPIC:
|
|||
|
break;
|
|||
|
case MM_BITMAP:
|
|||
|
dxpOrig = picInfo.bm.bmWidth;
|
|||
|
dypOrig = picInfo.bm.bmHeight;
|
|||
|
break;
|
|||
|
#if defined(OLE)
|
|||
|
case MM_OLE:
|
|||
|
{
|
|||
|
extern BOOL vfObjDisplaying;
|
|||
|
|
|||
|
if (lpOBJ_QUERY_INFO(&picInfo) == NULL)
|
|||
|
goto DontDraw;
|
|||
|
|
|||
|
/* just to be safe */
|
|||
|
if (!CheckPointer(lpOBJ_QUERY_INFO(&picInfo),1))
|
|||
|
goto DontDraw;
|
|||
|
|
|||
|
if (lpOBJ_QUERY_OBJECT(&picInfo) == NULL)
|
|||
|
{
|
|||
|
typeCP cpRet;
|
|||
|
|
|||
|
/* this can require memory, so unlock heap */
|
|||
|
MeltHp();
|
|||
|
vfObjDisplaying = TRUE;
|
|||
|
|
|||
|
cpRet = ObjLoadObjectInDoc(&picInfo,vfli.doc,cpPictStart);
|
|||
|
|
|||
|
vfObjDisplaying = FALSE;
|
|||
|
FreezeHp();
|
|||
|
pedl = &(**(pwwd->hdndl))[dl];
|
|||
|
|
|||
|
if (cpRet == cp0)
|
|||
|
goto DontDraw;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
#endif
|
|||
|
default:
|
|||
|
dxpOrig = PxlConvert( picInfo.mfp.mm, picInfo.mfp.xExt,
|
|||
|
GetDeviceCaps( hDC, HORZRES ),
|
|||
|
GetDeviceCaps( hDC, HORZSIZE ) );
|
|||
|
dypOrig = PxlConvert( picInfo.mfp.mm, picInfo.mfp.yExt,
|
|||
|
GetDeviceCaps( hDC, VERTRES ),
|
|||
|
GetDeviceCaps( hDC, VERTSIZE ) );
|
|||
|
if (! (dxpOrig && dypOrig) )
|
|||
|
{
|
|||
|
goto DontDraw;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
/* Save DC as a guard against DC attribute alteration by a metafile */
|
|||
|
#ifdef WINDOWS_BUG_FIXED /* Currently 0 is a valid level for Own DC's */
|
|||
|
if ((ilevel=SaveDC( hDC )) == 0)
|
|||
|
goto DontDraw;
|
|||
|
#endif
|
|||
|
ilevel = SaveDC( hDC );
|
|||
|
SetStretchBltMode( hDC, BLACKONWHITE );
|
|||
|
|
|||
|
/* Clip out top bar, selection bar */
|
|||
|
|
|||
|
IntersectClipRect( hDC, ((wwCur == wwClipboard) ? 0 : xpSelBar),
|
|||
|
pwwdCur->ypMin, pwwdCur->xpMac, pwwdCur->ypMac );
|
|||
|
|
|||
|
if (!vfWholePictInvalid)
|
|||
|
/* Repainting less than the whole picture; clip out
|
|||
|
what we're not drawing */
|
|||
|
IntersectClipRect( hDC, rcPictInvalid.left, rcPictInvalid.top,
|
|||
|
rcPictInvalid.right, rcPictInvalid.bottom );
|
|||
|
|
|||
|
/* Build rcEnclose, a rect enclosing the picture that
|
|||
|
includes the "space before" and "space after" fields */
|
|||
|
|
|||
|
rcEnclose.left = xpSelBar;
|
|||
|
if ((rcEnclose.top = rcPict.top -
|
|||
|
DypFromDya( vpapAbs.dyaBefore, FALSE )) < pwwd->ypMin)
|
|||
|
rcEnclose.top = pwwd->ypMin;
|
|||
|
rcEnclose.right = pwwd->xpMac;
|
|||
|
if ((rcEnclose.bottom = rcPict.bottom +
|
|||
|
DypFromDya( vpapAbs.dyaAfter, FALSE )) > pwwd->ypMac)
|
|||
|
rcEnclose.bottom = pwwd->ypMac;
|
|||
|
|
|||
|
/* White out enclosing rect */
|
|||
|
|
|||
|
PatBlt( hDC, rcEnclose.left, rcEnclose.top,
|
|||
|
rcEnclose.right - rcEnclose.left,
|
|||
|
rcEnclose.bottom - rcEnclose.top, ropErase );
|
|||
|
|
|||
|
/* If we have it cached, do display the easy way */
|
|||
|
|
|||
|
if (pwwd->doc == vdocBitmapCache && cpPictStart == vcpBitmapCache)
|
|||
|
{
|
|||
|
Assert( pwwd->doc != docNil && vhbmBitmapCache != NULL);
|
|||
|
|
|||
|
if ( ((hMDC = CreateCompatibleDC( hDC )) != NULL) &&
|
|||
|
SelectObject( hMDC, vhbmBitmapCache ))
|
|||
|
{
|
|||
|
Diag(CommSz("DisplayGraphics: BitBlt\n\r"));
|
|||
|
BitBlt( hDC, rcPict.left, rcPict.top, dxpDisplay, dypDisplay,
|
|||
|
hMDC, 0, 0, vfMonochrome && vfBMBitmapCache ?
|
|||
|
ropMonoBm : SRCCOPY );
|
|||
|
fDrew = TRUE;
|
|||
|
goto DontDraw;
|
|||
|
}
|
|||
|
else
|
|||
|
{ /* Using the cache failed -- empty it
|
|||
|
(SelectObject will fail if bitmap was discarded) */
|
|||
|
FreeBitmapCache();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
StartLongOp(); /* Put up an hourglass */
|
|||
|
|
|||
|
/* Build up all bytes associated with the picture (except the header)
|
|||
|
into the global Windows handle hBits */
|
|||
|
|
|||
|
if ( picInfo.mfp.mm != MM_OLE)
|
|||
|
{
|
|||
|
if ((hBits=GlobalAlloc( GMEM_MOVEABLE, (long)picInfo.cbSize )) == NULL)
|
|||
|
{ /* Not enough global heap space to load bitmap/metafile */
|
|||
|
goto DontDraw;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DCLIP
|
|||
|
{
|
|||
|
char rgch[200];
|
|||
|
wsprintf(rgch,"DisplayGraphics: picinfo.cbSize %lu \n\r", picInfo.cbSize);
|
|||
|
CommSz(rgch);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
for ( cbPict = 0, cp = cpPictStart + picInfo.cbHeader;
|
|||
|
cbPict < picInfo.cbSize;
|
|||
|
cbPict += cchRun, cp += (typeCP) cchRun )
|
|||
|
{
|
|||
|
CHAR rgch[ 256 ];
|
|||
|
#if WINVER >= 0x300
|
|||
|
HPCH lpch;
|
|||
|
#else
|
|||
|
LPCH lpch;
|
|||
|
#endif
|
|||
|
|
|||
|
#define ulmin(a,b) ((unsigned long)(a) < (unsigned long)(b) ? \
|
|||
|
(unsigned long)(a) : (unsigned long)(b))
|
|||
|
|
|||
|
FetchRgch( &cchRun, rgch, vfli.doc, cp, cpMac,
|
|||
|
(int) ulmin( picInfo.cbSize - cbPict, 256 ) );
|
|||
|
if ((lpch=GlobalLock( hBits )) != NULL)
|
|||
|
{
|
|||
|
#ifdef DCLIP
|
|||
|
{
|
|||
|
char rgch[200];
|
|||
|
wsprintf(rgch," copying %d bytes from %lX to %lX \n\r",cchRun,(LPSTR)rgch,lpch+cbPict);
|
|||
|
CommSz(rgch);
|
|||
|
}
|
|||
|
|
|||
|
{
|
|||
|
char rgchT[200];
|
|||
|
int i;
|
|||
|
for (i = 0; i< min(20,cchRun); i++,i++)
|
|||
|
{
|
|||
|
wsprintf(rgchT,"%X ",* (int *) &(rgch[i]));
|
|||
|
CommSz(rgchT);
|
|||
|
}
|
|||
|
CommSz("\n\r");
|
|||
|
}
|
|||
|
#endif
|
|||
|
#if WINVER >= 0x300
|
|||
|
bltbh( (LPSTR)rgch, lpch+cbPict, cchRun );
|
|||
|
#else
|
|||
|
bltbx( (LPSTR)rgch, lpch+cbPict, cchRun );
|
|||
|
#endif
|
|||
|
GlobalUnlock( hBits );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
goto DontDraw;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* Display the picture */
|
|||
|
|
|||
|
MeltHp();
|
|||
|
|
|||
|
#if defined(OLE)
|
|||
|
/* CASE 0: OLE */
|
|||
|
if (picInfo.mfp.mm == MM_OLE)
|
|||
|
{
|
|||
|
Diag(CommSz("Case 0:\n\r"));
|
|||
|
if (ObjDisplayObjectInDoc(&picInfo, vfli.doc, cpPictStart,
|
|||
|
hDC, &rcPict) == FALSE)
|
|||
|
goto DontDraw;
|
|||
|
fDrew = true;
|
|||
|
}
|
|||
|
else
|
|||
|
#endif
|
|||
|
/* CASE 1: Bitmap */
|
|||
|
if (fBitmap = (picInfo.mfp.mm == MM_BITMAP))
|
|||
|
{
|
|||
|
Diag(CommSz("Case 1: \n\r"));
|
|||
|
if ( ((hMDC = CreateCompatibleDC( hDC )) != NULL) &&
|
|||
|
((picInfo.bm.bmBits = GlobalLock( hBits )) != NULL) &&
|
|||
|
((hbm=CreateBitmapIndirect((LPBITMAP)&picInfo.bm))!=NULL))
|
|||
|
{
|
|||
|
picInfo.bm.bmBits = NULL;
|
|||
|
GlobalUnlock( hBits );
|
|||
|
GlobalFree( hBits ); /* Free handle to bits to allow max room */
|
|||
|
hBits = NULL;
|
|||
|
SelectObject( hMDC, hbm );
|
|||
|
|
|||
|
goto CacheIt;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Case 2: non-scalable metafile pictures which we are, for
|
|||
|
user interface consistency, scaling by force using StretchBlt */
|
|||
|
|
|||
|
else if ( ((dxpDisplay != dxpOrig) || (dypDisplay != dypOrig)) &&
|
|||
|
(picInfo.mfp.mm != MM_ISOTROPIC) &&
|
|||
|
(picInfo.mfp.mm != MM_ANISOTROPIC) )
|
|||
|
{
|
|||
|
|
|||
|
Diag(CommSz("Case 2: \n\r"));
|
|||
|
if (((hMDC=CreateCompatibleDC( hDC)) != NULL) &&
|
|||
|
((hbm=CreateCompatibleBitmap( hDC, dxpOrig, dypOrig ))!=NULL) &&
|
|||
|
SelectObject( hMDC, hbm ) && SelectObject( hMDC, hbrBkgrnd ))
|
|||
|
{
|
|||
|
extern int vfOutOfMemory;
|
|||
|
|
|||
|
PatBlt( hMDC, 0, 0, dxpOrig, dypOrig, ropErase );
|
|||
|
SetMapMode( hMDC, picInfo.mfp.mm );
|
|||
|
/* To cover StretchBlt calls within the metafile */
|
|||
|
SetStretchBltMode( hMDC, BLACKONWHITE );
|
|||
|
PlayMetaFile( hMDC, hBits );
|
|||
|
/* Because we pass pixels to StretchBlt */
|
|||
|
SetMapMode( hMDC, MM_TEXT );
|
|||
|
|
|||
|
CacheIt: Assert( hbm != NULL && hMDC != NULL );
|
|||
|
|
|||
|
if (vfOutOfMemory)
|
|||
|
goto NoCache;
|
|||
|
#ifndef NOCACHE
|
|||
|
FreeBitmapCache();
|
|||
|
/* Among other things, this code caches the current picture.
|
|||
|
Notice that there are two assumptions: (1) all bitmaps are
|
|||
|
monochrome, and (2) a newly created memory DC has a monochrome
|
|||
|
bitmap selected in. */
|
|||
|
if ( ((hMDCCache = CreateCompatibleDC( hDC )) != NULL) &&
|
|||
|
((vhbmBitmapCache = CreateDiscardableBitmap(
|
|||
|
fBitmap ? hMDCCache : hDC, dxpDisplay, dypDisplay )) !=
|
|||
|
NULL) &&
|
|||
|
SelectObject( hMDCCache, vhbmBitmapCache ))
|
|||
|
{
|
|||
|
if (!StretchBlt( hMDCCache, 0, 0, dxpDisplay,
|
|||
|
dypDisplay, hMDC, 0, 0, dxpOrig, dypOrig, SRCCOPY ))
|
|||
|
{ /* may get here if memory is low */
|
|||
|
DeleteDC( hMDCCache );
|
|||
|
hMDCCache = NULL;
|
|||
|
DeleteObject( vhbmBitmapCache );
|
|||
|
vhbmBitmapCache = NULL;
|
|||
|
goto NoCache;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DCLIP
|
|||
|
if (vfMonochrome && fBitmap)
|
|||
|
CommSzNum("BitBlt using ropMonoBm == ",ropMonoBm);
|
|||
|
#endif
|
|||
|
|
|||
|
BitBlt( hDC, rcPict.left, rcPict.top, dxpDisplay,
|
|||
|
dypDisplay, hMDCCache, 0, 0, vfMonochrome && fBitmap ?
|
|||
|
ropMonoBm : SRCCOPY );
|
|||
|
|
|||
|
/* Cached bitmap OK, make cache valid */
|
|||
|
vdocBitmapCache = pwwd->doc;
|
|||
|
vcpBitmapCache = cpPictStart;
|
|||
|
vfBMBitmapCache = fBitmap;
|
|||
|
}
|
|||
|
else
|
|||
|
#endif /* ndef NOCACHE */
|
|||
|
{
|
|||
|
NoCache:
|
|||
|
StretchBlt( hDC, rcPict.left, rcPict.top,
|
|||
|
dxpDisplay, dypDisplay,
|
|||
|
hMDC, 0, 0, dxpOrig, dypOrig, vfMonochrome &&
|
|||
|
fBitmap ? ropMonoBm : SRCCOPY );
|
|||
|
}
|
|||
|
fDrew = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Case 3: A metafile picture which can be directly scaled
|
|||
|
or does not need to be because its size has not changed */
|
|||
|
else
|
|||
|
{
|
|||
|
fDrew = true;
|
|||
|
Diag(CommSz("Case 3:\n\r"));
|
|||
|
SetMapMode( hDC, picInfo.mfp.mm );
|
|||
|
|
|||
|
SetViewportOrg( hDC, rcPict.left, rcPict.top );
|
|||
|
switch( picInfo.mfp.mm ) {
|
|||
|
case MM_ISOTROPIC:
|
|||
|
if (picInfo.mfp.xExt && picInfo.mfp.yExt)
|
|||
|
/* So we get the correct shape rectangle when
|
|||
|
SetViewportExt gets called */
|
|||
|
SetWindowExt( hDC, picInfo.mfp.xExt, picInfo.mfp.yExt );
|
|||
|
/* FALL THROUGH */
|
|||
|
case MM_ANISOTROPIC:
|
|||
|
/** (9.17.91) v-dougk
|
|||
|
Set the window extent in case the metafile is bad
|
|||
|
and doesn't call it itself. This will prevent
|
|||
|
possible gpfaults in GDI
|
|||
|
**/
|
|||
|
SetWindowExt( hDC, dxpDisplay, dypDisplay );
|
|||
|
|
|||
|
SetViewportExt( hDC, dxpDisplay, dypDisplay );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
PlayMetaFile( hDC, hBits );
|
|||
|
}
|
|||
|
DontDraw:
|
|||
|
|
|||
|
/* Clean up */
|
|||
|
if ( *(pLocalHeap+1) )
|
|||
|
MeltHp();
|
|||
|
|
|||
|
if (ilevel > 0)
|
|||
|
RestoreDC( hDC, ilevel );
|
|||
|
if (hMDCCache != NULL)
|
|||
|
DeleteDC( hMDCCache );
|
|||
|
if (hMDC != NULL)
|
|||
|
DeleteDC( hMDC );
|
|||
|
if (hbm != NULL)
|
|||
|
DeleteObject( hbm );
|
|||
|
if (hBits != NULL)
|
|||
|
{
|
|||
|
if (fBitmap && picInfo.bm.bmBits != NULL)
|
|||
|
GlobalUnlock( hBits );
|
|||
|
GlobalFree( hBits );
|
|||
|
}
|
|||
|
|
|||
|
if (!fDrew)
|
|||
|
{
|
|||
|
void DrawBlank(HDC hDC, RECT FAR *rc);
|
|||
|
DrawBlank(hDC,&rcPict);
|
|||
|
}
|
|||
|
|
|||
|
/* Invert the selection */
|
|||
|
if (ww == wwDocument && !vfSelHidden && !vfPMS)
|
|||
|
{
|
|||
|
extern int vypCursLine;
|
|||
|
|
|||
|
ilevel = SaveDC( hDC ); /* Because of clip calls below */
|
|||
|
|
|||
|
if (!vfWholePictInvalid)
|
|||
|
/* Repainting less than the whole picture; clip out
|
|||
|
what we're not drawing */
|
|||
|
IntersectClipRect( hDC, rcPictInvalid.left, rcPictInvalid.top,
|
|||
|
rcPictInvalid.right, rcPictInvalid.bottom );
|
|||
|
|
|||
|
/* Clip out top bar, selection bar */
|
|||
|
|
|||
|
IntersectClipRect( hDC, xpSelBar,
|
|||
|
pwwdCur->ypMin, pwwdCur->xpMac, pwwdCur->ypMac );
|
|||
|
|
|||
|
if (selCur.cpLim > cpPictStart && selCur.cpFirst <= cpPictStart)
|
|||
|
{ /* Take into account 'space before' field */
|
|||
|
rcEnclose.left = rcPict.left;
|
|||
|
rcEnclose.right = rcPict.right;
|
|||
|
InvertRect( hDC, (LPRECT) &rcEnclose );
|
|||
|
}
|
|||
|
else if ((selCur.cpLim == selCur.cpFirst) &&
|
|||
|
(selCur.cpFirst == cpPictStart) &&
|
|||
|
(vfWholePictInvalid || rcPictInvalid.top < vypCursLine))
|
|||
|
{ /* We erased the insert point */
|
|||
|
vfInsertOn = fFalse;
|
|||
|
}
|
|||
|
RestoreDC( hDC, ilevel );
|
|||
|
}
|
|||
|
|
|||
|
vfWholePictInvalid = TRUE; /* Next picture, start invalidation anew */
|
|||
|
{
|
|||
|
extern int vfPMS;
|
|||
|
extern HCURSOR vhcPMS;
|
|||
|
|
|||
|
|
|||
|
EndLongOp( vfPMS ? vhcPMS : vhcIBeam );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifdef ENABLE /* Don't use this anymore */
|
|||
|
int
|
|||
|
FPointInPict(pt)
|
|||
|
POINT pt;
|
|||
|
{ /* Return true if point is within the picture frame */
|
|||
|
struct EDL *pedl;
|
|||
|
struct PICINFOX picInfo;
|
|||
|
RECT rcPict;
|
|||
|
|
|||
|
GetPicInfo(selCur.cpFirst, cpMacCur, docCur, &picInfo);
|
|||
|
|
|||
|
if (!FGetPictPedl(&pedl))
|
|||
|
return false;
|
|||
|
|
|||
|
ComputePictRect( &rcPict, &picInfo, pedl, wwCur );
|
|||
|
|
|||
|
return PtInRect( (LPRECT)&rcPict, pt );
|
|||
|
}
|
|||
|
#endif /* ENABLE */
|
|||
|
|
|||
|
|
|||
|
/* C O M P U T E P I C T R E C T */
|
|||
|
ComputePictRect( prc, ppicInfo, pedl, ww )
|
|||
|
RECT *prc;
|
|||
|
register struct PICINFOX *ppicInfo;
|
|||
|
struct EDL *pedl;
|
|||
|
int ww;
|
|||
|
{ /* Compute rect containing picture indicated by passed ppicInfo,
|
|||
|
pedl, in the indicated ww. Return the computed rect through
|
|||
|
prc. picInfo structure is not altered. */
|
|||
|
|
|||
|
int dypTop, xaLeft;
|
|||
|
struct WWD *pwwd = &rgwwd[ww];
|
|||
|
int xaStart;
|
|||
|
int dxaText, dxa;
|
|||
|
int dxpSize, dypSize;
|
|||
|
int dxaSize, dyaSize;
|
|||
|
|
|||
|
CacheSectPic(pwwd->doc, pedl->cpMin);
|
|||
|
|
|||
|
if (ppicInfo->mfp.mm == MM_BITMAP && ((ppicInfo->dxaSize == 0) ||
|
|||
|
(ppicInfo->dyaSize == 0)))
|
|||
|
{
|
|||
|
GetBitmapSize( &dxpSize, &dypSize, ppicInfo, FALSE );
|
|||
|
dxaSize = DxaFromDxp( dxpSize, FALSE );
|
|||
|
dyaSize = DyaFromDyp( dypSize, FALSE );
|
|||
|
}
|
|||
|
#if defined(OLE)
|
|||
|
else if (ppicInfo->mfp.mm == MM_OLE)
|
|||
|
{
|
|||
|
dxpSize = DxpFromDxa(ppicInfo->dxaSize, FALSE );
|
|||
|
dypSize = DypFromDya(ppicInfo->dyaSize, FALSE );
|
|||
|
dxpSize = MultDiv( dxpSize, ppicInfo->mx, mxMultByOne );
|
|||
|
dypSize = MultDiv( dypSize, ppicInfo->my, myMultByOne );
|
|||
|
dxaSize = DxaFromDxp( dxpSize, FALSE );
|
|||
|
dyaSize = DyaFromDyp( dypSize, FALSE );
|
|||
|
}
|
|||
|
#endif
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
dxpSize = DxpFromDxa( dxaSize = ppicInfo->dxaSize, FALSE );
|
|||
|
dypSize = DypFromDya( dyaSize = ppicInfo->dyaSize, FALSE );
|
|||
|
}
|
|||
|
|
|||
|
dypTop = pedl->dcpMac != 0 ?
|
|||
|
/* Last line of picture */
|
|||
|
DypFromDya( dyaSize + vpapAbs.dyaAfter, FALSE ) :
|
|||
|
(pedl->ichCpMin + 1) * dypPicSizeMin;
|
|||
|
dypTop = pedl->yp - dypTop;
|
|||
|
|
|||
|
xaStart = DxaFromDxp( xpSelBar - (int) pwwd->xpMin, FALSE );
|
|||
|
dxaText = vsepAbs.dxaText;
|
|||
|
switch (vpapAbs.jc)
|
|||
|
{
|
|||
|
case jcBoth:
|
|||
|
case jcLeft:
|
|||
|
dxa = ppicInfo->dxaOffset;
|
|||
|
break;
|
|||
|
case jcCenter:
|
|||
|
dxa = (dxaText - (int)vpapAbs.dxaRight + (int)vpapAbs.dxaLeft -
|
|||
|
dxaSize) / 2;
|
|||
|
break;
|
|||
|
case jcRight:
|
|||
|
dxa = dxaText - (int)vpapAbs.dxaRight - dxaSize;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
xaLeft = xaStart + max( (int)vpapAbs.dxaLeft, dxa );
|
|||
|
|
|||
|
prc->right = (prc->left = DxpFromDxa( xaLeft, FALSE )) + dxpSize;
|
|||
|
prc->bottom = (prc->top = dypTop) + dypSize;
|
|||
|
}
|
|||
|
|
|||
|
FGetPictPedl(ppedl)
|
|||
|
struct EDL **ppedl;
|
|||
|
{
|
|||
|
int dlLim = pwwdCur->dlMac;
|
|||
|
int dl;
|
|||
|
typeCP cpFirst = selCur.cpFirst;
|
|||
|
struct EDL *pedl;
|
|||
|
|
|||
|
//Assert(vfPictSel);
|
|||
|
|
|||
|
if (!vfPictSel)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
pedl = &(**(pwwdCur->hdndl)[0]);
|
|||
|
|
|||
|
for (dl = 0; dl < dlLim; ++dl, ++pedl)
|
|||
|
{
|
|||
|
//if (!pedl->fValid)
|
|||
|
//return false;
|
|||
|
|
|||
|
if (pedl->cpMin == cpFirst)
|
|||
|
break;
|
|||
|
}
|
|||
|
if (dl >= dlLim)
|
|||
|
return false; /* No part of picture is on screen */
|
|||
|
|
|||
|
*ppedl = pedl;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* C P W I N G R A P H I C */
|
|||
|
typeCP CpWinGraphic(pwwd)
|
|||
|
struct WWD *pwwd;
|
|||
|
{
|
|||
|
int cdlPict, dl;
|
|||
|
struct EDL *dndl = &(**(pwwd->hdndl))[0];
|
|||
|
|
|||
|
Assert( !pwwd->fDirty ); /* So we can rely on dl info */
|
|||
|
CachePara(pwwd->doc, dndl->cpMin);
|
|||
|
for (dl = 0; (dl < pwwd->dlMac - 1 && dndl[dl].fIchCpIncr); ++dl)
|
|||
|
;
|
|||
|
Assert(dndl[dl].fGraphics);
|
|||
|
cdlPict = dndl[dl].ichCpMin + 1;
|
|||
|
return (dndl[0].cpMin +
|
|||
|
(vcpLimParaCache - vcpFirstParaCache) * dndl[0].ichCpMin / cdlPict);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CacheSectPic(doc, cp)
|
|||
|
int doc;
|
|||
|
typeCP cp;
|
|||
|
{ /* Cache section and para props, taking into account that footnotes take props
|
|||
|
from the reference point */
|
|||
|
#ifdef FOOTNOTES
|
|||
|
struct DOD *pdod = &(**hpdocdod)[doc];
|
|||
|
struct FNTB (**hfntb) = pdod->hfntb;
|
|||
|
#endif
|
|||
|
|
|||
|
CachePara(doc, cp);
|
|||
|
|
|||
|
#ifdef FOOTNOTES
|
|||
|
if ( (hfntb != 0) && (cp >= (**hfntb).rgfnd[0].cpFtn) )
|
|||
|
CacheSect( doc, CpRefFromFtn( doc, cp ) )
|
|||
|
else
|
|||
|
#endif
|
|||
|
CacheSect(doc, cp); /* Normal text */
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void DrawBlank(HDC hDC, RECT FAR *rc)
|
|||
|
{ /* To tell us when the draw tried but failed */
|
|||
|
int xpMid=rc->left + (rc->right-rc->left)/2;
|
|||
|
int ypMid=rc->top + (rc->bottom - rc->top)/2;
|
|||
|
int dxpQ=(rc->right-rc->left)/4;
|
|||
|
int dypQ=(rc->bottom-rc->top)/4;
|
|||
|
HPEN hOldPen;
|
|||
|
HBRUSH hOldBrush;
|
|||
|
|
|||
|
hOldPen = SelectObject( hDC, GetStockObject( BLACK_PEN ) );
|
|||
|
hOldBrush = SelectObject( hDC, GetStockObject( WHITE_BRUSH ) );
|
|||
|
Rectangle(hDC,rc->left,rc->top,rc->right,rc->bottom);
|
|||
|
MoveTo( hDC, rc->left, rc->top );
|
|||
|
LineTo( hDC, rc->right, rc->bottom );
|
|||
|
MoveTo( hDC, rc->left, rc->bottom );
|
|||
|
LineTo( hDC, rc->right, rc->top );
|
|||
|
MoveTo( hDC, xpMid, rc->top );
|
|||
|
LineTo( hDC, xpMid, rc->bottom );
|
|||
|
MoveTo( hDC, rc->left, ypMid );
|
|||
|
LineTo( hDC, rc->right, ypMid );
|
|||
|
Ellipse( hDC,
|
|||
|
xpMid-dxpQ, ypMid-dypQ,
|
|||
|
xpMid+dxpQ, ypMid+dypQ );
|
|||
|
SelectObject( hDC, hOldPen );
|
|||
|
SelectObject( hDC, hOldBrush );
|
|||
|
}
|
|||
|
|
|||
|
|