524 lines
13 KiB
C
524 lines
13 KiB
C
/****************************** Module Header ******************************\
|
|
* Module Name: MetaSup.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
|
|
*
|
|
*
|
|
* Public Functions:
|
|
* EnumMetaFile
|
|
* Private Functions:
|
|
*
|
|
*
|
|
* Created: 02-Jul-1991
|
|
*
|
|
* Copyright (c) 1985, 1991 Microsoft Corporation
|
|
*
|
|
* History:
|
|
* 02-Jul-1991 -by- John Colleran [johnc]
|
|
* Combined From Win 3.1 and WLO 1.0 sources
|
|
\***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include "gdi16.h"
|
|
|
|
extern HANDLE hFirstMetaFile;
|
|
extern HDC hScreenDC;
|
|
|
|
#define MYSTOCKBITMAP (SYSTEM_FIXED_FONT+1)
|
|
#define MYSTOCKRGN (SYSTEM_FIXED_FONT+2)
|
|
#define CNT_GDI_STOCK_OBJ (MYSTOCKRGN+1)
|
|
|
|
HANDLE ahStockObject[CNT_GDI_STOCK_OBJ] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
|
|
HBITMAP hStaticBitmap;
|
|
|
|
// Provide a Mapping from Object type to a stock object; See GetCurObject
|
|
int mpObjectToStock[] =
|
|
{ -1, // UNUSED 0
|
|
WHITE_PEN, // OBJ_PEN 1
|
|
BLACK_BRUSH, // OBJ_BRUSH 2
|
|
-1, // OBJ_DC 3
|
|
-1, // OBJ_METADC 4
|
|
DEFAULT_PALETTE, // OBJ_PALETTE 5
|
|
SYSTEM_FONT, // OBJ_FONT 6
|
|
MYSTOCKBITMAP, // OBJ_BITMAP 7
|
|
MYSTOCKRGN, // OBJ_RGN 8 //!!!!! init
|
|
-1, // OBJ_METAFILE 9
|
|
-1 }; // OBJ_MEMDC 10
|
|
|
|
|
|
HANDLE INTERNAL GetCurObject(HDC hdc, WORD wObjType)
|
|
{
|
|
HANDLE cur;
|
|
|
|
|
|
//!!!!! fix to work with meta DCs as well
|
|
|
|
GdiLogFunc3( " GetCurObject" );
|
|
|
|
ASSERTGDI( wObjType <= MAX_OBJ, "GetCurObject invalid Obj" );
|
|
|
|
//!!!!! fix regions when new API is done
|
|
if( wObjType == OBJ_RGN )
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if( wObjType == OBJ_PALETTE)
|
|
{
|
|
cur = SelectPalette( hdc, ahStockObject[DEFAULT_PALETTE], FALSE );
|
|
SelectPalette( hdc, cur, FALSE );
|
|
}
|
|
else
|
|
{
|
|
cur = SelectObject(hdc,ahStockObject[mpObjectToStock[wObjType]]);
|
|
SelectObject( hdc, cur );
|
|
}
|
|
|
|
ASSERTGDIW( cur, "GetCurObect Failed. Type %d", wObjType );
|
|
return(cur);
|
|
}
|
|
|
|
#if 0 // this is going to gdi.dll
|
|
|
|
/******************************** Public Function **************************\
|
|
* BOOL GDIENTRY EnumMetaFile(hmf)
|
|
*
|
|
* The EnumMetaFile function enumerates the GDI calls within the metafile
|
|
* identified by the hMF parameter. The EnumMetaFile function retrieves each
|
|
* GDI call within the metafile and passes it to the function pointed to by the
|
|
* lpCallbackFunc parameter. This callback function, an application-supplied
|
|
* function, can process each GDI call as desired. Enumeration continues until
|
|
* there are no more GDI calls or the callback function returns zero.
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL GDIENTRY EnumMetaFile(hdc, hMF, lpCallbackFunction, lpClientData)
|
|
HDC hdc;
|
|
LOCALHANDLE hMF;
|
|
FARPROC lpCallbackFunction;
|
|
LPBYTE lpClientData;
|
|
{
|
|
WORD i;
|
|
WORD noObjs;
|
|
BOOL bPrint=TRUE;
|
|
HANDLE hObject;
|
|
HANDLE hLBrush;
|
|
HANDLE hLPen;
|
|
HANDLE hLFont;
|
|
HANDLE hRegion;
|
|
HANDLE hPalette;
|
|
LPMETAFILE lpMF;
|
|
LPMETARECORD lpMR = NULL;
|
|
LPHANDLETABLE lpHandleTable = NULL;
|
|
GLOBALHANDLE hHandleTable = NULL;
|
|
|
|
|
|
GdiLogFunc( "EnumMetaFile");
|
|
|
|
if (!ISDCVALID(hdc))
|
|
{
|
|
ASSERTGDI( FALSE, "EnumMetaFile: DC is invalid");
|
|
return (FALSE);
|
|
}
|
|
|
|
/* use GlobalFix() instead of GlobalLock() to insure that the
|
|
** memory never moves, keeping our aliased selector pointing to the
|
|
** right place
|
|
*/
|
|
// !!!!! replaced GlobalFix with GlobalLock
|
|
if (hMF && (lpMF = (LPMETAFILE)(DWORD)(0xFFFF0000 & (DWORD)GlobalLock(hMF))))
|
|
{
|
|
if ((noObjs = lpMF->MetaFileHeader.mtNoObjects) > 0)
|
|
{
|
|
if (!(hHandleTable =
|
|
GlobalAlloc((WORD)(GMEM_ZEROINIT | GMEM_MOVEABLE), (LONG)
|
|
((sizeof(HANDLE) * lpMF->MetaFileHeader.mtNoObjects) +
|
|
sizeof(WORD)))))
|
|
{
|
|
goto ABRRT2;
|
|
}
|
|
lpHandleTable = (LPHANDLETABLE)GlobalLock(hHandleTable);
|
|
}
|
|
|
|
/* only do object save/reselect for real DC's */
|
|
if (hdc && !ISMETADC(hdc))
|
|
{
|
|
hLPen = GetCurObject( hdc, OBJ_PEN ); /* save the old objects so */
|
|
hLBrush = GetCurObject( hdc, OBJ_BRUSH); /* we can put them back */
|
|
hLFont = GetCurObject( hdc, OBJ_FONT);
|
|
hRegion = GetCurObject( hdc, OBJ_RGN);
|
|
hPalette = GetCurObject( hdc, OBJ_PALETTE);
|
|
}
|
|
|
|
while(lpMR = GetEvent(lpMF, lpMR, FALSE))
|
|
{
|
|
typedef int (FAR PASCAL *ENUMPROC)(HDC, LPHANDLETABLE, LPMETARECORD, int, LPBYTE);
|
|
|
|
if ((bPrint = (*((ENUMPROC)lpCallbackFunction))(hdc, lpHandleTable, lpMR, noObjs, lpClientData))
|
|
== 0)
|
|
{
|
|
GetEvent(lpMF,lpMR,TRUE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hdc && !ISMETADC(hdc))
|
|
{
|
|
SelectObject(hdc, hLPen);
|
|
SelectObject(hdc, hLBrush);
|
|
SelectObject(hdc, hLFont);
|
|
if (hRegion)
|
|
SelectObject(hdc, hRegion);
|
|
SelectPalette(hdc, hPalette, 0);
|
|
}
|
|
|
|
for(i = 0; i < lpMF->MetaFileHeader.mtNoObjects; ++i)
|
|
if (hObject = lpHandleTable->objectHandle[i])
|
|
DeleteObject(hObject);
|
|
|
|
if (hHandleTable)
|
|
{
|
|
GlobalUnlock(hHandleTable);
|
|
GlobalFree(hHandleTable);
|
|
}
|
|
ABRRT2:;
|
|
GlobalUnfix(hMF);
|
|
}
|
|
return(bPrint);
|
|
}
|
|
#endif // this is going to gdi.dll
|
|
|
|
/***************************** Internal Function **************************\
|
|
* BOOL FAR PASCAL PlayIntoAMetafile
|
|
*
|
|
* if this record is being played into another metafile, simply record
|
|
* it into that metafile, without hassling with a real playing.
|
|
*
|
|
* Returns: TRUE if record was played (copied) into another metafile
|
|
* FALESE if destination DC was a real (non-meta) DC
|
|
*
|
|
* Effects: ?
|
|
*
|
|
* Warnings: ?
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL INTERNAL PlayIntoAMetafile(LPMETARECORD lpMR, HDC hdcDest)
|
|
{
|
|
GdiLogFunc3( " PlayIntoAMetafile");
|
|
|
|
if (!ISMETADC(hdcDest))
|
|
return(FALSE);
|
|
else
|
|
{
|
|
/* the size is the same minus 3 words for the record header */
|
|
RecordParms(hdcDest, lpMR->rdFunction, (DWORD)lpMR->rdSize - 3,
|
|
(LPWORD)&(lpMR->rdParm[0]));
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
BOOL INTERNAL IsDCValid(HDC hdc)
|
|
{
|
|
NPMETARECORDER npdc;
|
|
|
|
hdc = (HDC)HANDLEFROMMETADC(hdc);
|
|
|
|
// Is the DC a valid Real DC
|
|
switch (GetObjectType(hdc))
|
|
{
|
|
case OBJ_DC:
|
|
case OBJ_METADC:
|
|
case OBJ_MEMDC:
|
|
return(TRUE);
|
|
break;
|
|
}
|
|
|
|
// Is the DC a GDI16 metafile DC
|
|
if (npdc = (NPMETARECORDER)LocalLock(hdc))
|
|
{
|
|
if( npdc->metaDCHeader.ident == ID_METADC )
|
|
return(TRUE);
|
|
}
|
|
|
|
ASSERTGDI(FALSE, "Invalid DC");
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/***************************** Internal Function **************************\
|
|
* IsMetaDC(hdc)
|
|
*
|
|
*
|
|
* Returns TRUE iff hdc is a valid GDI16 Metafile
|
|
*
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL INTERNAL IsMetaDC(HDC hdc)
|
|
{
|
|
NPMETARECORDER npdc;
|
|
BOOL fMeta = FALSE;
|
|
|
|
GdiLogFunc3(" IsMetaDC");
|
|
|
|
if( ((UINT)hdc) & METADCBIT )
|
|
if( npdc = (NPMETARECORDER)LocalLock( (HANDLE)HANDLEFROMMETADC(hdc)))
|
|
{
|
|
if( npdc->metaDCHeader.ident == ID_METADC )
|
|
fMeta = TRUE;
|
|
|
|
LocalUnlock( (HANDLE)HANDLEFROMMETADC(hdc) );
|
|
}
|
|
|
|
return( fMeta );
|
|
}
|
|
|
|
|
|
/***************************** Public Function ****************************\
|
|
* HANDLE INTERNAL GetPMetaFile( HDC hdc )
|
|
*
|
|
* if hdc is a DC it is validated as a metafile
|
|
* if hdc is a PALETTE the metafile the palette is selected into is returned
|
|
*
|
|
* Returns:
|
|
* -1 iff Error
|
|
* HANDLE to metafile if valid meta DC
|
|
* 0 if valid object
|
|
*
|
|
* Effects:
|
|
*
|
|
* History:
|
|
* 08-Jul-1991 -by- John Colleran [johnc]
|
|
* Wrote it.
|
|
\***************************************************************************/
|
|
|
|
HANDLE INTERNAL GetPMetaFile( HDC hdc )
|
|
{
|
|
NPMETARECORDER npMR;
|
|
|
|
GdiLogFunc3( " GetPMetaFile");
|
|
|
|
|
|
if( hdc & METADCBIT )
|
|
{
|
|
if( npMR = (NPMETARECORDER)LocalLock(HANDLEFROMMETADC(hdc)) )
|
|
{
|
|
if(npMR->metaDCHeader.ident == ID_METADC )
|
|
{
|
|
LocalUnlock(HANDLEFROMMETADC(hdc));
|
|
return( HANDLEFROMMETADC(hdc) );
|
|
}
|
|
LocalUnlock(HANDLEFROMMETADC(hdc));
|
|
}
|
|
}
|
|
|
|
// is hdc really a palette or object for the strange no-DC APIs
|
|
// Validate the object is real
|
|
if( (hdc != (HDC)NULL) && (GetObjectType( hdc ) == 0))
|
|
{
|
|
extern int iLogLevel; // Gdi.asm
|
|
// WinWord has a bug where it deletes valid objects so
|
|
// only log this error if the loglevel is high.
|
|
ASSERTGDI( (iLogLevel < 5), "GetPMetaFile: Invalid metafile or object")
|
|
return( -1 ); // Not a valid object
|
|
}
|
|
else
|
|
return( 0 ); // Valid Object
|
|
}
|
|
|
|
|
|
BOOL INTERNAL IsObjectStock(HANDLE hObj)
|
|
{
|
|
int ii;
|
|
|
|
// handle Bitmaps and regions !!!!!
|
|
|
|
// Get all the Stock Objects
|
|
for( ii=WHITE_BRUSH; ii<=NULL_PEN; ii++ )
|
|
if( ahStockObject[ii] == hObj )
|
|
return( TRUE );
|
|
|
|
for( ii=OEM_FIXED_FONT; ii<=SYSTEM_FIXED_FONT; ii++ )
|
|
if( ahStockObject[ii] == hObj )
|
|
return( TRUE );
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
/***************************** Internal Function **************************\
|
|
* GetObjectAndType
|
|
*
|
|
*
|
|
* Returns the object type, eg OBJ_FONT, as well as a the LogObject
|
|
*
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int INTERNAL GetObjectAndType(HANDLE hObj, LPSTR lpObjectBuf)
|
|
{
|
|
int iObj = -1;
|
|
|
|
GdiLogFunc3( " GetObjectAndType" );
|
|
|
|
GetObject(hObj, MAXOBJECTSIZE, lpObjectBuf);
|
|
switch( iObj = (int)GetObjectType(hObj) )
|
|
{
|
|
case OBJ_PEN:
|
|
case OBJ_BITMAP:
|
|
case OBJ_BRUSH:
|
|
case OBJ_FONT:
|
|
break;
|
|
|
|
// Watch out for Palettes; returns the number of entries.
|
|
case OBJ_PALETTE:
|
|
GetPaletteEntries( hObj, 0, 1, (LPPALETTEENTRY)lpObjectBuf );
|
|
iObj = OBJ_PALETTE;
|
|
break;
|
|
|
|
case OBJ_RGN:
|
|
break;
|
|
|
|
default:
|
|
ASSERTGDIW( 0, "GetObject unknown object type: %d", iObj);
|
|
break;
|
|
}
|
|
return( iObj );
|
|
}
|
|
|
|
|
|
/***************************** Internal Function **************************\
|
|
* BOOL GDIENTRY InitializeGdi
|
|
*
|
|
* Initializes the GDI16.exe
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* Returns: TRUE iff GDI was initilized successfully
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL INTERNAL InitializeGdi(void)
|
|
{
|
|
BOOL status;
|
|
int ii;
|
|
|
|
GdiLogFunc2 ( " InitializeGDI");
|
|
if( !(hScreenDC = CreateCompatibleDC(NULL)))
|
|
goto ExitInit;
|
|
|
|
// Get all the Stock Objects
|
|
for( ii=WHITE_BRUSH; ii<=NULL_PEN; ii++ )
|
|
ahStockObject[ii] = GetStockObject( ii );
|
|
|
|
for( ii=OEM_FIXED_FONT; ii<=SYSTEM_FIXED_FONT; ii++ )
|
|
ahStockObject[ii] = GetStockObject( ii );
|
|
|
|
// Create a fake Stock Region and Bitmap
|
|
ahStockObject[MYSTOCKRGN] = CreateRectRgn(1,1,3,3);
|
|
hStaticBitmap = ahStockObject[MYSTOCKBITMAP] = CreateBitmap(1,1,1,1,NULL);
|
|
|
|
status = TRUE;
|
|
|
|
ExitInit:
|
|
ASSERTGDI( status, "GDI16 Failed to initialized correctly");
|
|
return( status );
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
debugging support
|
|
|
|
***************************************************************************/
|
|
|
|
#ifdef DEBUG
|
|
|
|
void dDbgOut(int iLevel, LPSTR lpszFormat, ...)
|
|
{
|
|
char buf[256];
|
|
char far *lpcLogLevel;
|
|
extern int iLogLevel; // Gdi.asm
|
|
extern int iBreakLevel; // Gdi.asm
|
|
|
|
// Get the external logging level from the emulated ROM
|
|
|
|
(LONG)lpcLogLevel = 0x00400042;
|
|
if (*lpcLogLevel >= '0' && *lpcLogLevel <= '9')
|
|
iLogLevel = (*lpcLogLevel-'0')*10+(*(lpcLogLevel+1)-'0');
|
|
|
|
if (iLevel<=iLogLevel)
|
|
{
|
|
OutputDebugString(" W16GDI:");
|
|
wvsprintf(buf, lpszFormat, (LPSTR)(&lpszFormat + 1));
|
|
OutputDebugString(buf);
|
|
OutputDebugString("\r\n");
|
|
|
|
if( iLevel<=iBreakLevel )
|
|
_asm int 3;
|
|
}
|
|
}
|
|
|
|
void dDbgAssert(LPSTR str, LPSTR file, int line)
|
|
{
|
|
static char buf3[256];
|
|
|
|
wsprintf(buf3, "Assertion FAILED: %s %d : %s", file, line, str );
|
|
OutputDebugString(buf3);
|
|
OutputDebugString("\r\n");
|
|
_asm int 3;
|
|
}
|
|
|
|
|
|
|
|
#undef LocalLock
|
|
#undef LocalUnlock
|
|
#undef LocalAlloc
|
|
#undef GlobalLock
|
|
#undef GlobalUnlock
|
|
#undef GlobalAlloc
|
|
PSTR INTERNAL _LocalLock(HANDLE h )
|
|
{
|
|
PSTR p;
|
|
dDbgOut(7, "LocalLock 0x%X", h );
|
|
p = LocalLock(h);
|
|
if( p == NULL )
|
|
_asm int 3
|
|
return( p );
|
|
}
|
|
BOOL INTERNAL _LocalUnlock(HANDLE h )
|
|
{
|
|
dDbgOut(7, "LocalUnlock 0x%X", h );
|
|
return( LocalUnlock(h) );
|
|
}
|
|
HANDLE INTERNAL _LocalAlloc(WORD w, WORD w2)
|
|
{
|
|
dDbgOut(7, "LocalAlloc");
|
|
return( LocalAlloc(w,w2) );
|
|
}
|
|
LPSTR INTERNAL _GlobalLock(HANDLE h )
|
|
{
|
|
dDbgOut(7, "GlobalLock 0x%X", h );
|
|
return( GlobalLock(h) );
|
|
}
|
|
BOOL INTERNAL _GlobalUnlock(HANDLE h )
|
|
{
|
|
dDbgOut(7, "GlobalUnlock 0x%X", h );
|
|
return( GlobalUnlock(h) );
|
|
}
|
|
HANDLE INTERNAL _GlobalAlloc(WORD w, DWORD dw )
|
|
{
|
|
dDbgOut(7, "GlobalAlloc");
|
|
return( GlobalAlloc(w,dw) );
|
|
}
|
|
|
|
|
|
|
|
#endif
|