mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5194 lines
136 KiB
5194 lines
136 KiB
/*****************************************************************************
|
|
* Module Name: fontlink.cxx
|
|
*
|
|
* FontLink (EUDC) API's for NT graphics engine.
|
|
*
|
|
* History:
|
|
*
|
|
* 1-18-96 Gerrit van Wingerden Moved to kernel mode.
|
|
* 1-14-96 Hideyuki Nagase Add Font Association emulation features.
|
|
* 1-09-95 Hideyuki Nagase Rewrote it for new fontlink features.
|
|
* 1-04-94 Hideyuki Nagase Update for Daytona fontlink.
|
|
* 2-10-93 Gerrit van Wingerden Wrote it.
|
|
*****************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#ifdef FE_SB
|
|
|
|
LONG cCapString(WCHAR *pwcDst,WCHAR *pwcSrc,INT cMax);
|
|
LONG lNormAngle(LONG lAngle);
|
|
VOID vInitializeFontAssocStatus(VOID);
|
|
|
|
#define EUDC_USER_REGISTRY_KEY \
|
|
L"\\EUDC\\"
|
|
#define EUDC_SYSTEM_REGISTRY_KEY \
|
|
L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink"
|
|
#define FONT_ASSOC_REGISTRY_KEY \
|
|
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FontAssoc"
|
|
|
|
#define DEFAULT_EUDC_FONT L"EUDC.TTE"
|
|
|
|
// protects gbEUDCRequest and gcEUDCCount
|
|
|
|
GRE_EXCLUSIVE_RESOURCE gfmEUDC1;
|
|
|
|
// used to signal the EUDC API's that it is okay to change EUDC link data
|
|
|
|
GRE_EXCLUSIVE_RESOURCE gfmEUDC2;
|
|
|
|
// used to protects gappfeSysEUDC[] and gawcEUDCPath
|
|
// - This mutex should be locked during referring above two values without
|
|
// holding gfmEUDC1. and updating above two data anytime.
|
|
|
|
GRE_EXCLUSIVE_RESOURCE gfmEUDC3;
|
|
|
|
// used to protects BaseFontListHead
|
|
// - This mutex should be locked during referring above list without
|
|
// holding gfmEUDC1. and updating above list anytime.
|
|
|
|
GRE_EXCLUSIVE_RESOURCE gfmEUDC4;
|
|
|
|
BOOL gbEUDCRequest = FALSE;
|
|
ULONG gcEUDCCount = 0;
|
|
|
|
// Global variables for System EUDC.
|
|
|
|
|
|
// FontLink Configuration value.
|
|
|
|
ULONG ulFontLinkControl = 0L;
|
|
ULONG ulFontLinkChange = 0L;
|
|
|
|
|
|
// HPFE for system EUDC font.
|
|
|
|
PFE *gappfeSysEUDC[2] = { PPFENULL , PPFENULL };
|
|
|
|
// Path of system EUDC font
|
|
|
|
WCHAR gawcEUDCPath[MAX_PATH+1];
|
|
|
|
// QUICKLOOKUP for system EUDC font && TT System Font
|
|
|
|
QUICKLOOKUP gqlEUDC;
|
|
QUICKLOOKUP gqlTTSystem;
|
|
|
|
// System eudc uniq number
|
|
|
|
ULONG ulSystemEUDCTimeStamp = 0;
|
|
|
|
// FaceName eudc uniq number
|
|
|
|
ULONG ulFaceNameEUDCTimeStamp = 0;
|
|
|
|
// Global variables for FaceName EUDC.
|
|
|
|
// Count of face name links in the system
|
|
UINT gcNumLinks = 0;
|
|
|
|
// Pointer to list of base font list
|
|
|
|
LIST_ENTRY BaseFontListHead = { (PLIST_ENTRY)&BaseFontListHead ,
|
|
(PLIST_ENTRY)&BaseFontListHead };
|
|
|
|
LIST_ENTRY NullListHead = { (PLIST_ENTRY)&NullListHead ,
|
|
(PLIST_ENTRY)&NullListHead };
|
|
|
|
WCHAR gawcSystemACP[10];
|
|
|
|
// Eudc Default Unicode codepoint
|
|
|
|
WCHAR EudcDefaultChar = 0x30fb;
|
|
|
|
extern BOOL bSetupDefaultFlEntry(VOID);
|
|
|
|
|
|
//
|
|
// global EUDC debugging flags
|
|
//
|
|
#if DBG
|
|
FLONG gflEUDCDebug = 0x0000;
|
|
FLONG gflDumpDebug = 0x0000;
|
|
#endif
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* VOID PFFOBJ::vGetEUDC(PEUDCLOAD)
|
|
*
|
|
* This function finds requested facename PFEs
|
|
*
|
|
* History
|
|
* 4-14-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
VOID PFFOBJ::vGetEUDC
|
|
(
|
|
PEUDCLOAD pEudcLoadData
|
|
)
|
|
{
|
|
ASSERTGDI(pEudcLoadData != NULL,"PFFOBJ::vGetEUDC() pEudcLoadData == NULL\n");
|
|
|
|
//
|
|
// Initialize return buffer with NULL.
|
|
//
|
|
|
|
pEudcLoadData->pppfeData[PFE_NORMAL] = NULL;
|
|
pEudcLoadData->pppfeData[PFE_VERTICAL] = NULL;
|
|
|
|
if( pEudcLoadData->LinkedFace == NULL )
|
|
{
|
|
//
|
|
// Linked face name is not specified. In this case if the font has 2 PFEs
|
|
// we assume first entry is for Normal face, and 2nd is Verical face.
|
|
//
|
|
//
|
|
// Fill it with normal face PFE.
|
|
//
|
|
pEudcLoadData->pppfeData[PFE_NORMAL] = ppfe(PFE_NORMAL);
|
|
|
|
//
|
|
// if this font has 2 PFEs, get 2nd PFE for vertical face. otherwise
|
|
// use same PFE as normal face for Vertical face.
|
|
//
|
|
if( cFonts() == 2 )
|
|
pEudcLoadData->pppfeData[PFE_VERTICAL] = ppfe(PFE_VERTICAL);
|
|
else
|
|
pEudcLoadData->pppfeData[PFE_VERTICAL] = ppfe(PFE_NORMAL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Linked face name is specified, try to find out its PFE.
|
|
//
|
|
|
|
COUNT cFont;
|
|
|
|
for( cFont = 0; cFont < cFonts(); cFont++ )
|
|
{
|
|
PFEOBJ pfeo(ppfe(cFont));
|
|
PWSTR pwszEudcFace = pfeo.pwszFamilyName();
|
|
ULONG iPfeOffset = PFE_NORMAL;
|
|
|
|
//
|
|
// Is this a vertical face ?
|
|
//
|
|
if( pwszEudcFace[0] == (WCHAR) L'@' )
|
|
{
|
|
pwszEudcFace++; // skip L'@'
|
|
iPfeOffset = PFE_VERTICAL;
|
|
}
|
|
|
|
//
|
|
// Is this a face that we want ?
|
|
//
|
|
if( _wcsicmp(pwszEudcFace,pEudcLoadData->LinkedFace) == 0 )
|
|
{
|
|
//
|
|
// Yes....., keep it.
|
|
//
|
|
pEudcLoadData->pppfeData[iPfeOffset] = pfeo.ppfeGet();
|
|
|
|
//
|
|
// if this is a PFE for Normal face, also keep it for Vertical face.
|
|
// after this, this value might be over-written by CORRRCT vertical
|
|
// face's PFE.
|
|
//
|
|
// NOTE :
|
|
// This code assume Normal face come faster than Vertical face...
|
|
//
|
|
if( iPfeOffset == PFE_NORMAL )
|
|
{
|
|
pEudcLoadData->pppfeData[PFE_VERTICAL] = pfeo.ppfeGet();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bValidFontLinkParameter(PWSTR,PWSTR *)
|
|
*
|
|
* This function make sure the linked font parameter is valid or not.
|
|
*
|
|
* History
|
|
* 3-29-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bValidFontLinkParameter
|
|
(
|
|
PWSTR LinkedFontName, // IN
|
|
PWSTR *LinkedFaceName // OUT
|
|
)
|
|
{
|
|
PWSTR lp = LinkedFontName;
|
|
BOOL bFound = FALSE;
|
|
|
|
*LinkedFaceName = NULL;
|
|
|
|
while( *lp )
|
|
{
|
|
if( *lp == L',' )
|
|
{
|
|
if(bFound)
|
|
{
|
|
*LinkedFaceName = NULL;
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
*LinkedFaceName = lp + 1;
|
|
*lp = (WCHAR)NULL;
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
lp++;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* BOOL bComputeQuickLookup( QUICKLOOKUP *pql, FD_GLYPHSET *pfdg, BOOL bSystemEUDC )
|
|
*
|
|
* This routine computes a quick lookup structure from an FD_GLYPHSET structure.
|
|
*
|
|
* History:
|
|
* 7-7-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
#define uiMask2(X) (0xFFFFFFFF << (31-(X)))
|
|
#define uiMask1(X) (0xFFFFFFFF >> (X))
|
|
|
|
BOOL bComputeQuickLookup( QUICKLOOKUP *pql, FD_GLYPHSET *pfdg, BOOL bSystemEUDC )
|
|
{
|
|
WCRUN *pwcrun = pfdg->awcrun;
|
|
WCHAR wcHigh = 0x0000;
|
|
WCHAR wcLow = 0xFFFF;
|
|
UINT ui;
|
|
|
|
|
|
// if this is not SystemEUDC and puiBits has pointer, the Lookup table
|
|
// was already initialized.
|
|
|
|
if ( !bSystemEUDC && pql->puiBits )
|
|
return (TRUE);
|
|
|
|
// first figure out the high and low glyphs for this font
|
|
|
|
for( ui = 0; ui < pfdg->cRuns; ui++ )
|
|
{
|
|
if( wcLow > pwcrun[ui].wcLow )
|
|
{
|
|
wcLow = pwcrun[ui].wcLow;
|
|
}
|
|
|
|
if( wcHigh < pwcrun[ui].wcLow + pwcrun[ui].cGlyphs )
|
|
{
|
|
wcHigh = ( pwcrun[ui].wcLow + pwcrun[ui].cGlyphs - 1 );
|
|
}
|
|
}
|
|
|
|
(*pql).wcLow = wcLow;
|
|
(*pql).wcHigh = wcHigh;
|
|
|
|
// Now we need to allocate puiBits. In the case of the system EUDC font will
|
|
// do this only once even though the glyph set can change dynamically. This
|
|
// means we will always allocate 0xFFFF bits. If *pql.puiBits != NULL then
|
|
// we assume the glyphset has been allocated before and leave it alone
|
|
|
|
if( bSystemEUDC )
|
|
{
|
|
// see if already allocated before and if so don't allocate it again
|
|
// we determine this by checking if *pql.auiBits is NULL or not
|
|
|
|
if( (*pql).puiBits == NULL )
|
|
{
|
|
(*pql).puiBits = (UINT*)PALLOCMEM( 0xFFFF / 8, 'flnk' );
|
|
|
|
}
|
|
else
|
|
{
|
|
RtlZeroMemory( (*pql).puiBits, 0xFFFF / 8 );
|
|
}
|
|
|
|
wcLow = 0;
|
|
}
|
|
else
|
|
{
|
|
(*pql).puiBits = (UINT*)PALLOCMEM(((wcHigh-wcLow+31)/32)*4,'flnk');
|
|
}
|
|
|
|
if((*pql).puiBits == (UINT*) NULL)
|
|
{
|
|
WARNING("bComputeQuickLookup out of memory.\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
for( ui = 0; ui < pfdg->cRuns ; ui++ )
|
|
{
|
|
UINT uiFirst = ( pwcrun[ui].wcLow - wcLow ) / 32 ;
|
|
UINT uiLast = ( pwcrun[ui].wcLow - wcLow + pwcrun[ui].cGlyphs - 1 ) / 32;
|
|
|
|
if( uiFirst == uiLast )
|
|
{
|
|
|
|
(*pql).puiBits[uiFirst] |= uiMask2(pwcrun[ui].cGlyphs-1) >>
|
|
( ( pwcrun[ui].wcLow - wcLow ) % 32 );
|
|
}
|
|
else
|
|
{
|
|
(*pql).puiBits[uiFirst] |= uiMask1((pwcrun[ui].wcLow - wcLow)%32);
|
|
|
|
for( UINT uiRun = uiFirst+1; uiRun < uiLast; uiRun++ )
|
|
{
|
|
(*pql).puiBits[uiRun] = 0xFFFFFFFF;
|
|
}
|
|
|
|
(*pql).puiBits[uiLast] |=
|
|
uiMask2((pwcrun[ui].wcLow - wcLow + pwcrun[ui].cGlyphs-1)%32);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* BOOL bAppendSysDirectory( WCHAR *pwcTarget, WCHAR *pwcSource )
|
|
*
|
|
* Given a file name in pwcSource, this function appends it to the
|
|
* appropirate directory and returns it into the buffer pointed to
|
|
* by pwcTarget. If the file already has a path it just copies
|
|
* pwcSource to pwcTarget.
|
|
* This function return FALSE when pwcTarget string is not eqaul to
|
|
* pwcSource.
|
|
*
|
|
* History:
|
|
* 8-30-93 Hideyuki Nagase [hideyukn]
|
|
* Add code for searching path
|
|
*
|
|
* 3-23-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bAppendSysDirectory( WCHAR *pwcTarget, WCHAR *pwcSource )
|
|
{
|
|
|
|
WCHAR pwcTemp[MAX_PATH];
|
|
|
|
// Check it is file name only or full path name
|
|
|
|
if( wcschr(pwcSource,L'\\') != NULL )
|
|
{
|
|
WCHAR *pSystemRoot;
|
|
|
|
// full path.
|
|
|
|
cCapString(pwcTarget,pwcSource,MAX_PATH);
|
|
|
|
// Replace %SystemRoot%\FileName with \SystemRoot\FileName.
|
|
|
|
if( (pSystemRoot = wcsstr(pwcTarget,L"%SYSTEMROOT%")) != NULL )
|
|
{
|
|
pSystemRoot[0] = L'\\';
|
|
wcscpy(&(pSystemRoot[11]),&(pSystemRoot[12]));
|
|
|
|
#if DBG
|
|
DbgPrint("bAppenSysDirectory():Path --> %ws\n",pwcTarget);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WARNING("bAppenSysDirectory():Need conversion (DosPath -> NtPath)\n");
|
|
}
|
|
|
|
return TRUE; // need to update registry.
|
|
}
|
|
else
|
|
{
|
|
// assume it is in the "fonts" directory
|
|
|
|
wcscpy(pwcTemp,L"\\SystemRoot\\fonts\\");
|
|
wcscat(pwcTemp,pwcSource);
|
|
cCapString(pwcTarget,pwcTemp,MAX_PATH);
|
|
return(FALSE); // dont need to update
|
|
}
|
|
}
|
|
|
|
|
|
WCHAR *pwcFileIsUnderWindowsRoot( WCHAR *pwcTarget )
|
|
{
|
|
WCHAR awcWindowsRoot[MAX_PATH+1];
|
|
UINT WindowsRootLength;
|
|
|
|
#ifdef FIX_THIS
|
|
|
|
WindowsRootLength = GetWindowsDirectoryW( awcWindowsRoot , MAX_PATH );
|
|
|
|
if( wcsnicmp( awcWindowsRoot, pwcTarget, WindowsRootLength ) == 0 )
|
|
return (pwcTarget + WindowsRootLength);
|
|
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* GetUserEUDCRegistryPath(LPWSTR,USHORT)
|
|
*
|
|
* Get EUDC registry path for current loggedon user.
|
|
*
|
|
* History:
|
|
* 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
***************************************************************************/
|
|
|
|
VOID GetUserEUDCRegistryPath
|
|
(
|
|
LPWSTR UserEUDCPathBuffer,
|
|
USHORT UserEUDCPathLen
|
|
)
|
|
{
|
|
UNICODE_STRING UserEUDCPath;
|
|
UNICODE_STRING UserRegistryPath;
|
|
|
|
UserEUDCPath.Length = 0;
|
|
UserEUDCPath.MaximumLength = UserEUDCPathLen;
|
|
UserEUDCPath.Buffer = UserEUDCPathBuffer;
|
|
|
|
// Get path of CurrentUser key.
|
|
|
|
|
|
if(NT_SUCCESS(RtlFormatCurrentUserKeyPath(&UserRegistryPath)))
|
|
{
|
|
// Build path for EUDC data
|
|
|
|
RtlAppendUnicodeStringToString(&UserEUDCPath,&UserRegistryPath);
|
|
RtlAppendUnicodeToString(&UserEUDCPath,EUDC_USER_REGISTRY_KEY);
|
|
RtlAppendUnicodeToString(&UserEUDCPath,gawcSystemACP);
|
|
|
|
RtlFreeUnicodeString(&UserRegistryPath);
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("GetUserEUDCRegistryPath():RtlFormatCurrentUserKeyPath\n");
|
|
|
|
// just retuen default path..
|
|
|
|
RtlAppendUnicodeToString(&UserEUDCPath,L"\\Registry\\User\\.DEFAULT");
|
|
RtlAppendUnicodeToString(&UserEUDCPath,EUDC_USER_REGISTRY_KEY);
|
|
RtlAppendUnicodeToString(&UserEUDCPath,gawcSystemACP);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* bWriteUserSystemEUDCRegistry(LPWSTR)
|
|
*
|
|
* Write system wide eudc font file path for request user.
|
|
*
|
|
* History:
|
|
* 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bWriteUserSystemEUDCRegistry
|
|
(
|
|
LPWSTR DataBuffer,
|
|
USHORT DataLen
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
WCHAR RegistryPathBuffer[MAX_PATH];
|
|
|
|
// Get EUDC registry path for requested user
|
|
|
|
GetUserEUDCRegistryPath(RegistryPathBuffer,sizeof(RegistryPathBuffer));
|
|
|
|
// Write registry.
|
|
|
|
NtStatus = RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPathBuffer,
|
|
L"SystemDefaultEUDCFont",
|
|
REG_SZ,
|
|
DataBuffer,
|
|
DataLen * sizeof(WCHAR) );
|
|
|
|
if(!NT_SUCCESS(NtStatus))
|
|
{
|
|
WARNING("bWriteUserSystemEUDCRegistry():fail\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* bReadUserSystemEUDCRegistry(LPWSTR,USHORT)
|
|
*
|
|
* Read system wide eudc font file path for request user.
|
|
*
|
|
* History:
|
|
* 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bReadUserSystemEUDCRegistry
|
|
(
|
|
LPWSTR FilePathBuffer,
|
|
USHORT FilePathLen
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
WCHAR NoExpandFilePathBuffer[MAX_PATH];
|
|
WCHAR RegistryPathBuffer[MAX_PATH];
|
|
UNICODE_STRING FilePath;
|
|
|
|
// Get EUDC registry path for requested user
|
|
|
|
GetUserEUDCRegistryPath(RegistryPathBuffer,sizeof(RegistryPathBuffer));
|
|
|
|
|
|
FilePath.Length = 0;
|
|
FilePath.MaximumLength = sizeof(NoExpandFilePathBuffer);
|
|
FilePath.Buffer = NoExpandFilePathBuffer;
|
|
|
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
|
|
RTL_QUERY_REGISTRY_DIRECT;
|
|
QueryTable[0].Name = (PWSTR) L"SystemDefaultEUDCFont";
|
|
QueryTable[0].EntryContext = (PVOID) &FilePath;
|
|
QueryTable[0].DefaultType = REG_NONE;
|
|
QueryTable[0].DefaultData = NULL;
|
|
QueryTable[0].DefaultLength = 0;
|
|
|
|
QueryTable[1].QueryRoutine = NULL;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = NULL;
|
|
|
|
// Read registry.
|
|
|
|
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPathBuffer,
|
|
QueryTable,
|
|
NULL,
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(NtStatus) || FilePath.Length == 0)
|
|
{
|
|
#if DBG
|
|
DbgPrint("bReadUserSystemEUDCRegistry():fail NtStatus - %x\n",NtStatus);
|
|
#endif
|
|
|
|
if(NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
{
|
|
WCHAR *LastBackslash = NULL;
|
|
|
|
//
|
|
// if the user does not have EUDC\ActiveCodePage\SystemDefaultEUDCFont
|
|
// key\value, we create the key and set the default value here..
|
|
//
|
|
// Create key.
|
|
|
|
LastBackslash = wcsrchr(RegistryPathBuffer,L'\\');
|
|
|
|
if(LastBackslash != NULL && _wcsicmp(LastBackslash+1,gawcSystemACP) == 0)
|
|
{
|
|
// Create HKEY_CURRENT_USER\EUDC key.
|
|
|
|
*LastBackslash = L'\0';
|
|
RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,RegistryPathBuffer);
|
|
|
|
// Create HKEY_CURRENT_USER\EUDC\ActiveCodePage key.
|
|
|
|
*LastBackslash = L'\\';
|
|
RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,RegistryPathBuffer);
|
|
|
|
// Set value.
|
|
|
|
if(bWriteUserSystemEUDCRegistry(DEFAULT_EUDC_FONT,
|
|
wcslen(DEFAULT_EUDC_FONT)+1) )
|
|
{
|
|
//
|
|
// Initialize FilePath with default.
|
|
//
|
|
|
|
RtlInitUnicodeString(&FilePath,DEFAULT_EUDC_FONT);
|
|
}
|
|
else goto ErrorReturn;
|
|
}
|
|
else goto ErrorReturn;
|
|
}
|
|
else goto ErrorReturn;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure the null-terminate string
|
|
//
|
|
|
|
FilePath.Buffer[FilePath.Length/sizeof(WCHAR)] = L'\0';
|
|
}
|
|
|
|
wcsncpy(FilePathBuffer,FilePath.Buffer,FilePathLen);
|
|
return(TRUE);
|
|
|
|
ErrorReturn:
|
|
return(FALSE);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bKillEudcRFONTs( RFONT *prfntVictims )
|
|
*
|
|
* Given a linked list of EUDC RFONT this routine kills them all.
|
|
*
|
|
* History
|
|
* 6-30-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bKillEudcRFONTs( RFONT *prfntVictims )
|
|
{
|
|
PRFONT prfnt;
|
|
|
|
while( (prfnt = prfntVictims ) != (PRFONT) NULL )
|
|
{
|
|
prfntVictims = prfntVictims->rflPDEV.prfntNext;
|
|
|
|
{
|
|
RFONTTMPOBJ rfloVictim(prfnt);
|
|
|
|
// Need this so we can remove this from the PFF's RFONT list.
|
|
|
|
PFFOBJ pffo(prfnt->pPFF);
|
|
|
|
ASSERTGDI(pffo.bValid(), "gdisrv!vKillEudcRFONTs: bad HPFF");
|
|
|
|
// We pass in NULL for ppdo because we've already removed it from the
|
|
// PDEV list.
|
|
|
|
if( !rfloVictim.bDeleteRFONT((PDEVOBJ *) NULL, &pffo))
|
|
{
|
|
WARNING("Unable vKillEudcRFONTs unable to delete RFONT.\n");
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* RFONT *prfntDeactivateEudcRFONTs(PFE **)
|
|
*
|
|
* Tracks down all the EUDC RFONTS in the system removes them from the active
|
|
* and deactive lists and puts them on a list for deletion which it then
|
|
* returns to the caller.
|
|
*
|
|
* The public font table semaphore must be held by the caller for this to work.
|
|
*
|
|
* History
|
|
* 23-01-95 Hideyuki Nagase
|
|
* Rewrote it.
|
|
*
|
|
* 2-10-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
VOID vDeactivateEudcRFONTsWorker
|
|
(
|
|
PPFE *appfe,
|
|
PPFF pPFF,
|
|
RFONT **pprfntToBeKilled
|
|
)
|
|
{
|
|
while(pPFF)
|
|
{
|
|
PFFOBJ pffo(pPFF);
|
|
|
|
// Check if this font file is really loaded as EUDC font..
|
|
|
|
if(pffo.bEUDC())
|
|
{
|
|
for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
|
|
{
|
|
PRFONT prfntNext;
|
|
|
|
{
|
|
RFONTTMPOBJ rflo(prfnt);
|
|
prfntNext = rflo.prflPFF()->prfntNext;
|
|
}
|
|
|
|
if( ( prfnt->ppfe == appfe[PFE_NORMAL] ) ||
|
|
( prfnt->ppfe == appfe[PFE_VERTICAL] ) )
|
|
{
|
|
FLINKMESSAGE2(DEBUG_FONTLINK_UNLOAD,
|
|
"Removing EUDC font %x.\n", prfnt);
|
|
|
|
RFONTTMPOBJ rfo(prfnt);
|
|
|
|
PDEVOBJ pdo(prfnt->hdevConsumer);
|
|
PRFONT prf;
|
|
|
|
// remove it from the active or inactive list
|
|
|
|
if( prfnt->cSelected != 0 )
|
|
{
|
|
prf = pdo.prfntActive();
|
|
rfo.vRemove(&prf, PDEV_LIST);
|
|
pdo.prfntActive(prf);
|
|
}
|
|
else
|
|
{
|
|
prf = pdo.prfntInactive();
|
|
rfo.vRemove(&prf, PDEV_LIST);
|
|
pdo.prfntInactive(prf);
|
|
pdo.cInactive( pdo.cInactive()-1 );
|
|
}
|
|
|
|
// add it to the kill list
|
|
|
|
rfo.vInsert( pprfntToBeKilled, PDEV_LIST );
|
|
}
|
|
|
|
prfnt = prfntNext;
|
|
}
|
|
}
|
|
|
|
pPFF = pPFF->pPFFNext;
|
|
}
|
|
}
|
|
|
|
RFONT *prfntDeactivateEudcRFONTs( PPFE *appfe )
|
|
{
|
|
RFONT *prfntToBeKilled = PRFNTNULL;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,"Deactivating EUDC RFONTs.\n");
|
|
|
|
SEMOBJ so1(gpsemPublicPFT);
|
|
SEMOBJ so2(gpsemRFONTList);
|
|
|
|
COUNT cBuckets;
|
|
PPFF pPFF;
|
|
|
|
PUBLIC_PFTOBJ pftoPublic; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vDeactivateEudcRFONTsWorker( appfe, pPFF, &prfntToBeKilled );
|
|
}
|
|
}
|
|
|
|
return(prfntToBeKilled);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bUnloadEudcFont( PFE ** )
|
|
*
|
|
* This function delete RFONTs and unload fontfile for specified PFE
|
|
*
|
|
* History:
|
|
* 24-01-1995 -by- Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bUnloadEudcFont( PFE **ppfe )
|
|
{
|
|
WCHAR awcPathBuffer[MAX_PATH + 1];
|
|
|
|
PUBLIC_PFTOBJ pfto; // access the public font table
|
|
|
|
PFEOBJ pfeo( ppfe[PFE_NORMAL] );
|
|
PFFOBJ pffo( pfeo.pPFF() );
|
|
|
|
// get font file path.
|
|
|
|
wcscpy(awcPathBuffer,pffo.pwszPathname());
|
|
|
|
QUICKLOOKUP *pqlDelete;
|
|
|
|
// Progress Normal face..
|
|
|
|
pqlDelete = pfeo.pql();
|
|
|
|
// if this is system wide eudc, won't need to free it.
|
|
|
|
if( pqlDelete->puiBits != NULL )
|
|
{
|
|
VFREEMEM(pqlDelete->puiBits);
|
|
pqlDelete->puiBits = NULL;
|
|
}
|
|
|
|
PFEOBJ pfeoVert( ppfe[PFE_VERTICAL] );
|
|
|
|
if( pfeoVert.bValid() )
|
|
{
|
|
pqlDelete = pfeoVert.pql();
|
|
|
|
// if this is system wide eudc, won't need to free it.
|
|
|
|
if( pqlDelete->puiBits != NULL )
|
|
{
|
|
VFREEMEM(pqlDelete->puiBits);
|
|
pqlDelete->puiBits = NULL;
|
|
}
|
|
}
|
|
|
|
// Deactivate all RFONT for this PFE
|
|
|
|
PRFONT prfntToBeKilled = prfntDeactivateEudcRFONTs( ppfe );
|
|
|
|
// Kill all RFONT for this PFE
|
|
|
|
if(!bKillEudcRFONTs( prfntToBeKilled ))
|
|
{
|
|
WARNING("bDeleteAllFlEntry():Can not kill Eudc RFONTs\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Unload this font file.
|
|
//
|
|
// if others link are using this font file, the font
|
|
// is not unloaded here. At the last link that is using
|
|
// this font, it will be really unloaded.
|
|
//
|
|
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Unloading... %ws\n",awcPathBuffer);
|
|
}
|
|
#endif
|
|
|
|
if(!pfto.bUnloadEUDCFont(awcPathBuffer))
|
|
{
|
|
#if DBG
|
|
DbgPrint("bDeleteAllFlEntry():Can not unload Eudc %ws\n",awcPathBuffer);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* PFLENTRY FindBaseFontEntry(PWSTR)
|
|
*
|
|
* This function scan the base font list to find specified font is already
|
|
* exist or not.
|
|
*
|
|
* Return.
|
|
* Exist - Pointer to FLENTRY strucrure.
|
|
* Not exist - NULL
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
PFLENTRY FindBaseFontEntry
|
|
(
|
|
PWSTR BaseFontName
|
|
)
|
|
{
|
|
PLIST_ENTRY p;
|
|
PFLENTRY pFlEntry;
|
|
|
|
p = BaseFontListHead.Flink;
|
|
pFlEntry = NULL;
|
|
|
|
while( p != &BaseFontListHead )
|
|
{
|
|
pFlEntry = CONTAINING_RECORD(p,FLENTRY,baseFontList);
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_FONTLINK_INIT) )
|
|
{
|
|
DbgPrint("%ws v.s. %ws\n",BaseFontName,pFlEntry->awcFaceName);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// if this is Vertical font name, compair without '@'
|
|
//
|
|
PWSTR pFaceName;
|
|
PWSTR pBaseFaceName;
|
|
|
|
pFaceName = ( (pFlEntry->awcFaceName[0] != L'@') ? &(pFlEntry->awcFaceName[0]) :
|
|
&(pFlEntry->awcFaceName[1]) );
|
|
|
|
pBaseFaceName = ( (BaseFontName[0] != L'@') ? &BaseFontName[0] :
|
|
&BaseFontName[1] );
|
|
|
|
//
|
|
// Compair font face name.
|
|
//
|
|
|
|
if( _wcsicmp(pBaseFaceName,pFaceName) == 0 )
|
|
{
|
|
//
|
|
// Find it.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// try next.
|
|
//
|
|
|
|
p = p->Flink;
|
|
pFlEntry = NULL;
|
|
}
|
|
|
|
return(pFlEntry);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* PPFEDATA FindLinkedFontEntry(PLIST_ENTRY,PWSTR,PWSTR)
|
|
*
|
|
* This function scan the linked font list to find specified font is already
|
|
* exist or not.
|
|
*
|
|
* Return.
|
|
* Exist - Pointer to PPFEDATA strucrure.
|
|
* Not exist - NULL
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
PPFEDATA FindLinkedFontEntry
|
|
(
|
|
PLIST_ENTRY LinkedFontList,
|
|
PWSTR LinkedFontPath,
|
|
PWSTR LinkedFontFace
|
|
)
|
|
{
|
|
PLIST_ENTRY p;
|
|
PPFEDATA ppfeData;
|
|
|
|
p = LinkedFontList->Flink;
|
|
ppfeData = NULL;
|
|
|
|
while( p != LinkedFontList )
|
|
{
|
|
ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
|
|
|
|
//
|
|
// get PFE and PFF user object.
|
|
//
|
|
|
|
PFEOBJ pfeo( ppfeData->appfe[PFE_NORMAL] );
|
|
PFFOBJ pffo( pfeo.pPFF() );
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_FONTLINK_INIT) )
|
|
{
|
|
DbgPrint("%ws v.s. %ws\n",pffo.pwszPathname(),LinkedFontPath);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// compair file path
|
|
//
|
|
|
|
if( _wcsicmp( pffo.pwszPathname() , LinkedFontPath ) == 0 )
|
|
{
|
|
//
|
|
// if facename of linked font is specified, check it also.
|
|
//
|
|
|
|
if( ((LinkedFontFace == NULL) &&
|
|
((ppfeData->FontLinkFlag & FLINK_FACENAME_SPECIFIED) == 0)) ||
|
|
((LinkedFontFace != NULL ) &&
|
|
((ppfeData->FontLinkFlag & FLINK_FACENAME_SPECIFIED) != 0) &&
|
|
((_wcsicmp(pfeo.pwszFamilyName() , LinkedFontFace))== 0)
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// Find it.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// try next.
|
|
//
|
|
|
|
p = p->Flink;
|
|
ppfeData = NULL;
|
|
}
|
|
|
|
return(ppfeData);
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* BOOL FindDefaultLinkedFontEntry
|
|
*
|
|
* This codepath check the passed facename is registered as Default link
|
|
* facename in Default link table. if so, keep its facename for the facename.
|
|
*
|
|
* History
|
|
* 1-14-96 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL FindDefaultLinkedFontEntry
|
|
(
|
|
PWSTR CandidateFaceName,
|
|
PWSTR CandidatePathName
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
UINT iIndex;
|
|
|
|
for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
|
|
{
|
|
//
|
|
// Check the data can be read from registry or not.
|
|
//
|
|
if( FontAssocDefaultTable[iIndex].ValidRegData )
|
|
{
|
|
//
|
|
// Check this path is not filled.
|
|
//
|
|
if( FontAssocDefaultTable[iIndex].DefaultFontPathName[0] == L'\0' )
|
|
{
|
|
//
|
|
// Check the candidate is matched with the facename from registry.
|
|
//
|
|
if( _wcsicmp(CandidateFaceName,FontAssocDefaultTable[iIndex].DefaultFontFaceName) == 0 )
|
|
{
|
|
//
|
|
// Mark the candidate path to default table. This font file will be RE-loaded
|
|
// EUDC font file when GreEnableEUDC() was called next time.
|
|
//
|
|
wcscpy(FontAssocDefaultTable[iIndex].DefaultFontPathName,CandidatePathName);
|
|
|
|
#if DBG
|
|
DbgPrint("GDISRV:FONTASSOC DEFAULT:%ws -> %ws\n",
|
|
FontAssocDefaultTable[iIndex].DefaultFontTypeID,
|
|
FontAssocDefaultTable[iIndex].DefaultFontPathName);
|
|
#endif
|
|
|
|
bRet |= TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* VOID vLinkEudcPFEs(PFLENTRY)
|
|
*
|
|
* This routine will find base font PFE from PFT, and set up Eudc data.
|
|
*
|
|
* History:
|
|
* 24-Jan-1995 -by- Hideyuki Nagase
|
|
* Wrote it.
|
|
****************************************************************************/
|
|
|
|
VOID vLinkEudcPFEsWorker
|
|
(
|
|
PFLENTRY pFlEntry,
|
|
PPFF pPFF
|
|
)
|
|
{
|
|
while(pPFF)
|
|
{
|
|
//
|
|
// get PFF user object
|
|
//
|
|
|
|
PFFOBJ pffo(pPFF);
|
|
|
|
//
|
|
// if this font is loaded as EUDC, it can not be a BaseFont.
|
|
//
|
|
|
|
if( !pffo.bEUDC() )
|
|
{
|
|
for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
|
|
{
|
|
PFEOBJ pfeo(pffo.ppfe(c));
|
|
|
|
if( pfeo.bValid() )
|
|
{
|
|
BOOL bFound = FALSE;
|
|
PFLENTRY pFlEntrySelected = pFlEntry;
|
|
|
|
if( pFlEntrySelected )
|
|
{
|
|
bFound =
|
|
(_wcsicmp(pFlEntrySelected->awcFaceName,
|
|
pfeo.pwszFamilyName()) == 0);
|
|
}
|
|
else
|
|
{
|
|
bFound =
|
|
((pFlEntrySelected =
|
|
FindBaseFontEntry(pfeo.pwszFamilyName())) != NULL);
|
|
}
|
|
|
|
if( bFound )
|
|
{
|
|
//
|
|
// set eudc list..
|
|
//
|
|
|
|
pfeo.vSetLinkedFontEntry( pFlEntrySelected );
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FACENAME_EUDC )
|
|
{
|
|
PLIST_ENTRY p = pfeo.pGetLinkedFontList()->Flink;
|
|
|
|
DbgPrint("Found FaceName EUDC for %ws (%ws) is ",
|
|
pfeo.pwszFamilyName(),pffo.pwszPathname());
|
|
|
|
while( p != &(pFlEntrySelected->linkedFontListHead) )
|
|
{
|
|
PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
|
|
PFEOBJ pfeoTemp( ppfeData->appfe[PFE_NORMAL] );
|
|
PFFOBJ pffoTemp( pfeoTemp.pPFF() );
|
|
|
|
DbgPrint(" %ws ",pffoTemp.pwszPathname());
|
|
|
|
p = p->Flink;
|
|
}
|
|
|
|
DbgPrint("\n");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// mark the FaceNameEUDC pfe as NULL
|
|
|
|
pfeo.vSetLinkedFontEntry( NULL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pPFF = pPFF->pPFFNext;
|
|
}
|
|
}
|
|
|
|
VOID vLinkEudcPFEs
|
|
(
|
|
PFLENTRY pFlEntry
|
|
)
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
|
|
{
|
|
DbgPrint( "vLinkEudcPFEs():Linking All EUDC PFEs.\n");
|
|
}
|
|
#endif
|
|
|
|
SEMOBJ so(gpsemPublicPFT);
|
|
|
|
//
|
|
// WE HAD BETTER USE FONTHASH TO SEARCH BASE FONT'S PFF.
|
|
//
|
|
|
|
COUNT cBuckets;
|
|
PPFF pPFF;
|
|
|
|
//
|
|
// get PFT user object.
|
|
//
|
|
|
|
PUBLIC_PFTOBJ pftoPublic; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vLinkEudcPFEsWorker( pFlEntry, pPFF );
|
|
}
|
|
}
|
|
|
|
DEVICE_PFTOBJ pftoDevice; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vLinkEudcPFEsWorker( pFlEntry, pPFF );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* VOID vUnlinkEudcRFONTs( PPFE * )
|
|
*
|
|
* This routine reset RFONT that has specified linked font.
|
|
*
|
|
* History:
|
|
* 23-Jan-1995 -by- Hideyuki Nagase
|
|
* Wrote it
|
|
****************************************************************************/
|
|
|
|
VOID vUnlinkEudcRFONTsWorker
|
|
(
|
|
PPFE *appfe,
|
|
PPFF pPFF
|
|
)
|
|
{
|
|
while(pPFF)
|
|
{
|
|
PFFOBJ pffo(pPFF);
|
|
|
|
// if this font is loaded as EUDC, it can not be a BaseFont.
|
|
|
|
if( !pffo.bEUDC() )
|
|
{
|
|
// Unlink Eudc from the RFONTs if it has specified Eudc..
|
|
|
|
for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
|
|
{
|
|
PRFONT prfntNext;
|
|
|
|
{
|
|
RFONTTMPOBJ rflo(prfnt);
|
|
prfntNext = rflo.prflPFF()->prfntNext;
|
|
}
|
|
|
|
// if this RFONT has Eudc font, search this Eudc..
|
|
|
|
for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
|
|
{
|
|
// Is this the Eudc RFONT that we want to remove?
|
|
|
|
|
|
if((prfnt->paprfntFaceName[ii] != NULL ) &&
|
|
(((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_NORMAL]) ||
|
|
((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_VERTICAL])))
|
|
{
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Removing face name EUDC pair %x -> %x\n",
|
|
prfnt, prfnt->paprfntFaceName[ii]);
|
|
}
|
|
#endif
|
|
|
|
prfnt->paprfntFaceName[ii] = NULL;
|
|
}
|
|
}
|
|
|
|
// this RFONT's linked font array will be updated with new configuration
|
|
// when this RFONT is used again (see vInitEUDC()).
|
|
// and, if all Eudc font has been removed for this RFONT.
|
|
// the array, its pointer and other information for Eudc will be
|
|
// deleted/updated, vUnlinkEudcRFONTsAndPFEs() will be called instead
|
|
// of this.
|
|
|
|
prfnt->flEUDCState = 0;
|
|
|
|
prfnt = prfntNext;
|
|
}
|
|
}
|
|
|
|
pPFF = pPFF->pPFFNext;
|
|
}
|
|
}
|
|
|
|
VOID vUnlinkEudcRFONTs
|
|
(
|
|
PPFE *appfe
|
|
)
|
|
{
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,"vUnlinkEudcRFONTs():Unlinking EUDC RFONTs.\n");
|
|
|
|
SEMOBJ so1(gpsemPublicPFT);
|
|
SEMOBJ so2(gpsemRFONTList);
|
|
|
|
COUNT cBuckets;
|
|
PPFF pPFF;
|
|
|
|
PUBLIC_PFTOBJ pftoPublic; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkEudcRFONTsWorker(appfe,pPFF);
|
|
}
|
|
}
|
|
|
|
DEVICE_PFTOBJ pftoDevice; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkEudcRFONTsWorker(appfe,pPFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* VOID vUnlinkEudcRFONTsAndPFEs(PPFE *,PFLENTRY)
|
|
*
|
|
* This routine reset RFONT and PFE structure that has specified linked font.
|
|
*
|
|
* History:
|
|
* 23-Jan-1995 -by- Hideyuki Nagase
|
|
* Wrote it
|
|
****************************************************************************/
|
|
|
|
VOID vUnlinkEudcRFONTsAndPFEsWorker
|
|
(
|
|
PPFE *appfe,
|
|
PFLENTRY pFlEntry,
|
|
PPFF pPFF
|
|
)
|
|
{
|
|
while(pPFF)
|
|
{
|
|
PFFOBJ pffo(pPFF);
|
|
|
|
// if this font is loaded as EUDC, it can not be a BaseFont.
|
|
|
|
if( !pffo.bEUDC() )
|
|
{
|
|
// Unlink Eudc from the RFONTs if it has specified Eudc..
|
|
|
|
for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
|
|
{
|
|
PRFONT prfntNext;
|
|
|
|
{
|
|
RFONTTMPOBJ rflo(prfnt);
|
|
prfntNext = rflo.prflPFF()->prfntNext;
|
|
}
|
|
|
|
// if this RFONT has Eudc font, search this Eudc..
|
|
|
|
|
|
BOOL bFound = FALSE;
|
|
|
|
for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
|
|
{
|
|
// Is this the Eudc RFONT that we want to remove?
|
|
|
|
if(((prfnt->paprfntFaceName[ii]) != NULL ) &&
|
|
(((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_NORMAL]) ||
|
|
((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_VERTICAL])))
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Removing face name EUDC pair %x -> %x\n",
|
|
prfnt, prfnt->paprfntFaceName[ii]);
|
|
}
|
|
|
|
//
|
|
// Invalidate it for checking.
|
|
//
|
|
prfnt->paprfntFaceName[ii] = NULL;
|
|
#endif
|
|
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bFound )
|
|
{
|
|
#if DBG
|
|
// make sure the linked font array is really empty.
|
|
|
|
for( UINT jj = 0; jj < prfnt->uiNumLinks ; jj++ )
|
|
{
|
|
if( prfnt->paprfntFaceName[jj] != NULL )
|
|
{
|
|
DbgPrint("vUnloadEudcRFONTsAndPFEs():*** Deleteing Eudc \
|
|
array that has valid data\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// if the linked RFONT table was allocated, free it here
|
|
|
|
if( prfnt->paprfntFaceName != prfnt->aprfntQuickBuff )
|
|
VFREEMEM( prfnt->paprfntFaceName );
|
|
|
|
// we have no facename eudc for this RFONT.
|
|
|
|
prfnt->paprfntFaceName = NULL;
|
|
prfnt->uiNumLinks = 0;
|
|
prfnt->bFilledEudcArray = FALSE;
|
|
prfnt->ulTimeStamp = 0L;
|
|
}
|
|
|
|
prfnt->flEUDCState = 0;
|
|
|
|
prfnt = prfntNext;
|
|
}
|
|
|
|
// Unlink Eudcs from All PFEs that has Eudcs.
|
|
|
|
for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
|
|
{
|
|
PFEOBJ pfeo(pffo.ppfe(c));
|
|
|
|
if( pfeo.pGetLinkedFontEntry() == pFlEntry )
|
|
{
|
|
FLINKMESSAGE2(DEBUG_FONTLINK_UNLOAD,
|
|
"Removing face name PFE for %x (PFE)\n",pffo.ppfe(c));
|
|
|
|
pfeo.vSetLinkedFontEntry( NULL );
|
|
}
|
|
}
|
|
}
|
|
|
|
pPFF = pPFF->pPFFNext;
|
|
}
|
|
}
|
|
|
|
VOID vUnlinkEudcRFONTsAndPFEs
|
|
(
|
|
PPFE *appfe,
|
|
PFLENTRY pFlEntry
|
|
)
|
|
{
|
|
FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,
|
|
"vUnlinkEudcRFONTsAndPFEs():Unlinking EUDC RFONTs ans PFEs.\n");
|
|
|
|
SEMOBJ so1(gpsemPublicPFT);
|
|
SEMOBJ so2(gpsemRFONTList);
|
|
|
|
COUNT cBuckets;
|
|
PPFF pPFF;
|
|
|
|
// get PFT user object.
|
|
|
|
PUBLIC_PFTOBJ pftoPublic; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkEudcRFONTsAndPFEsWorker(appfe,pFlEntry,pPFF);
|
|
}
|
|
}
|
|
|
|
DEVICE_PFTOBJ pftoDevice; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkEudcRFONTsAndPFEsWorker(appfe,pFlEntry,pPFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* VOID vUnlinkAllEudcRFONTsAndPFEs(BOOL,BOOL)
|
|
*
|
|
* This routine reset RFONT and PFE structure that has any linked font.
|
|
*
|
|
* History:
|
|
* 23-Jan-1995 -by- Hideyuki Nagase
|
|
* Wrote it
|
|
****************************************************************************/
|
|
|
|
VOID vUnlinkAllEudcRFONTsAndPFEsWorker
|
|
(
|
|
BOOL bUnlinkSystem,
|
|
BOOL bUnlinkFaceName,
|
|
PPFF pPFF
|
|
)
|
|
{
|
|
while(pPFF)
|
|
{
|
|
//
|
|
// get PFF user obejct.
|
|
//
|
|
|
|
PFFOBJ pffo(pPFF);
|
|
|
|
//
|
|
// if this font is loaded as EUDC, it can not be a BaseFont.
|
|
//
|
|
|
|
if( !pffo.bEUDC() )
|
|
{
|
|
//
|
|
// Unlink Eudc from All RFONTs that has Eudc..
|
|
//
|
|
|
|
for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
|
|
{
|
|
PRFONT prfntNext;
|
|
|
|
{
|
|
RFONTTMPOBJ rflo(prfnt);
|
|
prfntNext = rflo.prflPFF()->prfntNext;
|
|
}
|
|
|
|
//
|
|
// if this RFONT has system wide eudc, unlink it..
|
|
//
|
|
|
|
if( bUnlinkSystem )
|
|
{
|
|
#if DBG
|
|
if( prfnt->prfntSysEUDC != (PRFONT) NULL )
|
|
{
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Removing system wide EUDC pair %x -> %x\n",
|
|
prfnt, prfnt->prfntSysEUDC);
|
|
}
|
|
|
|
prfnt->prfntSysEUDC = NULL;
|
|
}
|
|
#else
|
|
|
|
prfnt->prfntSysEUDC = NULL;
|
|
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// if this RFONT has face name eudc, unlink it..
|
|
//
|
|
|
|
if( bUnlinkFaceName )
|
|
{
|
|
//
|
|
// NOTE :
|
|
//
|
|
// We will unlink the pointer to Rfont, even some of
|
|
// eudc link will valid (i.g. if we have on-bit of FONTLINK_SYSTEM in
|
|
// FontLinkChange value. the type of EUDC may not need to unlink.
|
|
// Because we should restructure the Rfonts array for following case,
|
|
// when even we want to only USER attribute EUDC....
|
|
//
|
|
// Before :
|
|
// BaseFont -> FaceNameEUDC(SYS) -> FaceNameEUDC(USER) -> FaceNameEUDC(SYS)
|
|
//
|
|
// After :
|
|
// BaseFont -> FaceNameEUDC(SYS) -> FaceNameEUDC(SYS)
|
|
//
|
|
|
|
if( prfnt->paprfntFaceName != NULL )
|
|
{
|
|
for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
|
|
{
|
|
#if DBG
|
|
if( prfnt->paprfntFaceName[ii] != NULL )
|
|
{
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Removing face name EUDC pair %x -> %x\n",
|
|
prfnt, prfnt->paprfntFaceName[ii]);
|
|
}
|
|
prfnt->paprfntFaceName[ii] = NULL;
|
|
}
|
|
#else
|
|
|
|
prfnt->paprfntFaceName[ii] = NULL;
|
|
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// if the linked RFONT table was allocated, free it here
|
|
//
|
|
|
|
if( prfnt->paprfntFaceName != prfnt->aprfntQuickBuff )
|
|
VFREEMEM( prfnt->paprfntFaceName );
|
|
|
|
//
|
|
// we have no facename eudc for this RFONT.
|
|
//
|
|
|
|
prfnt->uiNumLinks = 0;
|
|
prfnt->paprfntFaceName = NULL;
|
|
prfnt->bFilledEudcArray = FALSE;
|
|
prfnt->ulTimeStamp = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// initialize EUDC state.
|
|
//
|
|
|
|
prfnt->flEUDCState = 0;
|
|
|
|
//
|
|
// next...
|
|
//
|
|
|
|
prfnt = prfntNext;
|
|
}
|
|
|
|
//
|
|
// Unlink Eudcs from All PFEs that has Eudcs.
|
|
//
|
|
|
|
if( bUnlinkFaceName )
|
|
{
|
|
for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
|
|
{
|
|
PFEOBJ pfeo(pffo.ppfe(c));
|
|
|
|
#if DBG
|
|
if( pfeo.pGetLinkedFontEntry() != NULL )
|
|
{
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Removing face name PFE for %x (PFE)\n",pffo.ppfe(c));
|
|
}
|
|
|
|
pfeo.vSetLinkedFontEntry( NULL );
|
|
}
|
|
#else
|
|
|
|
pfeo.vSetLinkedFontEntry( NULL );
|
|
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
pPFF = pPFF->pPFFNext;
|
|
}
|
|
}
|
|
|
|
VOID vUnlinkAllEudcRFONTsAndPFEs
|
|
(
|
|
BOOL bUnlinkSystem,
|
|
BOOL bUnlinkFaceName
|
|
)
|
|
{
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,
|
|
"vUnlinkAllEudcRFONTsAndPFEs():Unlinking All EUDC RFONTs and PFEs.\n");
|
|
|
|
SEMOBJ so1(gpsemPublicPFT);
|
|
SEMOBJ so2(gpsemRFONTList);
|
|
|
|
COUNT cBuckets;
|
|
PPFF pPFF;
|
|
|
|
//
|
|
// get PFT user object.
|
|
//
|
|
|
|
PUBLIC_PFTOBJ pftoPublic; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkAllEudcRFONTsAndPFEsWorker(bUnlinkSystem,bUnlinkFaceName,pPFF);
|
|
}
|
|
}
|
|
|
|
DEVICE_PFTOBJ pftoDevice; // access the public font table
|
|
|
|
for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
|
|
{
|
|
if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
|
|
{
|
|
vUnlinkAllEudcRFONTsAndPFEsWorker(bUnlinkSystem,bUnlinkFaceName,pPFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bDeleteFlEntry(PWSTR,PWSTR,INT)
|
|
*
|
|
* This function delete base font and linked font pair from list.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bDeleteFlEntry
|
|
(
|
|
PWSTR BaseFontName,
|
|
PWSTR LinkedFontPathAndName,
|
|
INT iFontLinkType // FONTLINK_SYSTEM or FONTLINK_USER
|
|
)
|
|
{
|
|
PFLENTRY pFlEntry = NULL;
|
|
PPFEDATA ppfeData = NULL;
|
|
PWSTR LinkedFaceName = NULL;
|
|
WCHAR awcPathBuffer[MAX_PATH];
|
|
WCHAR LinkedFontName[LF_FACESIZE+MAX_PATH+1];
|
|
|
|
//
|
|
// Have a local copy...
|
|
//
|
|
|
|
wcscpy(LinkedFontName,LinkedFontPathAndName);
|
|
|
|
//
|
|
// Find ',' char from LinkedFontName
|
|
//
|
|
// Registry format :
|
|
//
|
|
// Type 1:
|
|
//
|
|
// This format is for the specified Linked font contains only 1 font resource.
|
|
// Except Vertical "@" face font, such as TrueType font (not TTC), and Vector font.
|
|
//
|
|
// BaseFontFaceName = REG_MULTI_SZ "FontPathFileName" , ...
|
|
//
|
|
// Type 2:
|
|
//
|
|
// This format is for the specified Linked font contains more than 1 font resource,
|
|
// TTC TrueType font, and Bitmap font.
|
|
//
|
|
// BaseFontFaceName = REG_MULTI_SZ "FontPathFileName,FontFaceNameInTheFile" , ...
|
|
//
|
|
// After calling ValidLinkedRegistry(), the ',' character is replaced with NULL if
|
|
// found.
|
|
//
|
|
|
|
if( !bValidFontLinkParameter(LinkedFontName,&LinkedFaceName) )
|
|
{
|
|
#if DBG
|
|
DbgPrint("Invalid Registry format - %ws\n",LinkedFontName);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Get full path name for this font file.
|
|
//
|
|
|
|
bAppendSysDirectory(awcPathBuffer, LinkedFontName);
|
|
|
|
// If this file is being used as the system EUDC file then it can't be used
|
|
// as a facename EUDC file.
|
|
|
|
|
|
if( _wcsicmp(awcPathBuffer,gawcEUDCPath) == 0 )
|
|
{
|
|
#if DBG
|
|
DbgPrint("%ws can't be unload as a facename link because it is the system \
|
|
EUDC file.\n", LinkedFontName);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Check base font list, To remove, the base font should be listed..
|
|
//
|
|
|
|
if( IsListEmpty( &BaseFontListHead ) ||
|
|
(pFlEntry = FindBaseFontEntry( BaseFontName )) == NULL )
|
|
{
|
|
//
|
|
// We can not find out this base font in current link list.
|
|
//
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// The Entry for this base font is already exist....
|
|
//
|
|
|
|
#if DBG
|
|
//
|
|
// The FLENTRY should have one or more PFEDATA.
|
|
//
|
|
if( IsListEmpty( &(pFlEntry->linkedFontListHead) ) )
|
|
{
|
|
DbgPrint("This FLENTRY has no PFEDATA (%ws)\n",pFlEntry->awcFaceName);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Scan linked font list for this base font.
|
|
// if this linked font is already listed, we do not add this.
|
|
//
|
|
|
|
if( (ppfeData = FindLinkedFontEntry( &(pFlEntry->linkedFontListHead) ,
|
|
awcPathBuffer, LinkedFaceName ) ) == NULL )
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_FONTLINK_INIT|DEBUG_FONTLINK_LOAD|DEBUG_FACENAME_EUDC) )
|
|
{
|
|
DbgPrint("Can not find linked font %ws -> %ws\n",BaseFontName,LinkedFontName);
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Check we can really unload this eudc font.
|
|
//
|
|
|
|
if( ppfeData->FontLinkType == iFontLinkType )
|
|
{
|
|
//
|
|
// Now we can find out target PFEDATA.
|
|
//
|
|
|
|
AcquireGreResource( &gfmEUDC4 );
|
|
|
|
//
|
|
// Remove the PFEDATA from current list.
|
|
//
|
|
|
|
RemoveEntryList( &(ppfeData->linkedFontList) );
|
|
|
|
//
|
|
// Decrement number of linked list count.
|
|
//
|
|
|
|
pFlEntry->uiNumLinks--;
|
|
|
|
//
|
|
// if there is no PFEDATA for this FLENTRY...
|
|
//
|
|
|
|
if( pFlEntry->uiNumLinks == 0 )
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
DbgPrint("Deleting FLENTRY for %ws\n",pFlEntry->awcFaceName);
|
|
}
|
|
|
|
if(!IsListEmpty(&(pFlEntry->linkedFontListHead)))
|
|
{
|
|
DbgPrint("bDeleteFlEntry():Deleting FLENTRY that has PFEDATA \
|
|
(%ws -> %ws)\n", BaseFontName,LinkedFontName);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// disable the link of this facename.
|
|
//
|
|
|
|
vUnlinkEudcRFONTsAndPFEs(ppfeData->appfe,pFlEntry);
|
|
|
|
//
|
|
// Remove this FLENTRY from BaseFontList.
|
|
//
|
|
|
|
RemoveEntryList( &(pFlEntry->baseFontList) );
|
|
|
|
//
|
|
// Free this FLENTRY.
|
|
//
|
|
|
|
VFREEMEM( pFlEntry );
|
|
|
|
//
|
|
// Decrement global base font number
|
|
//
|
|
|
|
gcNumLinks--;
|
|
|
|
//
|
|
// BaseFontList has been change, update TimeStamp
|
|
//
|
|
|
|
ulFaceNameEUDCTimeStamp++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// disable the link of this facename Eudc.
|
|
//
|
|
|
|
vUnlinkEudcRFONTs(ppfeData->appfe);
|
|
|
|
//
|
|
// Update time stamp for this facename link.
|
|
//
|
|
|
|
pFlEntry->ulTimeStamp++;
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC4 );
|
|
|
|
//
|
|
// Unload this Eudc font.
|
|
//
|
|
|
|
if( !bUnloadEudcFont( ppfeData->appfe ) )
|
|
{
|
|
DbgPrint("bDeleteFlEntry():bUnloadEudcFont() fail - %ws\n",LinkedFontName);
|
|
}
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
|
|
{
|
|
PFEOBJ pfeo(ppfeData->appfe[PFE_NORMAL]);
|
|
PFFOBJ pffo(pfeo.pPFF());
|
|
|
|
DbgPrint("Deleting PFEDATA for %ws\n",pffo.pwszPathname());
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Free this PFEDATA.
|
|
//
|
|
|
|
VFREEMEM( ppfeData );
|
|
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* BOOL bAddFlEntry(PWSTR,PWSTR,INT,PFLENTRY *)
|
|
*
|
|
* This function add new base font and linked font pair into list.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bAddFlEntry
|
|
(
|
|
PWSTR BaseFontName,
|
|
PWSTR LinkedFontPathAndName,
|
|
INT iFontLinkType, // FONTLINK_SYSTEM or FONTLINK_USER
|
|
INT iPriority,
|
|
PFLENTRY *ppFlEntry
|
|
)
|
|
{
|
|
PFLENTRY pFlEntry = NULL;
|
|
PWSTR LinkedFaceName = NULL;
|
|
WCHAR awcPathBuffer[MAX_PATH];
|
|
WCHAR LinkedFontName[LF_FACESIZE+MAX_PATH+1];
|
|
|
|
//
|
|
// if ppFlEntry is presented, initialize with NULL.
|
|
//
|
|
|
|
if( ppFlEntry != NULL ) *ppFlEntry = NULL;
|
|
|
|
//
|
|
// Have a local copy...
|
|
//
|
|
|
|
wcscpy(LinkedFontName,LinkedFontPathAndName);
|
|
|
|
//
|
|
// Find ',' char from LinkedFontName
|
|
//
|
|
// Registry format :
|
|
//
|
|
// Type 1:
|
|
//
|
|
// This format is for the specified Linked font contains only 1 font resource.
|
|
// Except Vertical "@" face font, such as TrueType font (not TTC), and Vector font.
|
|
//
|
|
// BaseFontFaceName = REG_MULTI_SZ "FontPathFileName" , ...
|
|
//
|
|
// Type 2:
|
|
//
|
|
// This format is for the specified Linked font contains more than 1 font resource,
|
|
// TTC TrueType font, and Bitmap font.
|
|
//
|
|
// BaseFontFaceName = REG_MULTI_SZ "FontPathFileName,FontFaceNameInTheFile" , ...
|
|
//
|
|
// After calling ValidLinkedRegistry(), the ',' character is replaced with NULL if
|
|
// found.
|
|
//
|
|
|
|
if( !bValidFontLinkParameter(LinkedFontName,&LinkedFaceName) )
|
|
{
|
|
#if DBG
|
|
DbgPrint("Invalid Registry format - %ws\n",LinkedFontName);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
|
|
{
|
|
if( LinkedFaceName )
|
|
{
|
|
DbgPrint("FontFile - %ws : FontFace - %ws\n",LinkedFontName,LinkedFaceName);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Get full path name for this font file.
|
|
//
|
|
|
|
bAppendSysDirectory( awcPathBuffer, LinkedFontName );
|
|
|
|
//
|
|
// If this file is being used as the system EUDC file then it can't be used
|
|
// as a facename EUDC file.
|
|
//
|
|
|
|
if( _wcsicmp(awcPathBuffer,gawcEUDCPath) == 0 )
|
|
{
|
|
#if DBG
|
|
DbgPrint(
|
|
"%ws can't be load as a facename link because it is the system EUDC file.\n",
|
|
LinkedFontName
|
|
);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Check base font list, it is a new one ?
|
|
//
|
|
|
|
if( !IsListEmpty( &BaseFontListHead ) &&
|
|
(pFlEntry = FindBaseFontEntry( BaseFontName )) != NULL )
|
|
{
|
|
//
|
|
// The Entry for this base font is already exist....
|
|
//
|
|
|
|
if( !IsListEmpty( &(pFlEntry->linkedFontListHead) ) )
|
|
{
|
|
//
|
|
// Scan linked font list for this base font.
|
|
// if this linked font is already listed, we do not add this.
|
|
//
|
|
|
|
if( FindLinkedFontEntry( &(pFlEntry->linkedFontListHead) ,
|
|
awcPathBuffer , LinkedFaceName ) != NULL )
|
|
{
|
|
#if DBG
|
|
DbgPrint("Dupulicate linked font - %ws\n",LinkedFontName);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// get and validate PFT user object
|
|
//
|
|
|
|
PUBLIC_PFTOBJ pfto; // access the public font table
|
|
PPFE appfeLink[2]; // temporary buffer
|
|
LONG cFonts; // count of fonts
|
|
EUDCLOAD EudcLoadData; // eudc load data
|
|
|
|
//
|
|
// parameter for PFTOBJ::bLoadFonts()
|
|
//
|
|
|
|
FLONG flParam = PFF_STATE_EUDC_FONT;
|
|
|
|
//
|
|
// Fill up EudcLoadData structure
|
|
//
|
|
|
|
EudcLoadData.pppfeData = (PPFE *) &appfeLink;
|
|
EudcLoadData.LinkedFace = LinkedFaceName;
|
|
|
|
//
|
|
// if the FontLinkType is system, it should be a Permanent font.
|
|
//
|
|
|
|
if( iFontLinkType == FONTLINK_SYSTEM )
|
|
{
|
|
flParam |= PFF_STATE_PERMANENT_FONT;
|
|
}
|
|
|
|
//
|
|
// Load the linked font.
|
|
//
|
|
|
|
PFF *placeHolder;
|
|
|
|
if( pfto.bLoadAFont( awcPathBuffer,
|
|
(PULONG) &cFonts,
|
|
flParam,
|
|
&placeHolder,
|
|
&EudcLoadData ) )
|
|
{
|
|
PFEOBJ pfeo( appfeLink[PFE_NORMAL] );
|
|
|
|
//
|
|
// Check we really succeed to load requested facename font.
|
|
//
|
|
if( !pfeo.bValid() ||
|
|
//
|
|
// Compute table for normal face
|
|
//
|
|
!bComputeQuickLookup( pfeo.pql(), pfeo.pfdg(), FALSE ))
|
|
{
|
|
WARNING("Unable to compute QuickLookUp for face name link\n");
|
|
|
|
pfto.bUnloadEUDCFont(awcPathBuffer);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Compute table for vertical face, if vertical face font is provided,
|
|
//
|
|
|
|
PFEOBJ pfeoVert( appfeLink[PFE_VERTICAL] );
|
|
|
|
if( pfeoVert.bValid() )
|
|
{
|
|
if( !bComputeQuickLookup( pfeoVert.pql(), pfeoVert.pfdg(), FALSE ))
|
|
{
|
|
WARNING("Unable to compute QuickLookUp for face name link\n");
|
|
|
|
pfto.bUnloadEUDCFont(awcPathBuffer);
|
|
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
AcquireGreResource( &gfmEUDC4 );
|
|
|
|
//
|
|
// if we still not have FLENTRY for this, allocate here..
|
|
//
|
|
|
|
if( pFlEntry == NULL )
|
|
{
|
|
|
|
FLINKMESSAGE2(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT|DEBUG_FACENAME_EUDC,
|
|
"Allocate FLENTRY for %ws\n",BaseFontName);
|
|
|
|
// Allocate new FLENTRY..
|
|
|
|
pFlEntry = (PFLENTRY) PALLOCNOZ( sizeof(FLENTRY), 'flnk' );
|
|
|
|
// Initialize number of linked font count.
|
|
|
|
pFlEntry->uiNumLinks = 0;
|
|
|
|
// Initialize link time stamp
|
|
|
|
pFlEntry->ulTimeStamp = 0;
|
|
|
|
// Copy base font name to buffer.
|
|
|
|
wcscpy(pFlEntry->awcFaceName,BaseFontName);
|
|
|
|
// Initialize linked font list for this base font.
|
|
|
|
InitializeListHead( &(pFlEntry->linkedFontListHead) );
|
|
|
|
// Add this entry to BaseFontList.
|
|
|
|
InsertTailList( &BaseFontListHead , &(pFlEntry->baseFontList) );
|
|
|
|
// Increment global base font number
|
|
|
|
gcNumLinks++;
|
|
|
|
// just notify new FLENTRY was allocated to caller
|
|
|
|
if( ppFlEntry != NULL ) *(PFLENTRY *)ppFlEntry = pFlEntry;
|
|
|
|
// BaseFontList has been change, update TimeStamp
|
|
|
|
ulFaceNameEUDCTimeStamp++;
|
|
}
|
|
|
|
#if DBG
|
|
if(gflEUDCDebug&(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT|DEBUG_FACENAME_EUDC))
|
|
{
|
|
DbgPrint("Allocate PFEDATA for %ws - %ws\n",BaseFontName,LinkedFontName);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Allocate new PFEDATA...
|
|
//
|
|
|
|
PPFEDATA ppfeData = (PPFEDATA) PALLOCNOZ(sizeof(PFEDATA), 'flnk' );
|
|
|
|
//
|
|
// Set PFE for linked font into the structure.
|
|
//
|
|
|
|
ppfeData->appfe[PFE_NORMAL] = appfeLink[PFE_NORMAL];
|
|
ppfeData->appfe[PFE_VERTICAL] = appfeLink[PFE_VERTICAL];
|
|
|
|
//
|
|
// Set FontLinkType.
|
|
//
|
|
|
|
ppfeData->FontLinkType = iFontLinkType;
|
|
|
|
//
|
|
// Set FontLinkFlag.
|
|
//
|
|
|
|
ppfeData->FontLinkFlag = 0L;
|
|
|
|
if( EudcLoadData.LinkedFace )
|
|
ppfeData->FontLinkFlag |= FLINK_FACENAME_SPECIFIED;
|
|
|
|
//
|
|
// Incremant number of linked font count for this base face name.
|
|
//
|
|
|
|
pFlEntry->uiNumLinks++;
|
|
|
|
//
|
|
// Update time stamp
|
|
//
|
|
|
|
pFlEntry->ulTimeStamp++;
|
|
|
|
//
|
|
// add pfe for this font our list of flinks
|
|
//
|
|
|
|
if( iPriority < 0 )
|
|
{
|
|
//
|
|
// Insert end of this list.
|
|
//
|
|
|
|
InsertTailList(&(pFlEntry->linkedFontListHead),
|
|
&(ppfeData->linkedFontList) );
|
|
}
|
|
else // LATER if( iPriority == 0 )
|
|
{
|
|
//
|
|
// Insert top of this list.
|
|
//
|
|
|
|
InsertHeadList(&(pFlEntry->linkedFontListHead),
|
|
&(ppfeData->linkedFontList));
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC4 );
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint("Failed to load EUDC font - %ws\n",awcPathBuffer);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bDeleteAllFlEntry(BOOL,BOOL)
|
|
*
|
|
* This function delete all linked font information including system wide eudc.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bDeleteAllFlEntry
|
|
(
|
|
BOOL bDeleteSystem,
|
|
BOOL bDeleteFaceName
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
// disable the link of all facename and system wide eudc.
|
|
|
|
vUnlinkAllEudcRFONTsAndPFEs(bDeleteSystem,bDeleteFaceName);
|
|
|
|
// if there is no system wife eudc font.. skip it.
|
|
|
|
if( bDeleteSystem && IS_SYSTEM_EUDC_PRESENT() )
|
|
{
|
|
// Unload system wide eudc font
|
|
|
|
if( !bUnloadEudcFont( gappfeSysEUDC ) )
|
|
{
|
|
WARNING("bDeleteAllFlEntry():Can not unload system wide eudc\n");
|
|
}
|
|
|
|
// Clear global data.
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = NULL;
|
|
gappfeSysEUDC[PFE_VERTICAL] = NULL;
|
|
|
|
wcscpy(gawcEUDCPath,L"\0");
|
|
|
|
ulSystemEUDCTimeStamp++;
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
|
|
// if there is no facename eudc, just return here.
|
|
|
|
if( bDeleteFaceName && !IsListEmpty(&BaseFontListHead) )
|
|
{
|
|
COUNT NumberOfLinks = gcNumLinks;
|
|
|
|
AcquireGreResource( &gfmEUDC4 );
|
|
|
|
// start to scan facename link list.
|
|
|
|
PLIST_ENTRY p = BaseFontListHead.Flink;
|
|
|
|
while( p != &BaseFontListHead )
|
|
{
|
|
PFLENTRY pFlEntry;
|
|
PLIST_ENTRY pDelete = p;
|
|
ULONG AlivePfeData = 0;
|
|
|
|
pFlEntry = CONTAINING_RECORD(pDelete,FLENTRY,baseFontList);
|
|
|
|
// if there is no linked font for this base face, try next base font.
|
|
|
|
if(IsListEmpty(&(pFlEntry->linkedFontListHead)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// get pointer to PFEDATA list.
|
|
|
|
PLIST_ENTRY pp = pFlEntry->linkedFontListHead.Flink;
|
|
|
|
FLINKMESSAGE2((DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_UNLOAD),
|
|
"Delete %ws link\n",pFlEntry->awcFaceName);
|
|
|
|
while( pp != &(pFlEntry->linkedFontListHead) )
|
|
{
|
|
PPFEDATA ppfeData;
|
|
PLIST_ENTRY ppDelete = pp;
|
|
|
|
ppfeData = CONTAINING_RECORD(ppDelete,PFEDATA,linkedFontList);
|
|
|
|
// Check Current FontLinkChange state to see if we can really unload
|
|
// EUDC font.
|
|
|
|
if( (ppfeData->FontLinkType == FONTLINK_SYSTEM &&
|
|
ulFontLinkChange & FLINK_UNLOAD_FACENAME_SYSTEM) ||
|
|
(ppfeData->FontLinkType == FONTLINK_USER &&
|
|
ulFontLinkChange & FLINK_UNLOAD_FACENAME_USER))
|
|
{
|
|
// Unload font of this PFE..
|
|
|
|
if( !bUnloadEudcFont( ppfeData->appfe ) )
|
|
{
|
|
WARNING("bDeleteAllFlEntry():Can not unload facename eudc\n");
|
|
}
|
|
|
|
pp = ppDelete->Flink;
|
|
|
|
// Delete this PFEDATA from this link list
|
|
|
|
RemoveEntryList(ppDelete);
|
|
|
|
// Free PFEDATA.
|
|
|
|
VFREEMEM(ppDelete);
|
|
}
|
|
else
|
|
{
|
|
// This PFEDATA is still valid...
|
|
|
|
AlivePfeData++;
|
|
pp = ppDelete->Flink;
|
|
}
|
|
}
|
|
|
|
// next FLENTRY...
|
|
|
|
p = pDelete->Flink;
|
|
|
|
if( AlivePfeData == 0 )
|
|
{
|
|
// Delete this FLENTRY from link list
|
|
|
|
RemoveEntryList(pDelete);
|
|
|
|
// Free FLENTRY
|
|
|
|
VFREEMEM(pDelete);
|
|
|
|
// Decrement number of facename links
|
|
|
|
gcNumLinks--;
|
|
}
|
|
else
|
|
{
|
|
if( pFlEntry->uiNumLinks != AlivePfeData )
|
|
{
|
|
// Update Timestamp for this
|
|
|
|
pFlEntry->ulTimeStamp++;
|
|
|
|
// Update number of linked font.
|
|
|
|
pFlEntry->uiNumLinks = AlivePfeData;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( NumberOfLinks != gcNumLinks )
|
|
{
|
|
// BaseFontList has been changed, update TimeStamp
|
|
|
|
ulFaceNameEUDCTimeStamp++;
|
|
}
|
|
|
|
if( gcNumLinks != 0 )
|
|
{
|
|
// Connect to loaded PFEs for valid FLENTRY/PFEDATA.
|
|
|
|
vLinkEudcPFEs(NULL);
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC4 );
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* NTSTATUS BuildAndLoadLinkedFontRoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
|
|
*
|
|
* This is a callback function that is called by RtlQueryRegistryValues()
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
extern "C"
|
|
NTSTATUS
|
|
BuildAndLoadLinkedFontRoutine
|
|
(
|
|
PWSTR ValueName,
|
|
ULONG ValueType,
|
|
PVOID ValueData,
|
|
ULONG ValueLength,
|
|
PVOID Context,
|
|
PVOID EntryContext
|
|
)
|
|
{
|
|
WCHAR FontPathName[MAX_PATH+LF_FACESIZE+1];
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_FACENAME_EUDC|DEBUG_FONTLINK_INIT) )
|
|
{
|
|
DbgPrint("BaseFontName - %ws : LinkedFont - %ws\n",ValueName,ValueData);
|
|
}
|
|
#endif
|
|
|
|
// if this is a value for System EUDC, return here...
|
|
|
|
if( _wcsicmp(ValueName,(PWSTR)L"SystemDefaultEUDCFont") == 0 )
|
|
return(STATUS_SUCCESS);
|
|
|
|
// Copy it to local buffer and make sure its null-termination.
|
|
|
|
RtlMoveMemory(FontPathName,ValueData,ValueLength);
|
|
FontPathName[ValueLength/sizeof(WCHAR)] = L'\0';
|
|
|
|
// Add base font and linked font pair into global list..
|
|
|
|
if(!bAddFlEntry(ValueName,(PWSTR)FontPathName,(INT)EntryContext,-1,NULL))
|
|
{
|
|
WARNING("BuildAndLoadLinkedFontRoutine():lAddFlEntry() fail\n");
|
|
}
|
|
|
|
// return STATUS_SUCCESS everytime,even we got error from above call, to
|
|
// get next enumuration.
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* NTSTATUS bAddAllFlEntryWorker(LPWSTR,INT)
|
|
*
|
|
* This function load font and build link for eudc font according to registry.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS bAddAllFlEntryWorker
|
|
(
|
|
LPWSTR EUDCRegistryPath,
|
|
INT FontLinkType // FONTLINK_SYSTEM or FONTLINK_USER
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
//
|
|
// initialize/load face name eudc
|
|
//
|
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
|
|
QueryTable[0].QueryRoutine = BuildAndLoadLinkedFontRoutine;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[0].Name = (PWSTR)NULL;
|
|
QueryTable[0].EntryContext = (PVOID)FontLinkType;
|
|
QueryTable[0].DefaultType = REG_NONE;
|
|
QueryTable[0].DefaultData = NULL;
|
|
QueryTable[0].DefaultLength = 0;
|
|
|
|
QueryTable[1].QueryRoutine = NULL;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = (PWSTR)NULL;
|
|
|
|
//
|
|
// Enumurate registry values
|
|
//
|
|
|
|
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
EUDCRegistryPath,
|
|
QueryTable,
|
|
NULL,
|
|
NULL);
|
|
|
|
return(NtStatus);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* BOOL bAddAllFlEntry(BOOL,BOOL,INT)
|
|
*
|
|
* This function load font and build link for eudc font according to registry.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL bAddAllFlEntry
|
|
(
|
|
BOOL bAddSystem,
|
|
BOOL bAddFaceName
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
BOOL bLoadSystem = FALSE;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_INIT|DEBUG_FONTLINK_LOAD,
|
|
"bAddAllFlEntry():Initializing EUDC data.\n");
|
|
|
|
// initialize/load the system-wide ( all face-name EUDC font )
|
|
|
|
if( bAddSystem && !IS_SYSTEM_EUDC_PRESENT() )
|
|
{
|
|
WCHAR awcPathBuffer1[MAX_PATH];
|
|
WCHAR awcPathBuffer2[MAX_PATH];
|
|
|
|
//
|
|
// read registry data for System eudc
|
|
//
|
|
|
|
if(bReadUserSystemEUDCRegistry(awcPathBuffer1, MAX_PATH))
|
|
{
|
|
PPFE appfeSysEUDC[2];
|
|
|
|
//
|
|
// Search system-wide EUDC font. if the specified registry value does not
|
|
// contain full path name.
|
|
//
|
|
// bAppendSysDirectory return TRUE, when we have to update registry data.
|
|
// otherwise return FALSE.
|
|
//
|
|
// If the Eudc file is under Windows root directory (ex. WINNT) we want to
|
|
// update registry data. because we might fail to load EUDC after user had
|
|
// change System root with Disk Administrator.
|
|
//
|
|
|
|
if( bAppendSysDirectory( awcPathBuffer2, awcPathBuffer1 ) )
|
|
{
|
|
#ifdef PORTABLE_WINDOWS_DIR
|
|
//
|
|
// Update registry data.
|
|
//
|
|
|
|
LPWSTR pwcSavePath;
|
|
|
|
//
|
|
// if registry data contains full path, and the file is under windows
|
|
// directory, replace the hardcodeed path with %SystemRoot%....
|
|
//
|
|
if((pwcSavePath = pwcFileIsUnderWindowsRoot( awcPathBuffer1 ) ) != NULL )
|
|
{
|
|
WCHAR awcSystemEudcPath[MAX_PATH+1];
|
|
|
|
wcscpy( awcSystemEudcPath, L"%SystemRoot%" );
|
|
if( *pwcSavePath != L'\\' ) wcscat( awcSystemEudcPath, L"\\" );
|
|
wcscat( awcSystemEudcPath, pwcSavePath );
|
|
|
|
pwcSavePath = awcSystemEudcPath;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_LOAD,
|
|
"bAddAllFlEntry():Eudc Path %ws is Saved\n");
|
|
|
|
if(!bWriteUserSystemEUDCRegistry(pwcSavePath,wcslen(pwcSavePath)+1))
|
|
{
|
|
WARNING("Unable to write new link to registry.\n");
|
|
}
|
|
}
|
|
#else
|
|
;
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// NOTE :
|
|
//
|
|
// Currently Systen wide EUDC does not support Type 1 Registry format.
|
|
// See description in bAddFlEntry().
|
|
//
|
|
|
|
//
|
|
// get and validate PFT user object
|
|
//
|
|
|
|
PUBLIC_PFTOBJ pfto; // access the public font table
|
|
|
|
ASSERTGDI (
|
|
pfto.bValid(),
|
|
"gdisrv!bAddAllFlEntry(): could not access the public font table\n"
|
|
);
|
|
|
|
{
|
|
SEMOBJ so(gpsemPublicPFT);
|
|
|
|
//
|
|
// Check this font is already loaded as Eudc font or not.
|
|
//
|
|
|
|
if( !pfto.pPFFGet(awcPathBuffer2,NULL,TRUE) )
|
|
{
|
|
EUDCLOAD EudcLoadData;
|
|
|
|
//
|
|
// fill up EUDCLOAD structure
|
|
//
|
|
|
|
EudcLoadData.pppfeData = (PPFE *) &appfeSysEUDC;
|
|
EudcLoadData.LinkedFace = NULL;
|
|
|
|
//
|
|
// load this font as eudc font.
|
|
//
|
|
|
|
LONG cFonts; // count of fonts
|
|
PFF *placeHolder;
|
|
|
|
|
|
bLoadSystem = pfto.bLoadAFont( (PWSZ) awcPathBuffer2,
|
|
(PULONG) &cFonts,
|
|
PFF_STATE_EUDC_FONT,
|
|
&placeHolder,
|
|
&EudcLoadData );
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint("bAddAllElEntry():%ws is loaded as EUDC already\n",
|
|
awcPathBuffer2);
|
|
#endif
|
|
|
|
bLoadSystem = FALSE;
|
|
}
|
|
}
|
|
|
|
if( bLoadSystem )
|
|
{
|
|
//
|
|
// Compute table besed on normal face
|
|
//
|
|
|
|
PFEOBJ pfeo( appfeSysEUDC[PFE_NORMAL] );
|
|
|
|
if( !pfeo.bValid() ||
|
|
!bComputeQuickLookup( &gqlEUDC, pfeo.pfdg(), TRUE ) )
|
|
{
|
|
WARNING("Unable to compute QuickLookUp for system EUDC\n");
|
|
|
|
//
|
|
// Unload font..
|
|
//
|
|
|
|
pfto.bUnloadEUDCFont(awcPathBuffer2);
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = NULL;
|
|
gappfeSysEUDC[PFE_VERTICAL] = NULL;
|
|
|
|
wcscpy(gawcEUDCPath,L"\0");
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We believe that vertical face has same glyphset as normal face.
|
|
//
|
|
|
|
//
|
|
// Update system wide Eudc global data..
|
|
//
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = appfeSysEUDC[PFE_NORMAL];
|
|
gappfeSysEUDC[PFE_VERTICAL] = appfeSysEUDC[PFE_VERTICAL];
|
|
|
|
wcscpy(gawcEUDCPath,awcPathBuffer2);
|
|
|
|
//
|
|
// Update global eudc timestamp.
|
|
//
|
|
|
|
ulSystemEUDCTimeStamp++;
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("Failed to load system wide EUDC font.\n");
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = PPFENULL;
|
|
gappfeSysEUDC[PFE_VERTICAL] = PPFENULL;
|
|
|
|
wcscpy(gawcEUDCPath,L"\0");
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_SYSTEM_EUDC|DEBUG_FONTLINK_INIT) )
|
|
{
|
|
DbgPrint("EUDC system wide %ws hpfe is %x vert hpfe is %x\n",
|
|
gawcEUDCPath, gappfeSysEUDC[PFE_NORMAL],
|
|
gappfeSysEUDC[PFE_VERTICAL]);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WARNING("GDISRV:Fail to read system wide eudc\n");
|
|
}
|
|
}
|
|
|
|
if( bAddFaceName )
|
|
{
|
|
WCHAR EUDCRegistryPathBuffer[MAX_PATH];
|
|
|
|
if( ulFontLinkChange & FLINK_LOAD_FACENAME_SYSTEM )
|
|
{
|
|
//
|
|
// Get Registry path for Eudc..
|
|
//
|
|
|
|
wcscpy(EUDCRegistryPathBuffer,EUDC_SYSTEM_REGISTRY_KEY);
|
|
|
|
//
|
|
// Call worker function.
|
|
//
|
|
|
|
NtStatus = bAddAllFlEntryWorker(EUDCRegistryPathBuffer,FONTLINK_SYSTEM);
|
|
|
|
#if DBG
|
|
if( !NT_SUCCESS(NtStatus) )
|
|
{
|
|
WARNING("Face name eudc is disabled (FONTLINK_SYSTEM)\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if( ulFontLinkChange & FLINK_LOAD_FACENAME_USER )
|
|
{
|
|
//
|
|
// Get Registry path for Eudc..
|
|
//
|
|
|
|
GetUserEUDCRegistryPath(EUDCRegistryPathBuffer,
|
|
sizeof(EUDCRegistryPathBuffer));
|
|
|
|
//
|
|
// Call worker function.
|
|
//
|
|
|
|
NtStatus = bAddAllFlEntryWorker(EUDCRegistryPathBuffer,FONTLINK_USER);
|
|
|
|
#if DBG
|
|
if( !NT_SUCCESS(NtStatus) )
|
|
{
|
|
WARNING("Face name eudc is disabled (FONTLINK_USER)\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Connect to loaded PFEs.
|
|
//
|
|
|
|
vLinkEudcPFEs(NULL);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* VOID vInitializeEUDC(VOID)
|
|
*
|
|
* This is called once during win32k.sys initialization and initializes the
|
|
* system EUDC information. First it creates a FLINKOBJ and set ghflEUDC to
|
|
* it. Then it initializes the FLINKOBJ with information from the registry.
|
|
* After that it loads all the EUDC fonts and sets up links between base
|
|
* font PFE's and EUDC font pfe's.
|
|
*
|
|
* History
|
|
* 1-09-95 Hideyuki Nagase
|
|
* Rewrote it.
|
|
*
|
|
* 2-10-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
VOID vInitializeEUDC(VOID)
|
|
{
|
|
|
|
NTSTATUS NtStatus;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_INIT,
|
|
"vInitializeEUDC():Initializing EUDC data.\n");
|
|
|
|
gawcEUDCPath[0] = L'\0';
|
|
|
|
|
|
// Set up Global EUDC semaphores
|
|
|
|
//!!!!!! gfmEUDC2 needs to be initialized locked. We need to do something here
|
|
//!!!!!! perhaps even use something other than a GRE_EXCLUSIVE_RESOURCE here
|
|
|
|
|
|
if ( (!(NT_SUCCESS(InitializeGreResource(&gfmEUDC1)))) ||
|
|
(!(NT_SUCCESS(InitializeGreResource(&gfmEUDC2)))) ||
|
|
(!(NT_SUCCESS(InitializeGreResource(&gfmEUDC3)))) ||
|
|
(!(NT_SUCCESS(InitializeGreResource(&gfmEUDC4)))))
|
|
{
|
|
ASSERTGDI(FALSE, "vInitializeEUDC could not initialize Gre Resources\n");
|
|
}
|
|
|
|
// Set up EUDC QUICKLOOKUP Table
|
|
|
|
gqlEUDC.puiBits = NULL;
|
|
gqlEUDC.wcLow = 1;
|
|
gqlEUDC.wcHigh = 0;
|
|
|
|
|
|
// Get Current codepage to access registry..
|
|
|
|
|
|
USHORT usACP,usOEMCP;
|
|
|
|
EngGetCurrentCodePage(&usOEMCP,&usACP);
|
|
|
|
// Convert Integer to Unicode string..
|
|
|
|
UNICODE_STRING SystemACPString;
|
|
|
|
SystemACPString.Length = 0;
|
|
SystemACPString.MaximumLength = sizeof(gawcSystemACP);
|
|
SystemACPString.Buffer = gawcSystemACP;
|
|
|
|
RtlIntegerToUnicodeString( (int) usACP, 10, &SystemACPString );
|
|
|
|
FLINKMESSAGE2(DEBUG_FONTLINK_INIT,"GDISRV:System ACP is %ws\n",gawcSystemACP);
|
|
|
|
// Read FontLink configuration value.
|
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
|
|
RTL_QUERY_REGISTRY_DIRECT;
|
|
QueryTable[0].Name = (PWSTR)L"FontLinkControl";
|
|
QueryTable[0].EntryContext = (PVOID) &ulFontLinkControl;
|
|
QueryTable[0].DefaultType = REG_DWORD;
|
|
QueryTable[0].DefaultData = 0;
|
|
QueryTable[0].DefaultLength = 0;
|
|
|
|
QueryTable[1].QueryRoutine = NULL;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = (PWSTR)NULL;
|
|
|
|
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
|
|
L"FontLink",
|
|
QueryTable,
|
|
NULL,
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(NtStatus))
|
|
{
|
|
WARNING("Error reading FontLinkControl\n");
|
|
ulFontLinkControl = 0L;
|
|
}
|
|
|
|
FLINKMESSAGE2(DEBUG_FONTLINK_CONTROL,
|
|
"win32ksys:FontLinkControl = %x\n",ulFontLinkControl);
|
|
|
|
|
|
// initialize Eudc default char code in Unicode.
|
|
|
|
DWORD dwEudcDefaultChar;
|
|
|
|
QueryTable[0].Name = (PWSTR)L"FontLinkDefaultChar";
|
|
QueryTable[0].EntryContext = (PVOID) &dwEudcDefaultChar;
|
|
|
|
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
|
|
L"FontLink",
|
|
QueryTable,
|
|
NULL,
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(NtStatus))
|
|
{
|
|
WARNING("Error reading FontLinkDefaultChar\n");
|
|
EudcDefaultChar = 0x30fb;
|
|
}
|
|
else
|
|
{
|
|
EudcDefaultChar = (WCHAR)dwEudcDefaultChar;
|
|
}
|
|
|
|
// initialize base font list
|
|
|
|
|
|
InitializeListHead(&BaseFontListHead);
|
|
|
|
|
|
// if FontLink feature is disabled, nothing to do.....
|
|
|
|
if( ulFontLinkControl & FLINK_DISABLE_FONTLINK )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Load and setup SYSTEM Global facename EUDC data.
|
|
|
|
|
|
ulFontLinkChange = FLINK_LOAD_FACENAME_SYSTEM |
|
|
FLINK_UNLOAD_FACENAME_SYSTEM;
|
|
|
|
|
|
// Enable only FaceName (system common) EUDC.
|
|
|
|
bAddAllFlEntry(FALSE,TRUE);
|
|
|
|
// After load system global EUDC, we will only allow to user to
|
|
// load/unload per user eudc configuration.
|
|
|
|
|
|
ulFontLinkChange = FLINK_LOAD_FACENAME_USER |
|
|
FLINK_UNLOAD_FACENAME_USER;
|
|
|
|
// Initialize font association scheme.
|
|
|
|
vInitializeFontAssocStatus();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************\
|
|
* GreEnableEUDC( BOOL bEnable )
|
|
*
|
|
* This routine enable/disable system wide/face name specific EUDCs
|
|
*
|
|
* History:
|
|
* 23-Jan-1995 Hideyuki Nagase
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL GreEnableEUDC
|
|
(
|
|
BOOL bEnableEUDC
|
|
)
|
|
{
|
|
BOOL bRet = TRUE, bWait = FALSE;
|
|
|
|
//
|
|
// make sure we are the only ones changing the EUDC data
|
|
//
|
|
|
|
AcquireGreResource( &gfmEUDC1 );
|
|
|
|
if( gbEUDCRequest )
|
|
{
|
|
//
|
|
// someone else is calling the EUDC API's right now so we will fail
|
|
// the call
|
|
//
|
|
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// signal that we are accessing the EUDC data
|
|
//
|
|
|
|
gbEUDCRequest = TRUE;
|
|
|
|
//
|
|
// if text related API's using EUDC characters are in progess we must
|
|
// wait
|
|
//
|
|
|
|
bWait = ( gcEUDCCount == 0 ) ? FALSE : TRUE;
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC1 );
|
|
|
|
if( bRet == FALSE )
|
|
{
|
|
//
|
|
// another EUDC API is currently in progress
|
|
//
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
if( bWait )
|
|
{
|
|
FLINKMESSAGE(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_UNLOAD,
|
|
"GreEnableEUDC() is waiting.\n");
|
|
|
|
// When the last text related API using EUDC characters finishes it will
|
|
// release us.
|
|
|
|
AcquireGreResource( &gfmEUDC2 );
|
|
}
|
|
|
|
if( bEnableEUDC )
|
|
{
|
|
//
|
|
// Enable EUDC link.
|
|
//
|
|
|
|
bRet = bAddAllFlEntry(TRUE,TRUE);
|
|
|
|
//
|
|
// if DefaultLink is ready to initalize and its is not initialized,
|
|
// do the initialization.
|
|
//
|
|
|
|
if( (bReadyToInitializeFontAssocDefault == TRUE ) &&
|
|
(bFinallyInitializeFontAssocDefault == FALSE) )
|
|
{
|
|
BOOL bRetLoadDefault;
|
|
|
|
//
|
|
// Load default linked font and fill up nessesary data fields.
|
|
//
|
|
|
|
bRetLoadDefault = bSetupDefaultFlEntry();
|
|
|
|
if( bRetLoadDefault ) {
|
|
|
|
//
|
|
// Yes, we finally initialized default link font successfully.
|
|
//
|
|
|
|
bFinallyInitializeFontAssocDefault = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable EUDC link.
|
|
//
|
|
|
|
bRet = bDeleteAllFlEntry(TRUE,TRUE);
|
|
}
|
|
|
|
//
|
|
// Let others use EUDC characters again
|
|
//
|
|
|
|
gbEUDCRequest = FALSE;
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* GreEudcLoadLinkW(LPWSTR,COUNT,LPWSTR,COUNT,INT,INT)
|
|
*
|
|
* Establishes a font file as the source of EUDC glyphs for the system. Any
|
|
* subsequent TextOut or GetTextMetrics related calls will reflect this
|
|
* change immediately.
|
|
*
|
|
* History:
|
|
* 13-01-95 Hideyuki Nagase
|
|
* Rewrote it.
|
|
* 02-10-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL GreEudcLoadLinkW
|
|
(
|
|
LPWSTR lpBaseFaceName, // guaranteed to be NULL terminated
|
|
COUNT cwcBaseFaceName,
|
|
LPWSTR lpEudcFontPath, // guaranteed to be NULL terminated
|
|
COUNT cwcEudcFontPath,
|
|
INT iPriority,
|
|
INT iFontLinkType
|
|
)
|
|
{
|
|
|
|
|
|
BOOL bRet = TRUE,bWait = FALSE;
|
|
|
|
ASSERTGDI(lpEudcFontPath != NULL,"GreEudcLoadLinkW():lpEudcFontPath == NULL\n");
|
|
ASSERTGDI(cwcEudcFontPath != 0,"GreEudcLoadLinkW():cwcEudcFontPath == 0\n");
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_LOAD,"GreEudcLoadLinkW\n");
|
|
|
|
AcquireGreResource( &gfmEUDC1 );
|
|
|
|
if( gbEUDCRequest )
|
|
{
|
|
//
|
|
// someone else is calling the EUDC API's right now so we will fail
|
|
// the call
|
|
//
|
|
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// signal that we are accessing the EUDC data
|
|
//
|
|
|
|
gbEUDCRequest = TRUE;
|
|
|
|
//
|
|
// if text related API's using EUDC characters are in progess we must
|
|
// wait
|
|
//
|
|
|
|
bWait = ( gcEUDCCount == 0 ) ? FALSE : TRUE;
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC1 );
|
|
|
|
if( bRet == FALSE )
|
|
{
|
|
//
|
|
// another EUDC API is currently in progress
|
|
//
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
if( bWait )
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
|
|
{
|
|
DbgPrint("GreEudcLoadLinkW is waiting.\n");
|
|
}
|
|
#endif
|
|
|
|
// When the last text related API using EUDC characters finishes it will
|
|
// release us.
|
|
|
|
AcquireGreResource( &gfmEUDC2 );
|
|
}
|
|
|
|
//
|
|
// Is this a request to load system wide eudc ?
|
|
//
|
|
|
|
if( lpBaseFaceName == NULL )
|
|
{
|
|
WCHAR awcSystemEudcPath[MAX_PATH+1];
|
|
|
|
//
|
|
// Get full path name of the requested font..
|
|
//
|
|
|
|
bAppendSysDirectory( awcSystemEudcPath , lpEudcFontPath );
|
|
|
|
PPFE appfeNew[2];
|
|
|
|
{
|
|
SEMOBJ so(gpsemPublicPFT);
|
|
|
|
//
|
|
// Get and validate PFT user object
|
|
//
|
|
|
|
PUBLIC_PFTOBJ pfto;
|
|
|
|
ASSERTGDI(pfto.bValid(),
|
|
"GreLoadLinkW():could not access the public font table\n");
|
|
|
|
//
|
|
// check this font file is loaded as eudc already.
|
|
//
|
|
|
|
if( !pfto.pPFFGet(awcSystemEudcPath,NULL,TRUE) )
|
|
{
|
|
EUDCLOAD EudcLoadData;
|
|
|
|
//
|
|
// fill up EUDCLOAD structure
|
|
//
|
|
|
|
EudcLoadData.pppfeData = (PPFE *) &appfeNew;
|
|
EudcLoadData.LinkedFace = NULL;
|
|
|
|
//
|
|
// load font..
|
|
//
|
|
|
|
ULONG cFonts;
|
|
PFF *placeHolder;
|
|
|
|
bRet = pfto.bLoadAFont( awcSystemEudcPath,
|
|
(PULONG) &cFonts,
|
|
PFF_STATE_EUDC_FONT,
|
|
&placeHolder,
|
|
&EudcLoadData);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// this font file is already loaded as EUDC..
|
|
//
|
|
|
|
#if DBG
|
|
DbgPrint("GreLoadLinkW():%ws is loaded as EUDC already\n",
|
|
awcSystemEudcPath);
|
|
#endif
|
|
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
if( bRet )
|
|
{
|
|
//
|
|
// now we can load new system wide eudc font..
|
|
// if we have system wide eudc font, deactivate and unload it..
|
|
//
|
|
|
|
if( IS_SYSTEM_EUDC_PRESENT() )
|
|
{
|
|
//
|
|
// disable the link of all facename and system wide eudc.
|
|
//
|
|
|
|
vUnlinkAllEudcRFONTsAndPFEs(TRUE,FALSE);
|
|
|
|
//
|
|
// Unload system wide eudc font
|
|
//
|
|
|
|
bUnloadEudcFont( gappfeSysEUDC );
|
|
}
|
|
|
|
//
|
|
// set new system wide eudc data to global variable.
|
|
//
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = appfeNew[PFE_NORMAL];
|
|
gappfeSysEUDC[PFE_VERTICAL] = appfeNew[PFE_VERTICAL];
|
|
|
|
wcscpy(gawcEUDCPath,awcSystemEudcPath);
|
|
|
|
//
|
|
// Update global eudc timestamp.
|
|
//
|
|
|
|
ulSystemEUDCTimeStamp++;
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
|
|
//
|
|
// Finally compute the QuickLookup structure for the system EUDC font
|
|
//
|
|
|
|
PFEOBJ pfeo( appfeNew[PFE_NORMAL] );
|
|
|
|
if( !pfeo.bValid() || !bComputeQuickLookup( &gqlEUDC, pfeo.pfdg(), TRUE ))
|
|
{
|
|
WARNING("GreLoadLinkW:Unable to compute QuickLookUp for system EUDC\n");
|
|
}
|
|
|
|
//
|
|
// Update registry data.
|
|
//
|
|
|
|
LPWSTR pwcSavePath;
|
|
|
|
#ifdef PORTABLE_WINDOWS_DIR
|
|
if( ( pwcSavePath = pwcFileIsUnderWindowsRoot( gawcEUDCPath ) ) != NULL )
|
|
#else
|
|
if( FALSE )
|
|
#endif
|
|
{
|
|
wcscpy( awcSystemEudcPath, L"%SystemRoot%" );
|
|
if( *pwcSavePath != L'\\' ) wcscat( awcSystemEudcPath, L"\\" );
|
|
wcscat( awcSystemEudcPath, pwcSavePath );
|
|
|
|
pwcSavePath = awcSystemEudcPath;
|
|
}
|
|
else
|
|
{
|
|
pwcSavePath = gawcEUDCPath;
|
|
}
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_LOAD,"GreLoadLinkW():Eudc Path %ws is Saved\n");
|
|
|
|
if( !bWriteUserSystemEUDCRegistry(pwcSavePath,wcslen(pwcSavePath)+1) )
|
|
{
|
|
WARNING("Unable to write new link to registry.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fail to load ...
|
|
//
|
|
|
|
#if DBG
|
|
DbgPrint("GreLoadLinkW():%ws is could not be loaded\n",awcSystemEudcPath);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PFLENTRY pFlEntry;
|
|
|
|
//
|
|
// if we got invalid fontlink type, just force change to FONTLINK_USER
|
|
//
|
|
|
|
if( (iFontLinkType != FONTLINK_SYSTEM) &&
|
|
(iFontLinkType != FONTLINK_USER ) )
|
|
{
|
|
iFontLinkType = FONTLINK_USER;
|
|
}
|
|
|
|
//
|
|
// this is request for facename link.
|
|
//
|
|
|
|
bRet = bAddFlEntry(lpBaseFaceName,lpEudcFontPath,iFontLinkType,iPriority,
|
|
&pFlEntry);
|
|
|
|
if( bRet )
|
|
{
|
|
//
|
|
// check new FLENTRY is allocated or not.
|
|
//
|
|
|
|
if( pFlEntry != NULL )
|
|
{
|
|
//
|
|
// if new FLENTRY is allocated, Update base font's PFE.
|
|
// Connect to loaded PFEs.
|
|
//
|
|
vLinkEudcPFEs( pFlEntry );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Let others use EUDC characters again
|
|
//
|
|
|
|
gbEUDCRequest = FALSE;
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* GreEudcUnloadLinkW()
|
|
*
|
|
* Unloads the current system wide EUDC link. Subsequent TextOut or
|
|
* GetTextMetrics related calls will reflect this immediately.
|
|
*
|
|
* History
|
|
* 26-01-95 Hideyuki Nagase
|
|
* Rewrote it.
|
|
* 4-01-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
BOOL GreEudcUnloadLinkW
|
|
(
|
|
LPWSTR lpBaseFaceName,
|
|
COUNT cwcBaseFaceName,
|
|
LPWSTR lpEudcFontPath,
|
|
COUNT cwcEudcFontPath
|
|
)
|
|
{
|
|
BOOL bRet = TRUE,bWait = FALSE;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD, "GreEudcUnloadLinkW()....\n");
|
|
|
|
|
|
AcquireGreResource( &gfmEUDC1 );
|
|
|
|
if( gbEUDCRequest )
|
|
{
|
|
//
|
|
// someone else is calling the EUDC API's right now so we will fail
|
|
// the call
|
|
//
|
|
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// signal that we are accessing the EUDC data
|
|
//
|
|
|
|
gbEUDCRequest = TRUE;
|
|
|
|
//
|
|
// if text related API's using EUDC characters are in progess we must
|
|
// wait
|
|
//
|
|
|
|
bWait = ( gcEUDCCount == 0 ) ? FALSE : TRUE;
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC1 );
|
|
|
|
if( bRet == FALSE )
|
|
{
|
|
//
|
|
// another EUDC API is currently in progress
|
|
//
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
if( bWait )
|
|
{
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
|
|
{
|
|
DbgPrint("GreEudcLoadLinkW is waiting.\n");
|
|
}
|
|
#endif
|
|
|
|
// When the last text related API using EUDC characters finishes it will
|
|
// release us.
|
|
|
|
AcquireGreResource( &gfmEUDC2 );
|
|
}
|
|
|
|
//
|
|
// Is this a request to load system wide eudc ?
|
|
//
|
|
|
|
if( lpBaseFaceName == NULL )
|
|
{
|
|
//
|
|
// if we have system wide eudc font, deactivate and unload it..
|
|
//
|
|
|
|
if( IS_SYSTEM_EUDC_PRESENT() )
|
|
{
|
|
//
|
|
// disable the link of all facename and system wide eudc.
|
|
//
|
|
|
|
vUnlinkAllEudcRFONTsAndPFEs(TRUE,FALSE);
|
|
|
|
//
|
|
// Unload system wide eudc font
|
|
//
|
|
|
|
bUnloadEudcFont( gappfeSysEUDC );
|
|
|
|
//
|
|
// set new system wide eudc data to global variable.
|
|
//
|
|
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
gappfeSysEUDC[PFE_NORMAL] = NULL;
|
|
gappfeSysEUDC[PFE_VERTICAL] = NULL;
|
|
|
|
wcscpy(gawcEUDCPath,L"\0");
|
|
|
|
//
|
|
// Update global eudc timestamp.
|
|
//
|
|
|
|
ulSystemEUDCTimeStamp++;
|
|
|
|
if( !bWriteUserSystemEUDCRegistry(L"\0",1) )
|
|
{
|
|
WARNING("Unable to write new link to registry.\n");
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WCHAR awcBaseFaceName[LF_FACESIZE+MAX_PATH+1];
|
|
WCHAR awcEudcFontPath[MAX_PATH+1];
|
|
|
|
ASSERTGDI(lpBaseFaceName != NULL,"GreEudcLoadLinkW():lpBaseFaceName == NULL\n");
|
|
ASSERTGDI(cwcBaseFaceName != 0,"GreEudcLoadLinkW():cwcBaseFaceName == 0\n");
|
|
|
|
ASSERTGDI(lpEudcFontPath != NULL,"GreEudcLoadLinkW():lpEudcFontPath == NULL\n");
|
|
ASSERTGDI(cwcEudcFontPath != 0,"GreEudcLoadLinkW():cwcEudcFontPath == 0\n");
|
|
|
|
//
|
|
// copy parameter to local buffer and make sure it is terminated bu NULL
|
|
//
|
|
|
|
RtlMoveMemory(awcBaseFaceName,lpBaseFaceName,(INT)cwcBaseFaceName*sizeof(WCHAR));
|
|
awcBaseFaceName[cwcBaseFaceName] = L'\0';
|
|
|
|
RtlMoveMemory(awcEudcFontPath,lpEudcFontPath,(INT)cwcEudcFontPath*sizeof(WCHAR));
|
|
awcEudcFontPath[cwcEudcFontPath] = L'\0';
|
|
|
|
//
|
|
// this is a request for facename link Eudc.
|
|
//
|
|
|
|
bRet = bDeleteFlEntry(awcBaseFaceName,awcEudcFontPath,FONTLINK_USER);
|
|
|
|
//
|
|
// if above call is failed, try FONTLINK_SYSTEM....
|
|
//
|
|
|
|
if( !bRet )
|
|
bRet = bDeleteFlEntry(awcBaseFaceName,awcEudcFontPath,FONTLINK_SYSTEM);
|
|
}
|
|
|
|
//
|
|
// Let others use EUDC characters again
|
|
//
|
|
|
|
gbEUDCRequest = FALSE;
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* UINT GreEudcQuerySystemLinkW(LPWSTR,COUNT)
|
|
*
|
|
* EudcQueryLink
|
|
*
|
|
* History
|
|
* 3-2-95 Hideyuki Nagase
|
|
* Rewrote it.
|
|
* 4-1-93 Gerrit van Wingerden
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
ULONG GreEudcQuerySystemLinkW
|
|
(
|
|
LPWSTR lpwstrEudcFileStr,
|
|
COUNT cwcEudcFileStr
|
|
)
|
|
{
|
|
UINT uiRet = 0;
|
|
|
|
ASSERTGDI(lpwstrEudcFileStr != NULL,
|
|
"GreEudcQuerySystemLinkW():lpwstrEudcFileStr == NULL\n");
|
|
ASSERTGDI(cwcEudcFileStr != 0,"GreEudcQuerySystemLinkW():cwcEudcFileStr == 0\n");
|
|
|
|
RtlZeroMemory(lpwstrEudcFileStr,cwcEudcFileStr*sizeof(WCHAR));
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FONTLINK_QUERY )
|
|
{
|
|
DbgPrint("Calling GreEudcQuerySystemLink\n");
|
|
}
|
|
#endif
|
|
|
|
if( IS_SYSTEM_EUDC_PRESENT() )
|
|
{
|
|
AcquireGreResource( &gfmEUDC3 );
|
|
|
|
wcsncpy(lpwstrEudcFileStr, gawcEUDCPath,
|
|
min((cwcEudcFileStr-1),(wcslen(gawcEUDCPath)+1)));
|
|
|
|
uiRet = wcslen(lpwstrEudcFileStr) + 1;
|
|
|
|
ReleaseGreResource( &gfmEUDC3 );
|
|
}
|
|
|
|
return(uiRet);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* UINT GreEudcEnumFaceNameLinkW(LPWSTR,COUNT,LPWSTR,COUNT)
|
|
*
|
|
* EudcEnumFaceNameLink
|
|
*
|
|
* History
|
|
* 3-2-95 Hideyuki Nagase
|
|
* Wrote it.
|
|
****************************************************************************/
|
|
|
|
ULONG GreEudcEnumFaceNameLinkW
|
|
(
|
|
LPWSTR lpwstrBaseFaceNameStr, // guaranteed to be NULL terminated
|
|
LPWSTR lpwstrBuffer,
|
|
COUNT cwclpwstrBuffer
|
|
)
|
|
{
|
|
BOOL bRetBufferIsPresent = FALSE;
|
|
|
|
LPWSTR lpBuffer = lpwstrBuffer;
|
|
COUNT cLeft = cwclpwstrBuffer;
|
|
COUNT cRet = 0;
|
|
BOOL bError = FALSE;
|
|
|
|
if( lpBuffer )
|
|
{
|
|
//
|
|
// at least we need 2 bytes or more.
|
|
//
|
|
|
|
if( cLeft < 2 ) return (0);
|
|
|
|
//
|
|
// Reserve space for NULL.
|
|
//
|
|
|
|
cLeft--;
|
|
|
|
//
|
|
// make sure double null terminated for first out in below loop.
|
|
//
|
|
|
|
lpBuffer[0] = L'\0'; lpBuffer[1] = L'\0';
|
|
|
|
bRetBufferIsPresent = TRUE;
|
|
}
|
|
|
|
AcquireGreResource( &gfmEUDC4 );
|
|
|
|
if( lpwstrBaseFaceNameStr == NULL )
|
|
{
|
|
//
|
|
// No specified base face name, let enumurate all base face name.
|
|
//
|
|
|
|
//
|
|
// Scan BaseFaceName list.
|
|
//
|
|
|
|
PLIST_ENTRY p;
|
|
|
|
p = BaseFontListHead.Flink;
|
|
|
|
if(IsListEmpty(&BaseFontListHead))
|
|
{
|
|
bError = TRUE;
|
|
}
|
|
else
|
|
{
|
|
while( p != &BaseFontListHead )
|
|
{
|
|
PFLENTRY pFlEntry;
|
|
|
|
pFlEntry = CONTAINING_RECORD(p,FLENTRY,baseFontList);
|
|
|
|
UINT cLen = wcslen(pFlEntry->awcFaceName) + 1;
|
|
|
|
if(bRetBufferIsPresent)
|
|
{
|
|
if(cLeft >= cLen)
|
|
{
|
|
RtlMoveMemory(lpBuffer,pFlEntry->awcFaceName,cLen*sizeof(WCHAR));
|
|
cLeft -= cLen;
|
|
lpBuffer += cLen;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
cRet += cLen;
|
|
|
|
p = p->Flink;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// Find specified BaseFaceName from list.
|
|
//
|
|
|
|
PFLENTRY pFlEntry;
|
|
|
|
if( (pFlEntry = FindBaseFontEntry(lpwstrBaseFaceNameStr)) != NULL )
|
|
{
|
|
//
|
|
// find it..
|
|
//
|
|
|
|
PLIST_ENTRY p = pFlEntry->linkedFontListHead.Flink;
|
|
|
|
while( p != &(pFlEntry->linkedFontListHead) )
|
|
{
|
|
PPFEDATA ppfeData;
|
|
|
|
ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
|
|
|
|
PFEOBJ pfeo(ppfeData->appfe[PFE_NORMAL]);
|
|
|
|
if(pfeo.bValid())
|
|
{
|
|
PFFOBJ pffo(pfeo.pPFF());
|
|
|
|
if(pffo.bValid())
|
|
{
|
|
if( ppfeData->FontLinkFlag & FLINK_FACENAME_SPECIFIED )
|
|
{
|
|
UINT cLen = (wcslen(pffo.pwszPathname()) +
|
|
wcslen(pfeo.pwszFamilyName())+2); //+2 for"," NULL
|
|
if(bRetBufferIsPresent)
|
|
{
|
|
if(cLeft >= cLen)
|
|
{
|
|
wcscpy(lpBuffer,pffo.pwszPathname());
|
|
wcscat(lpBuffer,L",");
|
|
wcscat(lpBuffer,pfeo.pwszFamilyName());
|
|
cLeft -= cLen;
|
|
lpBuffer += cLen;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
cRet += cLen;
|
|
}
|
|
else
|
|
{
|
|
UINT cLen = wcslen(pffo.pwszPathname()) + 1;
|
|
if(bRetBufferIsPresent)
|
|
{
|
|
if(cLeft >= cLen)
|
|
{
|
|
RtlMoveMemory(lpBuffer,pffo.pwszPathname(),
|
|
cLen*sizeof(WCHAR));
|
|
cLeft -= cLen;
|
|
lpBuffer += cLen;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
cRet += cLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
p = p->Flink;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC4 );
|
|
|
|
//
|
|
// if Error, return 0.
|
|
//
|
|
|
|
if(bError) return(0);
|
|
|
|
if(bRetBufferIsPresent )
|
|
{
|
|
//
|
|
// make sure double null terminated, the room for this is already reserved.
|
|
//
|
|
|
|
*lpBuffer = L'\0';
|
|
}
|
|
|
|
//
|
|
// return how many characters is required.
|
|
//
|
|
|
|
return( cRet + 1 );
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* ULONG NtGdiGetEudcTimeStampEx
|
|
*
|
|
* Shared kernel mode entry point for GetEudcTimeStamp and GetEudcTimeStampEx
|
|
*
|
|
* History
|
|
* 3-28-96 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
****************************************************************************/
|
|
|
|
extern "C" ULONG NtGdiGetEudcTimeStampEx
|
|
(
|
|
LPWSTR lpBaseFaceName,
|
|
ULONG cwcBaseFaceName,
|
|
BOOL bSystemTimeStamp
|
|
)
|
|
{
|
|
WCHAR awcBaseFaceName[LF_FACESIZE+1];
|
|
ULONG ulRet = 0;
|
|
|
|
if(bSystemTimeStamp)
|
|
{
|
|
return(ulSystemEUDCTimeStamp);
|
|
}
|
|
else
|
|
if((lpBaseFaceName == NULL) || (cwcBaseFaceName == 0))
|
|
{
|
|
return(ulFaceNameEUDCTimeStamp);
|
|
}
|
|
|
|
if(cwcBaseFaceName <= LF_FACESIZE)
|
|
{
|
|
|
|
__try
|
|
{
|
|
ProbeForRead(lpBaseFaceName,cwcBaseFaceName*sizeof(WCHAR),sizeof(WCHAR));
|
|
RtlCopyMemory(awcBaseFaceName,lpBaseFaceName,
|
|
cwcBaseFaceName * sizeof(WCHAR));
|
|
|
|
awcBaseFaceName[cwcBaseFaceName] = L'\0';
|
|
ulRet = 0;
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3100);
|
|
}
|
|
|
|
if(ulRet)
|
|
{
|
|
AcquireGreResource( &gfmEUDC4 );
|
|
|
|
PFLENTRY pFlEntry;
|
|
|
|
if( (pFlEntry = FindBaseFontEntry(awcBaseFaceName)) != NULL )
|
|
{
|
|
ulRet = pFlEntry->ulTimeStamp;
|
|
}
|
|
else
|
|
{
|
|
ulRet = 0;
|
|
}
|
|
|
|
ReleaseGreResource( &gfmEUDC4 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("NtGdiGetEudcTimeStampEx: Facename too big\n");
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return(ulRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* VOID vDrawGlyph( BYTE, UINT, GLYPHPOS )
|
|
*
|
|
* This routine draws a single glyph to a monochrome bitmap. It was stolen
|
|
* from textblt.cxx and modified to be faster since clipping doesn't come in
|
|
* to play in GetStringBitmapW.
|
|
*
|
|
* History:
|
|
* 5-18-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
static BYTE ajMask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
|
|
|
|
VOID vDrawGlyph(
|
|
BYTE *pjBits, // pointer to base of bitmap bits
|
|
UINT cjScan, // size of a scan line
|
|
GLYPHPOS *pgp // glyph bits and location.
|
|
)
|
|
{
|
|
GLYPHBITS *pgb = pgp->pgdf->pgb;
|
|
ULONG cx, cy, xDst, yDst;
|
|
PBYTE pjDst;
|
|
PBYTE pjSrc;
|
|
PBYTE pjSrcHolder = pgb->aj;
|
|
PBYTE pjDstHolder;
|
|
ULONG cjScanSrc = (pgb->sizlBitmap.cx + 7) >> 3;
|
|
|
|
xDst = pgp->ptl.x;
|
|
yDst = pgp->ptl.y;
|
|
|
|
cx = (ULONG) pgb->sizlBitmap.cx;
|
|
cy = (ULONG) pgb->sizlBitmap.cy;
|
|
|
|
pjDstHolder = pjBits;
|
|
pjDstHolder += (yDst * cjScan );
|
|
pjDstHolder += (xDst >> 3);
|
|
|
|
// Set the source bits into the mono dib.
|
|
// We can make use of the fact that either xSrcDib or xDstDib is 0.
|
|
|
|
if( !(xDst & 0x7) )
|
|
{
|
|
// Handle the simple case where xDib is byte-alligned
|
|
|
|
do
|
|
{
|
|
ULONG cBytes = cx >> 3;
|
|
|
|
pjSrc = pjSrcHolder;
|
|
pjDst = pjDstHolder;
|
|
|
|
pjSrcHolder += cjScanSrc;
|
|
pjDstHolder += cjScan;
|
|
|
|
while (cBytes--)
|
|
*pjDst++ |= *pjSrc++;
|
|
|
|
// Do the last partial byte.
|
|
|
|
if (cx & 0x7)
|
|
*pjDst |= *pjSrc & ajMask[cx & 0x7];
|
|
} while (--cy);
|
|
}
|
|
else // if (xDstDib)
|
|
{
|
|
// Handle the case where xDstDib is not byte-aligned.
|
|
|
|
int cShift = (int) xDst & 0x7;
|
|
do
|
|
{
|
|
ULONG cBytes = ((xDst + cx) >> 3) - (xDst >> 3);
|
|
|
|
pjSrc = pjSrcHolder;
|
|
pjDst = pjDstHolder;
|
|
|
|
pjSrcHolder += cjScanSrc;
|
|
pjDstHolder += cjScan;
|
|
|
|
WORD wSrc = (WORD) (*pjSrc++);
|
|
while (cBytes--)
|
|
{
|
|
*pjDst++ |= (BYTE) (wSrc >> cShift);
|
|
// don't read beyond src limit!
|
|
if (pjSrc == pjSrcHolder)
|
|
wSrc = (wSrc << 8);
|
|
else
|
|
wSrc = (wSrc << 8) | (WORD) (*pjSrc++);
|
|
}
|
|
|
|
// Do the last partial byte.
|
|
if ((xDst + cx) & 0x7)
|
|
*pjDst |= (BYTE) (wSrc >> cShift) & ajMask[(xDst+cx) & 0x7];
|
|
} while (--cy);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* VOID vStringBitmapTextOut( STROBJ, BYTE, UINT )
|
|
*
|
|
* This routine draws a STROBJ to a monochrome bitmap. It is essentially
|
|
* EngTextOut but much faster since it doesn't have to wory about opaqueing,
|
|
* clipping, simulated rects, etc.
|
|
*
|
|
* History:
|
|
* 9-19-95 Hideyuki Nagase [hideyukn]
|
|
* Rewrote it.
|
|
*
|
|
* 5-18-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
VOID vStringBitmapTextOut(
|
|
STROBJ *pstro, // Pointer to STROBJ.
|
|
BYTE *pjBits, // Pointer to buffer to store glyph image.
|
|
UINT cjScan // Size of buffer.
|
|
)
|
|
{
|
|
BOOL bMoreGlyphs;
|
|
GLYPHPOS *pgp = (GLYPHPOS*)NULL;
|
|
ULONG cGlyph;
|
|
|
|
LONG xAdjust = ( pstro->rclBkGround.left > 0 ) ? 0 : pstro->rclBkGround.left;
|
|
LONG yAdjust = pstro->rclBkGround.top;
|
|
|
|
((ESTROBJ*)pstro)->vEnumStart();
|
|
|
|
if( pstro->pgp == (GLYPHPOS *) NULL )
|
|
{
|
|
bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp);
|
|
}
|
|
else
|
|
{
|
|
cGlyph = pstro->cGlyphs;
|
|
pgp = pstro->pgp;
|
|
bMoreGlyphs = FALSE;
|
|
}
|
|
|
|
ASSERTGDI(bMoreGlyphs == FALSE,"vStringBitmapTextOut() bMoreGlyphs is TRUE.\n");
|
|
|
|
GLYPHBITS *pgb = pgp[0].pgdf->pgb;
|
|
|
|
pgp[0].ptl.x += pgb->ptlOrigin.x - xAdjust;
|
|
pgp[0].ptl.y += pgb->ptlOrigin.y - yAdjust;
|
|
|
|
//
|
|
// Blt the glyph into the bitmap
|
|
//
|
|
vDrawGlyph( pjBits, cjScan, &pgp[0] );
|
|
}
|
|
|
|
/******************************************************************************
|
|
* UINT GreGetStringBitmapW
|
|
*
|
|
* This routine does a kindof fast text out ( with restrictions ) to a monochrome
|
|
* bitmap.
|
|
*
|
|
* History:
|
|
* 9-19-95 Hideyuki Nagase [hideyukn]
|
|
* Rewrote it.
|
|
*
|
|
* 5-18-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*****************************************************************************/
|
|
|
|
UINT GreGetStringBitmapW(
|
|
HDC hdc,
|
|
LPWSTR pwsz,
|
|
UINT cwc, // should be 1....
|
|
LPSTRINGBITMAP lpSB,
|
|
UINT cj,
|
|
UINT *puiOffset // not used...
|
|
)
|
|
{
|
|
// Parameter check, early out...
|
|
|
|
if( cwc != 1 )
|
|
{
|
|
WARNING("GreGetStringBitmap only works when char count is 1.\n");
|
|
return(0);
|
|
}
|
|
|
|
if( puiOffset != 0 && *puiOffset != 0 )
|
|
{
|
|
WARNING("GreGetStringBitmap only works when offset is 0.\n");
|
|
return(0);
|
|
}
|
|
|
|
// Lock the DC and set the new attributes.
|
|
|
|
DCOBJ dco(hdc); // Lock the DC.
|
|
|
|
if (!dco.bValid()) // Check if it's good.
|
|
{
|
|
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
|
|
return(0);
|
|
}
|
|
|
|
// Get the transform from the DC.
|
|
|
|
EXFORMOBJ xo(dco,WORLD_TO_DEVICE);
|
|
|
|
|
|
// we only allow identity transforms for GetStringBitmap
|
|
|
|
if( !xo.bIdentity() )
|
|
{
|
|
WARNING("GreGetStringBitmap only works with identity WtoD xforms.\n");
|
|
return(0);
|
|
}
|
|
|
|
|
|
// Locate the font cache.
|
|
|
|
RFONTOBJ rfo(dco,FALSE);
|
|
|
|
if (!rfo.bValid())
|
|
{
|
|
WARNING("gdisrv!GreGetStringBitmap(): could not lock RFONTOBJ\n");
|
|
return (0);
|
|
}
|
|
|
|
// GetStringBitmap doesn't support vector fonts.
|
|
|
|
if( rfo.bPathFont() )
|
|
{
|
|
WARNING("gdisrv!GetStringBitmap() : vector fonts aren't supported.\n");
|
|
return(0);
|
|
}
|
|
|
|
|
|
// GetStringBitmap doesn't support sny rotations.
|
|
|
|
if((dco.pdc->lEscapement() | rfo.ulOrientation() ) != 0)
|
|
{
|
|
WARNING("gdisrv!GreGetStringBitmap(): Text isn't Horizontal.\n" );
|
|
return(0);
|
|
}
|
|
|
|
// Initialize ESTROBJ. Compute glyph layout positions.
|
|
|
|
ESTROBJ to; to.vInitSimple(pwsz,cwc,dco,rfo,0L,0L,NULL);
|
|
|
|
if (!to.bValid())
|
|
{
|
|
WARNING("gdisrv!GetStringBitmap() : could not lock ESTROBJ.\n");
|
|
return(0);
|
|
}
|
|
|
|
|
|
// Compute the target string rectangle.
|
|
|
|
UINT uiWidth = (UINT)( to.rclBkGround.right - to.rclBkGround.left );
|
|
UINT uiHeight = (UINT)( to.rclBkGround.bottom - to.rclBkGround.top );
|
|
|
|
|
|
// Offset the width by the C space of the last character and the A space of
|
|
// the first character to get the true extent
|
|
|
|
GLYPHDATA *pgd;
|
|
EGLYPHPOS *pg = (EGLYPHPOS*)to.pgpGet();
|
|
|
|
pgd = pg->pgd();
|
|
uiWidth += FXTOL(pgd->fxA);
|
|
pg = &pg[to.cGlyphsGet()-1];
|
|
pgd = pg->pgd();
|
|
uiWidth += FXTOL((pgd->fxD-pgd->fxAB));
|
|
|
|
|
|
// compute width of scanline in bytes ( must be byte alligned )
|
|
|
|
UINT cjScan = (uiWidth + 7) / 8;
|
|
UINT cjSize = offsetof(STRINGBITMAP,ajBits) + (cjScan * uiHeight);
|
|
PBYTE pjBits = lpSB->ajBits;
|
|
|
|
|
|
// If the user only want the size return now.
|
|
// And check the buffer is enough to store glyph image
|
|
|
|
if( cj < cjSize ) return( cjSize );
|
|
|
|
// Clear the target buffer.
|
|
|
|
RtlZeroMemory( pjBits, cjScan * uiHeight );
|
|
|
|
// Fill up its bitmap size...
|
|
|
|
lpSB->uiHeight = uiHeight;
|
|
lpSB->uiWidth = uiWidth;
|
|
|
|
|
|
// adjust the baseline of the Sys EUDC for win 3.1 compatability
|
|
|
|
POINTFIX fxBaseLineAdjust = {0,0};
|
|
LONG lFontType = EUDCTYPE_BASEFONT;
|
|
|
|
|
|
// Is the character linked one ?
|
|
|
|
if( to.bLinkedGlyphs() )
|
|
{
|
|
PRFONT pLinkedRfont = NULL;
|
|
|
|
// Setup its font type...
|
|
|
|
lFontType = *(LONG *)(to.plPartitionGet());
|
|
|
|
// Get corresponding RFONT with current linked font.
|
|
|
|
switch (lFontType)
|
|
{
|
|
case EUDCTYPE_SYSTEM_WIDE:
|
|
pLinkedRfont = rfo.prfntSysEUDC();
|
|
break;
|
|
case EUDCTYPE_SYSTEM_TT_FONT:
|
|
pLinkedRfont = rfo.prfntSystemTT();
|
|
break;
|
|
case EUDCTYPE_DEFAULT:
|
|
pLinkedRfont = rfo.prfntDefEUDC();
|
|
break;
|
|
case EUDCTYPE_BASEFONT:
|
|
// it's possible for this to be the case since the EUDC character
|
|
// could have been a singular character or a blank character in which
|
|
// case we will have already have set flags saying we have linked
|
|
// glyphs but in actuality will grab the default glyph from the base font
|
|
break;
|
|
default:
|
|
ASSERTGDI(lFontType >= EUDCTYPE_FACENAME,
|
|
"GDISRV:GreGetStringBitmapW() Error lFontType\n");
|
|
pLinkedRfont = rfo.prfntFaceName(lFontType - EUDCTYPE_FACENAME);
|
|
break;
|
|
}
|
|
|
|
// Is the RFONT is valid ?
|
|
|
|
if( pLinkedRfont != NULL )
|
|
{
|
|
RFONTTMPOBJ rfoLink(pLinkedRfont);
|
|
|
|
//
|
|
// Compute baseline diffs.
|
|
//
|
|
// *** Base font Height == Linked font Height ***
|
|
//
|
|
// Base font EUDC font Base font EUDC font
|
|
//
|
|
// -------
|
|
// ------- | | ------- -------
|
|
// | | | | -----> | | | |
|
|
// | 15 | | 20 | | 15 | | 15 |
|
|
// | | | | | | | |
|
|
// -------------------- BaseLine ---------------------
|
|
// | 5 | | 5 | | 5 |
|
|
// ------- ------- -------
|
|
//
|
|
// *** Base font Ascent >= Linked font Height ****
|
|
//
|
|
// Base font EUDC font Base font EUDC font
|
|
//
|
|
// ------- -------
|
|
// | | | | -------
|
|
// | | ------- -----> | | | |
|
|
// | 20 | | 10 | | 20 | | 15 |
|
|
// | | | | | | | |
|
|
// -------------------- BaseLine ---------------------
|
|
// | 5 | | 5 | | 5 |
|
|
// ------- ------- -------
|
|
//
|
|
// *** Others ****
|
|
//
|
|
// TBD.
|
|
//
|
|
if( rfo.fxMaxAscent() >= (rfoLink.fxMaxAscent() - rfoLink.fxMaxDescent()) )
|
|
{
|
|
fxBaseLineAdjust.y = (rfoLink.fxMaxDescent() >> 4);
|
|
}
|
|
else
|
|
{
|
|
fxBaseLineAdjust.y = (rfoLink.fxMaxAscent() - rfo.fxMaxAscent()) >> 4;
|
|
}
|
|
|
|
//
|
|
// if we need to adjust baseline, force emulation....
|
|
//
|
|
if( fxBaseLineAdjust.y ) to.pgpSet(NULL);
|
|
}
|
|
}
|
|
|
|
// Set current font type.
|
|
|
|
to.vFontSet(lFontType);
|
|
|
|
// Set base line adjustment delta.
|
|
|
|
to.fxBaseLineAdjustSet( fxBaseLineAdjust );
|
|
|
|
// Draw the glyph
|
|
|
|
vStringBitmapTextOut( (STROBJ*)&to, pjBits, cjScan );
|
|
|
|
return( cj );
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
* void AdjustBaseline(RFONTOBJ&, RFONTOBJ&, POINTFIX*, ERECTL*)
|
|
*
|
|
* This function adjusts the baseline of the EUDC font in a way that is
|
|
* Win 3.1 compatible according to the following rules:
|
|
*
|
|
*
|
|
* Base font Height == Linked font Height ***
|
|
*
|
|
* Base font EUDC font Base font EUDC font
|
|
*
|
|
* -------
|
|
* ------- | | ------- -------
|
|
* | | | | -----> | | | |
|
|
* | 15 | | 20 | | 15 | | 15 |
|
|
* | | | | | | | |
|
|
* -------------------- BaseLine ---------------------
|
|
* | 5 | | 5 | | 5 |
|
|
* ------- ------- -------
|
|
*
|
|
* Base font Ascent >= Linked font Height ****
|
|
*
|
|
* Base font EUDC font Base font EUDC font
|
|
*
|
|
* ------- -------
|
|
* | | | | -------
|
|
* | | ------- -----> | | | |
|
|
* | 20 | | 10 | | 20 | | 15 |
|
|
* | | | | | | | |
|
|
* -------------------- BaseLine ---------------------
|
|
* | 5 | | 5 | | 5 |
|
|
* ------- ------- -------
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
void AdjustBaseline(
|
|
XDCOBJ& dco,
|
|
RFONTOBJ &rfoBase,
|
|
RFONTOBJ &rfoLink,
|
|
POINTFIX *pfxBaseLineAdjust,
|
|
LONG *plInflatedMax,
|
|
ERECTL *prclInflate)
|
|
{
|
|
|
|
LONG lBaseLineAdjustDelta;
|
|
LONG lInflateTextRect;
|
|
ULONG ulOrientation = 0;
|
|
|
|
// adjust base line with base font.
|
|
|
|
if(rfoBase.fxMaxAscent() >= (rfoLink.fxMaxAscent() - rfoLink.fxMaxDescent()))
|
|
{
|
|
lBaseLineAdjustDelta = (rfoLink.fxMaxDescent() >> 4);
|
|
lInflateTextRect = 0;
|
|
}
|
|
else
|
|
{
|
|
lBaseLineAdjustDelta =
|
|
(LONG)((rfoLink.fxMaxAscent() - rfoBase.fxMaxAscent()) >> 4);
|
|
|
|
lInflateTextRect =
|
|
(LONG)(((rfoLink.fxMaxAscent() - rfoLink.fxMaxDescent()) -
|
|
(rfoBase.fxMaxAscent() - rfoBase.fxMaxDescent())) >> 4);
|
|
}
|
|
|
|
if (dco.pdc->bYisUp())
|
|
ulOrientation = 3600-rfoLink.ulOrientation();
|
|
else
|
|
ulOrientation = rfoLink.ulOrientation();
|
|
|
|
// if Background rect is already inflated, no more inflatation.
|
|
|
|
if( lInflateTextRect <= *plInflatedMax )
|
|
lInflateTextRect = 0;
|
|
else
|
|
*plInflatedMax = lInflateTextRect;
|
|
|
|
if( lBaseLineAdjustDelta )
|
|
{
|
|
switch( ulOrientation )
|
|
{
|
|
case 0L :
|
|
pfxBaseLineAdjust->x = 0;
|
|
pfxBaseLineAdjust->y = lBaseLineAdjustDelta;
|
|
prclInflate->bottom = lInflateTextRect;
|
|
break;
|
|
|
|
case 900L :
|
|
pfxBaseLineAdjust->x = -(lBaseLineAdjustDelta);
|
|
pfxBaseLineAdjust->y = 0;
|
|
prclInflate->left = -(lInflateTextRect);
|
|
break;
|
|
|
|
case 1800L :
|
|
pfxBaseLineAdjust->x = 0;
|
|
pfxBaseLineAdjust->y = -(lBaseLineAdjustDelta);
|
|
prclInflate->top = -(lInflateTextRect);
|
|
break;
|
|
|
|
case 2700L :
|
|
pfxBaseLineAdjust->x = lBaseLineAdjustDelta;
|
|
pfxBaseLineAdjust->y = 0;
|
|
prclInflate->right = lInflateTextRect;
|
|
break;
|
|
|
|
default :
|
|
{
|
|
LONG x=0,y=0;
|
|
EFLOATEXT efAngle = (LONG)(3600-ulOrientation);
|
|
EFLOATEXT efLine = lBaseLineAdjustDelta;
|
|
|
|
efAngle /= (LONG) 10;
|
|
|
|
EFLOAT efCosine = efCos(efAngle);
|
|
EFLOAT efSine = efSin(efAngle);
|
|
EFLOAT efAdjustX;
|
|
EFLOAT efAdjustY;
|
|
|
|
efAdjustX.eqMul(efSine,efLine);
|
|
efAdjustY.eqMul(efCosine,efLine);
|
|
|
|
if(!efAdjustX.bEfToLTruncate(x))
|
|
WARNING("GDISRV:bEfToL(x) fail\n");
|
|
|
|
if(!efAdjustY.bEfToLTruncate(y))
|
|
WARNING("GDISRV:bEfToL(y) fail\n");
|
|
|
|
pfxBaseLineAdjust->x = x;
|
|
pfxBaseLineAdjust->y = y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pfxBaseLineAdjust->x = 0;
|
|
pfxBaseLineAdjust->y = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* BOOL bProxyDrvTextOut()
|
|
*
|
|
* This routine takes the place of a DrvTextOut in the case when there are EUDC
|
|
* characters in the ESTROBJ. It partitions the call into mutliple DrvTextOut
|
|
* calls, one for each font int the string.
|
|
*
|
|
* Partitioning information is stored in an array of LONGS in the RFONTOBJ.
|
|
* The i'th entry in the array tells what font the i'th glyph in the ESTROBJ
|
|
* belongs to.
|
|
*
|
|
* History:
|
|
* 7-14-93 Gerrit van Wingerden [gerritv]
|
|
* Rewrote it to handle multiple face name links and just be better.
|
|
* 2-10-93 Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// This routine is used to partition calls to the driver if there are EUDC
|
|
// characters in the string.
|
|
|
|
BOOL bProxyDrvTextOut
|
|
(
|
|
XDCOBJ& dco,
|
|
SURFACE *pSurf,
|
|
ESTROBJ& to,
|
|
ECLIPOBJ& co,
|
|
RECTL *prclExtra,
|
|
RECTL *prclBackground,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlBrushOrg,
|
|
RFONTOBJ& rfo,
|
|
PDEVOBJ *pdo,
|
|
FLONG flCaps,
|
|
RECTL *prclExclude
|
|
)
|
|
{
|
|
LONG *plPartition, *plPartitionEnd;
|
|
COUNT cTotalGlyphs = 0;
|
|
LONG lInflatedMax = 0;
|
|
WCHAR *pwcPartition, *pwcTmp, *pwcSave, *pwcSource;
|
|
ULONG cNumGlyphs = to.cGlyphsGet();
|
|
POINTFIX fxBaseLineAdjust = {0,0};
|
|
|
|
BOOL bRet = TRUE;
|
|
|
|
//!!! perhaps here we should be smarter and have special cases when the glyphs
|
|
//!!! are all EUDC glyphs from the same font and we can just call off to
|
|
//!!! the driver with the only change being to the FONTOBJ passed in.[gerritv]
|
|
|
|
pwcPartition = to.pwcPartitionGet();
|
|
|
|
// now partition the EUDC glyphs by font
|
|
|
|
pwcSave = to.pwszGet();
|
|
|
|
// set to NULL to force enumeration
|
|
|
|
to.pgpSet( NULL );
|
|
|
|
// Turn off acclerators since we'll seriously munge the properties of the string object.
|
|
|
|
to.flAccelSet( 0 );
|
|
|
|
for(LONG lFont = EUDCTYPE_BASEFONT ;
|
|
lFont < (EUDCTYPE_FACENAME + (LONG) rfo.uiNumFaceNameLinks()) ;
|
|
lFont++ )
|
|
{
|
|
RFONTTMPOBJ rfoLink;
|
|
RFONTOBJ *prfoLink;
|
|
UINT ii;
|
|
COUNT cLinkedGlyphs;
|
|
|
|
ERECTL rclInflate(0,0,0,0);
|
|
|
|
switch( lFont )
|
|
{
|
|
case EUDCTYPE_BASEFONT:
|
|
|
|
// If there aren't any glyphs in the base font just draw the
|
|
// opaque rectangle. We must draw the opaque rectangle here
|
|
// because the linked glyphs don't neccesarily fit into the
|
|
// the opaque rectangle. Passing such a rectangle to a driver
|
|
// can cause unexpected results.
|
|
|
|
cLinkedGlyphs = to.cSysGlyphsGet() + to.cDefGlyphsGet() +
|
|
to.cTTSysGlyphsGet();
|
|
|
|
for( ii = 0; ii < rfo.uiNumFaceNameLinks(); ii++ )
|
|
{
|
|
cLinkedGlyphs += to.cFaceNameGlyphsGet( ii );
|
|
}
|
|
|
|
if( cLinkedGlyphs == cNumGlyphs )
|
|
{
|
|
|
|
// Draw the opaque rectangle here if there is one
|
|
|
|
if( prclExclude != NULL && prclBackground != NULL)
|
|
{
|
|
co.erclExclude().left =
|
|
max(prclExclude->left,prclBackground->left);
|
|
|
|
co.erclExclude().right =
|
|
min(prclExclude->right,prclBackground->right);
|
|
|
|
co.erclExclude().top =
|
|
max(prclExclude->top,prclBackground->top);
|
|
co.erclExclude().bottom =
|
|
min(prclExclude->bottom,prclBackground->bottom);
|
|
}
|
|
|
|
// if not clipped, Just paint the rectangle.
|
|
|
|
if ((co.erclExclude().left < co.erclExclude().right) &&
|
|
(co.erclExclude().top < co.erclExclude().bottom) &&
|
|
prclBackground != NULL )
|
|
{
|
|
INC_SURF_UNIQ(pSurf);
|
|
|
|
(*(pSurf->pfnBitBlt()))
|
|
(
|
|
pSurf->pSurfobj(), // Destination surface.
|
|
(SURFOBJ *) NULL, // Source surface.
|
|
(SURFOBJ *) NULL, // Mask surface.
|
|
&co, // Clip object.
|
|
(XLATEOBJ *) NULL, // Palette translation object.
|
|
prclBackground, // Destination rectangle.
|
|
(POINTL *) NULL, // Source origin.
|
|
(POINTL *) NULL, // Mask origin.
|
|
(BRUSHOBJ *) pboOpaque, // Realized opaque brush.
|
|
pptlBrushOrg, // brush origin
|
|
0x0000f0f0 // PATCOPY
|
|
);
|
|
}
|
|
|
|
co.erclExclude() = *prclExclude;
|
|
|
|
// set prclBackground to NULL since we have just drawn it
|
|
|
|
prclBackground = NULL;
|
|
|
|
continue;
|
|
}
|
|
|
|
prfoLink = &rfo;
|
|
|
|
fxBaseLineAdjust.x = 0;
|
|
fxBaseLineAdjust.y = 0;
|
|
|
|
FLINKMESSAGE(DEBUG_FONTLINK_TEXTOUT,"Doing base font.\n");
|
|
break;
|
|
|
|
case EUDCTYPE_SYSTEM_TT_FONT:
|
|
|
|
if(to.cTTSysGlyphsGet() == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rfoLink.vInit(rfo.prfntSystemTT());
|
|
prfoLink = (RFONTOBJ *) &rfoLink;
|
|
|
|
AdjustBaseline(dco,rfo,rfoLink,&fxBaseLineAdjust,&lInflatedMax,&rclInflate);
|
|
to.vInflateTextRect(rclInflate);
|
|
break;
|
|
|
|
case EUDCTYPE_SYSTEM_WIDE:
|
|
|
|
if( to.cSysGlyphsGet() == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rfoLink.vInit( rfo.prfntSysEUDC() );
|
|
prfoLink = (RFONTOBJ *) &rfoLink;
|
|
|
|
AdjustBaseline(dco,rfo,rfoLink,&fxBaseLineAdjust,&lInflatedMax,&rclInflate);
|
|
to.vInflateTextRect(rclInflate);
|
|
break;
|
|
|
|
case EUDCTYPE_DEFAULT:
|
|
|
|
if( to.cDefGlyphsGet() == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rfoLink.vInit( rfo.prfntDefEUDC() );
|
|
prfoLink = (RFONTOBJ *) &rfoLink;
|
|
|
|
AdjustBaseline(dco,rfo,rfoLink,&fxBaseLineAdjust,&lInflatedMax,&rclInflate);
|
|
to.vInflateTextRect(rclInflate);
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
if( to.cFaceNameGlyphsGet( lFont-EUDCTYPE_FACENAME ) == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rfoLink.vInit(rfo.prfntFaceName(lFont - EUDCTYPE_FACENAME));
|
|
prfoLink = (RFONTOBJ *) &rfoLink;
|
|
AdjustBaseline(dco,rfo,rfoLink,&fxBaseLineAdjust,&lInflatedMax,&rclInflate);
|
|
to.vInflateTextRect(rclInflate);
|
|
break;
|
|
}
|
|
|
|
// Loop through all the glyphs in the TextObj using plPartition to
|
|
// and construct a wchar array to match this textobj.
|
|
|
|
for( plPartition = to.plPartitionGet(),plPartitionEnd = &plPartition[cNumGlyphs],
|
|
pwcSource = pwcSave, pwcTmp = pwcPartition;
|
|
plPartition < plPartitionEnd;
|
|
plPartition += 1, pwcSource += 1 )
|
|
{
|
|
if( *plPartition == lFont )
|
|
{
|
|
*pwcTmp++ = *pwcSource;
|
|
}
|
|
}
|
|
|
|
// Keep track of the total glyphs draw so far so we know when we are doing
|
|
// the last DrvTextOut. On the last DrvTextOut draw prclExtra.
|
|
|
|
cTotalGlyphs += pwcTmp - pwcPartition;
|
|
|
|
to.cGlyphsSet( (LONG) ( pwcTmp - pwcPartition ));
|
|
to.pwszSet( pwcPartition );
|
|
|
|
// set the font type and reset cGlyphPosCopied to 0
|
|
|
|
to.vFontSet( lFont );
|
|
|
|
// adjust the baseline of the Sys EUDC for win 3.1 compatability
|
|
|
|
to.fxBaseLineAdjustSet( fxBaseLineAdjust );
|
|
|
|
to.prfntSet( prfoLink );
|
|
|
|
// some drivers dink with the BkGround rectangle (like the Cirrus driver )
|
|
// so save a copy here and then restore it later to handle this situation
|
|
|
|
to.vSaveBkGroundRect();
|
|
|
|
// check this is a path draw or not.
|
|
|
|
if( prfoLink->bPathFont() )
|
|
{
|
|
PATHMEMOBJ po;
|
|
|
|
if( !po.bValid() )
|
|
{
|
|
SAVE_ERROR_CODE( ERROR_NOT_ENOUGH_MEMORY );
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if( !(prfoLink->bReturnsOutlines()) )
|
|
{
|
|
//
|
|
// VECTOR FONT CASE
|
|
//
|
|
if( !to.bTextToPath(po) ||
|
|
!po.bSimpleStroke1( flCaps,
|
|
pdo,
|
|
pSurf,
|
|
&co,
|
|
pboFore,
|
|
pptlBrushOrg,
|
|
( R2_COPYPEN | ( R2_COPYPEN << 8 ))
|
|
))
|
|
{
|
|
#if DBG
|
|
DbgPrint("ProxyDrvTextout:bTextToPath for vector font \
|
|
failed(%d).\n", lFont);
|
|
#endif
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// OUTLINE FONT CASE
|
|
//
|
|
if( !to.bTextToPath(po) ||
|
|
(( po.cCurves > 1 ) &&
|
|
!po.bSimpleFill( flCaps,
|
|
pdo,
|
|
pSurf,
|
|
&co,
|
|
pboFore,
|
|
pptlBrushOrg,
|
|
( R2_COPYPEN | ( R2_COPYPEN << 8 )),
|
|
WINDING
|
|
)
|
|
)
|
|
)
|
|
{
|
|
#if DBG
|
|
DbgPrint("ProxyDrvTextout:bTextToPath for outline font \
|
|
failed(%d).\n",lFont);
|
|
#endif
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !((*(pSurf->pfnTextOut()))
|
|
( pSurf->pSurfobj(),
|
|
(STROBJ *) &to,
|
|
prfoLink->pfo(),
|
|
&co,
|
|
(cTotalGlyphs == cNumGlyphs ) ? prclExtra : NULL,
|
|
prclBackground,
|
|
pboFore,
|
|
pboOpaque,
|
|
pptlBrushOrg,
|
|
(R2_COPYPEN | (R2_COPYPEN << 8))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
#if DBG
|
|
DbgPrint("ProxyDrvTextout:DrvTextOut for bitmap font failed(%d).\n",lFont);
|
|
#endif
|
|
bRet = FALSE;
|
|
}
|
|
|
|
// set this to NULL since we've already drawn it.
|
|
|
|
prclBackground = NULL;
|
|
}
|
|
|
|
to.vRestoreBkGroundRect();
|
|
}
|
|
|
|
// TextOut expects gpos to be correct so reset it
|
|
|
|
to.pwszSet( pwcSave );
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine*****************************\
|
|
* NtGdiEnableEudc
|
|
*
|
|
* Enable or disable system wide and per-user Eudc information.
|
|
*
|
|
* History:
|
|
* 27-Mar-1996 by Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
\*************************************************************************/
|
|
|
|
extern "C"
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiEnableEudc(
|
|
BOOL bEnable
|
|
)
|
|
{
|
|
return(GreEnableEUDC(bEnable));
|
|
}
|
|
|
|
/******************************Public*Routine*****************************\
|
|
* NtGdiQuerySystemLink
|
|
*
|
|
* Queries system link information
|
|
*
|
|
* History:
|
|
* 27-Mar-1996 by Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
\*************************************************************************/
|
|
|
|
extern "C"
|
|
UINT
|
|
APIENTRY
|
|
NtGdiEudcQuerySystemLink
|
|
(
|
|
LPWSTR pszOut,
|
|
UINT cChar
|
|
)
|
|
{
|
|
UINT cRet = 0;
|
|
BOOL bStatus = TRUE;
|
|
PWCHAR pwsz_km = (PWCHAR)NULL;
|
|
|
|
if ((cChar > 0) && (pszOut))
|
|
{
|
|
pwsz_km = (WCHAR*) PALLOCNOZ(cChar * sizeof(WCHAR), 'pacG');
|
|
if (pwsz_km == (PWCHAR)NULL)
|
|
{
|
|
bStatus = FALSE;
|
|
}
|
|
}
|
|
|
|
if (bStatus)
|
|
{
|
|
cRet = GreEudcQuerySystemLinkW(pwsz_km,cChar);
|
|
|
|
if ((cRet > 0) && (pszOut))
|
|
{
|
|
|
|
ASSERTGDI(cRet <= cChar, "GreEudcQuerySystemLinkW, cRet too big\n");
|
|
__try
|
|
{
|
|
ProbeForWrite(pszOut,cRet * sizeof(WCHAR), sizeof(BYTE));
|
|
RtlCopyMemory(pszOut,pwsz_km,cRet * sizeof(WCHAR));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3095);
|
|
// SetLastError(GetExceptionCode());
|
|
cRet = 0;
|
|
}
|
|
}
|
|
|
|
if (pwsz_km != (PWCHAR)NULL)
|
|
{
|
|
VFREEMEM(pwsz_km);
|
|
}
|
|
}
|
|
return(cRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine*****************************\
|
|
* NtGdiEudcLoadUnloadLink
|
|
*
|
|
* Queries system link information
|
|
o*
|
|
* History:
|
|
* 27-Mar-1996 by Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
\*************************************************************************/
|
|
|
|
extern "C"
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiEudcLoadUnloadLink(
|
|
LPCWSTR pBaseFaceName,
|
|
UINT cwcBaseFaceName,
|
|
LPCWSTR pEudcFontPath,
|
|
UINT cwcEudcFontPath,
|
|
INT iPriority,
|
|
INT iFontLinkType,
|
|
BOOL bLoadLink)
|
|
{
|
|
WCHAR FaceNameBuffer[LF_FACESIZE+1];
|
|
WCHAR *pPathBuffer;
|
|
BOOL bRet = FALSE;
|
|
|
|
if(cwcBaseFaceName > LF_FACESIZE || pEudcFontPath == NULL ||
|
|
cwcEudcFontPath == 0)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return(FALSE);
|
|
}
|
|
|
|
pPathBuffer = (WCHAR*) PALLOCNOZ((cwcEudcFontPath+1) * sizeof(WCHAR), 'pacG');
|
|
|
|
if(pPathBuffer)
|
|
{
|
|
__try
|
|
{
|
|
if(pBaseFaceName)
|
|
{
|
|
ProbeForRead(pBaseFaceName,cwcBaseFaceName,sizeof(WCHAR));
|
|
RtlCopyMemory(FaceNameBuffer,pBaseFaceName,
|
|
cwcBaseFaceName*sizeof(WCHAR));
|
|
|
|
FaceNameBuffer[cwcBaseFaceName] = (WCHAR) 0;
|
|
pBaseFaceName = FaceNameBuffer;
|
|
}
|
|
|
|
ProbeForRead(pEudcFontPath,cwcEudcFontPath,sizeof(WCHAR));
|
|
RtlCopyMemory(pPathBuffer,pEudcFontPath,
|
|
cwcEudcFontPath*sizeof(WCHAR));
|
|
|
|
pPathBuffer[cwcEudcFontPath] = (WCHAR) 0;
|
|
bRet = TRUE;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3096);
|
|
}
|
|
|
|
if(bRet)
|
|
{
|
|
if(bLoadLink)
|
|
{
|
|
bRet = GreEudcLoadLinkW((LPWSTR) pBaseFaceName,
|
|
cwcBaseFaceName,
|
|
pPathBuffer,
|
|
cwcEudcFontPath,
|
|
iPriority,
|
|
iFontLinkType);
|
|
}
|
|
else
|
|
{
|
|
bRet = GreEudcUnloadLinkW((LPWSTR)pBaseFaceName,
|
|
cwcBaseFaceName,
|
|
pPathBuffer,
|
|
cwcEudcFontPath);
|
|
}
|
|
}
|
|
VFREEMEM(pPathBuffer);
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
extern "C"
|
|
UINT
|
|
APIENTRY
|
|
NtGdiEudcEnumFaceNameLinkW(
|
|
LPWSTR pBaseFaceNameStr,
|
|
UINT cwcBaseFaceNameStr,
|
|
WCHAR *pBuffer,
|
|
UINT cBuffer
|
|
)
|
|
{
|
|
UINT cKernelModeBuffer = cwcBaseFaceNameStr + 1 + cBuffer; // +1 to NULL terminate
|
|
UINT uiReturn = 0;
|
|
BOOL bStatus = TRUE;
|
|
WCHAR *pOutputBuffer = NULL;
|
|
WCHAR *pKernelBuffer = NULL;
|
|
|
|
if(cKernelModeBuffer)
|
|
{
|
|
pKernelBuffer = (WCHAR*) PALLOCNOZ(cKernelModeBuffer * sizeof(WCHAR),'pmtG');
|
|
|
|
if(pKernelBuffer)
|
|
{
|
|
if(pBaseFaceNameStr)
|
|
{
|
|
__try
|
|
{
|
|
ProbeForRead(pBaseFaceNameStr,cwcBaseFaceNameStr,sizeof(WCHAR));
|
|
RtlCopyMemory(pKernelBuffer,pBaseFaceNameStr,cwcBaseFaceNameStr);
|
|
pBaseFaceNameStr = pKernelBuffer;
|
|
pKernelBuffer[cwcBaseFaceNameStr] = (WCHAR) 0;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3097);
|
|
bStatus = FALSE;
|
|
}
|
|
|
|
if(cBuffer)
|
|
{
|
|
pOutputBuffer = &pKernelBuffer[cwcBaseFaceNameStr+1];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bStatus = FALSE;
|
|
}
|
|
}
|
|
|
|
if(bStatus)
|
|
{
|
|
uiReturn = GreEudcEnumFaceNameLinkW(pBaseFaceNameStr,
|
|
pOutputBuffer,
|
|
cBuffer);
|
|
|
|
if(uiReturn && pBuffer)
|
|
{
|
|
// copy out data if there is an output buffer
|
|
|
|
ASSERTGDI(uiReturn <= cBuffer,
|
|
"NtGdiEudcEnumFaceNameLinkW uiReturn too small\n");
|
|
|
|
__try
|
|
{
|
|
ProbeForWrite(pBuffer, cBuffer, sizeof(WCHAR));
|
|
RtlCopyMemory(pBuffer, pOutputBuffer, cBuffer*sizeof(WCHAR));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3098);
|
|
bStatus = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pKernelBuffer)
|
|
{
|
|
VFREEMEM(pKernelBuffer);
|
|
}
|
|
|
|
return(bStatus) ? uiReturn : 0;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
UINT
|
|
APIENTRY
|
|
NtGdiGetStringBitmapW(
|
|
HDC hdc,
|
|
LPWSTR pwsz,
|
|
UINT cwc,
|
|
BYTE *lpSB,
|
|
UINT cj
|
|
)
|
|
{
|
|
WCHAR Character;
|
|
LPSTRINGBITMAP OutputBuffer = NULL;
|
|
UINT Status = 1;
|
|
|
|
if(cwc != 1)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if(cj)
|
|
{
|
|
if(!(OutputBuffer = (LPSTRINGBITMAP) PALLOCNOZ(cj,'pmtG')))
|
|
{
|
|
Status = 0;
|
|
}
|
|
}
|
|
|
|
if(Status)
|
|
{
|
|
__try
|
|
{
|
|
ProbeForRead(pwsz,sizeof(WCHAR), sizeof(WCHAR));
|
|
Character = pwsz[0];
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3099);
|
|
Status = 0;
|
|
}
|
|
|
|
if(Status)
|
|
{
|
|
Status = GreGetStringBitmapW(hdc,
|
|
&Character,
|
|
1,
|
|
(LPSTRINGBITMAP) OutputBuffer,
|
|
cj,
|
|
0);
|
|
}
|
|
|
|
if(Status && OutputBuffer)
|
|
{
|
|
__try
|
|
{
|
|
ProbeForWrite(lpSB,cj,sizeof(BYTE));
|
|
RtlCopyMemory(lpSB,OutputBuffer,cj);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(3100);
|
|
Status = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(OutputBuffer)
|
|
{
|
|
VFREEMEM(OutputBuffer);
|
|
}
|
|
|
|
|
|
return Status;
|
|
}
|
|
|
|
#endif
|