https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4e2826c73bb13ea9cdf6…
commit c4e2826c73bb13ea9cdf6a9178f93866ab6db00f
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun May 19 22:55:14 2019 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun May 19 23:10:41 2019 +0200
[CONSOLE][CONCFG][CONSRV] Provide support for specified additional TrueType fonts +
bugfixes.
CORE-12451 CORE-13182 CORE-13196
- CONSOLE: Initialize the additional TrueType fonts cache.
* Fix the font preview when a TrueType font has been selected.
* Refresh the available fonts and the font preview when the selected
code page is changed (Work In Progress), or when the OS pool of
font resources has changed (WM_FONTCHANGE message).
- CONCFG: Implement support for the additional TrueType fonts cache:
the contents of the cache is enumerated under the registry key
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
NT\CurrentVersion\Console\TrueTypeFont
* Add helper functions and macros.
* In CreateConsoleFontEx(), set the mandatory font pitch&family flags
and remove those that we do not support.
* In IsValidConsoleFont2(), update the validity checks and the
documentation links.
- CONSRV: Load/refresh the additional TrueType fonts cache when needed.
---
dll/cpl/console/console.c | 12 +-
dll/cpl/console/console.h | 17 ++
dll/cpl/console/font.c | 169 ++++++++----
dll/cpl/console/layout.c | 6 +
dll/cpl/console/options.c | 20 +-
win32ss/user/winsrv/concfg/font.c | 293 ++++++++++++++++++---
win32ss/user/winsrv/concfg/font.h | 71 ++++-
win32ss/user/winsrv/concfg/precomp.h | 3 +-
win32ss/user/winsrv/consrv/frontends/gui/conwnd.c | 2 +-
.../user/winsrv/consrv/frontends/gui/guisettings.c | 4 +-
win32ss/user/winsrv/consrv/frontends/gui/guiterm.c | 10 +-
11 files changed, 498 insertions(+), 109 deletions(-)
diff --git a/dll/cpl/console/console.c b/dll/cpl/console/console.c
index 89e9ac57fb3..09c204c630c 100644
--- a/dll/cpl/console/console.c
+++ b/dll/cpl/console/console.c
@@ -227,11 +227,9 @@ InitApplet(HANDLE hSectionOrWnd)
InitDefaultConsoleInfo(ConInfo);
}
- /* Initialize the font support */
- FontPreview.hFont = CreateConsoleFont(ConInfo);
- if (FontPreview.hFont == NULL)
- DPRINT1("InitApplet: CreateConsoleFont() failed\n");
- GetFontCellSize(NULL, FontPreview.hFont, &FontPreview.CharHeight,
&FontPreview.CharWidth);
+ /* Initialize the font support -- additional TrueType fonts cache and current preview
font */
+ InitTTFontCache();
+ RefreshFontPreview(&FontPreview, ConInfo);
/* Initialize the property sheet structure */
ZeroMemory(&psh, sizeof(psh));
@@ -274,8 +272,8 @@ InitApplet(HANDLE hSectionOrWnd)
UnRegisterWinPrevClass(hApplet);
/* Clear the font support */
- if (FontPreview.hFont) DeleteObject(FontPreview.hFont);
- FontPreview.hFont = NULL;
+ ResetFontPreview(&FontPreview);
+ ClearTTFontCache();
/* Save the console settings */
if (SetConsoleInfo)
diff --git a/dll/cpl/console/console.h b/dll/cpl/console/console.h
index 0f7b5924943..fbd7a81368d 100644
--- a/dll/cpl/console/console.h
+++ b/dll/cpl/console/console.h
@@ -49,6 +49,23 @@ extern FONT_PREVIEW FontPreview;
VOID ApplyConsoleInfo(HWND hwndDlg);
+
+VOID
+RefreshFontPreview(
+ IN FONT_PREVIEW* Preview,
+ IN PCONSOLE_STATE_INFO pConInfo);
+
+VOID
+UpdateFontPreview(
+ IN FONT_PREVIEW* Preview,
+ IN HFONT hFont,
+ IN UINT CharWidth,
+ IN UINT CharHeight);
+
+#define ResetFontPreview(Preview) \
+ UpdateFontPreview((Preview), NULL, 0, 0)
+
+
/* Preview Windows */
BOOL
RegisterWinPrevClass(
diff --git a/dll/cpl/console/font.c b/dll/cpl/console/font.c
index 66c9cc6a417..522a6fbaaf4 100644
--- a/dll/cpl/console/font.c
+++ b/dll/cpl/console/font.c
@@ -45,6 +45,31 @@ static INT CurrentSelFont = LB_ERR;
static DWORD CurrentFontType = (DWORD)-1; // Invalid font type
+VOID
+RefreshFontPreview(
+ IN FONT_PREVIEW* Preview,
+ IN PCONSOLE_STATE_INFO pConInfo)
+{
+ if (Preview->hFont) DeleteObject(Preview->hFont);
+ Preview->hFont = CreateConsoleFont(pConInfo);
+ if (Preview->hFont == NULL)
+ DPRINT1("RefreshFontPreview: CreateConsoleFont() failed\n");
+ GetFontCellSize(NULL, Preview->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(
@@ -284,13 +309,6 @@ EnumFaceNamesProc(
{
PFACE_NAMES_PROC_PARAM Param = (PFACE_NAMES_PROC_PARAM)lParam;
- /*
- * To install additional TrueType fonts to be available for the console,
- * add entries of type REG_SZ named "0", "00" etc... in:
- * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
NT\CurrentVersion\Console\TrueTypeFont
- * The names of the fonts listed there should match those in:
- * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
- */
if (IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
{
/* Add the font to the list */
@@ -374,7 +392,7 @@ FaceNameList_Initialize(
ZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
- // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+ // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
hDC = GetDC(NULL);
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFaceNamesProc,
(LPARAM)&Param, 0);
@@ -397,9 +415,14 @@ FaceNameList_Initialize(
}
static VOID
-FaceNameList_SelectFaceName(
+FaceNameList_SelectFont(
+ IN HWND hDlg,
IN HWND hWndList,
- IN LPCWSTR FaceName)
+ IN PFONTSIZE_LIST_CTL SizeList,
+ IN LPCWSTR FaceName,
+ IN ULONG FontFamily,
+ IN ULONG FontWeight,
+ IN COORD FontSize)
{
INT iItem;
@@ -410,6 +433,21 @@ FaceNameList_SelectFaceName(
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;
}
@@ -486,7 +524,6 @@ FontTypeChange(
{
HWND hListBox = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
INT Length, nSel;
- LOGFONTW lf;
LPWSTR FaceName;
DWORD FontType;
LPCWSTR FontGrpBoxLabelTpl = NULL;
@@ -518,12 +555,7 @@ FontTypeChange(
FaceName[Length] = L'\0';
StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
- DPRINT1("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
-
- ZeroMemory(&lf, sizeof(lf));
- lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
- // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
- StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
+ DPRINT("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
/*
* Retrieve the read-only font group box label string template,
@@ -560,6 +592,7 @@ FontTypeChange(
if ((CurrentFontType != FontType) ||
(FontType == RASTER_FONTTYPE && CurrentSelFont != nSel))
{
+ LOGFONTW lf;
HDC hDC;
if (SizeList->UseRasterOrTTList)
@@ -567,6 +600,11 @@ FontTypeChange(
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);
@@ -597,7 +635,9 @@ FontSizeChange(
IN PFONTSIZE_LIST_CTL SizeList,
IN OUT PCONSOLE_STATE_INFO pConInfo)
{
- LONG FontSize, CharWidth, CharHeight;
+ LONG FontSize;
+ UINT CharWidth, CharHeight;
+ HFONT hFont;
WCHAR szFontSize[100];
/*
@@ -610,35 +650,44 @@ FontSizeChange(
if (FontSize == 0)
return FALSE; // We have got an invalid font size...
- CharHeight = (SizeList->UseRasterOrTTList ? (LONG)HIWORD(FontSize) : FontSize);
- CharWidth = (SizeList->UseRasterOrTTList ? (LONG)LOWORD(FontSize) : 0);
+ /*
+ * 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);
- if (FontPreview.hFont) DeleteObject(FontPreview.hFont);
- FontPreview.hFont = CreateConsoleFont2(CharHeight, CharWidth, pConInfo);
- if (FontPreview.hFont == NULL)
+ hFont = CreateConsoleFont2((LONG)CharHeight, (LONG)CharWidth, pConInfo);
+ if (hFont == NULL)
DPRINT1("FontSizeChange: CreateConsoleFont2() failed\n");
/* Retrieve the real character size in pixels */
- GetFontCellSize(NULL, FontPreview.hFont, &FontPreview.CharHeight,
&FontPreview.CharWidth);
+ 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 ?
FontPreview.CharWidth : 0);
- pConInfo->FontSize.Y = (SHORT)FontPreview.CharHeight;
+ pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? CharWidth : 0);
+ pConInfo->FontSize.Y = (SHORT)CharHeight;
- DPRINT1("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x
%d)\n",
- pConInfo->FontSize.X, pConInfo->FontSize.Y,
- FontPreview.CharWidth, FontPreview.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",
FontPreview.CharWidth);
+ StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharWidth);
SetDlgItemText(hDlg, IDC_FONT_SIZE_X, szFontSize);
- StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d",
FontPreview.CharHeight);
+ StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharHeight);
SetDlgItemText(hDlg, IDC_FONT_SIZE_Y, szFontSize);
return TRUE;
@@ -689,22 +738,12 @@ FontProc(HWND hDlg,
/* Select the current font */
DPRINT1("ConInfo->FaceName = '%S'\n",
ConInfo->FaceName);
- FaceNameList_SelectFaceName(hFontList, ConInfo->FaceName);
-
- if (ConInfo->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(ConInfo->FontSize.X,
ConInfo->FontSize.Y);
- SizeList->CurrentTTSize = ConInfo->FontSize.Y;
- // FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
+ FaceNameList_SelectFont(hDlg, hFontList,
+ SizeList,
+ ConInfo->FaceName,
+ ConInfo->FontFamily,
+ ConInfo->FontWeight,
+ ConInfo->FontSize);
/* Refresh everything */
FontTypeChange(hDlg, SizeList, ConInfo);
@@ -737,6 +776,42 @@ FontProc(HWND hDlg,
break;
}
+#if 0
+ case PSM_QUERYSIBLINGS:
+ {
+ /*
+ * If this is a notification from the "Options" dialog because we
+ * changed the code page, treat it using the WM_FONTCHANGE case,
+ * otherwise ignore it.
+ */
+ if (wParam != IDL_CODEPAGE)
+ return FALSE;
+
+ /* Fall through */
+ }
+#endif
+
+ 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)
diff --git a/dll/cpl/console/layout.c b/dll/cpl/console/layout.c
index f8d998625c3..a94bcb53241 100644
--- a/dll/cpl/console/layout.c
+++ b/dll/cpl/console/layout.c
@@ -203,6 +203,9 @@ WinPrev_OnDraw(
* Compute the console window layout
*/
+ if (FontPreview.hFont == NULL)
+ RefreshFontPreview(&FontPreview, pConInfo);
+
/* We start with the console client area, rescaled for the preview */
SetRect(&rcWin, 0, 0,
pConInfo->WindowSize.X * FontPreview.CharWidth,
@@ -489,6 +492,9 @@ PaintText(
hBrush = CreateSolidBrush(nbkColor);
if (!hBrush) return;
+ if (FontPreview.hFont == NULL)
+ RefreshFontPreview(&FontPreview, pConInfo);
+
hOldFont = SelectObject(drawItem->hDC, FontPreview.hFont);
//if (hOldFont == NULL)
//{
diff --git a/dll/cpl/console/options.c b/dll/cpl/console/options.c
index 689553d516b..e35a2479439 100644
--- a/dll/cpl/console/options.c
+++ b/dll/cpl/console/options.c
@@ -72,7 +72,8 @@ AddCodePage(
static VOID
BuildCodePageList(
- IN HWND hDlg)
+ IN HWND hDlg,
+ IN UINT CurrentCodePage)
{
LIST_CTL ListCtl;
HKEY hKey;
@@ -126,7 +127,7 @@ BuildCodePageList(
AddCodePage(&ListCtl, CP_UTF8);
/* Find and select the current code page in the sorted list */
- if (BisectListSortedByValue(&ListCtl, ConInfo->CodePage, &CodePage, FALSE)
== CB_ERR ||
+ if (BisectListSortedByValue(&ListCtl, CurrentCodePage, &CodePage, FALSE) ==
CB_ERR ||
CodePage == CB_ERR)
{
/* Not found, select the first element */
@@ -212,7 +213,7 @@ OptionsProc(HWND hDlg,
{
case WM_INITDIALOG:
{
- BuildCodePageList(hDlg);
+ BuildCodePageList(hDlg, ConInfo->CodePage);
UpdateDialogElements(hDlg, ConInfo);
return TRUE;
}
@@ -332,6 +333,7 @@ OptionsProc(HWND hDlg,
}
}
else
+ // (HIWORD(wParam) == CBN_KILLFOCUS)
if ((HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_SELENDOK)
&&
(LOWORD(wParam) == IDL_CODEPAGE))
{
@@ -347,11 +349,15 @@ OptionsProc(HWND hDlg,
if (CodePage == CB_ERR)
break;
- ConInfo->CodePage = CodePage;
-
- /* Change the property sheet state only if the user validated */
- if (HIWORD(wParam) == CBN_SELENDOK)
+ /* If the user validated a different code page... */
+ if ((HIWORD(wParam) == CBN_SELENDOK) && (CodePage !=
ConInfo->CodePage))
+ {
+ /* ... update the code page, notify the siblings and change the
property sheet state */
+ ConInfo->CodePage = CodePage;
+ // PropSheet_QuerySiblings(GetParent(hDlg), IDL_CODEPAGE, 0);
+ ResetFontPreview(&FontPreview);
PropSheet_Changed(GetParent(hDlg), hDlg);
+ }
}
break;
diff --git a/win32ss/user/winsrv/concfg/font.c b/win32ss/user/winsrv/concfg/font.c
index fdc4e15f84b..6aa75b074e0 100644
--- a/win32ss/user/winsrv/concfg/font.c
+++ b/win32ss/user/winsrv/concfg/font.c
@@ -20,6 +20,11 @@
#include <debug.h>
+/* GLOBALS ********************************************************************/
+
+// RTL_STATIC_LIST_HEAD(TTFontCache);
+LIST_ENTRY TTFontCache = {&TTFontCache, &TTFontCache};
+
/* FUNCTIONS ******************************************************************/
/* Retrieves the character set associated with a given code page */
@@ -58,7 +63,10 @@ CreateConsoleFontEx(
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
- lf.lfPitchAndFamily = (BYTE)(FIXED_PITCH | FontFamily);
+
+ /* Set the mandatory flags and remove those that we do not support */
+ lf.lfPitchAndFamily = (BYTE)( (FIXED_PITCH | FF_MODERN | FontFamily) &
+ ~(VARIABLE_PITCH | FF_DECORATIVE | FF_ROMAN | FF_SCRIPT
| FF_SWISS));
if (!IsValidConsoleFont(FaceName, CodePage))
StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal");
@@ -179,13 +187,10 @@ IsValidConsoleFont2(
{
LPCWSTR FaceName = lplf->lfFaceName;
- /* Record the font's attributes (Fixedwidth and Truetype) */
- // BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
- // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
-
/*
- * According to:
http://support.microsoft.com/kb/247815
- * the criteria for console-eligible fonts are:
+ * According to:
https://web.archive.org/web/20140901124501/http://support.microsoft.com/kb/…
+ * "Necessary criteria for fonts to be available in a command window",
+ * the criteria for console-eligible fonts are as follows:
* - The font must be a fixed-pitch font.
* - The font cannot be an italic font.
* - The font cannot have a negative A or C space.
@@ -198,6 +203,10 @@ IsValidConsoleFont2(
* - If it is not a TrueType font, the face name must be "Terminal".
* - If it is an Asian TrueType font, it must also be an Asian character set.
*
+ * See also Raymond Chen's blog:
https://devblogs.microsoft.com/oldnewthing/?p=26843
+ * and MIT-licensed Microsoft Terminal source code:
https://github.com/microsoft/Terminal/blob/master/src/propsheet/misc.cpp
+ * for other details.
+ *
* To install additional TrueType fonts to be available for the console,
* add entries of type REG_SZ named "0", "00" etc... in:
* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
NT\CurrentVersion\Console\TrueTypeFont
@@ -205,27 +214,30 @@ IsValidConsoleFont2(
* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
*/
- /*
- * In ReactOS we relax some of the criteria:
- * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
- * that can be italic or have negative A or C space.
- * - If it is not a TrueType font, it can be from another character set
- * than OEM_CHARSET.
- * - We do not look into the magic registry key mentioned above.
- */
-
- /* Reject variable width fonts */
- if (((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
-#if 0 /* Reject italic and TrueType fonts with negative A or C space */
- || (lplf->lfItalic)
- || !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
+ /*
+ * In ReactOS we relax some of the criteria:
+ * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
+ * that can be italic or have negative A or C space.
+ * - If it is not a TrueType font, it can be from another character set
+ * than OEM_CHARSET. When an Asian codepage is active however, we require
+ * that this non-TrueType font has an Asian character set.
+ */
+
+ /* Reject variable-width fonts ... */
+ if ( ( ((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
+#if 0 /* Reject italic and TrueType fonts with negative A or C space ... */
+ || (lplf->lfItalic)
+ || !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
#endif
- )
+ ) &&
+ /* ... if they are not in the list of additional TrueType fonts to include */
+ !IsAdditionalTTFont(FaceName) )
{
- DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily =
%d).\n",
- FaceName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s
not FIXED_PITCH"
- : (!(lpntm->ntmFlags
& NTM_NONNEGATIVE_AC) ? " has negative A or C space"
-
: " is broken"),
+ DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily =
%d)\n",
+ FaceName,
+ !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not
FIXED_PITCH"
+ : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has
negative A or C space"
+ : " is
broken"),
lplf->lfPitchAndFamily);
return FALSE;
}
@@ -238,25 +250,66 @@ IsValidConsoleFont2(
return FALSE;
}
+ /* Reject vertical fonts (tategaki) */
+ if (FaceName[0] == L'@')
+ {
+ DPRINT1("Font '%S' rejected because it's vertical\n",
FaceName);
+ return FALSE;
+ }
+
/* Is the current code page Chinese, Japanese or Korean? */
if (IsCJKCodePage(CodePage))
{
- /* It's Asian */
+ /* It's CJK */
+
if (FontType == TRUETYPE_FONTTYPE)
{
- if (lplf->lfCharSet != CodePageToCharSet(CodePage))
+ /*
+ * Here we are inclusive and check for any CJK character set,
+ * instead of looking just at the current one via CodePageToCharSet().
+ */
+ if (!IsCJKCharSet(lplf->lfCharSet)
+#if 1 // FIXME: Temporary HACK!
+ && wcscmp(FaceName, L"Terminal") != 0
+#endif
+ )
{
- DPRINT1("TrueType font '%S' rejected because it's not
user Asian charset (lfCharSet = %d)\n",
+ DPRINT1("TrueType font '%S' rejected because it's not
Asian charset (lfCharSet = %d)\n",
+ FaceName, lplf->lfCharSet);
+ return FALSE;
+ }
+
+ /*
+ * If this is a cached TrueType font that is used only for certain
+ * code pages, verify that the charset it claims is the correct one.
+ *
+ * Since there may be multiple entries for a cached TrueType font,
+ * a general one (code page == 0) and one or more for explicit
+ * code pages, we need to perform two search queries instead of
+ * just one and retrieving the code page for this entry.
+ */
+ if (IsAdditionalTTFont(FaceName) && !IsAdditionalTTFontCP(FaceName,
0) &&
+ !IsCJKCharSet(lplf->lfCharSet))
+ {
+ DPRINT1("Cached TrueType font '%S' rejected because it
claims a code page that is not Asian charset (lfCharSet = %d)\n",
FaceName, lplf->lfCharSet);
return FALSE;
}
}
else
{
+ /* Reject non-TrueType fonts that do not have an Asian character set */
+ if (!IsCJKCharSet(lplf->lfCharSet) && (lplf->lfCharSet !=
OEM_CHARSET))
+ {
+ DPRINT1("Non-TrueType font '%S' rejected because it's
not Asian charset or OEM_CHARSET (lfCharSet = %d)\n",
+ FaceName, lplf->lfCharSet);
+ return FALSE;
+ }
+
/* Reject non-TrueType fonts that are not Terminal */
if (wcscmp(FaceName, L"Terminal") != 0)
{
- DPRINT1("Non-TrueType font '%S' rejected because it's
not Terminal\n", FaceName);
+ DPRINT1("Non-TrueType font '%S' rejected because it's
not 'Terminal'\n", FaceName);
return FALSE;
}
}
@@ -264,6 +317,8 @@ IsValidConsoleFont2(
else
{
/* Not CJK */
+
+ /* Reject non-TrueType fonts that are not OEM or similar */
if ((FontType != TRUETYPE_FONTTYPE) &&
(lplf->lfCharSet != ANSI_CHARSET) &&
(lplf->lfCharSet != DEFAULT_CHARSET) &&
@@ -275,13 +330,6 @@ IsValidConsoleFont2(
}
}
- /* Reject fonts that are vertical (tategaki) */
- if (FaceName[0] == L'@')
- {
- DPRINT1("Font '%S' rejected because it's vertical\n",
FaceName);
- return FALSE;
- }
-
/* All good */
return TRUE;
}
@@ -320,7 +368,7 @@ IsValidConsoleFont(
RtlZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
- // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+ // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
hDC = GetDC(NULL);
@@ -330,4 +378,173 @@ IsValidConsoleFont(
return Param.IsValidFont;
}
+/*
+ * To install additional TrueType fonts to be available for the console,
+ * add entries of type REG_SZ named "0", "00" etc... in:
+ * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
+ * The names of the fonts listed there should match those in:
+ * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
+ *
+ * This function initializes the cache of the fonts listed there.
+ */
+VOID
+InitTTFontCache(VOID)
+{
+ BOOLEAN Success;
+ HKEY hKeyTTFonts; // hKey;
+ DWORD dwNumValues = 0;
+ DWORD dwIndex;
+ DWORD dwType;
+ WCHAR szValueName[MAX_PATH];
+ DWORD dwValueName;
+ WCHAR szValue[LF_FACESIZE] = L"";
+ DWORD dwValue;
+ PTT_FONT_ENTRY FontEntry;
+ PWCHAR pszNext = NULL;
+ UINT CodePage;
+
+ if (!IsListEmpty(&TTFontCache))
+ return;
+ // InitializeListHead(&TTFontCache);
+
+ /* Open the key */
+ // "\\Registry\\Machine\\Software\\Microsoft\\Windows
NT\\CurrentVersion\\Console\\TrueTypeFont"
+ Success = (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\Windows
NT\\CurrentVersion\\Console\\TrueTypeFont",
+ 0,
+ KEY_READ,
+ &hKeyTTFonts) == ERROR_SUCCESS);
+ if (!Success)
+ return;
+
+ /* Enumerate each value */
+ if (RegQueryInfoKeyW(hKeyTTFonts, NULL, NULL, NULL, NULL, NULL, NULL,
+ &dwNumValues, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ {
+ DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
+ RegCloseKey(hKeyTTFonts);
+ return;
+ }
+
+ for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
+ {
+ dwValue = sizeof(szValue);
+ dwValueName = ARRAYSIZE(szValueName);
+ if (RegEnumValueW(hKeyTTFonts, dwIndex, szValueName, &dwValueName, NULL,
&dwType, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
+ {
+ DPRINT1("InitTTFontCache: RegEnumValueW failed, continuing...\n");
+ continue;
+ }
+ /* Only (multi-)string values are supported */
+ if ((dwType != REG_SZ) && (dwType != REG_MULTI_SZ))
+ continue;
+
+ /* The value name is a code page (in decimal), validate it */
+ CodePage = wcstoul(szValueName, &pszNext, 10);
+ if (*pszNext)
+ continue; // Non-numerical garbage followed...
+ // IsValidCodePage(CodePage);
+
+ FontEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(*FontEntry));
+ if (!FontEntry)
+ {
+ DPRINT1("InitTTFontCache: Failed to allocate memory,
continuing...\n");
+ continue;
+ }
+
+ FontEntry->CodePage = CodePage;
+
+ pszNext = szValue;
+
+ /* Check whether bold is disabled for this font */
+ if (*pszNext == L'*')
+ {
+ FontEntry->DisableBold = TRUE;
+ ++pszNext;
+ }
+ else
+ {
+ FontEntry->DisableBold = FALSE;
+ }
+
+ /* Copy the font name */
+ StringCchCopyNW(FontEntry->FaceName, ARRAYSIZE(FontEntry->FaceName),
+ pszNext, wcslen(pszNext));
+
+ if (dwType == REG_MULTI_SZ)
+ {
+ /* There may be an alternate face name as the second string */
+ pszNext += wcslen(pszNext) + 1;
+
+ /* Check whether bold is disabled for this font */
+ if (*pszNext == L'*')
+ {
+ FontEntry->DisableBold = TRUE;
+ ++pszNext;
+ }
+ // else, keep the original setting.
+
+ /* Copy the alternate font name */
+ StringCchCopyNW(FontEntry->FaceNameAlt,
ARRAYSIZE(FontEntry->FaceNameAlt),
+ pszNext, wcslen(pszNext));
+ }
+
+ InsertTailList(&TTFontCache, &FontEntry->Entry);
+ }
+
+ /* Close the key and quit */
+ RegCloseKey(hKeyTTFonts);
+}
+
+VOID
+ClearTTFontCache(VOID)
+{
+ PLIST_ENTRY Entry;
+ PTT_FONT_ENTRY FontEntry;
+
+ while (!IsListEmpty(&TTFontCache))
+ {
+ Entry = RemoveHeadList(&TTFontCache);
+ FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FontEntry);
+ }
+ InitializeListHead(&TTFontCache);
+}
+
+VOID
+RefreshTTFontCache(VOID)
+{
+ ClearTTFontCache();
+ InitTTFontCache();
+}
+
+PTT_FONT_ENTRY
+FindCachedTTFont(
+ IN LPCWSTR FaceName,
+ IN UINT CodePage)
+{
+ PLIST_ENTRY Entry;
+ PTT_FONT_ENTRY FontEntry;
+
+ /* Search for the font in the cache */
+ for (Entry = TTFontCache.Flink;
+ Entry != &TTFontCache;
+ Entry = Entry->Flink)
+ {
+ FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
+
+ /* NOTE: The font face names are case-sensitive */
+ if ((wcscmp(FontEntry->FaceName , FaceName) == 0) ||
+ (wcscmp(FontEntry->FaceNameAlt, FaceName) == 0))
+ {
+ /* Return a match if we don't look at the code pages, or when they match
*/
+ if ((CodePage == INVALID_CP) || (CodePage == FontEntry->CodePage))
+ {
+ return FontEntry;
+ }
+ }
+ }
+ return NULL;
+}
+
/* EOF */
diff --git a/win32ss/user/winsrv/concfg/font.h b/win32ss/user/winsrv/concfg/font.h
index 09b076aff80..ee1aa92736c 100644
--- a/win32ss/user/winsrv/concfg/font.h
+++ b/win32ss/user/winsrv/concfg/font.h
@@ -11,16 +11,50 @@
/* DEFINES ********************************************************************/
-#define CP_SHIFTJIS 932 // Japanese Shift-JIS
-#define CP_HANGUL 949 // Korean Hangul
-#define CP_GB2312 936 // Chinese Simplified (GB2312)
-#define CP_BIG5 950 // Chinese Traditional (Big5)
+#define INVALID_CP ((UINT)-1)
+
+#define CP_SHIFTJIS 932 // Japanese Shift-JIS
+#define CP_HANGUL 949 // Korean Hangul/Wansung
+#define CP_JOHAB 1361 // Korean Johab
+#define CP_GB2312 936 // Chinese Simplified (GB2312)
+#define CP_BIG5 950 // Chinese Traditional (Big5)
/* IsFarEastCP(CodePage) */
#define IsCJKCodePage(CodePage) \
((CodePage) == CP_SHIFTJIS || (CodePage) == CP_HANGUL || \
+ /* (CodePage) == CP_JOHAB || */ \
(CodePage) == CP_BIG5 || (CodePage) == CP_GB2312)
+#if !defined(_WINGDI_) || defined(NOGDI)
+#define SHIFTJIS_CHARSET 128
+#define HANGEUL_CHARSET 129
+#define HANGUL_CHARSET 129 // HANGEUL_CHARSET
+#if(WINVER >= 0x0400)
+#define JOHAB_CHARSET 130
+#endif /* WINVER */
+#define GB2312_CHARSET 134
+#define CHINESEBIG5_CHARSET 136
+#endif /* !defined(_WINGDI_) || defined(NOGDI) */
+
+/* IsAnyDBCSCharSet(CharSet) */
+#define IsCJKCharSet(CharSet) \
+ ((CharSet) == SHIFTJIS_CHARSET || (CharSet) == HANGUL_CHARSET || \
+ /* (CharSet) == JOHAB_CHARSET || */ \
+ (CharSet) == GB2312_CHARSET || (CharSet) == CHINESEBIG5_CHARSET)
+
+#define IsBoldFont(Weight) \
+ ((Weight) >= FW_SEMIBOLD) /* Sometimes, just > FW_MEDIUM */
+
+typedef struct _TT_FONT_ENTRY
+{
+ LIST_ENTRY Entry;
+ UINT CodePage;
+ BOOL DisableBold;
+ WCHAR FaceName[LF_FACESIZE];
+ WCHAR FaceNameAlt[LF_FACESIZE];
+} TT_FONT_ENTRY, *PTT_FONT_ENTRY;
+
+
/* FUNCTIONS ******************************************************************/
BYTE
@@ -65,4 +99,33 @@ IsValidConsoleFont(
IN LPCWSTR FaceName,
IN UINT CodePage);
+/*
+ * To install additional TrueType fonts to be available for the console,
+ * add entries of type REG_SZ named "0", "00" etc... in:
+ * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
+ * The names of the fonts listed there should match those in:
+ * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
+ *
+ * This function initializes the cache of the fonts listed there.
+ */
+VOID
+InitTTFontCache(VOID);
+
+VOID
+ClearTTFontCache(VOID);
+
+VOID
+RefreshTTFontCache(VOID);
+
+PTT_FONT_ENTRY
+FindCachedTTFont(
+ IN LPCWSTR FaceName,
+ IN UINT CodePage);
+
+#define IsAdditionalTTFont(FaceName) \
+ (FindCachedTTFont((FaceName), INVALID_CP) != NULL)
+
+#define IsAdditionalTTFontCP(FaceName, CodePage) \
+ (FindCachedTTFont((FaceName), (CodePage)) != NULL)
+
/* EOF */
diff --git a/win32ss/user/winsrv/concfg/precomp.h b/win32ss/user/winsrv/concfg/precomp.h
index cfa0519ca36..5f6ca4a333e 100644
--- a/win32ss/user/winsrv/concfg/precomp.h
+++ b/win32ss/user/winsrv/concfg/precomp.h
@@ -31,7 +31,8 @@
#include <ndk/obfuncs.h>
#include <ndk/rtlfuncs.h>
-#include <stdio.h> // for swprintf
+#include <stdio.h> // For swprintf()
+#include <stdlib.h> // For wcstoul()
#include <strsafe.h>
/* EOF */
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
index 13f5da948f8..6e3603fa360 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
@@ -20,7 +20,7 @@
#define NDEBUG
#include <debug.h>
-#include "font.h"
+#include "concfg/font.h"
#include "guiterm.h"
#include "resource.h"
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
index e317334790a..1ccee596beb 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
@@ -14,6 +14,7 @@
#define NDEBUG
#include <debug.h>
+#include "concfg/font.h"
#include "guiterm.h"
#include "guisettings.h"
@@ -331,7 +332,8 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
/* Set the terminal informations */
- /* Change the font */
+ /* Refresh the additional TrueType fonts cache and change the font */
+ RefreshTTFontCache();
InitFonts(GuiData,
pConInfo->FaceName,
pConInfo->FontFamily,
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
index c811c4c030c..afca59331a6 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
@@ -16,6 +16,7 @@
#define NDEBUG
#include <debug.h>
+#include "concfg/font.h"
#include "guiterm.h"
#include "resource.h"
@@ -294,12 +295,15 @@ GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
HANDLE hInputThread;
CLIENT_ID ClientId;
- /*
- * Initialize and register the console window class, if needed.
- */
+ /* Perform one-time initialization */
if (!ConsInitialized)
{
+ /* Initialize and register the console window class */
if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE;
+
+ /* Initialize the font support -- additional TrueType fonts cache */
+ InitTTFontCache();
+
ConsInitialized = TRUE;
}