windows-nt/Source/XPSP1/NT/shell/cpls/inetcpl/fonts.cpp
2020-09-26 16:20:57 +08:00

1795 lines
58 KiB
C++

//
// FONTS.C - Selecting character set default fonts dialog
//
// Copyright(c) Microsoft Corp., 1996 All rights reserved.
//
// History:
// 7/11/96 t-gpease trashed old International subdialog to create the new
// improved codepage compatiable Fonts dialog.
// WAS
//
// INTL.C - international dialog proc for inetcpl applet.
//
// Copyright(c) Microsoft Corp., 1996 All rights reserved.
//
// HISTORY:
// 2/2/96 yutakan created.
// 2/6/96 yutakan ported most of functions from IE2.0i.
// 8/20/98 weiwu add script base font dialog proc (UNICODE version only)
#include "inetcplp.h"
#include <mlang.h>
#include <mluisupp.h>
#ifdef UNIX
#include <mainwin.h>
#endif /*UNIX */
// Used for window property to remember the font created
static const TCHAR c_szPropDlgFont[] = TEXT("DefaultDlgFont");
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#ifdef UNICODE
PMIMECPINFO g_pCPInfo = NULL;
#else
PMIMECPINFO g_pCPInfoW = NULL;
typedef struct tagMIMECPINFOA
{
DWORD dwFlags;
UINT uiCodePage;
UINT uiFamilyCodePage;
CHAR wszDescription[MAX_MIMECP_NAME]; // NOTE:
CHAR wszWebCharset[MAX_MIMECSET_NAME]; // To make it simple, it has wsz
CHAR wszHeaderCharset[MAX_MIMECSET_NAME]; // prefix even though it's CHAR. So,
CHAR wszBodyCharset[MAX_MIMECSET_NAME]; // we don't need to put #ifdef UNICODE
CHAR wszFixedWidthFont[MAX_MIMEFACE_NAME]; // in below code anymore except
CHAR wszProportionalFont[MAX_MIMEFACE_NAME]; // conversion time.
BYTE bGDICharset;
} MIMECPINFOA, *PMIMECPINFOA;
PMIMECPINFOA g_pCPInfo = NULL;
#endif
ULONG g_cCPInfo = 0;
ULONG g_cSidInfo = 0;
IMLangFontLink2 *g_pMLFlnk2 = NULL;
typedef HRESULT (* PCOINIT) (LPVOID);
typedef VOID (* PCOUNINIT) (VOID);
typedef VOID (* PCOMEMFREE) (LPVOID);
typedef HRESULT (* PCOCREINST) (REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID * );
extern HMODULE hOLE32;
extern PCOINIT pCoInitialize;
extern PCOUNINIT pCoUninitialize;
extern PCOMEMFREE pCoTaskMemFree;
extern PCOCREINST pCoCreateInstance;
BOOL _StartOLE32();
#define IsVerticalFont(p) (*(p) == '@')
typedef struct {
TCHAR szPropFont[MAX_MIMEFACE_NAME];
TCHAR szFixedFont[MAX_MIMEFACE_NAME];
TCHAR szFriendlyName[MAX_MIMECP_NAME];
TCHAR szMIMEFont[MAX_MIMECP_NAME];
DWORD dwFontSize;
} CODEPAGEDATA;
typedef struct {
HWND hDlg;
HWND hwndPropCB;
HWND hwndFixedCB;
HWND hwndSizeCB;
HWND hwndMIMECB;
HWND hwndNamesLB;
DWORD dwDefaultCodePage;
BOOL bChanged;
CODEPAGEDATA *page;
LPCTSTR lpszKeyPath;
} FONTSDATA, *LPFONTSDATA;
typedef struct {
HWND hDlg;
HWND hwndPropLB;
HWND hwndFixedLB;
HWND hwndNamesCB;
SCRIPT_ID sidDefault;
BOOL bChanged;
PSCRIPTINFO pSidInfo;
LPCTSTR lpszKeyPath;
} FONTSCRIPTDATA, *LPFONTSCRIPTDATA;
const struct {
SCRIPT_ID Sid;
BYTE nCharSet;
UINT uiCp;
} g_CharSetTransTable[] =
{
sidAsciiLatin, ANSI_CHARSET, 1252,
sidLatin, ANSI_CHARSET, 1252,
sidCyrillic, RUSSIAN_CHARSET, 1251,
sidGreek, GREEK_CHARSET, 1253,
sidHebrew, HEBREW_CHARSET, 1255,
sidArabic, ARABIC_CHARSET, 1256,
sidThai, THAI_CHARSET, 874,
sidKana, SHIFTJIS_CHARSET, 932,
sidHan, GB2312_CHARSET, 936,
sidBopomofo, CHINESEBIG5_CHARSET,950,
sidHangul, HANGEUL_CHARSET, 949,
};
//
// Map script ID to charset
// We should use MLang service when it is available
//
BYTE CharSetFromSid(SCRIPT_ID Sid)
{
for (int i=0; i<ARRAYSIZE(g_CharSetTransTable); i++)
{
if (Sid == g_CharSetTransTable[i].Sid)
return g_CharSetTransTable[i].nCharSet;
}
return DEFAULT_CHARSET;
}
// SHLWAPI StrCmp/StrCmpI doesn't work.
// Make this simple function to tell if string is equal in character value
BOOL IsStringEqual(LPCTSTR lpString1, LPCTSTR lpString2)
{
if (lstrlen(lpString1) != lstrlen(lpString2))
return FALSE;
while(*lpString1 && *lpString2)
{
if (*lpString1 != *lpString2)
{
return FALSE;
}
lpString1++;
lpString2++;
}
return TRUE;
}
//
// Initialize script table with resource string
//
BOOL InitScriptTable(LPFONTSCRIPTDATA pFnt)
{
HRESULT hr;
BOOL bRet = FALSE;
IMultiLanguage2 * pML2;
ASSERT(IS_VALID_CODE_PTR(pCoInitialize, PCOINIT));
ASSERT(IS_VALID_CODE_PTR(pCoUninitialize, PCOUNINIT));
ASSERT(IS_VALID_CODE_PTR(pCoTaskMemFree, PCOMEMFREE));
ASSERT(IS_VALID_CODE_PTR(pCoCreateInstance, PCOCREINST));
hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (LPVOID *) &pML2);
if (SUCCEEDED(hr))
{
hr = pML2->QueryInterface(IID_IMLangFontLink2, (LPVOID *) &g_pMLFlnk2);
if (SUCCEEDED(hr))
{
IEnumScript *pEnumScript;
if (SUCCEEDED(pML2->EnumScripts(SCRIPTCONTF_SCRIPT_USER, INETCPL_GetUILanguage(), &pEnumScript)))
{
UINT cNum = 0;
pML2->GetNumberOfScripts(&cNum);
pFnt->pSidInfo = (PSCRIPTINFO)LocalAlloc(LPTR, sizeof(SCRIPTINFO) * cNum);
if (NULL != pFnt->pSidInfo)
{
hr = pEnumScript->Next(cNum, pFnt->pSidInfo, &g_cSidInfo);
if (SUCCEEDED(hr))
{
bRet = TRUE;
}
else
{
LocalFree(pFnt->pSidInfo);
pFnt->pSidInfo = NULL;
}
}
pEnumScript->Release();
}
}
if (pML2)
pML2->Release();
}
return bRet;
}
//
// DrawSampleString()
//
// Draw the sample string with current font
//
void DrawSampleString(LPFONTSDATA pFnt, int idSample, LPCTSTR lpFace, SCRIPT_ID ScriptId)
{
HDC hDC;
HFONT hFont, hTemp;
LOGFONT lf = {0};
DWORD rgbText, rgbBack;
RECT rc;
SIZE TextExtent;
TEXTMETRIC tm;
int len, x, y;
TCHAR szFontSample[1024];
if (!lpFace)
return;
MLLoadString(IDS_FONT_SAMPLE_DEFAULT+ScriptId, szFontSample, ARRAYSIZE(szFontSample));
GetWindowRect(GetDlgItem(pFnt->hDlg, idSample), &rc);
// Use MapWindowPoints() as it works for mirrored windows as well.
MapWindowRect(NULL, pFnt->hDlg, &rc);
// ScreenToClient(pFnt->hDlg, (LPPOINT)&rc.left);
// ScreenToClient(pFnt->hDlg, (LPPOINT)&rc.right);
hDC = GetDC(pFnt->hDlg);
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
rgbText = GetSysColor(COLOR_WINDOWTEXT);
rgbText = SetTextColor(hDC, rgbText);
hFont = GetWindowFont(pFnt->hDlg);
GetObject(hFont, sizeof(LOGFONT), &lf);
lf.lfCharSet = CharSetFromSid(ScriptId);
lf.lfHeight += lf.lfHeight/2;
lf.lfWidth += lf.lfWidth/2;
StrCpyN(lf.lfFaceName, lpFace, LF_FACESIZE);
hFont = CreateFontIndirect(&lf);
hTemp = (HFONT)SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
len = lstrlen(szFontSample);
GetTextExtentPoint32(hDC, szFontSample, len, &TextExtent);
TextExtent.cy = tm.tmAscent - tm.tmInternalLeading;
DrawEdge(hDC, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
if ((TextExtent.cx >= (rc.right - rc.left)) || (TextExtent.cx <= 0))
x = rc.left;
else
x = rc.left + ((rc.right - rc.left) - TextExtent.cx) / 2;
y = min(rc.bottom, rc.bottom - ((rc.bottom - rc.top) - TextExtent.cy) / 2);
if (lpFace[0])
ExtTextOut(hDC, x, y - (tm.tmAscent), ETO_OPAQUE | ETO_CLIPPED,
&rc, szFontSample, len, NULL );
else
ExtTextOut(hDC, x, y - (tm.tmAscent), ETO_OPAQUE | ETO_CLIPPED,
&rc, TEXT(" "), 1, NULL );
SetBkColor(hDC, rgbBack);
SetTextColor(hDC, rgbText);
if (hTemp)
DeleteObject(SelectObject(hDC, hTemp));
ReleaseDC(pFnt->hDlg, hDC);
}
//
// FillCharsetListBoxes()
//
// Fills the Web page and Plain text ListBoxes with the appropriate
// font data
//
BOOL FillScriptListBoxes(LPFONTSCRIPTDATA pFnt, SCRIPT_ID sid)
{
UINT i;
UINT nFonts = 0;
int iSidInfo = -1;
PSCRIPTFONTINFO pSidFont = NULL;
if (!pFnt->pSidInfo)
return FALSE;
// erase all the listboxes to start fresh
SendMessage(pFnt->hwndPropLB, LB_RESETCONTENT, 0, 0);
SendMessage(pFnt->hwndFixedLB, LB_RESETCONTENT, 0, 0);
for(i=0; i < g_cSidInfo; i++)
{
if (pFnt->pSidInfo[i].ScriptId == sid)
{
iSidInfo = i;
break;
}
}
if (-1 == iSidInfo)
return FALSE;
if (g_pMLFlnk2)
{
g_pMLFlnk2->GetScriptFontInfo(sid, SCRIPTCONTF_PROPORTIONAL_FONT, &nFonts, NULL);
if (nFonts)
{
pSidFont = (PSCRIPTFONTINFO) LocalAlloc(LPTR, sizeof(SCRIPTFONTINFO)*nFonts);
if (pSidFont)
{
g_pMLFlnk2->GetScriptFontInfo(sid, SCRIPTCONTF_PROPORTIONAL_FONT, &nFonts, pSidFont);
for (i=0; i<nFonts; i++)
{
if (LB_ERR == SendMessage(pFnt->hwndPropLB, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)((pSidFont+i)->wszFont)))
{
// add the font name to the combobox
SendMessage(pFnt->hwndPropLB, LB_ADDSTRING, 0, (LPARAM)((pSidFont+i)->wszFont));
}
}
// Hack PRC font problems on Win9x and NT4 (Bug #24641, #39946)
// Win9x does not ship with GBK-supporting fixed-pitch fonts,
// We provide user proportional fonts as plain text font candidates.
if (sid == sidHan && GetACP() == 936 && !IsOS(OS_WIN2000ORGREATER))
{
for (i=0; i<nFonts; i++)
{
// add the font name to the combobox
SendMessage(pFnt->hwndFixedLB, LB_ADDSTRING, 0, (LPARAM)((pSidFont+i)->wszFont));
}
}
LocalFree(pSidFont);
pSidFont = NULL;
}
}
// Get number of available fonts
g_pMLFlnk2->GetScriptFontInfo(sid, SCRIPTCONTF_FIXED_FONT, &nFonts, NULL);
if (nFonts)
{
pSidFont = (PSCRIPTFONTINFO) LocalAlloc(LPTR, sizeof(SCRIPTFONTINFO)*nFonts);
if (pSidFont)
{
g_pMLFlnk2->GetScriptFontInfo(sid, SCRIPTCONTF_FIXED_FONT, &nFonts, pSidFont);
if (!pFnt->pSidInfo[iSidInfo].wszFixedWidthFont[0])
{
StrCpyN(pFnt->pSidInfo[iSidInfo].wszFixedWidthFont, pSidFont->wszFont, LF_FACESIZE);
pFnt->bChanged = TRUE;
}
// All fixedwidth and proportional fonts are web page font candidates
for (i=0; i<nFonts; i++)
{
if (LB_ERR == SendMessage(pFnt->hwndFixedLB, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)((pSidFont+i)->wszFont)))
{
// add the font name to the combobox
SendMessage(pFnt->hwndFixedLB, LB_ADDSTRING, 0, (LPARAM)((pSidFont+i)->wszFont));
}
if (LB_ERR == SendMessage(pFnt->hwndPropLB, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)((pSidFont+i)->wszFont)))
{
// add the font name to the combobox
SendMessage(pFnt->hwndPropLB, LB_ADDSTRING, 0, (LPARAM)((pSidFont+i)->wszFont));
}
}
LocalFree(pSidFont);
}
}
}
// Add fonts to combobox
#ifdef UNIX
/* We would have called EnumFontFamiliesEx wherein we would have
* have populated the fonts list boxes with substitute fonts if any
*
* So, before we populate the proportional and the fixed fonts below,
* we must query and use substitute fonts if avbl.
*/
{
CHAR szSubstFont[MAX_MIMEFACE_NAME+1];
DWORD cchSubstFont = MAX_MIMEFACE_NAME + 1;
CHAR szFont[MAX_MIMEFACE_NAME + 1];
WideCharToMultiByte(CP_ACP, 0, pFnt->pSidInfo[iSidInfo].wszProportionalFont, -1, szFont,
MAX_MIMEFACE_NAME + 1, NULL, NULL);
if ((ERROR_SUCCESS == MwGetSubstituteFont(szFont, szSubstFont, &cchSubstFont)) &&
cchSubstFont)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSubstFont, -1,
pFnt->pSidInfo[iSidInfo].wszProportionalFont, MAX_MIMEFACE_NAME + 1);
}
WideCharToMultiByte(CP_ACP, 0, pFnt->pSidInfo[iSidInfo].wszFixedWidthFont, -1, szFont,
MAX_MIMEFACE_NAME + 1, NULL, NULL);
cchSubstFont = MAX_MIMEFACE_NAME + 1;
if ((ERROR_SUCCESS == MwGetSubstituteFont(szFont, szSubstFont, &cchSubstFont)) &&
cchSubstFont)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSubstFont, -1,
pFnt->pSidInfo[iSidInfo].wszFixedWidthFont, MAX_MIMEFACE_NAME + 1);
}
}
#endif /* UNIX */
// select the current prop default
if (pFnt->pSidInfo[iSidInfo].wszProportionalFont[0])
{
if (LB_ERR == SendMessage(pFnt->hwndPropLB, LB_SELECTSTRING, (WPARAM)-1,
(LPARAM)pFnt->pSidInfo[iSidInfo].wszProportionalFont))
pFnt->pSidInfo[iSidInfo].wszProportionalFont[0] = 0;
}
// Draw sample strings with current font
DrawSampleString((FONTSDATA *)pFnt, IDC_FONTS_PROP_SAMPLE, pFnt->pSidInfo[iSidInfo].wszProportionalFont, pFnt->pSidInfo[iSidInfo].ScriptId);
// select the current fixed default
if (pFnt->pSidInfo[iSidInfo].wszFixedWidthFont[0])
{
if (LB_ERR == SendMessage(pFnt->hwndFixedLB, LB_SELECTSTRING, (WPARAM)-1,
(LPARAM)pFnt->pSidInfo[iSidInfo].wszFixedWidthFont))
pFnt->pSidInfo[iSidInfo].wszFixedWidthFont[0] = 0;
}
// Draw sample strings with current font
DrawSampleString((FONTSDATA *)pFnt, IDC_FONTS_FIXED_SAMPLE, pFnt->pSidInfo[iSidInfo].wszFixedWidthFont, pFnt->pSidInfo[iSidInfo].ScriptId);
// we handled it
return TRUE;
} // FillScriptListBoxes()
//
// FontsDlgInitEx()
//
// Initializes the script based font dialog, use same dialog box template.
//
BOOL FontsDlgInitEx(IN HWND hDlg, LPCTSTR lpszKeyPath)
{
HKEY hkey;
// DWORD dw;
DWORD cb;
DWORD i;
TCHAR szKey[1024];
LPFONTSCRIPTDATA pFnt; // localize data
if (!hDlg)
return FALSE; // nothing to initialize
// get some space to store local data
// NOTE: LocalAlloc already zeroes the memory
pFnt = (LPFONTSCRIPTDATA)LocalAlloc(LPTR, sizeof(*pFnt));
if (!pFnt)
{
EndDialog(hDlg, 0);
return FALSE;
}
if (!InitScriptTable(pFnt))
{
EndDialog(hDlg, 0);
return FALSE;
}
// associate the memory with the dialog window
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pFnt);
// save the dialog handle
pFnt->hDlg = hDlg;
// get the dialog items
pFnt->hwndPropLB = GetDlgItem(pFnt->hDlg, IDC_FONTS_PROP_FONT_LIST);
pFnt->hwndFixedLB = GetDlgItem(pFnt->hDlg, IDC_FONTS_FIXED_FONT_LIST);
pFnt->hwndNamesCB = GetDlgItem(pFnt->hDlg, IDC_FONTS_CHAR_SET_COMBO);
pFnt->lpszKeyPath = lpszKeyPath ? lpszKeyPath: REGSTR_PATH_INTERNATIONAL_SCRIPTS;
if (!g_pMLFlnk2 || FAILED(g_pMLFlnk2->CodePageToScriptID(GetACP(), &(pFnt->sidDefault))))
pFnt->sidDefault = sidAsciiLatin;
// We shouldn't consider default script in registry since we no longer have UI to allow user to change default script
#if 0
// get values from registry
if (RegOpenKeyEx(HKEY_CURRENT_USER, pFnt->lpszKeyPath, NULL, KEY_READ, &hkey)
== ERROR_SUCCESS)
{
cb = sizeof(dw);
if (RegQueryValueEx(hkey, REGSTR_VAL_DEFAULT_SCRIPT, NULL, NULL, (LPBYTE)&dw, &cb)
== ERROR_SUCCESS)
{
pFnt->sidDefault = (SCRIPT_ID)dw;
}
RegCloseKey(hkey);
}
#endif
for (i = 0; i < g_cSidInfo; i++)
{
wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("%s\\%u"), pFnt->lpszKeyPath, pFnt->pSidInfo[i].ScriptId);
if (RegOpenKeyEx(HKEY_CURRENT_USER, szKey, NULL, KEY_READ, &hkey) == ERROR_SUCCESS)
{
TCHAR szFont[MAX_MIMEFACE_NAME];
cb = sizeof(szFont);
if (RegQueryValueEx(hkey, REGSTR_VAL_FIXED_FONT, NULL, NULL,
(LPBYTE)szFont, &cb) == ERROR_SUCCESS)
{
StrCpyN(pFnt->pSidInfo[i].wszFixedWidthFont, szFont, ARRAYSIZE(pFnt->pSidInfo[i].wszFixedWidthFont));
}
cb = sizeof(szFont);
if (RegQueryValueEx(hkey, REGSTR_VAL_PROP_FONT, NULL, NULL,
(LPBYTE)szFont, &cb) == ERROR_SUCCESS)
{
StrCpyN(pFnt->pSidInfo[i].wszProportionalFont, szFont, ARRAYSIZE(pFnt->pSidInfo[i].wszProportionalFont));
}
RegCloseKey(hkey);
}
// add the name to the listbox
SendMessage(pFnt->hwndNamesCB, CB_ADDSTRING, 0,
(LPARAM)pFnt->pSidInfo[i].wszDescription);
// check to see if it is the default code page
if (pFnt->sidDefault == pFnt->pSidInfo[i].ScriptId)
{
SendMessage(pFnt->hwndNamesCB, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)pFnt->pSidInfo[i].wszDescription);
}
}
pFnt->bChanged = FALSE;
FillScriptListBoxes(pFnt, pFnt->sidDefault);
if( g_restrict.fFonts )
{
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_PROP_FONT_LIST ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_FIXED_FONT_LIST ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_CHAR_SET_COMBO ), FALSE);
#ifdef UNIX
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_UPDATE_BUTTON ), FALSE);
#endif
}
// everything ok
return TRUE;
} // FontsDlgInit()
//
// SaveFontsDataEx()
//
// Save the new fonts settings into regestry
//
void SaveFontsDataEx(LPFONTSCRIPTDATA pFnt)
{
HKEY hkeyScript;
TCHAR szScript[MAX_SCRIPT_NAME];
HKEY hkey;
DWORD dw;
// get values from registry
if (RegCreateKeyEx(HKEY_CURRENT_USER, pFnt->lpszKeyPath, NULL, NULL, NULL, KEY_WRITE, NULL, &hkey, &dw)
== ERROR_SUCCESS)
{
UINT i;
RegSetValueEx(hkey, REGSTR_VAL_DEFAULT_SCRIPT, NULL, REG_BINARY, (LPBYTE)&pFnt->sidDefault, sizeof(pFnt->sidDefault));
for(i = 0; i < g_cSidInfo; i++)
{
wnsprintf(szScript, ARRAYSIZE(szScript), TEXT("%u"), pFnt->pSidInfo[i].ScriptId);
if (RegCreateKeyEx(hkey, szScript, NULL, NULL, NULL, KEY_WRITE, NULL, &hkeyScript, &dw) == ERROR_SUCCESS)
{
// Currently, no need for script name, save registry space
#if 0
RegSetValueEx(hkeyScript, REGSTR_VAL_FONT_SCRIPT_NAME, NULL, REG_SZ,
(LPBYTE)&pFnt->pSidInfo[i].wszDescription,
(lstrlen(pFnt->pSidInfo[i].wszDescription)+1)*sizeof(TCHAR));
#endif
RegSetValueEx(hkeyScript, REGSTR_VAL_SCRIPT_FIXED_FONT, NULL, REG_SZ,
(LPBYTE)pFnt->pSidInfo[i].wszFixedWidthFont,
(lstrlen(pFnt->pSidInfo[i].wszFixedWidthFont)+1)*sizeof(TCHAR));
RegSetValueEx(hkeyScript, REGSTR_VAL_SCRIPT_PROP_FONT, NULL, REG_SZ,
(LPBYTE)pFnt->pSidInfo[i].wszProportionalFont,
(lstrlen(pFnt->pSidInfo[i].wszProportionalFont)+1)*sizeof(TCHAR));
RegCloseKey(hkeyScript);
} // if RegCreateKeyEx
} // for
RegCloseKey(hkey);
} // if RegCreateKeyEx
} // SaveFontsDataEx()
//
// FontsOnCommandEx()
//
// Handles WM_COMMAND message for the script based Fonts subdialog
//
BOOL FontsOnCommandEx(LPFONTSCRIPTDATA pFnt, UINT id, UINT nCmd)
{
switch(id)
{
case IDOK:
if (pFnt->bChanged)
{
SaveFontsDataEx(pFnt);
// tell MSHTML to pick up changes and update
UpdateAllWindows();
}
return TRUE; // exit dialog
case IDCANCEL:
return TRUE; // exit dialog
case IDC_FONTS_PROP_FONT_LIST:
case IDC_FONTS_FIXED_FONT_LIST:
if (nCmd==LBN_SELCHANGE)
{
UINT i;
TCHAR szScript[MAX_SCRIPT_NAME];
pFnt->bChanged = TRUE; // we need to save
// find the currently selected item in the list box
GetDlgItemText(pFnt->hDlg, IDC_FONTS_CHAR_SET_COMBO, szScript, ARRAYSIZE(szScript));
// find the code page from the text
for(i=0; i < g_cSidInfo; i++)
{
INT_PTR j;
if (IsStringEqual(szScript, pFnt->pSidInfo[i].wszDescription))
{
// grab the new values
j = SendMessage(pFnt->hwndPropLB, LB_GETCURSEL, 0, 0);
SendMessage(pFnt->hwndPropLB, LB_GETTEXT, j, (LPARAM)(pFnt->pSidInfo[i].wszProportionalFont));
j = SendMessage(pFnt->hwndFixedLB, LB_GETCURSEL, 0, 0);
SendMessage(pFnt->hwndFixedLB, LB_GETTEXT, j, (LPARAM)(pFnt->pSidInfo[i].wszFixedWidthFont));
break;
}
}
// Redraw sample strings
DrawSampleString((LPFONTSDATA)pFnt, IDC_FONTS_PROP_SAMPLE, pFnt->pSidInfo[i].wszProportionalFont, pFnt->pSidInfo[i].ScriptId);
DrawSampleString((LPFONTSDATA)pFnt, IDC_FONTS_FIXED_SAMPLE, pFnt->pSidInfo[i].wszFixedWidthFont, pFnt->pSidInfo[i].ScriptId);
// if we don't find it... we are going to keep the default
ASSERT(i < g_cSidInfo); // something went wrong
}
break;
case IDC_FONTS_CHAR_SET_COMBO:
if (nCmd==CBN_SELCHANGE)
{
UINT i;
TCHAR szScript[MAX_SCRIPT_NAME];
GetDlgItemText(pFnt->hDlg, IDC_FONTS_CHAR_SET_COMBO, szScript, ARRAYSIZE(szScript));
// find the code page from the text
for(i=0; i < g_cSidInfo; i++)
{
if (IsStringEqual(szScript, pFnt->pSidInfo[i].wszDescription))
{
FillScriptListBoxes(pFnt, pFnt->pSidInfo[i].ScriptId);
break;
}
}
}
break;
#ifdef UNIX
case IDC_FONTS_UPDATE_BUTTON:
{
HCURSOR hOldCursor = NULL;
HCURSOR hNewCursor = NULL;
hNewCursor = LoadCursor(NULL, IDC_WAIT);
if (hNewCursor)
hOldCursor = SetCursor(hNewCursor);
DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_FONTUPD_PROG), pFnt->hDlg,FontUpdDlgProc, NULL);
if(hOldCursor)
SetCursor(hOldCursor);
}
break;
#endif
}
// don't exit dialog
return FALSE;
}
//
// FontsDlgProcEx()
//
// Message handler for the script based "Fonts" subdialog.
//
INT_PTR CALLBACK FontsDlgProcEx(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPFONTSCRIPTDATA pFnt = (LPFONTSCRIPTDATA) GetWindowLongPtr(hDlg, DWLP_USER);
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_INITDIALOG:
return FontsDlgInitEx(hDlg, (LPTSTR)lParam);
break;
case WM_DESTROY:
// Free memory
if (pFnt)
{
if (pFnt->pSidInfo)
LocalFree(pFnt->pSidInfo);
LocalFree(pFnt);
}
break;
case WM_PAINT:
if (BeginPaint(hDlg, &ps))
{
UINT i;
SCRIPT_ID sid = 0;
TCHAR szScript[MAX_SCRIPT_NAME];
GetDlgItemText(hDlg, IDC_FONTS_CHAR_SET_COMBO, szScript, ARRAYSIZE(szScript));
// find the script id from the text
for(i = 0; i < g_cSidInfo; i++)
{
if (IsStringEqual(szScript, pFnt->pSidInfo[i].wszDescription))
{
sid = pFnt->pSidInfo[i].ScriptId;
break;
}
}
if (i < g_cSidInfo)
{
// show sample strings with current font
DrawSampleString((LPFONTSDATA)pFnt, IDC_FONTS_PROP_SAMPLE, pFnt->pSidInfo[i].wszProportionalFont, pFnt->pSidInfo[i].ScriptId);
DrawSampleString((LPFONTSDATA)pFnt, IDC_FONTS_FIXED_SAMPLE, pFnt->pSidInfo[i].wszFixedWidthFont, pFnt->pSidInfo[i].ScriptId);
}
EndPaint(hDlg, &ps);
}
break;
case WM_COMMAND:
if (FontsOnCommandEx(pFnt, LOWORD(wParam), HIWORD(wParam)))
EndDialog(hDlg, LOWORD(wParam) == IDOK? 1: 0);
break;
case WM_HELP: // F1
ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
break;
case WM_CONTEXTMENU: // right mouse click
ResWinHelp( (HWND) wParam, IDS_HELPFILE,
HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
break;
#ifdef UNIX
case WM_DRAWITEM:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_FONTS_UPDATE_BUTTON:
DrawXFontButton(hDlg, (LPDRAWITEMSTRUCT)lParam);
return TRUE;
}
return FALSE;
#endif
default:
return FALSE;
}
return TRUE;
}
//
// Back out old font dialog for OE4
//
//
// InitMimeCsetTable()
//
// Initialize MimeCharsetTable[]'s string field with resource string
//
BOOL InitMimeCsetTable(BOOL bIsOE5)
{
IMultiLanguage *pML=NULL;
IMultiLanguage2 *pML2=NULL;
HRESULT hr;
if(!hOLE32)
{
if(!_StartOLE32())
{
ASSERT(FALSE);
return FALSE;
}
}
hr = pCoInitialize(NULL);
if (FAILED(hr))
return FALSE;
if (bIsOE5)
hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (LPVOID *) &pML2);
else
hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, (LPVOID *) &pML);
if (SUCCEEDED(hr))
{
IEnumCodePage *pEnumCP;
if (bIsOE5)
{
// Ignore MUI if cross code page, otherwise, we won't be able to save data in registry
char szUICP[1024] = {0};
LANGID uiLangId = INETCPL_GetUILanguage();
// We always support English (US)
if (uiLangId != 0x0409)
GetLocaleInfoA(MAKELCID(uiLangId, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szUICP, ARRAYSIZE(szUICP));
if (szUICP[0] && (UINT)StrToIntA(szUICP) != GetACP())
hr = pML2->EnumCodePages(MIMECONTF_VALID, GetSystemDefaultLangID(), &pEnumCP);
else
hr = pML2->EnumCodePages(MIMECONTF_VALID, uiLangId, &pEnumCP);
}
else
hr = pML->EnumCodePages(MIMECONTF_VALID, &pEnumCP);
if (SUCCEEDED(hr))
{
UINT cNum = 0;
if (bIsOE5)
pML2->GetNumberOfCodePageInfo(&cNum);
else
pML->GetNumberOfCodePageInfo(&cNum);
#ifdef UNICODE
g_pCPInfo = (PMIMECPINFO)LocalAlloc(LPTR, sizeof(MIMECPINFO) * cNum);
if (NULL != g_pCPInfo)
{
hr = pEnumCP->Next(cNum, g_pCPInfo, &g_cCPInfo);
if (SUCCEEDED(hr))
{
g_pCPInfo = (PMIMECPINFO)LocalReAlloc(g_pCPInfo, sizeof(MIMECPINFO) * g_cCPInfo, LMEM_MOVEABLE);
}
else
{
LocalFree(g_pCPInfo);
g_pCPInfo = NULL;
}
#else
g_pCPInfoW = (PMIMECPINFO)LocalAlloc(LPTR, sizeof(MIMECPINFO) * cNum);
if (NULL != g_pCPInfoW)
{
hr = pEnumCP->Next(cNum, g_pCPInfoW, &g_cCPInfo);
if (SUCCEEDED(hr))
{
g_pCPInfo = (PMIMECPINFOA)LocalAlloc(LPTR, sizeof(MIMECPINFOA) * g_cCPInfo);
if (NULL != g_pCPInfo)
{
UINT i;
for (i = 0; i < g_cCPInfo; i++)
{
g_pCPInfo[i].dwFlags = g_pCPInfoW[i].dwFlags;
g_pCPInfo[i].uiCodePage = g_pCPInfoW[i].uiCodePage;
g_pCPInfo[i].uiFamilyCodePage = g_pCPInfoW[i].uiFamilyCodePage;
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszDescription, -1, g_pCPInfo[i].wszDescription, sizeof(g_pCPInfo[i].wszDescription), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszWebCharset, -1, g_pCPInfo[i].wszWebCharset, sizeof(g_pCPInfo[i].wszWebCharset), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszHeaderCharset, -1, g_pCPInfo[i].wszHeaderCharset, sizeof(g_pCPInfo[i].wszHeaderCharset), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszBodyCharset, -1, g_pCPInfo[i].wszBodyCharset, sizeof(g_pCPInfo[i].wszBodyCharset), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszFixedWidthFont, -1, g_pCPInfo[i].wszFixedWidthFont, sizeof(g_pCPInfo[i].wszFixedWidthFont), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, (WCHAR *)g_pCPInfoW[i].wszProportionalFont, -1, g_pCPInfo[i].wszProportionalFont, sizeof(g_pCPInfo[i].wszProportionalFont), NULL, NULL);
g_pCPInfo[i].bGDICharset = g_pCPInfoW[i].bGDICharset;
}
}
}
LocalFree(g_pCPInfoW);
g_pCPInfoW = NULL;
#endif
}
pEnumCP->Release();
}
if (bIsOE5)
pML2->Release();
else
pML->Release();
}
pCoUninitialize();
return TRUE;
}
//
// FreeMimeCsetTable()
//
// Free string buffer of MimeCharsetTable[]'s string field
//
void FreeMimeCsetTable(void)
{
if (NULL != g_pCPInfo)
{
LocalFree(g_pCPInfo);
g_pCPInfo = NULL;
g_cCPInfo = 0;
}
}
//
// EnumFontsProc()
//
// Selects only one font per style
//
int CALLBACK EnumFontsProc(
ENUMLOGFONTEX FAR* elf, // address of logical-font data
TEXTMETRIC FAR* tm, // address of physical-font data
DWORD dwFontType, // type of font
LPARAM lParam // address of application-defined data
)
{
LOGFONT FAR* lf;
LPFONTSDATA pFnt;
ASSERT(lParam);
ASSERT(elf);
pFnt = (LPFONTSDATA)lParam;
lf = &(elf->elfLogFont);
if ( dwFontType == DEVICE_FONTTYPE || dwFontType == RASTER_FONTTYPE )
return TRUE; // keep going but don't use this font
/* We don't use the SYMBOL fonts */
if( lf->lfCharSet == SYMBOL_CHARSET )
return TRUE;
// we don't handle Mac Charset
if (lf->lfCharSet == MAC_CHARSET )
return TRUE;
if ( IsVerticalFont(lf->lfFaceName) )
return TRUE; // keep going but don't use this font
if ( lf->lfPitchAndFamily & FIXED_PITCH )
{
if (CB_ERR == SendMessage(pFnt->hwndFixedCB, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)elf->elfLogFont.lfFaceName))
{
// add the font name to the combobox
SendMessage(pFnt->hwndFixedCB, CB_ADDSTRING, 0, (LPARAM)elf->elfLogFont.lfFaceName);
}
}
if (CB_ERR == SendMessage(pFnt->hwndPropCB, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)elf->elfLogFont.lfFaceName))
{
// add the font name to the combobox
SendMessage(pFnt->hwndPropCB, CB_ADDSTRING, 0, (LPARAM)elf->elfLogFont.lfFaceName);
}
return TRUE;
}
//
// FillFontComboBox()
//
// Fills hwndCB with the names of fonts of family dwCodePage.
//
BOOL FillFontComboBox(IN LPFONTSDATA pFnt, IN BYTE CodePage)
{
HDC hDC;
LOGFONT lf;
HWND hWnd;
BOOL fReturn = FALSE;
// get system font info
hWnd = GetTopWindow(GetDesktopWindow());
hDC = GetDC(hWnd);
if (hDC)
{
lf.lfFaceName[0] = 0;
lf.lfPitchAndFamily = 0;
lf.lfCharSet = CodePage;
EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)EnumFontsProc,
(LPARAM)pFnt, 0);
// everthing went fine
fReturn = TRUE;
}
ReleaseDC(hWnd, hDC);
return fReturn;
} // FillFontComboBox()
//
// FillSizeComboBox()
//
// Fills font size combobox with the size of fonts.
//
BOOL FillSizeComboBox(IN LPFONTSDATA pFnt)
{
int i;
for (i = IDS_FONT_SIZE_SMALLEST; i <= IDS_FONT_SIZE_LARGEST ; i++)
{
TCHAR szSize[MAX_MIMEFACE_NAME];
MLLoadString(i, szSize, sizeof(szSize));
SendMessage(pFnt->hwndSizeCB, CB_ADDSTRING, 0, (LPARAM)szSize);
}
return TRUE;
}
//
// FillCharsetComboBoxes()
//
// Fills the Fixed, Prop, and MIME comboboxes with the appropriate
// font data
//
BOOL FillCharsetComboBoxes(LPFONTSDATA pFnt, DWORD dwCodePage)
{
UINT i;
int iPageInfo = -1;
DWORD grfFlag;
// erase all the comboboxes to start fresh
SendMessage(pFnt->hwndPropCB, CB_RESETCONTENT, 0, 0);
SendMessage(pFnt->hwndFixedCB, CB_RESETCONTENT, 0, 0);
SendMessage(pFnt->hwndSizeCB, CB_RESETCONTENT, 0, 0);
SendMessage(pFnt->hwndMIMECB, CB_RESETCONTENT, 0, 0);
// What happens if other one calls OpenFontDialog except Athena?
grfFlag = StrCmpI(pFnt->lpszKeyPath, REGSTR_PATH_INTERNATIONAL)? MIMECONTF_MAILNEWS: MIMECONTF_BROWSER;
for(i=0; i < g_cCPInfo; i++)
{
// find the codepage in our table
if (g_pCPInfo[i].uiFamilyCodePage == (UINT)dwCodePage)
{
//
// populate MIME combobox
//
if (g_pCPInfo[i].uiCodePage == (UINT)dwCodePage)
iPageInfo = i; // we store info per family codepage here
// add mime type to combobox
if (grfFlag & g_pCPInfo[i].dwFlags)
{
// HACK: We need to remove Japanese JIS 1 Byte Kana and Korean for MAILNEWS.
// 949 : Korean. We are using Korean (Auto Detect) instead
// 50225 : Korean ISO
// 50221 : Japanese JIS 1 byte Kana-ESC
// 50222 : Japanese JIS 1 byte Kana-SIO
if (grfFlag & MIMECONTF_MAILNEWS)
{
if (g_pCPInfo[i].uiCodePage == 949 || g_pCPInfo[i].uiCodePage == 50221 || g_pCPInfo[i].uiCodePage == 50222 || g_pCPInfo[i].uiCodePage == 50225)
continue;
}
SendMessage(pFnt->hwndMIMECB, CB_ADDSTRING, 0, (LPARAM)g_pCPInfo[i].wszDescription);
}
} // if CodePage
} // for i
if (-1 != iPageInfo)
{
// if nothing is defined, then copy the first possible value that
// we know of from our table
if (!pFnt->page[iPageInfo].szMIMEFont[0])
{
if (grfFlag & g_pCPInfo[iPageInfo].dwFlags)
StrCpyN(pFnt->page[iPageInfo].szMIMEFont, g_pCPInfo[iPageInfo].wszDescription, ARRAYSIZE(pFnt->page[iPageInfo].szMIMEFont));
else
{
for (i = 0; i < g_cCPInfo; i++)
{
if (g_pCPInfo[iPageInfo].uiCodePage == g_pCPInfo[i].uiFamilyCodePage)
{
if (grfFlag & g_pCPInfo[i].dwFlags)
{
StrCpyN(pFnt->page[iPageInfo].szMIMEFont, g_pCPInfo[i].wszDescription, ARRAYSIZE(pFnt->page[iPageInfo].szMIMEFont));
break;
}
}
}
}
}
// select the current default
SendMessage(pFnt->hwndMIMECB, CB_SELECTSTRING, (WPARAM)-1,
(LPARAM)pFnt->page[iPageInfo].szMIMEFont);
// Enable/disable MIME is when there is only one possibility
EnableWindow(pFnt->hwndMIMECB, (1 < SendMessage(pFnt->hwndMIMECB, CB_GETCOUNT, 0, (LPARAM)0)) && !g_restrict.fFonts);
// Add fonts to combobox
FillFontComboBox(pFnt, g_pCPInfo[iPageInfo].bGDICharset);
#ifdef UNIX
/* We would have called EnumFontFamiliesEx wherein we would have
* have populated the fonts list boxes with substitute fonts if any
*
* So, before we populate the proportional and the fixed fonts below,
* we must query and use substitute fonts if avbl.
*/
{
CHAR szSubstFont[MAX_MIMEFACE_NAME+1];
DWORD cchSubstFont = MAX_MIMEFACE_NAME + 1;
CHAR szFont[MAX_MIMEFACE_NAME + 1];
WideCharToMultiByte(CP_ACP, 0, pFnt->page[iPageInfo].szPropFont, -1, szFont,
MAX_MIMEFACE_NAME + 1, NULL, NULL);
if ((ERROR_SUCCESS == MwGetSubstituteFont(szFont, szSubstFont, &cchSubstFont)) &&
cchSubstFont)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSubstFont, -1,
pFnt->page[iPageInfo].szPropFont, MAX_MIMEFACE_NAME + 1);
}
WideCharToMultiByte(CP_ACP, 0, pFnt->page[iPageInfo].szFixedFont, -1, szFont,
MAX_MIMEFACE_NAME + 1, NULL, NULL);
cchSubstFont = MAX_MIMEFACE_NAME + 1;
if ((ERROR_SUCCESS == MwGetSubstituteFont(szFont, szSubstFont, &cchSubstFont)) &&
cchSubstFont)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSubstFont, -1,
pFnt->page[iPageInfo].szFixedFont, MAX_MIMEFACE_NAME + 1);
}
}
#endif /* UNIX */
// select the current prop default
SendMessage(pFnt->hwndPropCB, CB_SELECTSTRING, (WPARAM)-1,
(LPARAM)pFnt->page[iPageInfo].szPropFont);
// select the current fixed default
SendMessage(pFnt->hwndFixedCB, CB_SELECTSTRING, (WPARAM)-1,
(LPARAM)pFnt->page[iPageInfo].szFixedFont);
// Add font sizes to combobox
FillSizeComboBox(pFnt);
// select the current size default
SendMessage(pFnt->hwndSizeCB, CB_SETCURSEL, (WPARAM)pFnt->page[iPageInfo].dwFontSize, (LPARAM)0);
// we handled it
return TRUE;
}
return FALSE;
} // FillCharsetComboBoxes()
//
// FontsDlgInit()
//
// Initializes the Fonts dialog.
//
BOOL FontsDlgInit(IN HWND hDlg, LPCTSTR lpszKeyPath)
{
HKEY hkey;
DWORD grfFlag;
DWORD dw;
DWORD cb;
DWORD i;
BOOL bIsOE5 = FALSE;
TCHAR szKey[1024];
LPFONTSDATA pFnt; // localize data
if (!hDlg)
return FALSE; // nothing to initialize
// set system default character set where we possibly show
// the strings in native language.
SHSetDefaultDialogFont(hDlg, IDC_FONTS_PROP_FONT_COMBO);
SHSetDefaultDialogFont(hDlg, IDC_FONTS_FIXED_FONT_COMBO);
SHSetDefaultDialogFont(hDlg, IDC_FONTS_MIME_FONT_COMBO);
SHSetDefaultDialogFont(hDlg, IDC_FONTS_DEFAULT_LANG_TEXT);
SHSetDefaultDialogFont(hDlg, IDC_FONTS_CODE_PAGES_LIST);
// get some space to store local data
// NOTE: LocalAlloc already zeroes the memory
pFnt = (LPFONTSDATA)LocalAlloc(LPTR, sizeof(*pFnt));
if (!pFnt)
{
EndDialog(hDlg, 0);
return FALSE;
}
// We distinguish OE5 and OE4 by searching for "5.0" in its registry path,
// It works as long as there is no spec. change in OE5
if (NULL != StrStr(lpszKeyPath, TEXT("5.0")))
bIsOE5 = TRUE;
if (!InitMimeCsetTable(bIsOE5))
{
EndDialog(hDlg, 0);
return FALSE;
}
if (NULL == pFnt->page)
{
pFnt->page = (CODEPAGEDATA*)LocalAlloc(LPTR, sizeof(CODEPAGEDATA) * g_cCPInfo);
if (NULL == pFnt->page)
{
EndDialog(hDlg, 0);
return FALSE;
}
}
// associate the memory with the dialog window
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pFnt);
// save the dialog handle
pFnt->hDlg = hDlg;
// get the dialog items
pFnt->hwndPropCB = GetDlgItem(pFnt->hDlg, IDC_FONTS_PROP_FONT_COMBO);
pFnt->hwndFixedCB = GetDlgItem(pFnt->hDlg, IDC_FONTS_FIXED_FONT_COMBO);
pFnt->hwndSizeCB = GetDlgItem(pFnt->hDlg, IDC_FONTS_SIZE_FONT_COMBO);
pFnt->hwndMIMECB = GetDlgItem(pFnt->hDlg, IDC_FONTS_MIME_FONT_COMBO);
pFnt->hwndNamesLB = GetDlgItem(pFnt->hDlg, IDC_FONTS_CODE_PAGES_LIST);
pFnt->lpszKeyPath = lpszKeyPath ? lpszKeyPath: REGSTR_PATH_INTERNATIONAL;
pFnt->dwDefaultCodePage = GetACP();
// get values from registry
if (RegOpenKeyEx(HKEY_CURRENT_USER, pFnt->lpszKeyPath, NULL, KEY_READ, &hkey)
== ERROR_SUCCESS)
{
cb = sizeof(dw);
if (RegQueryValueEx(hkey, REGSTR_VAL_DEFAULT_CODEPAGE, NULL, NULL, (LPBYTE)&dw, &cb)
== ERROR_SUCCESS)
{
pFnt->dwDefaultCodePage = dw;
}
RegCloseKey(hkey);
}
// What happens if other one calls OpenFontDialog except Athena?
grfFlag = StrCmpI(pFnt->lpszKeyPath, REGSTR_PATH_INTERNATIONAL)? MIMECONTF_MAILNEWS: MIMECONTF_BROWSER;
for (i = 0; i < g_cCPInfo; i++)
{
if (g_pCPInfo[i].uiCodePage == g_pCPInfo[i].uiFamilyCodePage)
{
int iDef;
UINT j;
iDef = -1;
if (0 == (grfFlag & g_pCPInfo[i].dwFlags))
{
for (j = 0; j < g_cCPInfo; j++)
{
if (g_pCPInfo[i].uiCodePage == g_pCPInfo[j].uiFamilyCodePage)
{
if (grfFlag & g_pCPInfo[j].dwFlags)
{
iDef = j;
break;
}
}
}
if (-1 == iDef)
continue;
}
if (g_pCPInfo[i].uiCodePage == 50001) // skip CP_AUTO
continue;
wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("%s\\%u"), pFnt->lpszKeyPath, g_pCPInfo[i].uiCodePage);
if (RegOpenKeyEx(HKEY_CURRENT_USER, szKey, NULL, KEY_READ, &hkey) == ERROR_SUCCESS)
{
cb = sizeof(pFnt->page[i].szFriendlyName);
if (RegQueryValueEx(hkey, REGSTR_VAL_FONT_SCRIPT, NULL, NULL,
(LPBYTE)&pFnt->page[i].szFriendlyName, &cb)
!= ERROR_SUCCESS)
{
TCHAR *p;
StrCpyN(pFnt->page[i].szFriendlyName, g_pCPInfo[i].wszDescription, ARRAYSIZE(pFnt->page[i].szFriendlyName));
for (p = pFnt->page[i].szFriendlyName; *p != TEXT('\0'); p = CharNext(p))
{
// We'd better have a source of this string else where.
if (*p == TEXT('('))
{
*p = TEXT('\0');
break;
}
}
}
cb = sizeof(dw);
if (RegQueryValueEx(hkey, REGSTR_VAL_DEF_INETENCODING, NULL, NULL, (LPBYTE)&dw, &cb)
!= ERROR_SUCCESS)
{
dw = (DWORD)g_pCPInfo[i].uiCodePage;
// HACK ! It's only for Japanese Auto Select as Japanese default.
if (dw == 932) // 932 : Japanese Windows CodePage
dw = 50932; // 50932 : Japanese Auto Select InternetEncoding
}
for (j = 0; j < g_cCPInfo; j++)
{
if (g_pCPInfo[j].uiCodePage == (UINT)dw)
{
if (grfFlag & g_pCPInfo[j].dwFlags)
StrCpyN(pFnt->page[i].szMIMEFont, g_pCPInfo[j].wszDescription, ARRAYSIZE(pFnt->page[i].szMIMEFont));
else if (-1 != iDef)
StrCpyN(pFnt->page[i].szMIMEFont, g_pCPInfo[iDef].wszDescription, ARRAYSIZE(pFnt->page[i].szMIMEFont));
else
pFnt->page[i].szMIMEFont[0] = TEXT('\0');
break;
}
}
cb = sizeof(pFnt->page[i].szFixedFont);
if (RegQueryValueEx(hkey, REGSTR_VAL_FIXED_FONT, NULL, NULL,
(LPBYTE)pFnt->page[i].szFixedFont, &cb)
!= ERROR_SUCCESS)
{
StrCpyN(pFnt->page[i].szFixedFont, g_pCPInfo[i].wszFixedWidthFont, ARRAYSIZE(pFnt->page[i].szFixedFont));
}
cb = sizeof(pFnt->page[i].szPropFont);
if (RegQueryValueEx(hkey, REGSTR_VAL_PROP_FONT, NULL, NULL,
(LPBYTE)pFnt->page[i].szPropFont, &cb)
!= ERROR_SUCCESS)
{
StrCpyN(pFnt->page[i].szPropFont, g_pCPInfo[i].wszProportionalFont, ARRAYSIZE(pFnt->page[i].szPropFont));
}
cb = sizeof(pFnt->page[i].dwFontSize);
if (RegQueryValueEx(hkey, REGSTR_VAL_FONT_SIZE, NULL, NULL,
(LPBYTE)&pFnt->page[i].dwFontSize, &cb)
!= ERROR_SUCCESS)
{
pFnt->page[i].dwFontSize = REGSTR_VAL_FONT_SIZE_DEF;
}
RegCloseKey(hkey);
}
else
{
UINT j;
TCHAR *p;
StrCpyN(pFnt->page[i].szFriendlyName, g_pCPInfo[i].wszDescription, ARRAYSIZE(pFnt->page[i].szFriendlyName));
for (p = pFnt->page[i].szFriendlyName; *p != TEXT('\0'); p = CharNext(p))
{
if (*p == TEXT('('))
{
*p = TEXT('\0');
break;
}
}
j = (grfFlag & g_pCPInfo[i].dwFlags)? i: iDef;
// HACK ! It's only for Japanese Auto Select as Japanese default.
if (g_pCPInfo[j].uiCodePage == 932) // 932 : Japanese Windows CodePage
{
for (j = 0; j < g_cCPInfo; j++)
{
if (g_pCPInfo[j].uiCodePage == 50932) // 50932 : Japanese Auto Select InternetEncoding
break;
}
}
StrCpyN(pFnt->page[i].szMIMEFont, g_pCPInfo[j].wszDescription, ARRAYSIZE(pFnt->page[i].szMIMEFont));
StrCpyN(pFnt->page[i].szFixedFont, g_pCPInfo[i].wszFixedWidthFont, ARRAYSIZE(pFnt->page[i].szFixedFont));
StrCpyN(pFnt->page[i].szPropFont, g_pCPInfo[i].wszProportionalFont, ARRAYSIZE(pFnt->page[i].szPropFont));
pFnt->page[i].dwFontSize = REGSTR_VAL_FONT_SIZE_DEF;
}
// add the name to the listbox
SendMessage(pFnt->hwndNamesLB, LB_ADDSTRING, 0, (LPARAM)pFnt->page[i].szFriendlyName);
// check to see if it is the default code page
if (pFnt->dwDefaultCodePage == g_pCPInfo[i].uiCodePage)
{
if (LB_ERR == SendMessage(pFnt->hwndNamesLB, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)pFnt->page[i].szFriendlyName))
{
// Hack shlwapi problems for Win9x.
CHAR szAnsiString[1024] = {0};
WideCharToMultiByte(CP_ACP, 0, pFnt->page[i].szFriendlyName, -1, szAnsiString, 1024, NULL, NULL);
SendMessageA(pFnt->hwndNamesLB, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)szAnsiString);
}
SetDlgItemText(pFnt->hDlg, IDC_FONTS_DEFAULT_LANG_TEXT, pFnt->page[i].szFriendlyName);
}
}
}
FillCharsetComboBoxes(pFnt, pFnt->dwDefaultCodePage);
pFnt->bChanged = FALSE;
if( g_restrict.fFonts )
{
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_PROP_FONT_COMBO ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_FIXED_FONT_COMBO ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_SIZE_FONT_COMBO ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_MIME_FONT_COMBO ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_CODE_PAGES_LIST ), FALSE);
EnableWindow( GetDlgItem( hDlg, IDC_FONTS_SETDEFAULT_BUTTON ), FALSE);
}
// everything ok
return TRUE;
} // FontsDlgInit()
//
// SaveFontsData()
//
// Save the new fonts settings into regestry
//
void SaveFontsData(LPFONTSDATA pFnt)
{
HKEY hkeyCodePage;
TCHAR szCodePage [MAX_MIMEFACE_NAME];
HKEY hkey;
DWORD dw;
// get values from registry
if (RegCreateKeyEx(HKEY_CURRENT_USER, pFnt->lpszKeyPath, NULL, NULL, NULL, KEY_WRITE, NULL, &hkey, &dw)
== ERROR_SUCCESS)
{
UINT i;
RegSetValueEx(hkey, REGSTR_VAL_DEFAULT_CODEPAGE, NULL, REG_BINARY, (LPBYTE)&pFnt->dwDefaultCodePage, sizeof(pFnt->dwDefaultCodePage));
for(i = 0; i < g_cCPInfo; i++)
{
if (g_pCPInfo[i].uiCodePage == g_pCPInfo[i].uiFamilyCodePage)
{
wnsprintf(szCodePage, ARRAYSIZE(szCodePage), TEXT("%u"), g_pCPInfo[i].uiCodePage);
if (RegCreateKeyEx(hkey, szCodePage, NULL, NULL, NULL, KEY_WRITE, NULL, &hkeyCodePage, &dw) == ERROR_SUCCESS)
{
UINT j;
RegSetValueEx(hkeyCodePage, REGSTR_VAL_FONT_SCRIPT, NULL, REG_SZ,
(LPBYTE)&pFnt->page[i].szFriendlyName,
(lstrlen(pFnt->page[i].szFriendlyName)+1)*sizeof(TCHAR));
for (j = 0; j < g_cCPInfo; j++)
{
if (!StrCmpI(g_pCPInfo[j].wszDescription, pFnt->page[i].szMIMEFont))
{
dw = g_pCPInfo[j].uiCodePage;
break;
}
}
RegSetValueEx(hkeyCodePage, REGSTR_VAL_DEF_INETENCODING, NULL, REG_BINARY,
(LPBYTE)&dw, sizeof(dw));
RegSetValueEx(hkeyCodePage, REGSTR_VAL_FIXED_FONT, NULL, REG_SZ,
(LPBYTE)pFnt->page[i].szFixedFont,
(lstrlen(pFnt->page[i].szFixedFont)+1)*sizeof(TCHAR));
RegSetValueEx(hkeyCodePage, REGSTR_VAL_PROP_FONT, NULL, REG_SZ,
(LPBYTE)pFnt->page[i].szPropFont,
(lstrlen(pFnt->page[i].szPropFont)+1)*sizeof(TCHAR));
RegSetValueEx(hkeyCodePage, REGSTR_VAL_FONT_SIZE, NULL, REG_BINARY,
(LPBYTE)&pFnt->page[i].dwFontSize,
sizeof(pFnt->page[i].dwFontSize));
RegCloseKey(hkeyCodePage);
} // if RegCreateKeyEx
} // if uiCodePage == uiFamilyCodePage
} // for
RegCloseKey(hkey);
} // if RegCreateKeyEx
} // SaveFontsData()
//
// FontsOnCommand()
//
// Handles WM_COMMAN Dmessage for the Fonts subdialog
//
BOOL FontsOnCommand(LPFONTSDATA pFnt, UINT id, UINT nCmd)
{
switch(id)
{
case IDOK:
if (pFnt->bChanged)
{
SaveFontsData(pFnt);
// tell MSHTML to pick up changes and update
UpdateAllWindows();
}
return TRUE; // exit dialog
case IDCANCEL:
return TRUE; // exit dialog
case IDC_FONTS_MIME_FONT_COMBO:
if (nCmd==CBN_SELCHANGE)
{
g_fChangedMime = TRUE; // tell MSHTML that the Mime has changed
}
// fall thru...
case IDC_FONTS_PROP_FONT_COMBO:
case IDC_FONTS_FIXED_FONT_COMBO:
case IDC_FONTS_SIZE_FONT_COMBO:
if (nCmd==CBN_SELCHANGE)
{
UINT i;
TCHAR szCodePage[MAX_MIMECP_NAME];
pFnt->bChanged = TRUE; // we need to save
// find the currently selected item in the list box
INT_PTR itmp = SendMessage(pFnt->hwndNamesLB, LB_GETCURSEL, 0, 0);
SendMessage(pFnt->hwndNamesLB, LB_GETTEXT, itmp, (LPARAM)szCodePage);
// find the code page from the text
for(i=0; i < g_cCPInfo; i++)
{
if (!StrCmpI(szCodePage, pFnt->page[i].szFriendlyName))
{
// grab the new values
GetDlgItemText(pFnt->hDlg, IDC_FONTS_PROP_FONT_COMBO,
pFnt->page[i].szPropFont, ARRAYSIZE(pFnt->page[i].szPropFont));
GetDlgItemText(pFnt->hDlg, IDC_FONTS_FIXED_FONT_COMBO,
pFnt->page[i].szFixedFont, ARRAYSIZE(pFnt->page[i].szFixedFont));
pFnt->page[i].dwFontSize = (int) SendMessage(pFnt->hwndSizeCB, CB_GETCURSEL, 0, 0);
GetDlgItemText(pFnt->hDlg, IDC_FONTS_MIME_FONT_COMBO,
pFnt->page[i].szMIMEFont, ARRAYSIZE(pFnt->page[i].szMIMEFont));
break;
}
}
// if we don't find it... we are going to keep the default
ASSERT(i < g_cCPInfo); // something went wrong
}
break;
case IDC_FONTS_SETDEFAULT_BUTTON:
{
UINT i;
TCHAR szCodePage[MAX_MIMECP_NAME];
pFnt->bChanged = TRUE; // we need to save
// get the newly selected charset
INT_PTR itmp = SendMessage(pFnt->hwndNamesLB, LB_GETCURSEL, 0, 0);
SendMessage(pFnt->hwndNamesLB, LB_GETTEXT, itmp, (LPARAM)szCodePage);
// set the newly selected charset text
SetDlgItemText(pFnt->hDlg, IDC_FONTS_DEFAULT_LANG_TEXT, szCodePage);
// find the code page from the text
for (i = 0; i < g_cCPInfo; i++)
{
if (!StrCmpI(szCodePage, pFnt->page[i].szFriendlyName))
{
pFnt->dwDefaultCodePage = g_pCPInfo[i].uiFamilyCodePage;
g_fChangedMime = TRUE;
break;
}
}
// if we don't find it... we are going to keep the default
ASSERT(i < g_cCPInfo); // something went wrong
}
break;
case IDC_FONTS_CODE_PAGES_LIST:
if (nCmd==LBN_SELCHANGE)
{
UINT i;
TCHAR szCodePage[MAX_MIMECP_NAME];
INT_PTR itmp = SendMessage(pFnt->hwndNamesLB, LB_GETCURSEL, 0, 0);
SendMessage(pFnt->hwndNamesLB, LB_GETTEXT, itmp, (LPARAM)szCodePage);
// find the code page from the text
for(i=0; i < g_cCPInfo; i++)
{
if (!StrCmpI(szCodePage, pFnt->page[i].szFriendlyName))
{
FillCharsetComboBoxes(pFnt, g_pCPInfo[i].uiFamilyCodePage);
break;
}
}
}
break;
}
// don't exit dialog
return FALSE;
}
//
// FontsDlgProc()
//
// Message handler for the "Fonts" subdialog.
//
INT_PTR CALLBACK FontsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPFONTSDATA pFnt = (LPFONTSDATA) GetWindowLongPtr(hDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
return FontsDlgInit(hDlg, (LPTSTR)lParam);
case WM_DESTROY:
// give back the memory
FreeMimeCsetTable();
// destroy font if we created
SHRemoveDefaultDialogFont(hDlg);
if (pFnt)
{
if (pFnt->page)
LocalFree(pFnt->page);
LocalFree(pFnt);
}
break;
case WM_COMMAND:
if (FontsOnCommand(pFnt, LOWORD(wParam), HIWORD(wParam)))
EndDialog(hDlg, LOWORD(wParam) == IDOK? 1: 0);
break;
case WM_HELP: // F1
ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
break;
case WM_CONTEXTMENU: // right mouse click
ResWinHelp( (HWND) wParam, IDS_HELPFILE,
HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
break;
default:
return FALSE;
}
return TRUE;
}
//
// EXTERNAL API
//
STDAPI_(INT_PTR) OpenFontsDialog(HWND hDlg, LPCSTR lpszKeyPath)
{
#ifdef UNICODE
WCHAR wszKeyPath[1024];
MultiByteToWideChar(CP_ACP, 0, (char *)lpszKeyPath, -1, wszKeyPath, ARRAYSIZE(wszKeyPath));
return DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_FONTS_IE4), hDlg, FontsDlgProc, (LPARAM) wszKeyPath);
#else
return DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_FONTS_IE4), hDlg, FontsDlgProc, (LPARAM) lpszKeyPath);
#endif // UNICODE
}
// provide script based font dialog
STDAPI_(INT_PTR) OpenFontsDialogEx(HWND hDlg, LPCTSTR lpszKeyPath)
{
INT_PTR nRet = -1;
HRESULT hr;
BOOL fOLEPresent;
if (hOLE32 != NULL)
{
fOLEPresent = TRUE;
}
else
{
fOLEPresent = _StartOLE32();
}
ASSERT(fOLEPresent);
if (fOLEPresent)
{
ASSERT(IS_VALID_HANDLE(hOLE32, MODULE));
ASSERT(IS_VALID_CODE_PTR(pCoInitialize, PCOINIT));
hr = pCoInitialize(NULL);
if (SUCCEEDED(hr))
{
nRet = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_FONTS), hDlg, FontsDlgProcEx, (LPARAM) lpszKeyPath);
}
}
// Release interface
if (g_pMLFlnk2)
{
g_pMLFlnk2->Release();
g_pMLFlnk2 = NULL;
}
ASSERT(IS_VALID_CODE_PTR(pCoUninitialize, PCOUNIT));
pCoUninitialize();
return nRet;
}