mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
5d3915d0fc
CORE-12451, CORE-17601, CORE-17803 Replaces PR #4281. When changing the console output code page, check whether the current font can support it. If not, try to find a suitable font for the new code page. If none can be found: - if we are creating a new console, forcefully switch to codepage 437 (OEM USA) and retry finding a font, falling back to "Terminal" if none could be found; - if we were just changing the current CP, just fail and keep the old code page and font. Rework the console font selection/creation functions for this new job (see CreateConsoleFontEx() and friends). Elements of implementation based from https://github.com/microsoft/terminal ; see code for more information. Silence the noisy IsValidConsoleFont2() diagnostic messages. Add Doxygen documentation. [CONSOLE.CPL] Only add "Terminal" to the enumerated list of faces + add a TODO implementation comment.
953 lines
30 KiB
C
953 lines
30 KiB
C
/*
|
|
* PROJECT: ReactOS Console Configuration DLL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/cpl/console/font.c
|
|
* PURPOSE: Font dialog
|
|
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
|
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
*/
|
|
|
|
#include "console.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
/*
|
|
* Current active font, corresponding to the active console font,
|
|
* and used for painting the text samples.
|
|
*/
|
|
FONT_PREVIEW FontPreview = {NULL, 0, 0};
|
|
|
|
|
|
/*
|
|
* Standard font pixel/point heights for TrueType fonts
|
|
*/
|
|
static const SHORT TrueTypePoints[] =
|
|
{
|
|
5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
|
|
};
|
|
|
|
typedef struct _FONTSIZE_LIST_CTL
|
|
{
|
|
LIST_CTL RasterSizeList; // ListBox for Raster font sizes; needs to handle bisection.
|
|
HWND hWndTTSizeList; // ComboBox for TrueType font sizes.
|
|
BOOL bIsTTSizeDirty; // TRUE or FALSE depending on whether we have edited the edit zone.
|
|
BOOL UseRasterOrTTList; // TRUE: Use the Raster size list; FALSE: Use the TrueType size list.
|
|
BOOL TTSizePixelUnit; // TRUE: Size in pixels (default); FALSE: Size in points.
|
|
LONG CurrentRasterSize;
|
|
LONG CurrentTTSize; // In whatever unit (pixels or points) currently selected.
|
|
} FONTSIZE_LIST_CTL, *PFONTSIZE_LIST_CTL;
|
|
|
|
/* Used by FontTypeChange() only */
|
|
static INT CurrentSelFont = LB_ERR;
|
|
static DWORD CurrentFontType = (DWORD)-1; // Invalid font type
|
|
|
|
/* Detect whether the current code page has changed */
|
|
static UINT CurrentCodePage = INVALID_CP;
|
|
|
|
|
|
VOID
|
|
RefreshFontPreview(
|
|
IN FONT_PREVIEW* Preview,
|
|
IN PCONSOLE_STATE_INFO pConInfo)
|
|
{
|
|
HFONT hFont = CreateConsoleFont(pConInfo);
|
|
if (!hFont)
|
|
{
|
|
DPRINT1("RefreshFontPreview: CreateConsoleFont() failed\n");
|
|
return;
|
|
}
|
|
|
|
if (Preview->hFont) DeleteObject(Preview->hFont);
|
|
Preview->hFont = hFont;
|
|
GetFontCellSize(NULL, hFont, &Preview->CharHeight, &Preview->CharWidth);
|
|
}
|
|
|
|
VOID
|
|
UpdateFontPreview(
|
|
IN FONT_PREVIEW* Preview,
|
|
IN HFONT hFont,
|
|
IN UINT CharWidth,
|
|
IN UINT CharHeight)
|
|
{
|
|
if (Preview->hFont) DeleteObject(Preview->hFont);
|
|
Preview->hFont = hFont;
|
|
Preview->CharWidth = CharWidth;
|
|
Preview->CharHeight = CharHeight;
|
|
}
|
|
|
|
// PLIST_GETCOUNT
|
|
static INT
|
|
RasterSizeList_GetCount(
|
|
IN PLIST_CTL ListCtl)
|
|
{
|
|
return (INT)SendMessageW(ListCtl->hWndList, LB_GETCOUNT, 0, 0);
|
|
}
|
|
|
|
// PLIST_GETDATA
|
|
static ULONG_PTR
|
|
RasterSizeList_GetData(
|
|
IN PLIST_CTL ListCtl,
|
|
IN INT Index)
|
|
{
|
|
return (ULONG_PTR)SendMessageW(ListCtl->hWndList, LB_GETITEMDATA, (WPARAM)Index, 0);
|
|
}
|
|
|
|
|
|
INT
|
|
LogicalSizeToPointSize(
|
|
IN HDC hDC OPTIONAL,
|
|
IN UINT LogicalSize)
|
|
{
|
|
INT PointSize;
|
|
HDC hOrgDC = hDC;
|
|
|
|
if (!hDC)
|
|
hDC = GetDC(NULL);
|
|
|
|
// LogicalSize = tm.tmHeight - tm.tmInternalLeading;
|
|
PointSize = MulDiv(LogicalSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
|
|
|
|
if (!hOrgDC)
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
return PointSize;
|
|
}
|
|
|
|
INT
|
|
PointSizeToLogicalSize(
|
|
IN HDC hDC OPTIONAL,
|
|
IN INT PointSize)
|
|
{
|
|
INT LogicalSize;
|
|
HDC hOrgDC = hDC;
|
|
|
|
if (!hDC)
|
|
hDC = GetDC(NULL);
|
|
|
|
LogicalSize = MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
|
|
|
|
if (!hOrgDC)
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
return LogicalSize;
|
|
}
|
|
|
|
|
|
static VOID
|
|
FontSizeList_SelectFontSize(
|
|
IN PFONTSIZE_LIST_CTL SizeList,
|
|
IN ULONG FontSize)
|
|
{
|
|
INT nSel;
|
|
WCHAR szFontSize[100];
|
|
|
|
//
|
|
// FIXME: Check whether FontSize == 0
|
|
// (or in the case of raster font maybe, whether HIWORD(FontSize) == Height == 0) ??
|
|
//
|
|
|
|
/* Find and select the best font size in the list corresponding to the current size */
|
|
if (SizeList->UseRasterOrTTList)
|
|
{
|
|
INT idx;
|
|
|
|
/* Raster font size (in pixels) */
|
|
SizeList->CurrentRasterSize = FontSize;
|
|
|
|
nSel = BisectListSortedByValue(&SizeList->RasterSizeList, FontSize, NULL, FALSE);
|
|
idx = (INT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_GETCOUNT, 0, 0);
|
|
if (nSel == LB_ERR)
|
|
{
|
|
/* Not found, select the first element of the list */
|
|
nSel = 0;
|
|
}
|
|
else if (nSel >= idx)
|
|
{
|
|
/*
|
|
* We got an index beyond the end of the list (as per Bisect* functionality),
|
|
* so instead, select the last element of the list.
|
|
*/
|
|
nSel = idx - 1;
|
|
}
|
|
SendMessageW(SizeList->RasterSizeList.hWndList, LB_SETCURSEL, (WPARAM)nSel, 0);
|
|
}
|
|
else
|
|
{
|
|
/* TrueType font size (in pixels or points) */
|
|
SizeList->CurrentTTSize = FontSize;
|
|
|
|
// _ultow(szFontSize, FontSize, 10);
|
|
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", FontSize);
|
|
|
|
/* Find the font size in the list, or add it both in the ComboBox list, sorted by size value (string), and its edit box */
|
|
nSel = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
|
|
if (nSel == CB_ERR)
|
|
{
|
|
nSel = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_ADDSTRING, -1, (LPARAM)szFontSize);
|
|
// ComboBox_SetText(...)
|
|
SetWindowTextW(SizeList->hWndTTSizeList, szFontSize);
|
|
SizeList->bIsTTSizeDirty = TRUE;
|
|
}
|
|
SendMessageW(SizeList->hWndTTSizeList, CB_SETCURSEL, (WPARAM)nSel, 0);
|
|
}
|
|
}
|
|
|
|
static LONG
|
|
FontSizeList_GetSelectedFontSize(
|
|
IN PFONTSIZE_LIST_CTL SizeList)
|
|
{
|
|
INT nSel;
|
|
LONG FontSize;
|
|
PWCHAR pszNext = NULL;
|
|
WCHAR szFontSize[100];
|
|
|
|
if (SizeList->UseRasterOrTTList)
|
|
{
|
|
/* Raster font size (in pixels) */
|
|
|
|
nSel = (INT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_GETCURSEL, 0, 0);
|
|
if (nSel == LB_ERR) return 0;
|
|
|
|
FontSize = (LONG)SizeList->RasterSizeList.GetData(&SizeList->RasterSizeList, nSel);
|
|
if (FontSize == LB_ERR) return 0;
|
|
|
|
SizeList->CurrentRasterSize = FontSize;
|
|
}
|
|
else
|
|
{
|
|
/* TrueType font size (in pixels or points) */
|
|
|
|
if (!SizeList->bIsTTSizeDirty)
|
|
{
|
|
/*
|
|
* The user just selected an existing size, read the ComboBox selection.
|
|
*
|
|
* See: https://support.microsoft.com/en-us/help/66365/how-to-process-a-cbn-selchange-notification-message
|
|
* for more details.
|
|
*/
|
|
INT Length;
|
|
|
|
nSel = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_GETCURSEL, 0, 0);
|
|
if (nSel == CB_ERR) return 0;
|
|
|
|
Length = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_GETLBTEXTLEN, nSel, 0);
|
|
ASSERT((Length != LB_ERR) && (Length < ARRAYSIZE(szFontSize)));
|
|
|
|
Length = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_GETLBTEXT, nSel, (LPARAM)szFontSize);
|
|
ASSERT((Length != LB_ERR) && (Length < ARRAYSIZE(szFontSize)));
|
|
szFontSize[Length] = L'\0';
|
|
|
|
/* Validate the font size */
|
|
FontSize = wcstoul(szFontSize, &pszNext, 10);
|
|
if ((FontSize == 0) || (*pszNext))
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
/* Read the ComboBox edit string, as the user has entered a custom size */
|
|
// ComboBox_GetText(...)
|
|
GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
|
|
|
|
/* Validate the font size */
|
|
FontSize = wcstoul(szFontSize, &pszNext, 10);
|
|
if ((FontSize == 0) || (*pszNext))
|
|
return 0;
|
|
|
|
/* Find if the font size already exists in the list; if not, add it */
|
|
nSel = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
|
|
if (nSel == CB_ERR)
|
|
{
|
|
nSel = (INT)SendMessageW(SizeList->hWndTTSizeList, CB_ADDSTRING, -1, (LPARAM)szFontSize);
|
|
//// ComboBox_SetText(...)
|
|
//SetWindowTextW(SizeList->hWndTTSizeList, szFontSize);
|
|
//SizeList->bIsTTSizeDirty = TRUE;
|
|
}
|
|
SendMessageW(SizeList->hWndTTSizeList, CB_SETCURSEL, (WPARAM)nSel, 0);
|
|
}
|
|
|
|
SizeList->bIsTTSizeDirty = FALSE;
|
|
|
|
SizeList->CurrentTTSize = FontSize;
|
|
|
|
/*
|
|
* If the font size is given in points, instead of pixels,
|
|
* convert it into logical size.
|
|
*/
|
|
if (!SizeList->TTSizePixelUnit)
|
|
FontSize = -PointSizeToLogicalSize(NULL, FontSize);
|
|
}
|
|
|
|
return FontSize;
|
|
}
|
|
|
|
|
|
static VOID
|
|
AddFontToList(
|
|
IN HWND hWndList,
|
|
IN LPCWSTR pszFaceName,
|
|
IN DWORD FontType)
|
|
{
|
|
INT iItem;
|
|
|
|
/* Make sure the font doesn't already exist in the list */
|
|
if (SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)pszFaceName) != LB_ERR)
|
|
return;
|
|
|
|
/* Add the font */
|
|
iItem = (INT)SendMessageW(hWndList, LB_ADDSTRING, 0, (LPARAM)pszFaceName);
|
|
if (iItem == LB_ERR)
|
|
{
|
|
DPRINT1("Failed to add font '%S'\n", pszFaceName);
|
|
return;
|
|
}
|
|
|
|
DPRINT1("Add font '%S'\n", pszFaceName);
|
|
|
|
/* Store this information in the list-item's userdata area */
|
|
// SendMessageW(hWndList, LB_SETITEMDATA, idx, MAKELPARAM(fFixed, fTrueType));
|
|
SendMessageW(hWndList, LB_SETITEMDATA, iItem, (LPARAM)FontType);
|
|
}
|
|
|
|
typedef struct _FACE_NAMES_PROC_PARAM
|
|
{
|
|
HWND hWndList;
|
|
UINT CodePage;
|
|
} FACE_NAMES_PROC_PARAM, *PFACE_NAMES_PROC_PARAM;
|
|
|
|
static BOOL CALLBACK
|
|
EnumFaceNamesProc(
|
|
IN PLOGFONTW lplf,
|
|
IN PNEWTEXTMETRICW lpntm,
|
|
IN DWORD FontType,
|
|
IN LPARAM lParam)
|
|
{
|
|
PFACE_NAMES_PROC_PARAM Param = (PFACE_NAMES_PROC_PARAM)lParam;
|
|
|
|
if (IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
|
|
{
|
|
/* Add the face name to the list */
|
|
AddFontToList(Param->hWndList, lplf->lfFaceName, FontType);
|
|
}
|
|
|
|
/* Continue enumerating the faces */
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK
|
|
EnumFontSizesProc(
|
|
IN PLOGFONTW lplf,
|
|
IN PNEWTEXTMETRICW lpntm,
|
|
IN DWORD FontType,
|
|
IN LPARAM lParam)
|
|
{
|
|
PFONTSIZE_LIST_CTL SizeList = (PFONTSIZE_LIST_CTL)lParam;
|
|
UINT iItem, iDupItem;
|
|
WCHAR szFontSize[100];
|
|
|
|
if (FontType != TRUETYPE_FONTTYPE)
|
|
{
|
|
WPARAM FontSize;
|
|
|
|
/*
|
|
* Format:
|
|
* Width = FontSize.X = LOWORD(FontSize);
|
|
* Height = FontSize.Y = HIWORD(FontSize);
|
|
*/
|
|
|
|
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d x %d", lplf->lfWidth, lplf->lfHeight);
|
|
FontSize = MAKEWPARAM(lplf->lfWidth, lplf->lfHeight);
|
|
|
|
/* Add the font size into the list, sorted by size value. Avoid any duplicates. */
|
|
/* Store this information in the list-item's userdata area */
|
|
iDupItem = LB_ERR;
|
|
iItem = BisectListSortedByValue(&SizeList->RasterSizeList, FontSize, &iDupItem, TRUE);
|
|
if (iItem == LB_ERR)
|
|
iItem = 0;
|
|
if (iDupItem == LB_ERR)
|
|
{
|
|
iItem = (UINT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_INSERTSTRING, iItem, (LPARAM)szFontSize);
|
|
if (iItem != LB_ERR && iItem != LB_ERRSPACE)
|
|
iItem = SendMessageW(SizeList->RasterSizeList.hWndList, LB_SETITEMDATA, iItem, FontSize);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* TrueType or vectored font: list all the hardcoded font points */
|
|
ULONG i;
|
|
for (i = 0; i < ARRAYSIZE(TrueTypePoints); ++i)
|
|
{
|
|
// _ultow(szFontSize, TrueTypePoints[i], 10);
|
|
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", TrueTypePoints[i]);
|
|
|
|
/* Add the font size into the list, sorted by size value (string). Avoid any duplicates. */
|
|
if (SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize) == CB_ERR)
|
|
iItem = (UINT)SendMessageW(SizeList->hWndTTSizeList, CB_INSERTSTRING, -1, (LPARAM)szFontSize);
|
|
}
|
|
|
|
/* Stop the enumeration now */
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
FaceNameList_Initialize(
|
|
IN HWND hWndList,
|
|
IN UINT CodePage)
|
|
{
|
|
FACE_NAMES_PROC_PARAM Param;
|
|
HDC hDC;
|
|
LOGFONTW lf;
|
|
INT idx;
|
|
|
|
/* Reset the face names list */
|
|
SendMessageW(hWndList, LB_RESETCONTENT, 0, 0);
|
|
|
|
Param.hWndList = hWndList;
|
|
Param.CodePage = CodePage;
|
|
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
|
|
// lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
|
|
|
|
hDC = GetDC(NULL);
|
|
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFaceNamesProc, (LPARAM)&Param, 0);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
idx = (INT)SendMessageW(hWndList, LB_GETCOUNT, 0, 0);
|
|
if (idx != LB_ERR && idx != 0)
|
|
{
|
|
/* We have found some faces and filled the list, we are fine! */
|
|
return;
|
|
}
|
|
|
|
/* No fonts were found. Manually add default ones into the list. */
|
|
DPRINT1("The ideal console fonts were not found; manually add default ones.\n");
|
|
|
|
AddFontToList(hWndList, L"Terminal", RASTER_FONTTYPE);
|
|
#if 0
|
|
// TODO: insert only the *single* default TT font, that should
|
|
// be found in the TT font cache with the codepage number 0.
|
|
AddFontToList(hWndList, L"Lucida Console", TRUETYPE_FONTTYPE);
|
|
#endif
|
|
}
|
|
|
|
static VOID
|
|
FaceNameList_SelectFont(
|
|
IN HWND hDlg,
|
|
IN HWND hWndList,
|
|
IN PFONTSIZE_LIST_CTL SizeList,
|
|
IN LPCWSTR FaceName,
|
|
IN ULONG FontFamily,
|
|
IN ULONG FontWeight,
|
|
IN COORD FontSize)
|
|
{
|
|
INT iItem;
|
|
|
|
iItem = (INT)SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)FaceName);
|
|
if (iItem == LB_ERR)
|
|
iItem = (INT)SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)L"Terminal");
|
|
if (iItem == LB_ERR)
|
|
iItem = 0;
|
|
SendMessageW(hWndList, LB_SETCURSEL, (WPARAM)iItem, 0);
|
|
|
|
if (FontWeight >= FW_BOLD)
|
|
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_CHECKED);
|
|
else
|
|
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_UNCHECKED);
|
|
|
|
/* Select the current font size */
|
|
/*
|
|
* Format:
|
|
* Width = FontSize.X = LOWORD(FontSize);
|
|
* Height = FontSize.Y = HIWORD(FontSize);
|
|
*/
|
|
SizeList->CurrentRasterSize = MAKELONG(FontSize.X, FontSize.Y);
|
|
SizeList->CurrentTTSize = FontSize.Y;
|
|
// FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
|
|
|
|
// return iItem;
|
|
}
|
|
|
|
static VOID
|
|
UpdateFontSizeList(
|
|
IN HWND hDlg,
|
|
IN PFONTSIZE_LIST_CTL SizeList)
|
|
{
|
|
HWND hDlgItem;
|
|
|
|
if (SizeList->UseRasterOrTTList)
|
|
{
|
|
/*
|
|
* Raster font: show the Raster size list, and
|
|
* hide the TrueType size list and the units.
|
|
*/
|
|
|
|
// EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, FALSE);
|
|
|
|
hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
|
|
ShowWindow(hDlgItem, SW_HIDE);
|
|
EnableWindow(hDlgItem, FALSE);
|
|
|
|
hDlgItem = GetDlgItem(hDlg, IDC_RADIO_POINT_UNIT);
|
|
ShowWindow(hDlgItem, SW_HIDE);
|
|
EnableWindow(hDlgItem, FALSE);
|
|
|
|
hDlgItem = SizeList->hWndTTSizeList;
|
|
ShowWindow(hDlgItem, SW_HIDE);
|
|
EnableWindow(hDlgItem, FALSE);
|
|
|
|
hDlgItem = SizeList->RasterSizeList.hWndList;
|
|
EnableWindow(hDlgItem, TRUE);
|
|
ShowWindow(hDlgItem, SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* TrueType font: show the TrueType size list
|
|
* and the units, and hide the Raster size list.
|
|
*/
|
|
|
|
// EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, TRUE);
|
|
|
|
hDlgItem = SizeList->RasterSizeList.hWndList;
|
|
ShowWindow(hDlgItem, SW_HIDE);
|
|
EnableWindow(hDlgItem, FALSE);
|
|
|
|
hDlgItem = SizeList->hWndTTSizeList;
|
|
EnableWindow(hDlgItem, TRUE);
|
|
ShowWindow(hDlgItem, SW_SHOW);
|
|
|
|
hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
|
|
EnableWindow(hDlgItem, TRUE);
|
|
ShowWindow(hDlgItem, SW_SHOW);
|
|
|
|
hDlgItem = GetDlgItem(hDlg, IDC_RADIO_POINT_UNIT);
|
|
EnableWindow(hDlgItem, TRUE);
|
|
ShowWindow(hDlgItem, SW_SHOW);
|
|
}
|
|
}
|
|
|
|
static BOOL
|
|
FontSizeChange(
|
|
IN HWND hDlg,
|
|
IN PFONTSIZE_LIST_CTL SizeList,
|
|
IN OUT PCONSOLE_STATE_INFO pConInfo);
|
|
|
|
static BOOL
|
|
FontTypeChange(
|
|
IN HWND hDlg,
|
|
IN PFONTSIZE_LIST_CTL SizeList,
|
|
IN OUT PCONSOLE_STATE_INFO pConInfo)
|
|
{
|
|
HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
|
|
INT Length, nSel;
|
|
LPWSTR FaceName;
|
|
DWORD FontType;
|
|
LPCWSTR FontGrpBoxLabelTpl = NULL;
|
|
WCHAR FontGrpBoxLabel[260];
|
|
|
|
nSel = (INT)SendMessageW(hFontList, LB_GETCURSEL, 0, 0);
|
|
if (nSel == LB_ERR) return FALSE;
|
|
|
|
/*
|
|
* This is disabled, because there can be external parameters
|
|
* that may have changed (e.g. ConInfo->FontWeight, code page, ...)
|
|
* and that we don't control here, and that need a font refresh.
|
|
*/
|
|
#if 0
|
|
/* Check whether the selection has changed */
|
|
if (nSel == CurrentSelFont)
|
|
return FALSE;
|
|
#endif
|
|
|
|
Length = (INT)SendMessageW(hFontList, LB_GETTEXTLEN, nSel, 0);
|
|
if (Length == LB_ERR) return FALSE;
|
|
|
|
FaceName = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
(Length + 1) * sizeof(WCHAR));
|
|
if (FaceName == NULL) return FALSE;
|
|
|
|
Length = (INT)SendMessageW(hFontList, LB_GETTEXT, nSel, (LPARAM)FaceName);
|
|
ASSERT(Length != LB_ERR);
|
|
FaceName[Length] = L'\0';
|
|
|
|
StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
|
|
DPRINT("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
|
|
|
|
/*
|
|
* Retrieve the read-only font group box label string template,
|
|
* and set the group box label to the name of the selected font.
|
|
*/
|
|
Length = LoadStringW(hApplet, IDS_GROUPBOX_FONT_NAME, (LPWSTR)&FontGrpBoxLabelTpl, 0);
|
|
if (FontGrpBoxLabelTpl && Length > 0)
|
|
{
|
|
StringCchCopyNW(FontGrpBoxLabel, ARRAYSIZE(FontGrpBoxLabel), FontGrpBoxLabelTpl, Length);
|
|
StringCchCatW(FontGrpBoxLabel, ARRAYSIZE(FontGrpBoxLabel), FaceName);
|
|
SetDlgItemTextW(hDlg, IDC_GROUPBOX_FONT_NAME, FontGrpBoxLabel);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, FaceName);
|
|
|
|
/*
|
|
* Reset the font size list, only:
|
|
* - if we have changed the type of font, or
|
|
* - if the font type is the same and is RASTER but the font has changed.
|
|
* Otherwise, if the font type is not RASTER and has not changed,
|
|
* we always display the TrueType default sizes and we don't need to
|
|
* recreate the list when we change between different TrueType fonts.
|
|
*/
|
|
FontType = (DWORD)SendMessageW(hFontList, LB_GETITEMDATA, nSel, 0);
|
|
if (FontType != LB_ERR)
|
|
{
|
|
SizeList->UseRasterOrTTList = (FontType == RASTER_FONTTYPE);
|
|
|
|
/* Display the correct font size list (if needed) */
|
|
if (CurrentFontType != FontType)
|
|
UpdateFontSizeList(hDlg, SizeList);
|
|
|
|
/* Enumerate the available sizes for the selected font */
|
|
if ((CurrentFontType != FontType) ||
|
|
(FontType == RASTER_FONTTYPE && CurrentSelFont != nSel))
|
|
{
|
|
LOGFONTW lf;
|
|
HDC hDC;
|
|
|
|
if (SizeList->UseRasterOrTTList)
|
|
SendMessageW(SizeList->RasterSizeList.hWndList, LB_RESETCONTENT, 0, 0);
|
|
else
|
|
SendMessageW(SizeList->hWndTTSizeList, CB_RESETCONTENT, 0, 0);
|
|
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
|
|
// lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
|
|
StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), pConInfo->FaceName);
|
|
|
|
hDC = GetDC(NULL);
|
|
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontSizesProc, (LPARAM)SizeList, 0);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
/* Re-select the current font size */
|
|
if (SizeList->UseRasterOrTTList)
|
|
FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
|
|
else
|
|
FontSizeList_SelectFontSize(SizeList, SizeList->CurrentTTSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* We failed, display the raster fonts size list */
|
|
SizeList->UseRasterOrTTList = TRUE;
|
|
UpdateFontSizeList(hDlg, SizeList);
|
|
}
|
|
CurrentFontType = FontType;
|
|
CurrentSelFont = nSel;
|
|
|
|
FontSizeChange(hDlg, SizeList, pConInfo);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL
|
|
FontSizeChange(
|
|
IN HWND hDlg,
|
|
IN PFONTSIZE_LIST_CTL SizeList,
|
|
IN OUT PCONSOLE_STATE_INFO pConInfo)
|
|
{
|
|
LONG FontSize;
|
|
UINT CharWidth, CharHeight;
|
|
HFONT hFont;
|
|
WCHAR szFontSize[100];
|
|
|
|
/*
|
|
* Retrieve the current selected font size.
|
|
* - If SizeList->UseRasterOrTTList is TRUE, or if it is FALSE but
|
|
* if SizeList->TTSizePixelUnit is TRUE, then the font size is in pixels;
|
|
* - If SizeList->TTSizePixelUnit is FALSE, then the font size is in points.
|
|
*/
|
|
FontSize = FontSizeList_GetSelectedFontSize(SizeList);
|
|
if (FontSize == 0)
|
|
return FALSE; // We have got an invalid font size...
|
|
|
|
/*
|
|
* For TrueType fonts we set the requested width to zero
|
|
* so as to obtain a default aspect-ratio width.
|
|
*/
|
|
CharHeight = (UINT)(SizeList->UseRasterOrTTList ? HIWORD(FontSize) : FontSize);
|
|
CharWidth = (UINT)(SizeList->UseRasterOrTTList ? LOWORD(FontSize) : 0);
|
|
|
|
hFont = CreateConsoleFont2((LONG)CharHeight, (LONG)CharWidth, pConInfo);
|
|
if (!hFont)
|
|
{
|
|
DPRINT1("FontSizeChange: CreateConsoleFont2() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Retrieve the real character size in pixels */
|
|
GetFontCellSize(NULL, hFont, &CharHeight, &CharWidth);
|
|
|
|
/*
|
|
* Update the font preview as well, and store the font handle. It will be
|
|
* freed at later update or when the font preview is refreshed or reset.
|
|
* For TrueType fonts, the preview will show the actual character width.
|
|
*/
|
|
UpdateFontPreview(&FontPreview, hFont, CharWidth, CharHeight);
|
|
|
|
/*
|
|
* Format:
|
|
* Width = FontSize.X = LOWORD(FontSize);
|
|
* Height = FontSize.Y = HIWORD(FontSize);
|
|
*/
|
|
pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? CharWidth : 0);
|
|
pConInfo->FontSize.Y = (SHORT)CharHeight;
|
|
|
|
DPRINT("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x %d)\n",
|
|
pConInfo->FontSize.X, pConInfo->FontSize.Y, CharWidth, CharHeight);
|
|
|
|
InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
|
|
InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
|
|
|
|
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharWidth);
|
|
SetDlgItemText(hDlg, IDC_FONT_SIZE_X, szFontSize);
|
|
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharHeight);
|
|
SetDlgItemText(hDlg, IDC_FONT_SIZE_Y, szFontSize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT_PTR
|
|
CALLBACK
|
|
FontProc(HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PFONTSIZE_LIST_CTL SizeList;
|
|
|
|
SizeList = (PFONTSIZE_LIST_CTL)GetWindowLongPtrW(hDlg, DWLP_USER);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
SizeList = (PFONTSIZE_LIST_CTL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*SizeList));
|
|
if (!SizeList)
|
|
{
|
|
EndDialog(hDlg, 0);
|
|
return (INT_PTR)TRUE;
|
|
}
|
|
SizeList->RasterSizeList.hWndList = GetDlgItem(hDlg, IDC_LBOX_FONTSIZE);
|
|
SizeList->RasterSizeList.GetCount = RasterSizeList_GetCount;
|
|
SizeList->RasterSizeList.GetData = RasterSizeList_GetData;
|
|
SizeList->hWndTTSizeList = GetDlgItem(hDlg, IDC_CBOX_FONTSIZE);
|
|
SizeList->bIsTTSizeDirty = FALSE;
|
|
SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)SizeList);
|
|
|
|
/* By default show the raster font size list */
|
|
SizeList->UseRasterOrTTList = TRUE;
|
|
|
|
/* By default show the font sizes in pixel units */
|
|
CheckRadioButton(hDlg, IDC_RADIO_PIXEL_UNIT, IDC_RADIO_POINT_UNIT, IDC_RADIO_PIXEL_UNIT);
|
|
SizeList->TTSizePixelUnit = TRUE;
|
|
|
|
UpdateFontSizeList(hDlg, SizeList);
|
|
|
|
DPRINT1("ConInfo->FaceName = '%S'\n", ConInfo->FaceName);
|
|
|
|
/* Face names list and current font selection will be done during PSN_SETACTIVE notification */
|
|
// CurrentCodePage = INVALID_CP;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
if (SizeList)
|
|
HeapFree(GetProcessHeap(), 0, SizeList);
|
|
return (INT_PTR)TRUE;
|
|
}
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
|
|
|
|
if (drawItem->CtlID == IDC_STATIC_SELECT_FONT_PREVIEW)
|
|
PaintText(drawItem, ConInfo, Screen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
{
|
|
/* Retransmit to the preview window */
|
|
SendDlgItemMessageW(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW,
|
|
WM_DISPLAYCHANGE, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_FONTCHANGE:
|
|
{
|
|
/* The pool of font resources has changed, re-enumerate the fonts */
|
|
HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
|
|
|
|
/* Initialize the font list */
|
|
FaceNameList_Initialize(hFontList, ConInfo->CodePage);
|
|
|
|
/* Select the current font */
|
|
FaceNameList_SelectFont(hDlg, hFontList,
|
|
SizeList,
|
|
ConInfo->FaceName,
|
|
ConInfo->FontFamily,
|
|
ConInfo->FontWeight,
|
|
ConInfo->FontSize);
|
|
|
|
/* Refresh everything */
|
|
FontTypeChange(hDlg, SizeList, ConInfo);
|
|
break;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case PSN_APPLY:
|
|
{
|
|
ApplyConsoleInfo(hDlg);
|
|
return TRUE;
|
|
}
|
|
|
|
case PSN_SETACTIVE:
|
|
{
|
|
/* Check whether the current code page has changed.
|
|
* If so, re-enumerate the fonts. */
|
|
if (CurrentCodePage != ConInfo->CodePage)
|
|
{
|
|
HWND hFontList;
|
|
|
|
/* Save the new code page */
|
|
CurrentCodePage = ConInfo->CodePage;
|
|
|
|
hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
|
|
|
|
/* Initialize the font list */
|
|
FaceNameList_Initialize(hFontList, ConInfo->CodePage);
|
|
|
|
/* Select the current font */
|
|
FaceNameList_SelectFont(hDlg, hFontList,
|
|
SizeList,
|
|
ConInfo->FaceName,
|
|
ConInfo->FontFamily,
|
|
ConInfo->FontWeight,
|
|
ConInfo->FontSize);
|
|
|
|
/* Refresh everything */
|
|
FontTypeChange(hDlg, SizeList, ConInfo);
|
|
}
|
|
|
|
/* Fall back to default behaviour */
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
if (HIWORD(wParam) == LBN_SELCHANGE /* || CBN_SELCHANGE */)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_LBOX_FONTTYPE:
|
|
{
|
|
/* Change the property sheet state only if the font has really changed */
|
|
if (FontTypeChange(hDlg, SizeList, ConInfo))
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
break;
|
|
}
|
|
|
|
case IDC_LBOX_FONTSIZE:
|
|
case IDC_CBOX_FONTSIZE:
|
|
{
|
|
/* Change the property sheet state only if the font has really changed */
|
|
if (FontSizeChange(hDlg, SizeList, ConInfo))
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* NOTE: CBN_EDITUPDATE is sent first, and is followed by CBN_EDITCHANGE */
|
|
else if (HIWORD(wParam) == CBN_EDITUPDATE && LOWORD(wParam) == IDC_CBOX_FONTSIZE)
|
|
{
|
|
ULONG FontSize;
|
|
PWCHAR pszNext = NULL;
|
|
WCHAR szFontSize[100];
|
|
WCHAR szMessage[260];
|
|
|
|
/* Read the ComboBox edit string, as the user has entered a custom size */
|
|
GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
|
|
|
|
/* Validate the font size */
|
|
FontSize = wcstoul(szFontSize, &pszNext, 10);
|
|
if ((FontSize == 0) || (*pszNext))
|
|
{
|
|
// FIXME: Localize!
|
|
StringCchPrintfW(szMessage, ARRAYSIZE(szMessage), L"\"%s\" is not a valid font size.", szFontSize);
|
|
MessageBoxW(hDlg, szMessage, L"Error", MB_ICONINFORMATION | MB_OK);
|
|
}
|
|
/**/SizeList->bIsTTSizeDirty = TRUE;/**/
|
|
}
|
|
else if (HIWORD(wParam) == CBN_KILLFOCUS && LOWORD(wParam) == IDC_CBOX_FONTSIZE)
|
|
{
|
|
/* Change the property sheet state only if the font has really changed */
|
|
if (FontSizeChange(hDlg, SizeList, ConInfo))
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
}
|
|
else
|
|
if (HIWORD(wParam) == BN_CLICKED)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_CHECK_BOLD_FONTS:
|
|
{
|
|
if (IsDlgButtonChecked(hDlg, IDC_CHECK_BOLD_FONTS) == BST_CHECKED)
|
|
ConInfo->FontWeight = FW_BOLD;
|
|
else
|
|
ConInfo->FontWeight = FW_NORMAL;
|
|
|
|
FontTypeChange(hDlg, SizeList, ConInfo);
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
break;
|
|
}
|
|
|
|
case IDC_RADIO_PIXEL_UNIT:
|
|
case IDC_RADIO_POINT_UNIT:
|
|
{
|
|
SizeList->TTSizePixelUnit = (LOWORD(wParam) == IDC_RADIO_PIXEL_UNIT);
|
|
|
|
/* The call is valid only for TrueType fonts */
|
|
if (CurrentFontType != TRUETYPE_FONTTYPE)
|
|
break;
|
|
|
|
/* Change the property sheet state only if the font has really changed */
|
|
if (FontSizeChange(hDlg, SizeList, ConInfo))
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|