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

1836 lines
59 KiB
C

/****************************** Module Header ******************************\
* Module Name: Meta.c
*
* This file contains the routines for playing the GDI metafile. Most of these
* routines are adopted from windows gdi code. Most of the code is from
* win3.0 except for the GetEvent code which is taken from win2.1
*
* Created: 11-Oct-1989
*
* Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation
*
*
* Public Functions:
* PlayMetaFile
* PlayMetaFileRecord
* GetMetaFile
* DeleteMetaFile
* Private Functions:
* GetEvent
* IsDIBBlackAndWhite
*
* History:
* 02-Jul-1991 -by- John Colleran [johnc]
* Combined From Win 3.1 and WLO 1.0 sources
\***************************************************************************/
#include <windows.h>
#include <string.h>
#ifdef WIN32
#include "firewall.h"
#endif
#include "gdi16.h"
HDC hScreenDC = 0;
METACACHE MetaCache = { 0, 0, 0, 0 };
UINT INTERNAL GetFileNumber (LPMETAFILE lpMF);
HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo);
WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo);
#define MAX_META_DISPATCH 0x48
FARPROC alpfnMetaFunc[MAX_META_DISPATCH+1] =
/* 00 */ {(FARPROC)ScaleWindowExt,
/* 01 */ (FARPROC)SetBkColor,
/* 02 */ (FARPROC)SetBkMode,
/* 03 */ (FARPROC)SetMapMode,
/* 04 */ (FARPROC)SetROP2,
/* 05 */ DEFIFWIN16((FARPROC)SetRelAbs),
/* 06 */ (FARPROC)SetPolyFillMode,
/* 07 */ (FARPROC)SetStretchBltMode,
/* 08 */ (FARPROC)SetTextCharacterExtra,
/* 09 */ (FARPROC)SetTextColor,
/* 0A */ (FARPROC)SetTextJustification,
/* 0B */ (FARPROC)SetWindowOrg,
/* 0C */ (FARPROC)SetWindowExt,
/* 0D */ (FARPROC)SetViewportOrg,
/* 0E */ (FARPROC)SetViewportExt,
/* 0F */ (FARPROC)OffsetWindowOrg,
/* 10 */ 0,
/* 11 */ DEFIFWIN16((FARPROC)OffsetViewportOrg),
/* 12 */ DEFIFWIN16((FARPROC)ScaleViewportExt),
/* 13 */ (FARPROC)LineTo,
/* 14 */ DEFIFWIN16((FARPROC)MoveTo),
/* 15 */ (FARPROC)ExcludeClipRect,
/* 16 */ (FARPROC)IntersectClipRect,
/* 17 */ (FARPROC)Arc,
/* 18 */ (FARPROC)Ellipse,
/* 19 */ (FARPROC)FloodFill,
/* 1A */ (FARPROC)Pie,
/* 1B */ (FARPROC)Rectangle,
/* 1C */ (FARPROC)RoundRect,
/* 1D */ (FARPROC)PatBlt,
/* 1E */ (FARPROC)SaveDC,
/* 1F */ (FARPROC)SetPixel,
/* 20 */ (FARPROC)OffsetClipRgn,
/* 21 */ 0, // TextOut,
/* 22 */ 0, // BitBlt,
/* 23 */ 0, // StretchBlt.
/* 24 */ 0, // Polygon,
/* 25 */ 0, // Polyline,
/* 26 */ 0, // Escape,
/* 27 */ (FARPROC)RestoreDC,
/* 28 */ 0, // FillRegion,
/* 29 */ 0, // FrameRegion,
/* 2A */ 0, // InvertRegion,
/* 2B */ 0, // PaintRegion,
/* 2C */ (FARPROC)SelectClipRgn,
/* 2D */ 0, // SelectObject,
/* 2E */ (FARPROC)SetTextAlign,
/* 2F */ 0, // DrawText,
/* 30 */ (FARPROC)Chord,
/* 31 */ (FARPROC)SetMapperFlags,
/* 32 */ 0, // ExtTextOut,
/* 33 */ 0, // SetDibsToDevice,
/* 34 */ 0, // SelectPalette,
/* 35 */ 0, // RealizePalette,
/* 36 */ 0, // AnimatePalette,
/* 37 */ 0, // SetPaletteEntries,
/* 38 */ 0, // PolyPolygon,
/* 39 */ 0, // ResizePalette,
/* 3A */ 0,
/* 3B */ 0,
/* 3C */ 0,
/* 3D */ 0,
/* 3E */ 0,
/* 3F */ 0,
/* 40 */ 0, // DIBBitblt,
/* 41 */ 0, // DIBStretchBlt,
/* 42 */ 0, // DIBCreatePatternBrush,
/* 43 */ 0, // StretchDIB,
/* 44 */ 0,
/* 45 */ 0,
/* 46 */ 0,
/* 47 */ 0,
/* 48 */ (FARPROC)ExtFloodFill };
#if 0 // this is going to gdi.dll
/***************************** Public Function ****************************\
* BOOL APIENTRY PlayMetaFile(hdc, hmf)
* HDC hDC;
* HMETAFILE hMF;
*
* Play a windows metafile.
*
* History:
* Tue 27-Mar-1990 11:11:45 -by- Paul Klingler [paulk]
* Ported from Windows
\***************************************************************************/
BOOL GDIENTRY PlayMetaFile(HDC hdc, HMETAFILE hmf)
{
WORD i;
WORD noObjs;
BOOL bPrint=FALSE;
LPMETAFILE lpmf;
int oldMapMode = -1;
LPMETARECORD lpmr = NULL;
LPHANDLETABLE pht = NULL;
HANDLE hht = NULL;
#ifndef WIN32
HFONT hLFont;
HBRUSH hLBrush;
HPALETTE hLPal;
HPEN hLPen;
HRGN hClipRgn;
HRGN hRegion;
DWORD oldWndExt;
DWORD oldVprtExt;
#endif //WIN32
GdiLogFunc("PlayMetaFile");
if(!IsValidMetaFile(hmf))
goto exitPlayMetaFile;
if(lpmf = (LPMETAFILE)GlobalLock(hmf))
{
if((noObjs = lpmf->MetaFileHeader.mtNoObjects) > 0)
{
if(!(hht = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE,
(sizeof(HANDLE) * lpmf->MetaFileHeader.mtNoObjects) + sizeof(WORD ))))
{
goto exitPlayMetaFile10;
}
pht = (LPHANDLETABLE)GlobalLock(hht);
}
#ifdef CR1
IMP: Optmizations playing into another metafile. Look at the win3.0
IMP: code
#endif
// !!!!! what if this is a metafile DC
#ifndef WIN32
/* save the old objects so we can put them back */
hLPen = GetCurrentObject( hdc, OBJ_PEN );
hLBrush = GetCurrentObject( hdc, OBJ_BRUSH);
hLFont = GetCurrentObject( hdc, OBJ_FONT);
hClipRgn = GetCurrentObject( hdc, OBJ_RGN);
hLPal = GetCurrentObject( hdc, OBJ_PALETTE);
if(hRegion = GetCurrentObject( hdc, OBJ_RGN))
{
if(hClipRgn = CreateRectRgn(0,0,0,0))
CombineRgn(hClipRgn,hRegion,hRegion,RGN_COPY);
}
#endif // WIN32
// we should really remove this abort proc thing.
while(lpmr = GetEvent(lpmf,lpmr,FALSE))
{
#if 0 //!!!!!
if(GET_pAbortProc(pdc))
#else
if( 0 )
#endif //!!!!!
{
//!!!!! if((bPrint = (*(pdc->pAbortProc))(hdc,0)) == FALSE)
{
GetEvent(lpmf,lpmr,TRUE);
RestoreDC(hdc,0);
goto exitPlayMetaFile20;
}
}
PlayMetaFileRecord(hdc,pht,lpmr,noObjs);
}
bPrint = TRUE;
exitPlayMetaFile20:
/* if we fail restoring an object, we need to select some
default object so that we can DeleteObject any Metafile-
selected objects */
#ifndef WIN32
if(!SelectObject(hdc,hLPen))
SelectObject(hdc,GetStockObject(BLACK_PEN));
if(!SelectObject(hdc,hLBrush))
SelectObject(hdc,GetStockObject(BLACK_BRUSH));
if(!SelectPalette(hdc, GetCurrentObject( hdc, OBJ_PALETTE), FALSE))
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
if(!SelectObject(hdc,hLFont))
{
/* if we cannot select the original font back in, we
** select the system font. this will allow us to delete
** the metafile font selected. to insure that the system
** font gets selected, we reset the DC's transform to
** default. after the selection, we restore this stuff
*/
oldVprtExt = GetViewportExt(hdc);
oldWndExt = GetWindowExt(hdc);
oldMapMode = SetMapMode(hdc,MM_TEXT);
SelectObject(hdc,GetStockObject(SYSTEM_FONT));
SetMapMode(hdc,oldMapMode);
SetWindowExt(hdc,LOWORD (oldWndExt),HIWORD (oldWndExt));
SetViewportExt(hdc,LOWORD (oldVprtExt),HIWORD (oldVprtExt));
}
if(hClipRgn)
{
SelectObject(hdc,hClipRgn);
DeleteObject(hClipRgn);
}
#endif // WIN32
for(i = 0; i < lpmf->MetaFileHeader.mtNoObjects; ++i)
{
if(pht->objectHandle[i])
DeleteObject(pht->objectHandle[i]);
}
#ifndef WIN32
/* if we fiddled with the map mode because we could not
** restore the original font, then maybe we can restore the
** font now */
if(oldMapMode > 0)
SelectObject(hdc,hLFont);
#endif // WIN32
if(hht)
{
GlobalUnlock(hht);
GlobalFree(hht);
}
exitPlayMetaFile10:
GlobalUnlock(hmf);
}
exitPlayMetaFile:
return(bPrint);
}
#endif // this is going to gdi.dll
/***************************** Internal Function **************************\
* BOOL NEAR PASCAL IsDIBBlackAndWhite
*
* Check to see if this DIB is a black and white DIB (and should be
* converted into a mono bitmap as opposed to a color bitmap).
*
* Returns: TRUE it is a B&W bitmap
* FALSE this is for color
*
* Effects: ?
*
* Warnings: ?
*
* History:
\***************************************************************************/
BOOL INTERNAL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo)
{
LPDWORD lpRGB;
GdiLogFunc3( " IsDIBBlackAndWhite");
/* pointer color table */
lpRGB = (LPDWORD)((LPBITMAPINFO)lpDIBInfo)->bmiColors;
if ((lpDIBInfo->biBitCount == 1 && lpDIBInfo->biPlanes == 1)
&& (lpRGB[0] == (DWORD)0)
&& (lpRGB[1] == (DWORD)0xFFFFFF))
return(TRUE);
else
return(FALSE);
}
/***************************** Internal Function **************************\
* BigRead
*
* allows reads of greater than 64K
*
* Returns: Number of bytes read
*
\***************************************************************************/
DWORD INTERNAL BigRead(UINT fileNumber, LPSTR lpRecord, DWORD dwSizeRec)
{
DWORD dwRead = dwSizeRec;
HPBYTE hpStuff;
GdiLogFunc2( " BigRead");
hpStuff = (HPBYTE)lpRecord;
while (dwRead > MAXFILECHUNK)
{
if (_lread(fileNumber, (LPSTR)hpStuff, MAXFILECHUNK) != MAXFILECHUNK)
return(0);
dwRead -= MAXFILECHUNK;
hpStuff += MAXFILECHUNK;
}
if (_lread(fileNumber, (LPSTR)hpStuff, (UINT)dwRead) != (UINT)dwRead)
return(0);
return(dwSizeRec);
}
/***************************** Internal Function **************************\
* UseStretchDIBits
*
* set this directly to the device using StretchDIBits.
* if DIB is black&white, don't do this.
*
* Returns:
* TRUE --- operation successful
* FALSE -- decided not to use StretchDIBits
*
* Effects: ?
*
* Warnings: ?
*
* History:
\***************************************************************************/
BOOL INTERNAL UseStretchDIB(HDC hDC, WORD magic, LPMETARECORD lpMR)
{
LPBITMAPINFOHEADER lpDIBInfo;
int sExtX, sExtY;
int sSrcX, sSrcY;
int DstX, DstY, DstXE, DstYE;
if (magic == META_DIBBITBLT)
{
lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8];
DstX = lpMR->rdParm[7];
DstY = lpMR->rdParm[6];
sSrcX = lpMR->rdParm[3];
sSrcY = lpMR->rdParm[2];
DstXE = sExtX = lpMR->rdParm[5];
DstYE = sExtY = lpMR->rdParm[4];
}
else
{
lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10];
DstX = lpMR->rdParm[9];
DstY = lpMR->rdParm[8];
DstXE = lpMR->rdParm[7];
DstYE = lpMR->rdParm[6];
sSrcX = lpMR->rdParm[5];
sSrcY = lpMR->rdParm[4];
sExtX = lpMR->rdParm[3];
sExtY = lpMR->rdParm[2];
}
/* if DIB is black&white, we don't really want to do this */
if (IsDIBBlackAndWhite(lpDIBInfo))
return(FALSE);
StretchDIBits(hDC, DstX, DstY, DstXE, DstYE,
sSrcX, sSrcY, sExtX, sExtY,
(LPBYTE)((LPSTR)lpDIBInfo + lpDIBInfo->biSize
+ GetSizeOfColorTable(lpDIBInfo)),
(LPBITMAPINFO)lpDIBInfo, DIB_RGB_COLORS,
(MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0])));
return(TRUE);
}
/***************************** Internal Function **************************\
* GetEvent
*
* This routine will now open a disk metafile in READ_ONLY mode. This will
* allow us to play read-only metafiles or to share such file.
*
* [amitc: 06/19/91]
\***************************************************************************/
LPMETARECORD INTERNAL GetEvent(LPMETAFILE lpMF, HPMETARECORD lpMR, BOOL bFree)
// BOOL bFree; /* non-zero ==> done with metafile */
{
int fileNumber = 0;
WORD i;
LPWORD lpCache = NULL;
LPWORD lpMRbuf;
HANDLE hMF;
DWORD rdSize;
GdiLogFunc2( " GetEvent");
#ifdef WIN32
hMF = GlobalHandle(lpMF);
#else
hMF = LOWORD(GlobalHandle(HIWORD((DWORD)(lpMF))));
#endif
ASSERTGDI( hMF != (HANDLE)NULL, "GetEvent: Global Handle failed");
if (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE)
{
/* Are we at the end of the metafile */
if(lpMR && lpMR->rdFunction == 0)
return((LPMETARECORD)0);
/* done with metafile, so free up the temp selector */
else if (bFree)
{
if (lpMR)
#ifndef WIN32
FreeSelector(HIWORD(lpMR));
#endif
return((LPMETARECORD)0);
}
else
{
/* if we don't already have a selector, get one */
if (lpMR == NULL)
{
#ifdef WIN32
lpMR = (HPMETARECORD)((LPMETADATA)lpMF)->metaDataStuff;
// lpMR = (LPMETARECORD)GlobalLock(lpMF->hMetaData);
#else
lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)&lpMF->MetaFileNumber)),LOWORD((DWORD)&lpMF->MetaFileNumber));
#endif
}
else
lpMR = (LPMETARECORD) (((HPWORD)lpMR)+lpMR->rdSize);
/* end of the metafile. free up the selector we were using */
if (lpMR->rdFunction == 0)
{
#ifndef WIN32
FreeSelector(HIWORD(lpMR));
#endif
return((LPMETARECORD)0);
}
}
return(lpMR);
}
else if (lpMF->MetaFileHeader.mtType == DISKMETAFILE)
{
if (bFree)
goto errGetEvent; /* never TRUE on the first call to GetEvent */
if (lpMR == NULL)
{
if ((fileNumber = OpenFile((LPSTR)lpMF->MetaFileBuffer.szPathName, (LPOFSTRUCT)&(lpMF->MetaFileBuffer), (WORD)OF_PROMPT|OF_REOPEN|OF_READ)) != -1)
{
if (lpMF->MetaFileRecordHandle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)(lpMF->MetaFileHeader.mtMaxRecord * sizeof(WORD))))
{
lpMR = (LPMETARECORD)GlobalLock(lpMF->MetaFileRecordHandle);
lpMF->MetaFilePosition = _lread(lpMF->MetaFileNumber = fileNumber, (LPSTR)&lpMF->MetaFileHeader, sizeof(METAHEADER));
// Check for an Aldus header
if (*((LPDWORD)&(lpMF->MetaFileHeader)) == 0x9AC6CDD7)
{
_llseek( fileNumber, 22, 0);
lpMF->MetaFilePosition = 22 + _lread(fileNumber,(LPSTR)(&(lpMF->MetaFileHeader)),sizeof(METAHEADER));
}
lpMF->MetaFileHeader.mtType = DISKMETAFILE;
if (!MetaCache.hCache)
{
MetaCache.hCache = AllocBuffer(&MetaCache.wCacheSize);
MetaCache.wCacheSize >>= 1;
MetaCache.hMF = hMF;
/* force cache fill on first access */
MetaCache.wCachePos = MetaCache.wCacheSize;
}
if (!(lpMF->MetaFileBuffer.fFixedDisk))
{
_lclose(fileNumber);
/* need to update the following for floppy files -- amitc */
fileNumber = 0 ;
lpMF->MetaFileNumber = 0 ;
}
}
}
else
return((LPMETARECORD)0);
}
/* update fileNumber, this is so that floopy based files can be closed
and not left open -- amitc */
fileNumber = lpMF->MetaFileNumber ;
if (lpMR)
{
if (MetaCache.hMF == hMF)
{
lpCache = (LPWORD) GlobalLock(MetaCache.hCache);
lpMRbuf = (LPWORD) lpMR;
// Make sure we can read the size and function fields
if (MetaCache.wCachePos >= (WORD)(MetaCache.wCacheSize - 2))
{
WORD cwCopy;
if (!fileNumber)
if ((fileNumber = GetFileNumber(lpMF)) == -1)
goto errGetEvent;
// We need to fill up the cache but save any data already
// in the cache
cwCopy = MetaCache.wCacheSize - MetaCache.wCachePos;
for (i = 0; i < cwCopy; i++)
{
lpCache[i] = lpCache[MetaCache.wCacheSize-(cwCopy-i)];
}
lpMF->MetaFilePosition += _lread(fileNumber,
(LPSTR) (lpCache + cwCopy),
(MetaCache.wCacheSize-cwCopy) << 1);
MetaCache.wCachePos = 0;
}
lpCache += MetaCache.wCachePos;
rdSize = ((LPMETARECORD)lpCache)->rdSize;
/* Check for end */
if (!((LPMETARECORD)lpCache)->rdFunction)
goto errGetEvent;
// Make sure we can read the rest of the metafile record
if (rdSize + MetaCache.wCachePos > MetaCache.wCacheSize)
{
if (!fileNumber)
if ((fileNumber = GetFileNumber(lpMF))
== -1)
goto errGetEvent;
for (i=MetaCache.wCachePos; i < MetaCache.wCacheSize; ++i)
*lpMRbuf++ = *lpCache++;
lpMF->MetaFilePosition +=
BigRead(fileNumber, (LPSTR) lpMRbuf,
(DWORD)(rdSize
+ (DWORD)MetaCache.wCachePos
- (DWORD)MetaCache.wCacheSize) << 1);
// Mark the cache as depleted because we just read
// directly into the metafile record rather than the cache
MetaCache.wCachePos = MetaCache.wCacheSize;
}
else
{
ASSERTGDI( HIWORD(rdSize) == 0, "Huge rdsize");
for (i = 0; i < LOWORD(rdSize); ++i)
*lpMRbuf++ = *lpCache++;
MetaCache.wCachePos += LOWORD(rdSize);
}
GlobalUnlock(MetaCache.hCache);
return lpMR;
}
if ((fileNumber = GetFileNumber(lpMF)) == -1)
goto errGetEvent;
lpMF->MetaFilePosition += _lread(fileNumber, (LPSTR)&lpMR->rdSize, sizeof(DWORD));
lpMF->MetaFilePosition += BigRead(fileNumber, (LPSTR)&lpMR->rdFunction, (DWORD)(lpMR->rdSize * sizeof(WORD)) - sizeof(DWORD));
if (!(lpMF->MetaFileBuffer.fFixedDisk))
{
_lclose(fileNumber);
lpMF->MetaFileNumber = 0 ;
fileNumber = 0 ;
}
if (lpMR->rdFunction == 0)
{
errGetEvent:;
if (lpMF->MetaFileBuffer.fFixedDisk || fileNumber)
_lclose(lpMF->MetaFileNumber);
GlobalUnlock(lpMF->MetaFileRecordHandle);
GlobalFree(lpMF->MetaFileRecordHandle);
lpMF->MetaFileNumber = 0;
if (MetaCache.hMF == hMF)
{
if (lpCache)
GlobalUnlock(MetaCache.hCache);
GlobalFree(MetaCache.hCache);
MetaCache.hCache = MetaCache.hMF = 0;
}
return((LPMETARECORD)0);
}
}
return(lpMR);
}
return((LPMETARECORD)0);
}
/***************************** Internal Function **************************\
* void GDIENTRY PlayMetaFileRecord
*
* Plays a metafile record by executing the GDI function call contained
* withing the metafile record
*
* Effects:
*
\***************************************************************************/
#if 0 // this is going to gdi.dll
void
GDIENTRY PlayMetaFileRecord(
HDC hdc,
LPHANDLETABLE lpHandleTable,
LPMETARECORD lpMR,
WORD noObjs
)
{
WORD magic;
HANDLE hObject;
HANDLE hOldObject;
HBRUSH hBrush;
HRGN hRgn;
HANDLE hPal;
BOOL bExtraSel = FALSE;
dprintf( 3," PlayMetaFileRecord 0x%lX", lpMR);
if (!ISDCVALID(hdc))
return;
magic = lpMR->rdFunction;
/* being safe, make sure that the lp will give us full access to
** the record header without overstepping a segment boundary.
*/
#ifndef WIN32
if ((unsigned)(LOWORD((DWORD)lpMR)) > 0x7000)
{
lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)lpMR)),LOWORD((DWORD)lpMR));
bExtraSel = TRUE;
}
#endif // WIN32
switch (magic & 255)
{
case (META_BITBLT & 255):
case (META_STRETCHBLT & 255):
{
HDC hSDC;
HANDLE hBitmap;
LPBITMAP lpBitmap;
int delta = 0;
/* if playing into another Metafile, do direct copy */
if (PlayIntoAMetafile(lpMR, hdc))
goto errPlayMetaFileRecord20;
if ((lpMR->rdSize - 3) == (magic >> 8))
{
hSDC = hdc;
delta = 1;
}
else
{
if (hSDC = CreateCompatibleDC(hdc))
{
if (magic == META_BITBLT)
lpBitmap = (LPBITMAP)&lpMR->rdParm[8];
else
lpBitmap = (LPBITMAP)&lpMR->rdParm[10];
//!!!!! ALERT DWORD align on NT
if (hBitmap = CreateBitmap(lpBitmap->bmWidth,
lpBitmap->bmHeight,
lpBitmap->bmPlanes,
lpBitmap->bmBitsPixel,
(LPBYTE)&lpBitmap->bmBits))
hOldObject = SelectObject(hSDC, hBitmap);
else
goto errPlayMetaFileRecord10;
}
else
goto errPlayMetaFileRecord20;
}
if (hSDC)
{
if (magic == META_BITBLT)
BitBlt(hdc, lpMR->rdParm[7 + delta],
lpMR->rdParm[6 + delta],
lpMR->rdParm[5 + delta],
lpMR->rdParm[4 + delta],
hSDC,
lpMR->rdParm[3],
lpMR->rdParm[2],
MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
else
StretchBlt(hdc, lpMR->rdParm[9 + delta],
lpMR->rdParm[8 + delta],
lpMR->rdParm[7 + delta],
lpMR->rdParm[6 + delta],
hSDC,
lpMR->rdParm[5],
lpMR->rdParm[4],
lpMR->rdParm[3],
lpMR->rdParm[2],
MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
}
if (hSDC != hdc)
{
if (SelectObject(hSDC, hOldObject))
DeleteObject(hBitmap);
errPlayMetaFileRecord10:;
DeleteDC(hSDC);
errPlayMetaFileRecord20:;
}
}
break;
case (META_DIBBITBLT & 255):
case (META_DIBSTRETCHBLT & 255):
{
HDC hSDC;
HANDLE hBitmap;
LPBITMAPINFOHEADER lpDIBInfo ;
int delta = 0;
HANDLE hOldPal;
/* if playing into another metafile, do direct copy */
if (PlayIntoAMetafile(lpMR, hdc))
goto errPlayMetaFileRecord40;
if ((lpMR->rdSize - 3) == (magic >> 8))
{
hSDC = hdc;
delta = 1;
}
else
{
if( (magic & 255) == (META_DIBSTRETCHBLT & 255) )
if (UseStretchDIB(hdc, magic, lpMR))
goto errPlayMetaFileRecord40;
if (hSDC = CreateCompatibleDC(hdc))
{
/* set up the memDC to have the same palette */
hOldPal = SelectPalette(hSDC, GetCurrentObject(hdc,OBJ_PALETTE), TRUE);
if (magic == META_DIBBITBLT)
lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8];
else
lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10];
/* now create the bitmap for the MemDC and fill in the bits */
/* the processing for old and new format of metafiles is
different here (till hBitmap is obtained) */
/* new metafile version */
hBitmap = CreateBitmapForDC (hdc,lpDIBInfo);
if (hBitmap)
hOldObject = SelectObject (hSDC, hBitmap) ;
else
goto errPlayMetaFileRecord30 ;
}
else
goto errPlayMetaFileRecord40;
}
if (hSDC)
{
if (magic == META_DIBBITBLT)
BitBlt(hdc, lpMR->rdParm[7 + delta],
lpMR->rdParm[6 + delta],
lpMR->rdParm[5 + delta],
lpMR->rdParm[4 + delta],
hSDC,
lpMR->rdParm[3],
lpMR->rdParm[2],
MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
else
StretchBlt(hdc, lpMR->rdParm[9 + delta],
lpMR->rdParm[8 + delta],
lpMR->rdParm[7 + delta],
lpMR->rdParm[6 + delta],
hSDC,
lpMR->rdParm[5],
lpMR->rdParm[4],
lpMR->rdParm[3],
lpMR->rdParm[2],
MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
}
if (hSDC != hdc)
{
/* Deselect hDC's palette from memDC */
SelectPalette(hSDC, hOldPal, TRUE);
if (SelectObject(hSDC, hOldObject))
DeleteObject(hBitmap);
errPlayMetaFileRecord30:;
DeleteDC(hSDC);
errPlayMetaFileRecord40:;
}
}
break;
case (META_SELECTOBJECT & 255):
{
HANDLE hObject;
if (hObject = lpHandleTable->objectHandle[lpMR->rdParm[0]])
SelectObject(hdc, hObject);
}
break;
case (META_CREATEPENINDIRECT & 255):
{
#ifdef WIN32
LOGPEN lp;
lp.lopnStyle = lpMR->rdParm[0];
lp.lopnWidth.x = lpMR->rdParm[1];
lp.lopnColor = *((COLORREF *)&lpMR->rdParm[3]);
if (hObject = CreatePenIndirect(&lp))
#else
if (hObject = CreatePenIndirect((LPLOGPEN)&lpMR->rdParm[0]))
#endif
AddToHandleTable(lpHandleTable, hObject, noObjs);
break;
}
case (META_CREATEFONTINDIRECT & 255):
{
LOGFONT lf;
LPLOGFONT lplf = &lf;
LOGFONT32FROM16( lplf, ((LPLOGFONT)&lpMR->rdParm[0]));
if (hObject = CreateFontIndirect(lplf))
AddToHandleTable(lpHandleTable, hObject, noObjs);
}
break;
case (META_CREATEPATTERNBRUSH & 255):
{
HANDLE hBitmap;
LPBITMAP lpBitmap;
lpBitmap = (LPBITMAP)lpMR->rdParm;
//!!!!! ALERT DWORD align on NT
if (hBitmap = CreateBitmapIndirect(lpBitmap))
{
LPBITMAPINFO lpbmInfo;
HANDLE hmemInfo;
hmemInfo = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE,
sizeof(BITMAPINFO) + 2<<(lpBitmap->bmPlanes*lpBitmap->bmBitsPixel));
lpbmInfo = (LPBITMAPINFO)GlobalLock( hmemInfo);
lpbmInfo->bmiHeader.biPlanes = lpBitmap->bmPlanes;
lpbmInfo->bmiHeader.biBitCount = lpBitmap->bmBitsPixel;
SetDIBits( (HDC)NULL, hBitmap, 0, lpBitmap->bmHeight,
(LPBYTE)&lpMR->rdParm[8], lpbmInfo, DIB_RGB_COLORS );
if (hObject = CreatePatternBrush(hBitmap))
AddToHandleTable(lpHandleTable, hObject, noObjs);
GlobalUnlock(hmemInfo);
GlobalFree(hmemInfo);
DeleteObject(hBitmap);
}
}
break;
case (META_DIBCREATEPATTERNBRUSH & 255):
{
HDC hMemDC ;
HANDLE hBitmap;
LPBITMAPINFOHEADER lpDIBInfo ;
WORD nDIBSize; /* number of WORDs in packed DIB */
HANDLE hDIB;
LPWORD lpDIB;
LPWORD lpSourceDIB;
WORD i;
if (lpMR->rdParm[0] == BS_PATTERN)
{
/* the address of the second paramter is the address of the DIB
header, extract it */
lpDIBInfo = (BITMAPINFOHEADER FAR *) &lpMR->rdParm[2];
/* now create a device dependend bitmap compatible to the default
screen DC - hScreenDC and extract the bits from the DIB into it.
The following function does all these, and returns a HANDLE
to the device dependent BItmap. */
/* we will use a dummy memory DC compatible to the screen DC */
hMemDC = CreateCompatibleDC (hScreenDC) ;
hBitmap = CreateBitmapForDC (hScreenDC,lpDIBInfo) ;
if (hBitmap)
{
if (hObject = CreatePatternBrush(hBitmap))
AddToHandleTable(lpHandleTable, hObject, noObjs);
DeleteObject(hBitmap);
}
/* delete the dummy memory DC for new version Metafiles*/
DeleteDC (hMemDC) ;
}
/* this is a DIBPattern brush */
else
{
/* get size of just the packed DIB */
nDIBSize = (WORD) (lpMR->rdSize - 4);
if ((hDIB = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG)(nDIBSize << 1))))
{
lpDIB = (WORD FAR *) GlobalLock (hDIB);
lpSourceDIB = (WORD FAR *)&lpMR->rdParm[2];
/* copy the DIB into our new memory block */
for (i = 0; i < nDIBSize; i++)
*lpDIB++ = *lpSourceDIB++;
GlobalUnlock (hDIB);
if (hObject = CreateDIBPatternBrush(hDIB, lpMR->rdParm[1]))
AddToHandleTable(lpHandleTable, hObject, noObjs);
GlobalFree(hDIB);
}
}
}
break;
case (META_CREATEBRUSHINDIRECT & 255):
{
#ifdef WIN32
LOGBRUSH lb;
lb.lbStyle = lpMR->rdParm[0];
lb.lbColor = *((COLORREF *)&lpMR->rdParm[1]);
lb.lbHatch = lpMR->rdParm[3];
if (hObject = CreateBrushIndirect(&lb))
#else
if (hObject = CreateBrushIndirect((LPLOGBRUSH)&lpMR->rdParm[0]))
#endif
AddToHandleTable(lpHandleTable, hObject, noObjs);
break;
}
case (META_POLYLINE & 255):
{
LPPOINT lppt;
Polyline(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]);
FREECONVERT(lppt);
break;
}
case (META_POLYGON & 255):
{
LPPOINT lppt;
Polygon(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]);
FREECONVERT(lppt);
break;
}
case (META_POLYPOLYGON & 255):
{
LPPOINT lppt;
#ifdef WIN32
WORD cPts=0;
WORD ii;
for(ii=0; ii<lpMR->rdParm[0]; ii++)
cPts += ((LPWORD)&lpMR->rdParm[1])[ii];
#endif // WIN32
PolyPolygon(hdc,
(lppt=CONVERTPTS(&lpMR->rdParm[1] + lpMR->rdParm[0], cPts)),
(LPINT)&lpMR->rdParm[1],
lpMR->rdParm[0]);
FREECONVERT(lppt);
}
break;
case (META_EXTTEXTOUT & 255):
{
LPWORD lpdx;
LPSTR lpch;
LPRECT lprt;
lprt = (lpMR->rdParm[3] & (ETO_OPAQUE|ETO_CLIPPED)) ? (LPRECT)&lpMR->rdParm[4] : 0;
lpch = (LPSTR)&lpMR->rdParm[4] + ((lprt) ? sizeof(RECT) : 0);
/* dx array starts at next word boundary after char string */
lpdx = (LPWORD)(lpch + ((lpMR->rdParm[2] + 1) & 0xFFFE));
/* check to see if there is a Dx array by seeing if
structure ends after the string itself
*/
if ( ((DWORD)((LPWORD)lpdx - (LPWORD)(lpMR))) >= lpMR->rdSize)
lpdx = NULL;
else
lpdx = (LPWORD)CONVERTINTS((signed short FAR *)lpdx, lpMR->rdParm[2]);
ExtTextOut(hdc, lpMR->rdParm[1], lpMR->rdParm[0], lpMR->rdParm[3],
lprt, (LPSTR)lpch, lpMR->rdParm[2], (LPINT)lpdx);
if (lpdx != (LPWORD)NULL)
FREECONVERT(lpdx);
break;
}
case (META_TEXTOUT & 255):
TextOut(hdc, lpMR->rdParm[lpMR->rdSize-4], lpMR->rdParm[lpMR->rdSize-5], (LPSTR)&lpMR->rdParm[1], lpMR->rdParm[0]);
break;
case (META_ESCAPE & 255):
{
LPSTR lpStuff;
if (lpMR->rdParm[0] != MFCOMMENT)
{
lpStuff = (LPSTR)&lpMR->rdParm[2];
#ifdef OLDEXTTEXTOUT
if (lpMR->rdParm[0] == EXTTEXTOUT)
{
EXTTEXTDATA ExtData;
ExtData.xPos = lpMR->rdParm[2];
ExtData.yPos = lpMR->rdParm[3];
ExtData.cch = lpMR->rdParm[4];
ExtData.rcClip = *((LPRECT)&lpMR->rdParm[5]);
ExtData.lpString = (LPSTR)&lpMR->rdParm[9];
ExtData.lpWidths = (WORD FAR *)&lpMR->rdParm[9+((ExtData.cch+1)/2)];
lpStuff = (LPSTR)&ExtData;
}
#endif
Escape(hdc, lpMR->rdParm[0], lpMR->rdParm[1], lpStuff, (LPSTR)0);
}
}
break;
case (META_FRAMEREGION & 255):
if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
&& (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]]))
FrameRgn(hdc, hRgn, hBrush, lpMR->rdParm[3], lpMR->rdParm[2]);
break;
case (META_PAINTREGION & 255):
if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
PaintRgn(hdc, hRgn);
break;
case (META_INVERTREGION & 255):
if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
InvertRgn(hdc, hRgn);
break;
case (META_FILLREGION & 255):
if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
&& (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]]))
FillRgn(hdc, hRgn, hBrush);
break;
#ifdef DEADCODE
#ifdef GDI104
case (META_DRAWTEXT & 255):
MFDrawText(hdc, (LPPOINT)&lpMR->rdParm[6], lpMR->rdParm[1], (LPPOINT)&lpMR->rdParm[2], lpMR->rdParm[0]);
break;
#endif
#endif
/*
*** in win2, METACREATEREGION records contained an entire region object,
*** including the full header. this header changed in win3.
***
*** to remain compatible, the region records will be saved with the
*** win2 header. here we read a win2 header with region, and actually
*** create a win3 header with same region internals
*/
case (META_CREATEREGION & 255):
{
#if 0 //!!!!!
HANDLE hRgn;
WORD *pRgn;
WORD iChar;
LPWORD *lpTemp;
iChar = lpMR->rdSize*2 - sizeof(WIN2OBJHEAD) - RECHDRSIZE;
if (hRgn = LocalAlloc(LMEM_ZEROINIT, iChar + sizeof(ILOBJHEAD)))
{
pRgn = (WORD *)Lock IT(hRgn);
*((WIN2OBJHEAD *)pRgn) = *((WIN2OBJHEAD FAR *)&lpMR->rdParm[0]);
((ILOBJHEAD *)pRgn)->ilObjMetaList = 0;
lpTemp = (LPWORD)&(lpMR->rdParm[0]);
((WIN2OBJHEAD FAR *)lpTemp)++;
((ILOBJHEAD *)pRgn)++; /* --> actual region */
for(i = 0; i < (iChar >> 1) ; i++)
*pRgn++ = *lpTemp++;
pRgn = (WORD *)lock IT(hRgn);
((PRGN)pRgn)->rgnSize = iChar + sizeof(ILOBJHEAD);
AddToHandleTable(lpHandleTable, hRgn, noObjs);
}
#endif //!!!!!
HANDLE hRgn = NULL;
HANDLE hRgn2 = NULL;
WORD cScans;
WORD cPnts;
WORD cbIncr;
LPWIN3REGION lpW3Rgn = (LPWIN3REGION)lpMR->rdParm;
LPSCAN lpScan = lpW3Rgn->aScans;
LPWORD lpXs;
for( cScans=lpW3Rgn->cScans; cScans>0; cScans--)
{
// If this is the first scan then hRgn2 IS the region
// otherwise OR it in
if( hRgn == NULL )
{
// Create the first region in this scan
hRgn = CreateRectRgn( lpScan->scnPntsX[0], lpScan->scnPntTop,
lpScan->scnPntsX[1], lpScan->scnPntBottom);
// Allocate a worker region
hRgn2 = CreateRectRgn( 1, 1, 2, 2);
}
else
{
SetRectRgn( hRgn2, lpScan->scnPntsX[0], lpScan->scnPntTop,
lpScan->scnPntsX[1], lpScan->scnPntBottom );
CombineRgn( hRgn, hRgn, hRgn2, RGN_OR );
}
lpXs = &lpScan->scnPntsX[2];
// If there are more regions on this scan OR them in
for(cPnts = (WORD)(lpScan->scnPntCnt-2); cPnts>0; cPnts-=2)
{
SetRectRgn( hRgn2, *lpXs++, lpScan->scnPntTop,
*lpXs++, lpScan->scnPntBottom );
CombineRgn( hRgn, hRgn, hRgn2, RGN_OR );
}
cbIncr = (WORD)sizeof(SCAN) + (WORD)(lpScan->scnPntCnt-2);
cbIncr = (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2);
cbIncr = (WORD)sizeof(SCAN) + (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2);
cbIncr = (WORD)sizeof(SCAN) + (WORD)(sizeof(WORD)*(lpScan->scnPntCnt-2));
lpScan = (LPSCAN)((LPBYTE)lpScan + cbIncr);
}
if( hRgn2 != NULL )
DeleteObject( hRgn2 );
AddToHandleTable(lpHandleTable, hRgn, noObjs);
}
break;
case (META_DELETEOBJECT & 255):
{
HANDLE h;
if (h = lpHandleTable->objectHandle[lpMR->rdParm[0]])
{
DeleteObjectPriv(h);
lpHandleTable->objectHandle[lpMR->rdParm[0]] = NULL;
}
}
break;
case (META_CREATEPALETTE & 255):
if (hObject = CreatePalette((LPLOGPALETTE)&lpMR->rdParm[0]))
AddToHandleTable(lpHandleTable, hObject, noObjs);
break;
case (META_SELECTPALETTE & 255):
if(hPal = lpHandleTable->objectHandle[lpMR->rdParm[0]])
{
SelectPalette(hdc, hPal, 0);
}
break;
case (META_REALIZEPALETTE & 255):
RealizePalette(hdc);
break;
case (META_SETPALENTRIES & 255):
/* we know the palette being set is the current palette */
SetPaletteEntriesPriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0],
lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]);
break;
case (META_ANIMATEPALETTE & 255):
AnimatePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0],
lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]);
break;
case (META_RESIZEPALETTE & 255):
ResizePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0]);
break;
case (META_SETDIBTODEV & 255):
{
LPBITMAPINFOHEADER lpBitmapInfo;
WORD ColorSize;
/* if playing into another metafile, do direct copy */
if (PlayIntoAMetafile(lpMR, hdc))
goto DontReallyPlay;
lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[9]);
if (lpBitmapInfo->biClrUsed)
{
ColorSize = ((WORD)lpBitmapInfo->biClrUsed) *
(WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ?
sizeof(RGBQUAD) :
sizeof(WORD));
}
else if (lpBitmapInfo->biBitCount == 24)
ColorSize = 0;
else
ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) *
(WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ?
sizeof(RGBQUAD) :
sizeof(WORD));
ColorSize += sizeof(BITMAPINFOHEADER);
SetDIBitsToDevice(hdc, lpMR->rdParm[8], lpMR->rdParm[7],
lpMR->rdParm[6], lpMR->rdParm[5],
lpMR->rdParm[4], lpMR->rdParm[3],
lpMR->rdParm[2], lpMR->rdParm[1],
(BYTE FAR *)(((BYTE FAR *)lpBitmapInfo) + ColorSize),
(LPBITMAPINFO) lpBitmapInfo,
lpMR->rdParm[0]);
DontReallyPlay:;
}
break;
case (META_STRETCHDIB & 255):
{
LPBITMAPINFOHEADER lpBitmapInfo;
WORD ColorSize;
/* if playing into another metafile, do direct copy */
if (PlayIntoAMetafile(lpMR, hdc))
goto DontReallyPlay2;
lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[11]);
if (lpBitmapInfo->biClrUsed)
{
ColorSize = ((WORD)lpBitmapInfo->biClrUsed) *
(WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ?
sizeof(RGBQUAD) :
sizeof(WORD));
}
else if (lpBitmapInfo->biBitCount == 24)
ColorSize = 0;
else
ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) *
(WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ?
sizeof(RGBQUAD) :
sizeof(WORD));
ColorSize += sizeof(BITMAPINFOHEADER);
StretchDIBits(hdc, lpMR->rdParm[10], lpMR->rdParm[9],
lpMR->rdParm[8], lpMR->rdParm[7],
lpMR->rdParm[6], lpMR->rdParm[5],
lpMR->rdParm[4], lpMR->rdParm[3],
(LPBYTE)(((BYTE FAR *)lpBitmapInfo) + ColorSize),
(LPBITMAPINFO) lpBitmapInfo,
lpMR->rdParm[2],
MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0]));
DontReallyPlay2:;
}
break;
// Function that have new parameters on WIN32
// Or have DWORDs that stayed DWORDs; all other INTs to DWORDs
#ifdef WIN32
case (META_MOVETO & 255):
MoveTo( hdc, (long)lpMR->rdParm[1], (long)lpMR->rdParm[0], NULL );
break;
case (META_RESTOREDC & 255):
RestoreDC( hdc, (long)(signed short)lpMR->rdParm[0] );
break;
case (META_SETBKCOLOR & 255):
SetBkColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) );
break;
case (META_SETTEXTCOLOR & 255):
SetTextColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) );
break;
case (META_SETPIXEL & 255):
SetPixel( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2],
(UINT)*((LPDWORD)lpMR->rdParm) );
break;
case (META_SETMAPPERFLAGS & 255):
SetMapperFlags( hdc, (UINT)*((LPDWORD)lpMR->rdParm) );
break;
case (META_FLOODFILL & 255):
FloodFill( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2],
(UINT)*((LPDWORD)lpMR->rdParm) );
break;
case (META_EXTFLOODFILL & 255):
ExtFloodFill( hdc, (UINT)lpMR->rdParm[4], (UINT)lpMR->rdParm[3],
(UINT)*((LPDWORD)&lpMR->rdParm[1]), (UINT)lpMR->rdParm[0] );
break;
// These puppies all got a new NULL and have only two parameters and a DC.
case (META_SETWINDOWORG & 255):
case (META_SETWINDOWEXT & 255):
case (META_SETVIEWPORTORG & 255):
case (META_SETVIEWPORTEXT & 255):
case (META_OFFSETWINDOWORG & 255):
case (META_SCALEWINDOWEXT & 255):
case (META_OFFSETVIEWPORTORG & 255):
case (META_SCALEVIEWPORTEXT & 255):
{
FARPROC lpProc;
ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch1");
lpProc = alpfnMetaFunc[magic&0x00ff];
ASSERTGDI( lpProc != (FARPROC)NULL, "function not in dispatch table1 ");
if (lpProc != (FARPROC)NULL)
(*lpProc)(hdc, (long)(short)lpMR->rdParm[1], (long)(short)lpMR->rdParm[0], NULL );
}
break;
#endif // WIN32
default:
{
FARPROC lpProc;
signed short *pshort;
ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch");
lpProc = alpfnMetaFunc[magic&0x00ff];
ASSERTGDI( (lpProc != (FARPROC)NULL) || (magic == META_SETRELABS), "function not in dispatch table");
if ((lpProc == (FARPROC)NULL))
return;
// Switch to the corresponding dispatcher by number of parameters
// The number of parameters in the dispatch number does not include the DC.
switch (magic >> 8)
{
typedef int (FAR PASCAL *META1PROC)(HDC);
typedef int (FAR PASCAL *META2PROC)(HDC, int);
typedef int (FAR PASCAL *META3PROC)(HDC, int, int);
typedef int (FAR PASCAL *META4PROC)(HDC, int, int, int);
typedef int (FAR PASCAL *META5PROC)(HDC, int, int, int, int);
typedef int (FAR PASCAL *META6PROC)(HDC, int, int, int, int, int);
typedef int (FAR PASCAL *META7PROC)(HDC, int, int, int, int, int, int);
typedef int (FAR PASCAL *META9PROC)(HDC, int, int, int, int, int, int, int, int);
case 0:
(*((META1PROC)lpProc))(hdc);
break;
case 1:
(*((META2PROC)lpProc))(hdc,lpMR->rdParm[0]);
break;
case 2:
(*((META3PROC)lpProc))(hdc,lpMR->rdParm[1],lpMR->rdParm[0]);
break;
case 3:
(*((META4PROC)lpProc))(hdc,lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]);
break;
case 4:
(*((META5PROC)lpProc))(hdc,lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]);
break;
case 5:
(*((META6PROC)lpProc))(hdc,lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]);
break;
case 6:
(*((META7PROC)lpProc))(hdc,lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]);
break;
case 8:
(*((META9PROC)lpProc))(hdc,lpMR->rdParm[7],lpMR->rdParm[6],lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]);
break;
default:
ASSERTGDI( FALSE, "No dispatch for this count of args");
break;
}
}
break;
}
#ifndef WIN32
if (bExtraSel)
FreeSelector(HIWORD(lpMR));
#endif // WIN32
}
#endif // this is going to gdi.dll
/****************************** Internal Function **************************\
* AddToHandleTable
*
* Adds an object to the metafile table of objects
*
*
\***************************************************************************/
VOID INTERNAL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, WORD noObjs)
{
WORD i;
GdiLogFunc3( " AddToHandleTable");
/* linear search through table for first open slot */
for (i = 0; ((lpHandleTable->objectHandle[i] != NULL) && (i < noObjs));
++i);
if (i < noObjs) /* ok index */
lpHandleTable->objectHandle[i] = hObject;
else
{
ASSERTGDI( 0, "Too many objects in table");
FatalExit(METAEXITCODE); /* Why can't we store the handle? */
}
}
/****************************** Internal Function **************************\
* GetFileNumber
*
* Returns the DOS file number for a metafiles file
* -1 if failure
*
\***************************************************************************/
UINT INTERNAL GetFileNumber(LPMETAFILE lpMF)
{
int fileNumber;
GdiLogFunc3( " GetFileNumber");
if (!(fileNumber = lpMF->MetaFileNumber))
{
if ((fileNumber = OpenFile((LPSTR) lpMF->MetaFileBuffer.szPathName,
(LPOFSTRUCT) &(lpMF->MetaFileBuffer),
(WORD)OF_PROMPT | OF_REOPEN | OF_READ)
) != -1)
{
_llseek(fileNumber, (long)lpMF->MetaFilePosition, 0);
/* need to update MetaFileNumber for floppy files -- amitc */
lpMF->MetaFileNumber = fileNumber ;
}
}
return fileNumber;
}
#if 0
/****************************** Internal Function **************************\
* IsValidMetaFile(HANDLE hMetaData)
*
* Validates a metafile
*
* Returns TRUE iff hMetaData is a valid metafile
*
\***************************************************************************/
BOOL GDIENTRY IsValidMetaFile(HANDLE hMetaData)
{
LPMETADATA lpMetaData;
BOOL status = FALSE;
GdiLogFunc3( " IsValidMetaFile");
/* if this is a valid metafile we will save the version in a global variable */
if (hMetaData && (lpMetaData = (LPMETADATA) GlobalLock(hMetaData)))
{
status = (
(lpMetaData->dataHeader.mtType == MEMORYMETAFILE ||
lpMetaData->dataHeader.mtType == DISKMETAFILE) &&
(lpMetaData->dataHeader.mtHeaderSize == HEADERSIZE) &&
((lpMetaData->dataHeader.mtVersion ==METAVERSION) ||
(lpMetaData->dataHeader.mtVersion ==METAVERSION100))
);
GlobalUnlock(hMetaData);
}
return status;
}
#endif
#define INITIALBUFFERSIZE 16384
/****************************** Internal Function **************************\
*
* AllocBuffer - Allocates a buffer as "large" as possible
*
\***************************************************************************/
HANDLE INTERNAL AllocBuffer(LPWORD piBufferSize)
{
WORD iCurBufferSize = INITIALBUFFERSIZE;
HANDLE hBuffer;
GdiLogFunc3( " AllocBuffer");
while (!(hBuffer = GlobalAlloc(GMEM_MOVEABLE |
GMEM_NODISCARD, (LONG) iCurBufferSize))
&& iCurBufferSize)
iCurBufferSize >>= 1;
*piBufferSize = iCurBufferSize;
return (iCurBufferSize) ? hBuffer : NULL;
}
/****************************** Internal Function **************************\
* CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo)
*
* This routine takes a memory device context and a DIB bitmap, creates a
* compatible bitmap for the DC and fills it with the bits from the DIB (co-
* -nverting to the device dependent format). The pointer to the DIB bits
* start immediately after the color table in the INFO header. **
* **
* The routine returns the handle to the bitmap with the bits filled in if
* everything goes well else it returns NULL. **
\***************************************************************************/
HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo)
{
HBITMAP hBitmap ;
LPBYTE lpDIBits ;
GdiLogFunc3( " CreateBitmapForDC");
/* preserve monochrome if it started out as monochrome
** and check for REAL Black&white monochrome as opposed
** to a 2-color DIB
*/
if (IsDIBBlackAndWhite(lpDIBInfo))
hBitmap = CreateBitmap ((WORD)lpDIBInfo->biWidth,
(WORD)lpDIBInfo->biHeight,
1, 1, (LPBYTE) NULL);
else
/* otherwise, make a compatible bitmap */
hBitmap = CreateCompatibleBitmap (hMemDC,
(WORD)lpDIBInfo->biWidth,
(WORD)lpDIBInfo->biHeight);
if (!hBitmap)
goto CreateBitmapForDCErr ;
/* take a pointer past the header of the DIB, to the start of the color
table */
lpDIBits = (LPBYTE) lpDIBInfo + sizeof (BITMAPINFOHEADER) ;
/* take the pointer past the color table */
lpDIBits += GetSizeOfColorTable (lpDIBInfo) ;
/* get the bits from the DIB into the Bitmap */
if (!SetDIBits (hMemDC, hBitmap, 0, (WORD)lpDIBInfo->biHeight,
lpDIBits, (LPBITMAPINFO)lpDIBInfo, 0))
{
DeleteObject(hBitmap);
goto CreateBitmapForDCErr ;
}
/* return success */
return (hBitmap) ;
CreateBitmapForDCErr:
/* returm failure for function */
return (NULL) ;
}
/****************************** Internal Function **************************\
* GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
*
* Returns the number of bytes in the color table for the giving info header
*
\***************************************************************************/
WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
{
GdiLogFunc3( "GetSizeOfColorTable");
if (lpDIBInfo->biClrUsed)
return((WORD)lpDIBInfo->biClrUsed * (WORD)sizeof(RGBQUAD));
else
{
switch (lpDIBInfo->biBitCount)
{
case 1:
return (2 * sizeof (RGBQUAD)) ;
break ;
case 4:
return (16 * sizeof (RGBQUAD)) ;
break ;
case 8:
return (256 * sizeof (RGBQUAD)) ;
break ;
default:
return (0) ;
break ;
}
}
}
#if 0 // this is going to gdi.dll
/***************************** Public Function ****************************\
* BOOL APIENTRY DeleteMetaFile(hmf)
*
* Frees a metafile handle.
*
* Effects:
*
\***************************************************************************/
BOOL GDIENTRY DeleteMetaFile(HMETAFILE hmf)
{
GdiLogFunc("DeleteMetaFile");
GlobalFree(hmf);
return(TRUE);
}
/***************************** Public Function ****************************\
* HMETAFILE APIENTRY GetMetaFile(pzFilename)
*
* Returns a metafile handle for a disk based metafile.
*
* Effects:
*
* History:
* Sat 14-Oct-1989 14:21:37 -by- Paul Klingler [paulk]
* Wrote it.
\***************************************************************************/
HMETAFILE GDIENTRY GetMetaFile(LPSTR pzFilename)
{
BOOL status=FALSE;
UINT cBytes;
int file;
HMETAFILE hmf;
LPMETAFILE lpmf;
GdiLogFunc("GetMetaFile");
// Allocate the Metafile
if(hmf = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)sizeof(METAFILE)))
{
lpmf = (LPMETAFILE)GlobalLock(hmf);
// Make sure the file Exists
if((file = OpenFile(pzFilename,
&(lpmf->MetaFileBuffer),
(WORD)OF_PROMPT | OF_EXIST)) == -1L)
{
ASSERTGDI( FALSE, "GetMetaFile: Metafile does not exist");
goto exitGetMetaFile;
}
// Open the file
if((file = OpenFile(pzFilename,
&(lpmf->MetaFileBuffer),
(WORD)OF_PROMPT | OF_REOPEN | OF_READWRITE)) == -1)
{
ASSERTGDI( FALSE, "GetMetaFile: Unable to open Metafile");
goto exitGetMetaFile;
}
cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER));
// Check for an Aldus header
if (*((LPDWORD)&(lpmf->MetaFileHeader)) == 0x9AC6CDD7)
{
_llseek( file, 22, 0);
cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER));
}
_lclose(file);
// Validate the metafile
if(cBytes == sizeof(METAHEADER))
{
lpmf->MetaFileHeader.mtType = DISKMETAFILE;
status = TRUE;
}
exitGetMetaFile:
GlobalUnlock(hmf);
}
if(status == FALSE)
{
GlobalFree(hmf);
hmf = NULL;
}
return(hmf);
}
#endif // this is going to gdi.dll
#ifdef WIN32
#undef GetViewportExt
DWORD GetViewportExt32(HDC hdc)
{
SIZE sz;
GetViewportExt( hdc, &sz );
return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy)));
}
#undef GetWindowExt
DWORD GetWindowExt32(HDC hdc)
{
SIZE sz;
GetWindowExt( hdc, &sz );
return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy)));
}
#undef SetViewportExt
DWORD SetViewportExt32(HDC hdc, UINT x, UINT y)
{
SIZE sz;
SetViewportExt( hdc, x, y, &sz );
return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy)));
}
#undef SetWindowExt
DWORD SetWindowExt32(HDC hdc, UINT x, UINT y)
{
SIZE sz;
SetWindowExt( hdc, x, y, &sz );
return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy)));
}
/* Convert WORD arrays into DWORDs */
LPINT ConvertInts( signed short * pWord, UINT cWords )
{
UINT ii;
LPINT pInt;
pInt = (LPINT)LocalAlloc( LMEM_FIXED, cWords * sizeof(UINT));
for( ii=0; ii<cWords; ii++)
{
pInt[ii] = (long)(signed)pWord[ii];
}
return(pInt);
}
#endif // WIN32