/****************************** 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 #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