|
|
/*++
* * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WGFONT.C * WOW32 16-bit GDI API support * * History: * Created 07-Mar-1991 by Jeff Parsons (jeffpar) --*/
#include "precomp.h"
#pragma hdrstop
#include "wingdip.h"
MODNAME(wgfont.c);
extern int RemoveFontResourceTracking(LPCSTR psz, UINT id); extern int AddFontResourceTracking(LPCSTR psz, UINT id);
// for Quickbooks v4 & v5 OCR font support
void LoadOCRFont(void); char szOCRA[] = "OCR-A"; char szFonts[] = "\\FONTS"; char szOCRDotTTF[] = "\\OCR-A.TTF"; BOOL gfOCRFontLoaded = FALSE;
// a.k.a. WOWAddFontResource
ULONG FASTCALL WG32AddFontResource(PVDMFRAME pFrame) { ULONG ul; PSZ psz1; register PADDFONTRESOURCE16 parg16;
GETARGPTR(pFrame, sizeof(ADDFONTRESOURCE16), parg16); GETPSZPTR(parg16->f1, psz1);
// note: we will never get an hModule in the low word here.
// the 16-bit side resolves hModules to an lpsz before calling us
if( CURRENTPTD()->dwWOWCompatFlags & WOWCF_UNLOADNETFONTS ) { ul = GETINT16(AddFontResourceTracking(psz1,(UINT)CURRENTPTD())); } else { ul = GETINT16(AddFontResourceA(psz1)); }
FREEPSZPTR(psz1); FREEARGPTR(parg16);
RETURN(ul); }
#define PITCH_MASK ( FIXED_PITCH | VARIABLE_PITCH )
ULONG FASTCALL WG32CreateFont(PVDMFRAME pFrame) { ULONG ul; PSZ psz14; register PCREATEFONT16 parg16; INT iWidth; char achCapString[LF_FACESIZE]; BYTE lfCharSet; BYTE lfPitchAndFamily; #ifdef FE_SB
BOOL bUseAlternateFace = FALSE; #endif
GETARGPTR(pFrame, sizeof(CREATEFONT16), parg16); GETPSZPTR(parg16->f14, psz14);
// take careof compatiblity flags:
// if a specific width is specified and GACF_30AVGWIDTH compatiblity
// flag is set, scaledown the width by 7/8.
//
iWidth = INT32(parg16->f2); if (iWidth != 0 && (W32GetAppCompatFlags((HAND16)NULL) & GACF_30AVGWIDTH)) { iWidth = (iWidth * 7) / 8; }
lfCharSet = BYTE32(parg16->f9); lfPitchAndFamily = BYTE32(parg16->f13);
#ifdef FE_SB
if (psz14 && *psz14) #else // !FE_SB
if (psz14) #endif // !FE_SB
{ // Capitalize the string for faster compares.
WOW32_strncpy(achCapString, psz14, LF_FACESIZE); WOW32_strupr(achCapString);
// Here we are going to implement a bunch of Win 3.1 hacks rather
// than contaminate the 32-bit engine. These same hacks can be found
// in WOW (in the CreateFont/CreateFontIndirect code).
//
// These hacks are keyed off the facename in the LOGFONT. String
// comparisons have been unrolled for maximal performance.
// Win 3.1 facename-based hack. Some apps, like
// Publisher, create a "Helv" font but have the lfPitchAndFamily
// set to specify FIXED_PITCH. To work around this, we will patch
// the pitch field for a "Helv" font to be variable.
if ( !WOW32_strcmp(achCapString, szHelv) ) { lfPitchAndFamily |= ( (lfPitchAndFamily & ~PITCH_MASK) | VARIABLE_PITCH ); } else { // Win 3.1 hack for Legacy 2.0. When a printer does not enumerate
// a "Tms Rmn" font, the app enumerates and gets the LOGFONT for
// "Script" and then create a font with the name "Tms Rmn" but with
// the lfCharSet and lfPitchAndFamily taken from the LOGFONT for
// "Script". Here we will over the lfCharSet to be ANSI_CHARSET.
if ( !WOW32_strcmp(achCapString, szTmsRmn) ) { lfCharSet = ANSI_CHARSET; } else { // If the lfFaceName is "Symbol", "Zapf Dingbats", or "ZapfDingbats",
// enforce lfCharSet to be SYMBOL_CHARSET. Some apps (like Excel) ask
// for a "Symbol" font but have the char set set to ANSI. PowerPoint
// has the same problem with "Zapf Dingbats".
if ( !WOW32_strcmp(achCapString, szSymbol) || !WOW32_strcmp(achCapString, szZapfDingbats) || !WOW32_strcmp(achCapString, szZapf_Dingbats) ) { lfCharSet = SYMBOL_CHARSET; } } }
// Win3.1(Win95) hack for Mavis Beacon Teaches Typing 3.0
// The app uses a fixed width of 34*13 for the typing screen.
// NT returns 14 from GetTextExtent for Mavis Beacon Courier FP font (width of 14)
// while Win95 returns 13, thus long strings won't fit in the typing screen on NT.
// Force the width to 13.
if ( iWidth==14 && (INT32(parg16->f1)== 20) && !WOW32_strcmp(achCapString, szMavisCourier)) { iWidth = 13; }
#ifdef FE_SB
// WOWCF_FE_ICHITARO_ITALIC
// Ichitaro asks for System Mincho because WIFE fonts aren't installed
// we give it a proportional font which is can't handle. If we see
// this face name we will replace it with Ms Mincho
if (GetSystemDefaultLangID() == 0x411 && CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_ICHITARO_ITALIC ) { if(!WOW32_strcmp(achCapString, szSystemMincho)) { strcpy(achCapString, szMsMincho); bUseAlternateFace = TRUE; } } #endif // FE_SB
}
#ifdef FE_SB
ul = GETHFONT16(CreateFont(INT32(parg16->f1), iWidth, INT32(parg16->f3), INT32(parg16->f4), INT32(parg16->f5), BYTE32(parg16->f6), BYTE32(parg16->f7), BYTE32(parg16->f8), lfCharSet, BYTE32(parg16->f10), BYTE32(parg16->f11), BYTE32(parg16->f12), lfPitchAndFamily, (bUseAlternateFace ? achCapString : psz14) )); #else
ul = GETHFONT16(CreateFont(INT32(parg16->f1), iWidth, INT32(parg16->f3), INT32(parg16->f4), INT32(parg16->f5), BYTE32(parg16->f6), BYTE32(parg16->f7), BYTE32(parg16->f8), lfCharSet, BYTE32(parg16->f10), BYTE32(parg16->f11), BYTE32(parg16->f12), lfPitchAndFamily, psz14)); #endif
FREEPSZPTR(psz14); FREEARGPTR(parg16);
RETURN(ul); }
ULONG FASTCALL WG32CreateFontIndirect(PVDMFRAME pFrame) { ULONG ul; LOGFONT logfont; register PCREATEFONTINDIRECT16 parg16; char achCapString[LF_FACESIZE];
GETARGPTR(pFrame, sizeof(CREATEFONTINDIRECT16), parg16); GETLOGFONT16(parg16->f1, &logfont);
// Capitalize the string for faster compares.
WOW32_strncpy(achCapString, logfont.lfFaceName, LF_FACESIZE); CharUpperBuff(achCapString, LF_FACESIZE);
// Here we are going to implement a bunch of Win 3.1 hacks rather
// than contaminate the 32-bit engine. These same hacks can be found
// in WOW (in the CreateFont/CreateFontIndirect code).
//
// These hacks are keyed off the facename in the LOGFONT. String
// comparisons have been unrolled for maximal performance.
// Win 3.1 facename-based hack. Some apps, like
// Publisher, create a "Helv" font but have the lfPitchAndFamily
// set to specify FIXED_PITCH. To work around this, we will patch
// the pitch field for a "Helv" font to be variable.
if ( !WOW32_strcmp(achCapString, szHelv) ) { logfont.lfPitchAndFamily |= ( (logfont.lfPitchAndFamily & ~PITCH_MASK) | VARIABLE_PITCH ); #ifdef FE_SB
//
// FE Win 3.1 facename-based hack. Some FE apps
// create a "Helv" font but have the lfCharSet
// set to DBCS charset (ex. SHIFTJIS_CHARSET).
// To work around this, we will wipe out the
// lfFaceName[0] with '\0' and let GDI picks a
// DBCS font for us.
//
if (IS_ANY_DBCS_CHARSET(logfont.lfCharSet)) logfont.lfFaceName[0]='\0'; #endif // FE_SB
} else { // Win 3.1 hack for Legacy 2.0. When a printer does not enumerate
// a "Tms Rmn" font, the app enumerates and gets the LOGFONT for
// "Script" and then create a font with the name "Tms Rmn" but with
// the lfCharSet and lfPitchAndFamily taken from the LOGFONT for
// "Script". Here we will over the lfCharSet to be ANSI_CHARSET.
if ( !WOW32_strcmp(achCapString, szTmsRmn) ) { logfont.lfCharSet = ANSI_CHARSET; } // for Quickbooks v4 & v5 OCR font support (see LoadOCRFont for details)
else if ( !WOW32_strcmp(achCapString, szOCRA) ) {
// Further localize this hack to QuickBooks. Most other apps won't
// know about this quirk in this particular font.
if(logfont.lfCharSet == SYMBOL_CHARSET) { logfont.lfCharSet = DEFAULT_CHARSET;
if(!gfOCRFontLoaded) { LoadOCRFont(); } } } else { // If the lfFaceName is "Symbol", "Zapf Dingbats", or "ZapfDingbats",
// enforce lfCharSet to be SYMBOL_CHARSET. Some apps (like Excel) ask
// for a "Symbol" font but have the char set set to ANSI. PowerPoint
// has the same problem with "Zapf Dingbats".
if ( !WOW32_strcmp(achCapString, szSymbol) || !WOW32_strcmp(achCapString, szZapfDingbats) || !WOW32_strcmp(achCapString, szZapf_Dingbats) ) { logfont.lfCharSet = SYMBOL_CHARSET; }
#ifdef FE_SB
// WOWCF_FE_ICHITARO_ITALIC
// Ichitaro asks for System Mincho because WIFE fonts aren't installed
// we give it a proportional font which is can't handle. If we see
// this face name we will replace it with Ms Mincho
if (GetSystemDefaultLangID() == 0x411 && CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_ICHITARO_ITALIC ) { if(!WOW32_strcmp(achCapString, szSystemMincho)) { strcpy(logfont.lfFaceName, szMsMincho); } } #endif // FE_SB
} }
ul = GETHFONT16(CreateFontIndirect(&logfont));
FREEARGPTR(parg16);
RETURN(ul); }
LPSTR lpMSSansSerif = "MS Sans Serif"; LPSTR lpMSSerif = "MS Serif"; LPSTR lpHelvetica = "Helvetica";
INT W32EnumFontFunc(LPENUMLOGFONT pEnumLogFont, LPNEWTEXTMETRIC pNewTextMetric, INT nFontType, PFNTDATA pFntData) { INT iReturn; PARM16 Parm16; LPSTR lpFaceNameT = NULL;
WOW32ASSERT(pFntData);
// take care of compatibility flags:
// ORin DEVICE_FONTTYPE bit if the fonttype is truetype and the
// Compataibility flag GACF_CALLTTDEVICE is set.
//
if (nFontType & TRUETYPE_FONTTYPE) { if (W32GetAppCompatFlags((HAND16)NULL) & GACF_CALLTTDEVICE) { nFontType |= DEVICE_FONTTYPE; } }
// take care of compatibility flags:
// replace Ms Sans Serif with Helv and
// replace Ms Serif with Tms Rmn
//
// only if the facename is NULL and the compat flag GACF_ENUMHELVNTMSRMN
// is set.
if (pFntData->vpFaceName == (VPVOID)NULL) { if (W32GetAppCompatFlags((HAND16)NULL) & GACF_ENUMHELVNTMSRMN) { if (!WOW32_strcmp(pEnumLogFont->elfLogFont.lfFaceName, lpMSSansSerif)) { strcpy(pEnumLogFont->elfLogFont.lfFaceName, "Helv"); lpFaceNameT = lpMSSansSerif; } else if (!WOW32_strcmp(pEnumLogFont->elfLogFont.lfFaceName, lpHelvetica)) { strcpy(pEnumLogFont->elfLogFont.lfFaceName, "Helv"); lpFaceNameT = lpMSSansSerif; } else if (!WOW32_strcmp(pEnumLogFont->elfLogFont.lfFaceName, lpMSSerif)) { strcpy(pEnumLogFont->elfLogFont.lfFaceName, "Tms Rmn"); lpFaceNameT = lpMSSerif; } } }
CallAgain:
// be sure allocation size matches stackfree16() size below
pFntData->vpLogFont = stackalloc16(sizeof(ENUMLOGFONT16)+sizeof(NEWTEXTMETRIC16));
pFntData->vpTextMetric = (VPVOID)((LPSTR)pFntData->vpLogFont + sizeof(ENUMLOGFONT16));
PUTENUMLOGFONT16(pFntData->vpLogFont, pEnumLogFont); PUTNEWTEXTMETRIC16(pFntData->vpTextMetric, pNewTextMetric);
STOREDWORD(Parm16.EnumFontProc.vpLogFont, pFntData->vpLogFont); STOREDWORD(Parm16.EnumFontProc.vpTextMetric, pFntData->vpTextMetric); STOREDWORD(Parm16.EnumFontProc.vpData,pFntData->dwUserFntParam);
Parm16.EnumFontProc.nFontType = (SHORT)nFontType;
CallBack16(RET_ENUMFONTPROC, &Parm16, pFntData->vpfnEnumFntProc, (PVPVOID)&iReturn);
if(pFntData->vpLogFont) { stackfree16(pFntData->vpLogFont, (sizeof(ENUMLOGFONT16) + sizeof(NEWTEXTMETRIC16))); }
if (((SHORT)iReturn) && lpFaceNameT) { // if the callback returned true, now call with the actual facename
// Just to be sure, we again copy all the data for callback. This will
// take care of any apps which modify the passed in structures.
strcpy(pEnumLogFont->elfLogFont.lfFaceName, lpFaceNameT); lpFaceNameT = (LPSTR)NULL; goto CallAgain; } return (SHORT)iReturn; }
ULONG W32EnumFontHandler( PVDMFRAME pFrame, BOOL fEnumFontFamilies ) { ULONG ul = 0; PSZ psz2; FNTDATA FntData; register PENUMFONTS16 parg16;
GETARGPTR(pFrame, sizeof(ENUMFONTS16), parg16); GETPSZPTR(parg16->f2, psz2);
FntData.vpfnEnumFntProc = DWORD32(parg16->f3); FntData.dwUserFntParam = DWORD32(parg16->f4); FntData.vpFaceName = DWORD32(parg16->f2);
if ( fEnumFontFamilies ) { ul = GETINT16(EnumFontFamilies(HDC32(parg16->f1), psz2, (FONTENUMPROC)W32EnumFontFunc, (LPARAM)&FntData)); } else { ul = GETINT16(EnumFonts(HDC32(parg16->f1), psz2, (FONTENUMPROC)W32EnumFontFunc, (LPARAM)&FntData)); }
FREEPSZPTR(psz2); FREEARGPTR(parg16);
RETURN(ul); }
ULONG FASTCALL WG32EnumFonts(PVDMFRAME pFrame) { return( W32EnumFontHandler( pFrame, FALSE ) ); }
ULONG FASTCALL WG32GetAspectRatioFilter(PVDMFRAME pFrame) { ULONG ul = 0; SIZE size2; register PGETASPECTRATIOFILTER16 parg16;
GETARGPTR(pFrame, sizeof(GETASPECTRATIOFILTER16), parg16);
if (GETDWORD16(GetAspectRatioFilterEx(HDC32(parg16->f1), &size2))) { ul = (WORD)size2.cx | (size2.cy << 16); }
FREEARGPTR(parg16);
RETURN(ul); }
ULONG FASTCALL WG32GetCharWidth(PVDMFRAME pFrame) { ULONG ul = 0L; INT ci; PINT pi4; register PGETCHARWIDTH16 parg16; INT BufferT[256];
GETARGPTR(pFrame, sizeof(GETCHARWIDTH16), parg16);
ci = WORD32(parg16->wLastChar) - WORD32(parg16->wFirstChar) + 1; pi4 = STACKORHEAPALLOC(ci * sizeof(INT), sizeof(BufferT), BufferT);
if (pi4) { ULONG ulLast = WORD32(parg16->wLastChar); #ifdef FE_SB
/*
* If ulLast sets DBCS code (0x82xx), then below code is illigal. */ if (ulLast > 0xff && !(IsDBCSLeadByte(HIBYTE(ulLast)))) #else // !FE_SB
if (ulLast > 0xff) #endif // !FE_SB
ulLast = 0xff;
ul = GETBOOL16(GetCharWidth(HDC32(parg16->hDC), WORD32(parg16->wFirstChar), ulLast, pi4));
PUTINTARRAY16(parg16->lpIntBuffer, ci, pi4); STACKORHEAPFREE(pi4, BufferT);
}
FREEARGPTR(parg16);
RETURN(ul); }
// a.k.a. WOWRemoveFontResource
ULONG FASTCALL WG32RemoveFontResource(PVDMFRAME pFrame) { ULONG ul; PSZ psz1; register PREMOVEFONTRESOURCE16 parg16;
GETARGPTR(pFrame, sizeof(REMOVEFONTRESOURCE16), parg16);
GETPSZPTR(parg16->f1, psz1);
// note: we will never get an hModule in the low word here.
// the 16-bit side resolves hModules to an lpsz before calling us
if( CURRENTPTD()->dwWOWCompatFlags & WOWCF_UNLOADNETFONTS ) { ul = GETBOOL16(RemoveFontResourceTracking(psz1,(UINT)CURRENTPTD())); } else { ul = GETBOOL16(RemoveFontResource(psz1)); }
FREEPSZPTR(psz1);
FREEARGPTR(parg16);
RETURN(ul); }
/* WG32GetCurLogFont
* * This thunk implements the undocumented Win3.0 and Win3.1 API * GetCurLogFont (GDI.411). Symantec QA4.0 uses it. * * HFONT GetCurLogFont (HDC) * HDC hDC; // Device Context
* * This function returns the current Logical font selected for the * specified device context. * * To implement this undocumented API we will use the NT undocumented API * GetHFONT. * * SudeepB 08-Mar-1996 * */
extern HFONT APIENTRY GetHFONT (HDC hdc);
ULONG FASTCALL WG32GetCurLogFont(PVDMFRAME pFrame) {
ULONG ul; register PGETCURLOGFONT16 parg16;
GETARGPTR(pFrame, sizeof(GETCURLOGFONT16), parg16);
ul = GETHFONT16 (GetHFONT(HDC32 (parg16->hDC)));
FREEARGPTR(parg16);
return (ul); }
//
// This allows Quickbooks v4 & v5 to use their OCR-A.TTF font right after they
// install. At the end of installation on both versions, you are asked if you
// want to "restart" windows. If you click OK it logs you off of NT5, but does
// *not* reboot the system -- which the app is counting on to cause the OCR-A
// font to be loaded. The result on W2K is that whenever the app uses the OCR-A
// font, it will get mapped to wingdings instead.
//
// This is further complicated by the fact that the font file OCR-A.TTF doesn't
// specify the charset in the header. On Win3.1, Win95, & pre-NT5, unspecified
// charset's got mapped to the SYMBOL_CHARSET - therefore, Quickbooks specifies
// SYMBOL_CHARSET in its LOGFONT struct to accomodate this. (OCR-A apparently
// is licenced from Monotype Typography, Ltd. which presumably is why Intuit
// didn't fix the header issue in the font file).
//
// This changed on Win98 and W2K, unspecified charset's now get mapped to the
// DEFAULT_CHARSET. This was done so these fonts will always map to a default
// localized font that will always be readable. Hence, the hack where we change
// the charset from SYMBOL_CHARSET to DEFAULT_CHARSET in the LOGFONT struct.
//
// On v4, the install program copies OCR-A.FOT & OCR-A.TTF to the SYSTEM dir.
// Once you "restart" (not reboot) the system & log back on, the OCR-A font is
// added to the registry (as OCR-A.FOT) but the font files are still in the
// SYSTEM dir. Rebooting causes the fonts files to be moved to the FONTS dir,
// the registry entry is changed to OCR-A.TTF. (done by the "Font Sweeper")
//
// On v5, the install program copies the .ttf & .fot files to the FONTS dir
// but again, counts on the reboot to cause the fonts to be loaded. It puts
// correct registry entry (OCR-A.TTF) in the registry fonts section.
//
// The result of all this is:
// For either version of the app, without the charset hack, you will always get
// a wingding font instead of OCR-A. With the charset hack, you will get a
// readable font, such as Arial, until you reboot -- after which you will get
// OCR-A for v5 but Arial for v4. With this function (in conjunction with the
// charset hack) both version will always get OCR-A with or without rebooting.
//
// This function explicitly loads the OCR-A from the font files located in
// either the FONTS dir or the SYSTEM dir.
//
void LoadOCRFont(void) { char szFontPath[MAX_PATH]; DWORD dw; int cb;
// get equivalent of "c:\windows" for this system
dw = GetWindowsDirectory(szFontPath, MAX_PATH);
// we're going to add a maximum of 18 chars "\SYSTEM\OCR-A.TTF"
if(dw && ((MAX_PATH - 18) > dw)) {
// build "c:\windows\FONTS\OCR-A.TTF" (QuickBooks v5)
strcat(szFontPath, szFonts); strcat(szFontPath, szOCRDotTTF);
// If font file doesn't exist in FONTS dir, this must be QuickBooks v4
// The FR_PRIVATE flag means that the font will be unloaded when the vdm
// process goes away. The FR_NO_ENUM flag means that this instance of
// the font can't be enumerated by other processes (it might go away
// while the other processes are trying to use it).
cb = AddFontResourceEx(szFontPath, FR_PRIVATE | FR_NOT_ENUM, NULL); if(!cb) { // reset path to "c:\windows"
szFontPath[dw] = '\0';
// build "c:\windows\SYSTEM\OCR-A.TTF"
strcat(szFontPath, szSystem); strcat(szFontPath, szOCRDotTTF); cb = AddFontResourceEx(szFontPath, FR_PRIVATE | FR_NOT_ENUM, NULL);
// if it wasn't loaded from the SYSTEM dir either, punt
}
if(cb) {
// specify that the font is already loaded for the life of this VDM
gfOCRFontLoaded = TRUE; } } }
|