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.
657 lines
19 KiB
657 lines
19 KiB
#include "pch.hxx"
|
|
#include "shlwapi.h"
|
|
#include "fontcash.h"
|
|
#include "strconst.h"
|
|
#include "inetreg.h"
|
|
#include "oleutil.h"
|
|
#include "msoedbg.h"
|
|
#include <wingdi.h>
|
|
#include "demand.h"
|
|
|
|
|
|
HRESULT CreateFontCacheEntry(FONTCACHEENTRY **ppNewEntry)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FONTCACHEENTRY* pNew;
|
|
|
|
if (!MemAlloc((LPVOID *)&pNew, sizeof(FONTCACHEENTRY)))
|
|
hr = E_OUTOFMEMORY;
|
|
else
|
|
{
|
|
pNew->uiCodePage = 0;
|
|
pNew->szFaceName[0] = TCHAR(0);
|
|
for (int i = 0; i < FNT_SYS_LAST; i++)
|
|
pNew->rgFonts[i] = 0;
|
|
}
|
|
*ppNewEntry = pNew;
|
|
return S_OK;
|
|
}
|
|
|
|
void FreeFontsInEntry(FONTCACHEENTRY *pEntry)
|
|
{
|
|
for (int i = 0; i < FNT_SYS_LAST; i++)
|
|
if (pEntry->rgFonts[i])
|
|
{
|
|
DeleteObject(pEntry->rgFonts[i]);
|
|
pEntry->rgFonts[i] = 0;
|
|
}
|
|
}
|
|
|
|
HRESULT FreeFontCacheEntry(FONTCACHEENTRY *pEntry)
|
|
{
|
|
Assert(pEntry);
|
|
|
|
FreeFontsInEntry(pEntry);
|
|
MemFree(pEntry);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// =================================================================================
|
|
// Font Cache Implementation
|
|
// =================================================================================
|
|
|
|
CFontCache::CFontCache(IUnknown *pUnkOuter) : CPrivateUnknown(pUnkOuter),
|
|
m_pAdviseRegistry(NULL), m_pFontEntries(NULL),
|
|
m_pSysCacheEntry(NULL), m_bISO_2022_JP_ESC_SIO_Control(false),
|
|
m_uiSystemCodePage(0)
|
|
{
|
|
InitializeCriticalSection(&m_rFontCritSect);
|
|
InitializeCriticalSection(&m_rAdviseCritSect);
|
|
}
|
|
|
|
//***************************************************
|
|
CFontCache::~CFontCache()
|
|
{
|
|
if (m_pAdviseRegistry)
|
|
m_pAdviseRegistry->Release();
|
|
|
|
if (m_pFontEntries)
|
|
m_pFontEntries->Release();
|
|
|
|
if (m_pSysCacheEntry)
|
|
FreeFontCacheEntry(m_pSysCacheEntry);
|
|
|
|
DeleteCriticalSection(&m_rFontCritSect);
|
|
DeleteCriticalSection(&m_rAdviseCritSect);
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::InitSysFontEntry()
|
|
{
|
|
// Locals
|
|
NONCLIENTMETRICS ncm;
|
|
CHARSETINFO rCharsetInfo={0};
|
|
UINT nACP;
|
|
HRESULT hr = S_OK;
|
|
LOGFONT rSysLogFonts;
|
|
|
|
Assert(m_pSysCacheEntry);
|
|
|
|
// Get system ansi code page
|
|
nACP = GetACP();
|
|
m_pSysCacheEntry->uiCodePage = nACP;
|
|
m_uiSystemCodePage = nACP;
|
|
|
|
// Get the charset for the current ANSI code page
|
|
TranslateCharsetInfo((DWORD *)IntToPtr(MAKELONG(nACP, 0)), &rCharsetInfo, TCI_SRCCODEPAGE);
|
|
|
|
// Get icon font metrics
|
|
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &rSysLogFonts, 0))
|
|
{
|
|
StrCpyN(m_pSysCacheEntry->szFaceName, rSysLogFonts.lfFaceName, ARRAYSIZE(m_pSysCacheEntry->szFaceName));
|
|
|
|
// Reset lfCharset depending on the current ansi code page
|
|
rSysLogFonts.lfCharSet = (BYTE) rCharsetInfo.ciCharset;
|
|
|
|
//$HACK - This code is necessary to work around a bug in Windows.
|
|
// If the icon font has never been changed from the default,
|
|
// SystemParametersInfo returns the wrong height. We need
|
|
// to select the font into a DC and get the textmetrics to
|
|
// determine the correct height. (EricAn)
|
|
HFONT hFont;
|
|
if (hFont = CreateFontIndirect(&rSysLogFonts))
|
|
{
|
|
HDC hdc;
|
|
if (hdc = GetDC(NULL))
|
|
{
|
|
TEXTMETRIC tm;
|
|
HFONT hFontOld = SelectFont(hdc, hFont);
|
|
GetTextMetrics(hdc, &tm);
|
|
rSysLogFonts.lfHeight = -(tm.tmHeight - tm.tmInternalLeading);
|
|
SelectFont(hdc, hFontOld);
|
|
ReleaseDC(NULL, hdc);
|
|
}
|
|
DeleteObject(hFont);
|
|
}
|
|
if (m_pSysCacheEntry->rgFonts[FNT_SYS_ICON] == 0)
|
|
m_pSysCacheEntry->rgFonts[FNT_SYS_ICON] = CreateFontIndirect(&rSysLogFonts);
|
|
|
|
// Bold Icon Font
|
|
if (m_pSysCacheEntry->rgFonts[FNT_SYS_ICON_BOLD] == 0)
|
|
{
|
|
LONG lOldWeight = rSysLogFonts.lfWeight;
|
|
rSysLogFonts.lfWeight = (rSysLogFonts.lfWeight < 700) ? 700 : 1000;
|
|
m_pSysCacheEntry->rgFonts[FNT_SYS_ICON_BOLD] = CreateFontIndirect(&rSysLogFonts);
|
|
rSysLogFonts.lfWeight = lOldWeight;
|
|
}
|
|
|
|
if (m_pSysCacheEntry->rgFonts[FNT_SYS_ICON_STRIKEOUT] == 0)
|
|
{
|
|
rSysLogFonts.lfStrikeOut = TRUE;
|
|
m_pSysCacheEntry->rgFonts[FNT_SYS_ICON_STRIKEOUT] = CreateFontIndirect(&rSysLogFonts);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AssertSz (FALSE, "SystemParametersInfo (SPI_GETICONTITLELOGFONT) - Failed ---.");
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (m_pSysCacheEntry->rgFonts[FNT_SYS_MENU] == 0)
|
|
{
|
|
#ifndef WIN16 // WIN16FF - SPI_GETNONCLIENTMETRICS
|
|
// Prepare to get icon metrics
|
|
ncm.cbSize = sizeof(ncm);
|
|
|
|
// Get system menu font
|
|
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
|
|
{
|
|
CopyMemory((LPBYTE)&rSysLogFonts, (LPBYTE)&ncm.lfMenuFont, sizeof(LOGFONT));
|
|
m_pSysCacheEntry->rgFonts[FNT_SYS_MENU] = CreateFontIndirect(&rSysLogFonts);
|
|
}
|
|
else
|
|
{
|
|
AssertSz (FALSE, "SystemParametersInfo (SPI_GETNONCLIENTMETRICS) - Failed ---.");
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
#else
|
|
m_pSysCacheEntry->rgFonts[FNT_SYS_MENU] = m_pSysCacheEntry->rgFonts[FNT_SYS_ICON];
|
|
#endif
|
|
}
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::GetSysFont(FNTSYSTYPE fntType, HFONT *phFont)
|
|
{
|
|
// check params
|
|
Assert(fntType < FNT_SYS_LAST);
|
|
Assert(m_pSysCacheEntry);
|
|
|
|
EnterCriticalSection(&m_rFontCritSect);
|
|
|
|
// System Font
|
|
if (m_pSysCacheEntry->rgFonts[fntType] == NULL)
|
|
// This call might fail, but we can return NULL fonts, so is OK
|
|
(void)InitSysFontEntry();
|
|
|
|
// Done
|
|
*phFont = m_pSysCacheEntry->rgFonts[fntType];
|
|
|
|
LeaveCriticalSection(&m_rFontCritSect);
|
|
|
|
return ((*phFont) ? S_OK : E_FAIL);
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::FreeResources()
|
|
{
|
|
m_pFontEntries->ClearList();
|
|
FreeFontsInEntry(m_pSysCacheEntry);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::InitResources()
|
|
{
|
|
DWORD dummyCookie = 0;
|
|
|
|
#ifdef DEBUG
|
|
DWORD cCount;
|
|
m_pFontEntries->GetCount(&cCount);
|
|
Assert(cCount == 0);
|
|
#endif
|
|
|
|
HRESULT hr = InitSysFontEntry();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
void CFontCache::SendPostChangeNotifications()
|
|
{
|
|
DWORD cookie = 0;
|
|
IFontCacheNotify* pCurr;
|
|
IUnknown* pTempCurr;
|
|
|
|
while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
|
|
{
|
|
if (pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)==S_OK)
|
|
{
|
|
pCurr->OnPostFontChange();
|
|
pCurr->Release();
|
|
}
|
|
|
|
pTempCurr->Release();
|
|
}
|
|
}
|
|
|
|
//***************************************************
|
|
void CFontCache::SendPreChangeNotifications()
|
|
{
|
|
DWORD cookie = 0;
|
|
IFontCacheNotify* pCurr;
|
|
IUnknown* pTempCurr;
|
|
|
|
while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
|
|
{
|
|
if (pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)==S_OK)
|
|
{
|
|
pCurr->OnPreFontChange();
|
|
pCurr->Release();
|
|
}
|
|
|
|
pTempCurr->Release();
|
|
}
|
|
}
|
|
|
|
|
|
//************************************
|
|
// IFontCache interface implementation
|
|
//************************************
|
|
HRESULT CFontCache::Init(HKEY hkey, LPCSTR pszIntlKey, DWORD dwFlags)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dummyCookie, dw, cb;
|
|
HKEY hTopkey;
|
|
|
|
if (m_pSysCacheEntry)
|
|
return E_UNEXPECTED;
|
|
|
|
EnterCriticalSection(&m_rFontCritSect);
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
|
|
hr = IUnknownList_CreateInstance(&m_pAdviseRegistry);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
hr = m_pAdviseRegistry->Init(NULL, 0, 0);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = IVoidPtrList_CreateInstance(&m_pFontEntries);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = m_pFontEntries->Init(NULL, 0, (IVPL_FREEITEMFUNCTYPE)(&FreeFontCacheEntry), 0);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = CreateFontCacheEntry(&m_pSysCacheEntry);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
hr = InitResources();
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
m_hkey = hkey;
|
|
StrCpyN(m_szIntlKeyPath, pszIntlKey, ARRAYSIZE(m_szIntlKeyPath));
|
|
if (RegOpenKeyEx(m_hkey, m_szIntlKeyPath, NULL, KEY_READ, &hTopkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(dw);
|
|
if (RegQueryValueEx(hTopkey, c_szISO2022JPControl, NULL, NULL, (LPBYTE)&dw, &cb) == ERROR_SUCCESS)
|
|
m_bISO_2022_JP_ESC_SIO_Control = (BOOL) dw;
|
|
else
|
|
m_bISO_2022_JP_ESC_SIO_Control = false;
|
|
RegCloseKey(hTopkey);
|
|
}
|
|
else
|
|
m_bISO_2022_JP_ESC_SIO_Control = false;
|
|
|
|
Exit:
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
LeaveCriticalSection(&m_rFontCritSect);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::GetFont(FNTSYSTYPE fntType, HCHARSET hCharset, HFONT *phFont)
|
|
{
|
|
INETCSETINFO CsetInfo;
|
|
UINT uiCodePage = 0;
|
|
FONTCACHEENTRY *pCurrEntry = NULL;
|
|
DWORD cookie = 0;
|
|
|
|
// check params
|
|
Assert(fntType < FNT_SYS_LAST);
|
|
|
|
Assert(m_pSysCacheEntry);
|
|
|
|
if (hCharset == NULL)
|
|
return GetSysFont(fntType, phFont);
|
|
|
|
*phFont = 0;
|
|
|
|
/* get CodePage from HCHARSET */
|
|
MimeOleGetCharsetInfo(hCharset,&CsetInfo);
|
|
uiCodePage = (CP_JAUTODETECT == CsetInfo.cpiWindows) ? 932 : CsetInfo.cpiWindows;
|
|
if ( uiCodePage == CP_KAUTODETECT )
|
|
uiCodePage = 949 ;
|
|
|
|
// Don't want to duplicate the system codepage in the list.
|
|
if (m_pSysCacheEntry && (uiCodePage == m_uiSystemCodePage))
|
|
return GetSysFont(fntType, phFont);
|
|
|
|
EnterCriticalSection(&m_rFontCritSect);
|
|
|
|
// Check to see if code page is in cache
|
|
while (SUCCEEDED(m_pFontEntries->GetNext(LD_FORWARD, (LPVOID *)&pCurrEntry, &cookie)))
|
|
if (pCurrEntry->uiCodePage == uiCodePage)
|
|
break;
|
|
|
|
// If code page not in cache, add it
|
|
if (NULL == pCurrEntry)
|
|
{
|
|
if (FAILED(CreateFontCacheEntry(&pCurrEntry)))
|
|
goto ErrorExit;
|
|
if (FAILED(m_pFontEntries->AddItem(pCurrEntry, &cookie)))
|
|
goto ErrorExit;
|
|
pCurrEntry->uiCodePage = uiCodePage;
|
|
}
|
|
|
|
// See if desired font is available for code page. If not, create code page
|
|
if (0 == pCurrEntry->rgFonts[fntType])
|
|
{
|
|
// Locals
|
|
LOGFONT lf;
|
|
TCHAR szFaceName[LF_FACESIZE] = { TCHAR(0) } ;
|
|
BYTE bGDICharset;
|
|
|
|
// Get logfont for charset
|
|
if (0 == GetObject(m_pSysCacheEntry->rgFonts[fntType], sizeof (LOGFONT), &lf))
|
|
goto ErrorExit;
|
|
|
|
if (FAILED(SetGDIAndFaceNameInLF(uiCodePage, CsetInfo.cpiWindows, &lf)))
|
|
goto ErrorExit;
|
|
|
|
// Create the font
|
|
if ((CP_UNICODE == uiCodePage) || IsValidCodePage(uiCodePage))
|
|
pCurrEntry->rgFonts[fntType] = CreateFontIndirect(&lf);
|
|
else
|
|
goto ErrorExit;
|
|
}
|
|
|
|
*phFont = pCurrEntry->rgFonts[fntType];
|
|
|
|
LeaveCriticalSection(&m_rFontCritSect);
|
|
|
|
return S_OK;
|
|
|
|
ErrorExit:
|
|
LeaveCriticalSection(&m_rFontCritSect);
|
|
return GetSysFont(fntType, phFont);
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::OnOptionChange()
|
|
{
|
|
HRESULT hr;
|
|
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
SendPreChangeNotifications();
|
|
EnterCriticalSection(&m_rFontCritSect);
|
|
|
|
FreeResources();
|
|
// Even if this fails, still need to send notifications
|
|
InitResources();
|
|
|
|
LeaveCriticalSection(&m_rFontCritSect);
|
|
SendPostChangeNotifications();
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::GetJP_ISOControl(BOOL *pfUseSIO)
|
|
{
|
|
// 0 means use ESC, 1 means use SIO
|
|
*pfUseSIO = m_bISO_2022_JP_ESC_SIO_Control;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************
|
|
// IConnectionPoint interface implementation
|
|
//
|
|
// The only functions we care about right now
|
|
// are the Advise and Unadvise functions. The
|
|
// others return E_NOTIMPL
|
|
//******************************************
|
|
HRESULT CFontCache::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
|
|
{
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
HRESULT hr = m_pAdviseRegistry->AddItem(pUnkSink, pdwCookie);
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::Unadvise(DWORD dwCookie)
|
|
{
|
|
EnterCriticalSection(&m_rAdviseCritSect);
|
|
HRESULT hr = m_pAdviseRegistry->RemoveItem(dwCookie);
|
|
LeaveCriticalSection(&m_rAdviseCritSect);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::GetConnectionInterface(IID *pIID)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
|
|
{
|
|
*ppCPC = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::EnumConnections(IEnumConnections **ppEnum)
|
|
{
|
|
*ppEnum = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
|
|
{
|
|
TraceCall("CFontCache::PrivateQueryInterface");
|
|
|
|
if(!lplpObj)
|
|
return E_INVALIDARG;
|
|
|
|
*lplpObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IFontCache))
|
|
*lplpObj = (LPVOID)(IFontCache *)this;
|
|
else if (IsEqualIID(riid, IID_IConnectionPoint))
|
|
*lplpObj = (LPVOID)(IConnectionPoint *)this;
|
|
else
|
|
{
|
|
*lplpObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************
|
|
// szFaceName is assumed to be from LOGFONT->lfFaceName
|
|
HRESULT CFontCache::SetFaceNameFromReg(UINT uiCodePage, LPTSTR szFaceName, DWORD cchFaceName)
|
|
{
|
|
HKEY hkey, hTopkey;
|
|
DWORD cb, dw, i = 0;
|
|
TCHAR szName[LF_FACESIZE];
|
|
|
|
szFaceName[0] = TCHAR(0);
|
|
|
|
if (RegOpenKeyEx(m_hkey, m_szIntlKeyPath, NULL, KEY_READ, &hTopkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(szName);
|
|
while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hTopkey, i++, szName, &cb, 0, NULL, NULL, NULL))
|
|
{
|
|
UINT uiTempCodePage = StrToInt(szName);
|
|
if (uiTempCodePage == uiCodePage)
|
|
{
|
|
if (RegOpenKeyEx(hTopkey, szName, NULL, KEY_READ, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(TCHAR)*cchFaceName;
|
|
RegQueryValueEx(hkey, REGSTR_VAL_PROP_FONT, NULL, NULL, (LPBYTE)szFaceName, &cb);
|
|
|
|
RegCloseKey(hkey);
|
|
break;
|
|
}
|
|
}
|
|
cb = sizeof(szName);
|
|
}
|
|
RegCloseKey(hTopkey);
|
|
}
|
|
|
|
if (TCHAR(0) == szFaceName[0])
|
|
return E_FAIL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// =================================================================================
|
|
// EnumFontFamExProc
|
|
// =================================================================================
|
|
INT CALLBACK EnumFontFamExProc (ENUMLOGFONTEX *lpelfe,
|
|
NEWTEXTMETRICEX *lpntme,
|
|
INT FontType,
|
|
LPARAM lParam)
|
|
{
|
|
// Check Param
|
|
Assert (lpelfe && lpntme && lParam);
|
|
|
|
// NOTE: Assuming size of buffer is LF_FACESIZE. If it changes below, change
|
|
// here also.
|
|
StrCpyN((LPTSTR)lParam, lpelfe->elfLogFont.lfFaceName, LF_FACESIZE);
|
|
|
|
// End the enumeration by return 0
|
|
return 0;
|
|
}
|
|
|
|
//***************************************************
|
|
// szFaceName is assumed to be from LOGFONT->lfFaceName
|
|
HRESULT CFontCache::SetFaceNameFromGDI(BYTE bGDICharSet, LPTSTR szFaceName, DWORD cchFaceName)
|
|
{
|
|
HDC hdc;
|
|
LOGFONT rSysLogFont;
|
|
|
|
// I know these charsets support Arial
|
|
if (bGDICharSet == ANSI_CHARSET || bGDICharSet == EASTEUROPE_CHARSET ||
|
|
bGDICharSet == RUSSIAN_CHARSET || bGDICharSet == BALTIC_CHARSET ||
|
|
bGDICharSet == GREEK_CHARSET || bGDICharSet == TURKISH_CHARSET)
|
|
{
|
|
StrCpyN(szFaceName, TEXT("Arial"), cchFaceName);
|
|
goto Exit;
|
|
}
|
|
|
|
if (0 == GetObject(m_pSysCacheEntry->rgFonts[FNT_SYS_ICON], sizeof (LOGFONT), &rSysLogFont))
|
|
{
|
|
StrCpyN(szFaceName, rSysLogFont.lfFaceName, cchFaceName);
|
|
if (TCHAR(0) != szFaceName[0])
|
|
goto Exit;
|
|
}
|
|
|
|
// Get an hdc from the hwnd
|
|
hdc = GetDC (NULL);
|
|
|
|
TCHAR szName[LF_FACESIZE]; // Note: If we change size, change callback above.
|
|
|
|
// EnumFontFamilies
|
|
EnumFontFamiliesEx(hdc, &rSysLogFont, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)szName, 0);
|
|
|
|
StrCpyN(szFaceName, szName, cchFaceName);
|
|
|
|
// Done
|
|
ReleaseDC (NULL, hdc);
|
|
|
|
Exit:
|
|
return (0 != *szFaceName) ? S_OK : E_FAIL;
|
|
}
|
|
|
|
//***************************************************
|
|
// szFaceName is assumed to be from LOGFONT->lfFaceName
|
|
HRESULT CFontCache::SetFaceNameFromCPID(UINT cpID, LPTSTR szFaceName, DWORD cchFaceName)
|
|
{
|
|
CODEPAGEINFO CodePageInfo ;
|
|
|
|
/* get CodePageInfo from HCHARSET */
|
|
MimeOleGetCodePageInfo(cpID,&CodePageInfo);
|
|
if ( CodePageInfo.szVariableFont[0] != '\0' )
|
|
StrCpyN(szFaceName, CodePageInfo.szVariableFont, cchFaceName);
|
|
else
|
|
StrCpyN(szFaceName, CodePageInfo.szFixedFont, cchFaceName);
|
|
|
|
if (szFaceName[0] == '\0')
|
|
return E_FAIL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::SetGDIAndFaceNameInLF(UINT uiCodePage, CODEPAGEID cpID, LOGFONT *lpLF)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fDoLastChance = false;
|
|
CHARSETINFO rCharsetInfo;
|
|
|
|
if (FAILED(SetFaceNameFromReg(uiCodePage, lpLF->lfFaceName, ARRAYSIZE(lpLF->lfFaceName))))
|
|
if (FAILED(SetFaceNameFromCPID(cpID, lpLF->lfFaceName, ARRAYSIZE(lpLF->lfFaceName))))
|
|
fDoLastChance = true;
|
|
|
|
if ( TranslateCharsetInfo((LPDWORD) IntToPtr(uiCodePage), &rCharsetInfo, TCI_SRCCODEPAGE))
|
|
lpLF->lfCharSet = (BYTE) rCharsetInfo.ciCharset;
|
|
else
|
|
lpLF->lfCharSet = DEFAULT_CHARSET;
|
|
|
|
if (fDoLastChance)
|
|
hr = SetFaceNameFromGDI(lpLF->lfCharSet, lpLF->lfFaceName, ARRAYSIZE(lpLF->lfFaceName));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************
|
|
HRESULT CFontCache::CreateInstance(IUnknown* pUnkOuter, IUnknown** ppUnknown)
|
|
{
|
|
// Invalid Arg
|
|
Assert(ppUnknown);
|
|
|
|
// Initialize
|
|
*ppUnknown = NULL;
|
|
|
|
// Create me
|
|
CFontCache *pNew = new CFontCache(pUnkOuter);
|
|
if (NULL == pNew)
|
|
return (E_OUTOFMEMORY);
|
|
|
|
// Cast to unknown
|
|
*ppUnknown = (IFontCache*)pNew;
|
|
|
|
// Done
|
|
return S_OK;
|
|
}
|