https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5d3915d0fcc465f65a6146b3d6bd9c050638dc18

commit 5d3915d0fcc465f65a6146b3d6bd9c050638dc18
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Sat Jan 29 20:04:16 2022 +0100
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Tue Feb 8 15:59:07 2022 +0100

    [CONCFG:FONT][CONSRV] Use a suitable font when changing console output CP; 
fail if none found. (#4337)
    
    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.
---
 dll/cpl/console/font.c                             |   6 +-
 win32ss/user/winsrv/concfg/font.c                  | 703 +++++++++++++++++++--
 win32ss/user/winsrv/concfg/font.h                  |  33 +-
 win32ss/user/winsrv/consrv/frontends/gui/conwnd.c  | 113 +++-
 .../user/winsrv/consrv/frontends/gui/guisettings.c |  21 +-
 .../user/winsrv/consrv/frontends/gui/guisettings.h |   2 +-
 win32ss/user/winsrv/consrv/frontends/gui/guiterm.c |  27 +-
 win32ss/user/winsrv/consrv/frontends/gui/guiterm.h |  17 +-
 8 files changed, 794 insertions(+), 128 deletions(-)

diff --git a/dll/cpl/console/font.c b/dll/cpl/console/font.c
index 4cb5f4c61d3..888375924bb 100644
--- a/dll/cpl/console/font.c
+++ b/dll/cpl/console/font.c
@@ -429,9 +429,11 @@ FaceNameList_Initialize(
     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);
-    if (CodePageToCharSet(CodePage) != DEFAULT_CHARSET)
-        AddFontToList(hWndList, L"Droid Sans Fallback", TRUETYPE_FONTTYPE);
+#endif
 }
 
 static VOID
diff --git a/win32ss/user/winsrv/concfg/font.c 
b/win32ss/user/winsrv/concfg/font.c
index 2889d9dd5ef..59b12e3ae90 100644
--- a/win32ss/user/winsrv/concfg/font.c
+++ b/win32ss/user/winsrv/concfg/font.c
@@ -1,10 +1,9 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS Console Server DLL
- * FILE:            win32ss/user/winsrv/concfg/font.c
- * PURPOSE:         Console Fonts Management
- * PROGRAMMERS:     Hermes Belusca-Maito ([email protected])
- *                  Katayama Hirofumi MZ ([email protected])
+ * PROJECT:     ReactOS Console Server DLL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Console GDI Fonts Management.
+ * COPYRIGHT:   Copyright 2017-2022 Hermès Bélusca-Maïto
+ *              Copyright 2017 Katayama Hirofumi MZ 
([email protected])
  */
 
 /* INCLUDES 
*******************************************************************/
@@ -19,85 +18,594 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DBGFNT  DPRINT
+#define DBGFNT1 DPRINT1
+
 
 /* GLOBALS 
********************************************************************/
 
+#define TERMINAL_FACENAME   L"Terminal"
+
 // RTL_STATIC_LIST_HEAD(TTFontCache);
 LIST_ENTRY TTFontCache = {&TTFontCache, &TTFontCache};
 
+// NOTE: Used to tag code that makes sense only with a font cache.
+// #define FONT_CACHE_PRESENT
+
+
 /* FUNCTIONS 
******************************************************************/
 
-/* Retrieves the character set associated with a given code page */
+/**
+ * @brief
+ * Retrieves the character set associated with a given code page.
+ *
+ * @param[in]   CodePage
+ * The code page to convert.
+ *
+ * @return
+ * The character set corresponding to the code page, or @b DEFAULT_CHARSET.
+ **/
 BYTE
 CodePageToCharSet(
     _In_ UINT CodePage)
 {
     CHARSETINFO CharInfo;
     if (TranslateCharsetInfo(UlongToPtr(CodePage), &CharInfo, TCI_SRCCODEPAGE))
-        return CharInfo.ciCharset;
+        return (BYTE)CharInfo.ciCharset;
     else
         return DEFAULT_CHARSET;
 }
 
-HFONT
-CreateConsoleFontEx(
-    _In_     LONG Height,
-    _In_opt_ LONG Width,
-    _Inout_updates_z_(LF_FACESIZE)
-         PWSTR FaceName,
-    _In_ ULONG FontFamily,
-    _In_ ULONG FontWeight,
-    _In_ UINT  CodePage)
+/*****************************************************************************/
+
+typedef struct _FIND_SUITABLE_FONT_PROC_PARAM
+{
+    /* Search criteria */
+    _In_reads_or_z_(LF_FACESIZE) PCWSTR AltFaceName;
+    FONT_DATA SearchFont;
+    UINT CodePage;
+    BOOL StrictSearch; // TRUE to do strict search; FALSE for relaxed criteria.
+
+    /* Candidate font data */
+    BOOL FontFound;    // TRUE/FALSE if we have/haven't found a suitable font.
+    FONT_DATA CandidateFont;
+    WCHAR CandidateFaceName[LF_FACESIZE];
+} FIND_SUITABLE_FONT_PROC_PARAM, *PFIND_SUITABLE_FONT_PROC_PARAM;
+
+#define TM_IS_TT_FONT(x)    (((x) & TMPF_TRUETYPE) == TMPF_TRUETYPE)
+#define SIZE_EQUAL(s1, s2)  (((s1).X == (s2).X) && ((s1).Y == (s2).Y))
+
+/**
+ * @brief   EnumFontFamiliesEx() callback helper for FindSuitableFont().
+ *
+ * @remark
+ * It implements a nearly-identical console-suitable font search
+ * algorithm based on the one from FindCreateFont()
+ * 
https://github.com/microsoft/terminal/blob/main/src/propsheet/fontdlg.cpp#L1113
+ * excepting that for now, it does not support an internal font cache.
+ **/
+static BOOL CALLBACK
+FindSuitableFontProc(
+    _In_ PLOGFONTW lplf,
+    _In_ PNEWTEXTMETRICW lpntm,
+    _In_ DWORD  FontType,
+    _In_ LPARAM lParam)
+{
+    PFIND_SUITABLE_FONT_PROC_PARAM Param = 
(PFIND_SUITABLE_FONT_PROC_PARAM)lParam;
+    PFONT_DATA SearchFont = &Param->SearchFont;
+
+    if (!IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
+    {
+        /* This font does not suit us; continue enumeration */
+        return TRUE;
+    }
+
+#ifndef FONT_CACHE_PRESENT
+    /*
+     * Since we don't cache all the possible font sizes for TrueType fonts,
+     * we cannot check our requested size (and weight) against the enumerated
+     * one; therefore reset the enumerated values to the requested ones.
+     * On the contrary, Raster fonts get their specific font sizes (and 
weights)
+     * enumerated separately, so for them we can keep the enumerated values.
+     */
+    if (FontType == TRUETYPE_FONTTYPE)
+    {
+        lplf->lfHeight = SearchFont->Size.Y;
+        lplf->lfWidth  = 0; // SearchFont->Size.X;
+        lplf->lfWeight = FW_NORMAL;
+    }
+#endif
+
+    if (Param->StrictSearch)
+    {
+        /*
+         * Find whether this is an exact match.
+         */
+
+        /* If looking for a particular family, skip non-matches */
+        if ((SearchFont->Family != 0) &&
+            ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
+        {
+            /* Continue enumeration */
+            return TRUE;
+        }
+
+        /* Skip non-matching sizes */
+#if 0
+        if ((FontInfo[i].SizeWant.Y != Size.Y) &&
+            !SIZE_EQUAL(FontInfo[i].Size, Size))
+#endif
+        if ((lplf->lfHeight != SearchFont->Size.Y) &&
+            !(lplf->lfWidth == SearchFont->Size.X &&
+              lplf->lfHeight == SearchFont->Size.Y))
+        {
+            /* Continue enumeration */
+            return TRUE;
+        }
+
+        /* Skip non-matching weights */
+        if ((SearchFont->Weight != 0) &&
+            (SearchFont->Weight != lplf->lfWeight))
+        {
+            /* Continue enumeration */
+            return TRUE;
+        }
+
+        /* NOTE: We are making the font enumeration at fixed CharSet,
+         * with the one specified in the parameter block. */
+        ASSERT(lplf->lfCharSet == SearchFont->CharSet);
+
+        if ((FontType != TRUETYPE_FONTTYPE) && // 
!TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
+            (lplf->lfCharSet != SearchFont->CharSet) &&
+            !(lplf->lfCharSet == OEM_CHARSET && 
IsCJKCodePage(Param->CodePage))) // g_fEastAsianSystem
+        {
+            /* Continue enumeration */
+            return TRUE;
+        }
+
+        /*
+         * Size (and maybe family) match. If we don't care about the name or
+         * if it matches, use this font. Otherwise, if name doesn't match and
+         * it is a raster font, consider it.
+         *
+         * NOTE: The font face names are case-sensitive.
+         */
+        if (!SearchFont->FaceName || !*(SearchFont->FaceName) ||
+            (wcscmp(lplf->lfFaceName, SearchFont->FaceName) == 0) ||
+            (wcscmp(lplf->lfFaceName, Param->AltFaceName) == 0))
+        {
+            // FontIndex = i;
+
+            PFONT_DATA CandidateFont = &Param->CandidateFont;
+
+            CandidateFont->FaceName = Param->CandidateFaceName;
+            StringCchCopyNW(Param->CandidateFaceName,
+                            ARRAYSIZE(Param->CandidateFaceName),
+                            lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
+
+            CandidateFont->Weight = lplf->lfWeight;
+            CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
+
+            CandidateFont->Size.X = lplf->lfWidth;
+            CandidateFont->Size.Y = lplf->lfHeight;
+
+            CandidateFont->CharSet = lplf->lfCharSet;
+
+            /* The font is found, stop enumeration */
+            Param->FontFound = TRUE;
+            return FALSE;
+        }
+        else if (FontType != TRUETYPE_FONTTYPE) // 
!TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
+        {
+            // FontIndex = i;
+
+            PFONT_DATA CandidateFont = &Param->CandidateFont;
+
+            CandidateFont->FaceName = Param->CandidateFaceName;
+            StringCchCopyNW(Param->CandidateFaceName,
+                            ARRAYSIZE(Param->CandidateFaceName),
+                            lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
+
+            CandidateFont->Weight = lplf->lfWeight;
+            CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
+
+            CandidateFont->Size.X = lplf->lfWidth;
+            CandidateFont->Size.Y = lplf->lfHeight;
+
+            CandidateFont->CharSet = lplf->lfCharSet;
+
+            /* A close Raster Font fit was found; only the name doesn't match.
+             * Continue enumeration to see whether we can find better. */
+            Param->FontFound = TRUE;
+        }
+    }
+    else // !Param->StrictSearch
+    {
+        /*
+         * Failed to find exact match, even after enumeration, so now
+         * try to find a font of same family and same size or bigger.
+         */
+
+        if (IsCJKCodePage(Param->CodePage)) // g_fEastAsianSystem
+        {
+            if ((SearchFont->Family != 0) &&
+                ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
+            {
+                /* Continue enumeration */
+                return TRUE;
+            }
+
+            if ((FontType != TRUETYPE_FONTTYPE) && // 
!TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
+                (lplf->lfCharSet != SearchFont->CharSet))
+            {
+                /* Continue enumeration */
+                return TRUE;
+            }
+        }
+        else
+        {
+            if (// (SearchFont->Family != 0) &&
+                ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
+            {
+                /* Continue enumeration */
+                return TRUE;
+            }
+        }
+
+        if ((lplf->lfHeight >= SearchFont->Size.Y) &&
+            (lplf->lfWidth  >= SearchFont->Size.X))
+        {
+            /* Same family, size >= desired */
+            // FontIndex = i;
+
+            PFONT_DATA CandidateFont = &Param->CandidateFont;
+
+            CandidateFont->FaceName = Param->CandidateFaceName;
+            StringCchCopyNW(Param->CandidateFaceName,
+                            ARRAYSIZE(Param->CandidateFaceName),
+                            lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
+
+            CandidateFont->Weight = lplf->lfWeight;
+            CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
+
+            CandidateFont->Size.X = lplf->lfWidth;
+            CandidateFont->Size.Y = lplf->lfHeight;
+
+            CandidateFont->CharSet = lplf->lfCharSet;
+
+            /* The font is found, stop enumeration */
+            Param->FontFound = TRUE;
+            return FALSE;
+        }
+    }
+
+    /* Continue enumeration */
+    return TRUE;
+}
+
+/**
+ * @brief
+ * Finds a font suitable for the given code page, based on the current font
+ * and its characteristics provided in input.
+ *
+ * @param[in,out]   FontData
+ * In input: The face name and characteristics of the font to search for,
+ * possibly getting a best match.
+ * In output: The face name and characteristics of the suitable font,
+ * in case of success.
+ *
+ * @param[in]   CodePage
+ * The code page the font has to support.
+ *
+ * @return
+ * @b TRUE in case a suitable font has been found. Its name and characteristics
+ * are returned in @b FontData. @b FALSE if no suitable font has been found.
+ **/
+static BOOL
+FindSuitableFont(
+    _Inout_ PFONT_DATA FontData,
+    _In_ UINT CodePage)
 {
+    FIND_SUITABLE_FONT_PROC_PARAM Param;
+    _Inout_updates_z_(LF_FACESIZE) PWSTR FaceName;
+    HDC hDC;
     LOGFONTW lf;
+    PTT_FONT_ENTRY FontEntry;
+
+    /* Save the original FaceName pointer */
+    FaceName = FontData->FaceName;
+
+    /* Save our current search criteria */
+    RtlZeroMemory(&Param, sizeof(Param));
+    Param.SearchFont = *FontData;
+
+    Param.SearchFont.CharSet = CodePageToCharSet(CodePage);
+    Param.CodePage = CodePage;
+
+    /* Search for a TrueType alternative face name */
+    FontEntry = FindCachedTTFont(FaceName, CodePage);
+    if (FontEntry)
+    {
+        /* NOTE: The font face names are case-sensitive */
+        if (wcscmp(FontEntry->FaceName, FaceName) == 0)
+            Param.AltFaceName = FontEntry->FaceNameAlt;
+        else if (wcscmp(FontEntry->FaceNameAlt, FaceName) == 0)
+            Param.AltFaceName = FontEntry->FaceName;
+    }
+    else
+    {
+        Param.AltFaceName = FaceName;
+    }
+
+    /* Initialize the search: start with a strict search, then a relaxed one */
+    Param.FontFound = FALSE;
 
+    Param.StrictSearch = TRUE;
+SearchAgain:
+    /*
+     * Enumerate all fonts with the given character set.
+     * We will match them with the search criteria.
+     */
     RtlZeroMemory(&lf, sizeof(lf));
+    lf.lfCharSet = Param.SearchFont.CharSet;
+    // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
 
-    lf.lfHeight = Height;
-    lf.lfWidth  = Width;
+    hDC = GetDC(NULL);
+    EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)FindSuitableFontProc, 
(LPARAM)&Param, 0);
+    ReleaseDC(NULL, hDC);
+
+    /* If we failed to find any font, search again with relaxed criteria */
+    if (Param.StrictSearch && !Param.FontFound)
+    {
+        Param.StrictSearch = FALSE;
+        goto SearchAgain;
+    }
+
+    /* If no font was found again, return failure */
+    if (!Param.FontFound)
+        return FALSE;
+
+    /* Return the font details */
+    *FontData = Param.CandidateFont;
+    FontData->FaceName = FaceName; // Restore the original FaceName pointer.
+    StringCchCopyNW(FaceName, LF_FACESIZE,
+                    Param.CandidateFaceName,
+                    ARRAYSIZE(Param.CandidateFaceName));
+
+    return TRUE;
+}
+
+/**
+ * @brief
+ * Validates and creates a suitable console font based on the font
+ * characteristics given in input.
+ *
+ * @param[in]   FontData
+ * The face name and characteristics of the font to create.
+ *
+ * @param[in]   CodePage
+ * The code page the font has to support.
+ *
+ * @return
+ * A GDI handle to the created font, or @b NULL in case of failure.
+ **/
+static HFONT
+CreateConsoleFontWorker(
+    _In_ PFONT_DATA FontData,
+    _In_ UINT CodePage)
+{
+    LOGFONTW lf;
+
+    RtlZeroMemory(&lf, sizeof(lf));
+
+    lf.lfHeight = (LONG)(ULONG)FontData->Size.Y;
+    lf.lfWidth  = (LONG)(ULONG)FontData->Size.X;
 
     lf.lfEscapement  = 0;
     lf.lfOrientation = 0; // TA_BASELINE; // TA_RTLREADING; when the console 
supports RTL?
     // lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = FALSE;
-    lf.lfWeight  = FontWeight;
+    lf.lfWeight  = FontData->Weight;
     lf.lfCharSet = CodePageToCharSet(CodePage);
     lf.lfOutPrecision  = OUT_DEFAULT_PRECIS;
     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
     lf.lfQuality = DEFAULT_QUALITY;
 
     /* Set the mandatory flags and remove those that we do not support */
-    lf.lfPitchAndFamily = (BYTE)( (FIXED_PITCH | FF_MODERN | FontFamily) &
+    lf.lfPitchAndFamily = (BYTE)( (FIXED_PITCH | FF_MODERN | FontData->Family) 
&
                                  ~(VARIABLE_PITCH | FF_DECORATIVE | FF_ROMAN | 
FF_SCRIPT | FF_SWISS));
 
-    if (!IsValidConsoleFont(FaceName, CodePage))
+    if (!IsValidConsoleFont(FontData->FaceName, CodePage))
+        return NULL;
+
+    StringCchCopyNW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName),
+                    FontData->FaceName, LF_FACESIZE);
+
+    return CreateFontIndirectW(&lf);
+}
+
+/*****************************************************************************/
+
+/**
+ * @brief
+ * Validates and creates a suitable console font based on the font
+ * characteristics given in input.
+ *
+ * @param[in]   Height
+ * The font height in cell units (pixels).
+ *
+ * @param[in,opt]   Width
+ * The font width in cell units (pixels).
+ *
+ * @param[in,out]   FaceName
+ * A pointer to a maximally @b LF_FACESIZE-sized buffer.
+ * In input: The buffer contains the face name of the font to try to create.
+ * In output: The buffer receives the face name of the font that has been
+ * created, in case of success. It may, or may not be, identical to the face
+ * name provided in input, in case a substitute font has been chosen.
+ *
+ * @param[in]   FontWeight
+ * The font weight.
+ *
+ * @param[in]   FontFamily
+ * The font family.
+ *
+ * @param[in]   CodePage
+ * The code page the font has to support.
+ *
+ * @param[in]   UseDefaultFallback
+ * Whether (@b TRUE) or not (@b FALSE) to use a default fallback font in case
+ * neither the specified font nor any substitute font could be found and
+ * created for the specified code page.
+ *
+ * @param[out]  FontData
+ * The face name and characteristics of the created font.
+ *
+ * @return
+ * A GDI handle to the created font, or @b NULL in case of failure.
+ *
+ * @remark
+ * Similar to FindCreateFont()
+ * 
https://github.com/microsoft/terminal/blob/main/src/propsheet/fontdlg.cpp#L1113
+ * but:
+ * - does not support an internal font cache for now;
+ * - returns a font handle (and not a font index to the cache).
+ **/
+HFONT
+CreateConsoleFontEx(
+    _In_     LONG Height,
+    _In_opt_ LONG Width,
+    _Inout_updates_z_(LF_FACESIZE)
+         PWSTR FaceName,
+    _In_ ULONG FontWeight,
+    _In_ ULONG FontFamily,
+    _In_ UINT  CodePage,
+    _In_ BOOL  UseDefaultFallback,
+    _Out_ PFONT_DATA FontData)
+{
+    HFONT hFont;
+
+    FontData->FaceName = FaceName;
+    FontData->Weight = FontWeight;
+    FontData->Family = FontFamily;
+    /* NOTE: FontSize is always in cell height/width units (pixels) */
+    FontData->Size.X = Width;
+    FontData->Size.Y = Height;
+    FontData->CharSet = 0; // CodePageToCharSet(CodePage);
+
+    hFont = CreateConsoleFontWorker(FontData, CodePage);
+    if (hFont)
+        return hFont;
+
+    DBGFNT1("CreateConsoleFont('%S') failed - Try to find a suitable 
font...\n",
+            FaceName);
+
+    /*
+     * We could not create a font with the default settings.
+     * Try to find a suitable font and retry.
+     */
+    if (!FindSuitableFont(FontData, CodePage))
     {
-        StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal");
+        /* We could not find any suitable font, fall back
+         * to some default one if required to do so. */
+        DBGFNT1("FindSuitableFont could not find anything - %s\n",
+                UseDefaultFallback ? "Falling back to 'Terminal'"
+                                   : "Bailing out");
+
+        /* No fallback: no font! */
+        if (!UseDefaultFallback)
+            return NULL;
+
+        /* Use "Terminal" as the fallback */
+        StringCchCopyW(FaceName, LF_FACESIZE, TERMINAL_FACENAME);
+#if 0
+        // FIXME: CJK font choose workaround: Don't choose Asian
+        // charset font if there is no preferred font for CJK.
         if (IsCJKCodePage(CodePage))
-        {
-            lf.lfCharSet = ANSI_CHARSET;
-        }
+            FontData->CharSet = ANSI_CHARSET;
+#endif
+    }
+    else
+    {
+        DBGFNT1("FindSuitableFont found: '%S', size (%d x %d)\n",
+                FaceName, FontData->Size.X, FontData->Size.Y);
     }
 
-    StringCchCopyNW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName),
-                    FaceName, LF_FACESIZE);
+    /* Retry creating the font */
+    hFont = CreateConsoleFontWorker(FontData, CodePage);
+    if (!hFont)
+        DBGFNT1("CreateConsoleFont('%S') failed\n", FaceName);
 
-    return CreateFontIndirectW(&lf);
+    return hFont;
 }
 
+/**
+ * @brief
+ * A wrapper for CreateConsoleFontEx().
+ *
+ * @param[in]   Height
+ * The font height in cell units (pixels).
+ *
+ * @param[in,opt]   Width
+ * The font width in cell units (pixels).
+ *
+ * @param[in,out]   ConsoleInfo
+ * A pointer to console settings information, containing in particular
+ * (in input) the face name and characteristics of the font to create
+ * with the current console code page.
+ * In output, the font information gets updated.
+ * Note that a default fallback font is always being used in case neither
+ * the specified font nor any substitute font could be found and created
+ * for the specified code page.
+ *
+ * @return
+ * A GDI handle to the created font, or @b NULL in case of failure.
+ *
+ * @see CreateConsoleFontEx(), CreateConsoleFont()
+ **/
 HFONT
 CreateConsoleFont2(
     _In_     LONG Height,
     _In_opt_ LONG Width,
     _Inout_  PCONSOLE_STATE_INFO ConsoleInfo)
 {
-    return CreateConsoleFontEx(Height,
-                               Width,
-                               ConsoleInfo->FaceName,
-                               ConsoleInfo->FontFamily,
-                               ConsoleInfo->FontWeight,
-                               ConsoleInfo->CodePage);
+    FONT_DATA FontData;
+    HFONT hFont;
+
+    hFont = CreateConsoleFontEx(Height,
+                                Width,
+                                ConsoleInfo->FaceName,
+                                ConsoleInfo->FontWeight,
+                                ConsoleInfo->FontFamily,
+                                ConsoleInfo->CodePage,
+                                TRUE, // UseDefaultFallback
+                                &FontData);
+    if (hFont)
+    {
+        ConsoleInfo->FontWeight = FontData.Weight;
+        ConsoleInfo->FontFamily = FontData.Family;
+    }
+
+    return hFont;
 }
 
+/**
+ * @brief
+ * A wrapper for CreateConsoleFontEx().
+ *
+ * @param[in,out]   ConsoleInfo
+ * A pointer to console settings information, containing in particular
+ * (in input) the face name and characteristics of the font to create
+ * with the current console code page.
+ * In output, the font information gets updated.
+ * Note that a default fallback font is always being used in case neither
+ * the specified font nor any substitute font could be found and created
+ * for the specified code page.
+ *
+ * @return
+ * A GDI handle to the created font, or @b NULL in case of failure.
+ *
+ * @see CreateConsoleFontEx(), CreateConsoleFont2()
+ **/
 HFONT
 CreateConsoleFont(
     _Inout_ PCONSOLE_STATE_INFO ConsoleInfo)
@@ -108,14 +616,30 @@ CreateConsoleFont(
      * Height = FontSize.Y = HIWORD(FontSize);
      */
     /* NOTE: FontSize is always in cell height/width units (pixels) */
-    return CreateConsoleFontEx((LONG)(ULONG)ConsoleInfo->FontSize.Y,
-                               (LONG)(ULONG)ConsoleInfo->FontSize.X,
-                               ConsoleInfo->FaceName,
-                               ConsoleInfo->FontFamily,
-                               ConsoleInfo->FontWeight,
-                               ConsoleInfo->CodePage);
+    return CreateConsoleFont2((LONG)(ULONG)ConsoleInfo->FontSize.Y,
+                              (LONG)(ULONG)ConsoleInfo->FontSize.X,
+                              ConsoleInfo);
 }
 
+/**
+ * @brief
+ * Retrieves the cell size for a console font.
+ *
+ * @param[in,opt]   hDC
+ * An optional GDI device context handle.
+ *
+ * @param[in]   hFont
+ * The GDI handle to the font.
+ *
+ * @param[out]  Height
+ * In case of success, receives the cell height size (in pixels).
+ *
+ * @param[out]  Width
+ * In case of success, receives the cell height size (in pixels).
+ *
+ * @return
+ * @b TRUE if success, @b FALSE in case of failure.
+ **/
 _Success_(return)
 BOOL
 GetFontCellSize(
@@ -138,7 +662,7 @@ GetFontCellSize(
     hOldFont = SelectObject(hDC, hFont);
     if (hOldFont == NULL)
     {
-        DPRINT1("GetFontCellSize: SelectObject failed\n");
+        DBGFNT1("GetFontCellSize: SelectObject failed\n");
         goto Quit;
     }
 
@@ -152,7 +676,7 @@ GetFontCellSize(
      */
     if (!GetTextMetricsW(hDC, &tm))
     {
-        DPRINT1("GetFontCellSize: GetTextMetrics failed\n");
+        DBGFNT1("GetFontCellSize: GetTextMetrics failed\n");
         goto Cleanup;
     }
 
@@ -186,6 +710,31 @@ Quit:
     return Success;
 }
 
+/**
+ * @brief
+ * Validates whether a given font can be supported in the console,
+ * under the specified code page.
+ *
+ * @param[in]   lplf
+ * @param[in]   lpntm
+ * @param[in]   FontType
+ * The GDI font characteristics of the font to validate.
+ *
+ * @param[in]   CodePage
+ * The code page the font has to support.
+ *
+ * @return
+ * @b TRUE if the font is valid and supported in the console,
+ * @b FALSE if not.
+ *
+ * @remark
+ * Equivalent of the font validation tests in FontEnumForV2Console()
+ * (or the more restrictive ones in FontEnum())
+ * https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp#L465
+ * https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp#L607
+ *
+ * @see IsValidConsoleFont()
+ **/
 BOOL
 IsValidConsoleFont2(
     _In_ PLOGFONTW lplf,
@@ -212,7 +761,7 @@ IsValidConsoleFont2(
      * - 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
+     * and MIT-licensed Microsoft Terminal source code: 
https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp
      * for other details.
      *
      * To install additional TrueType fonts to be available for the console,
@@ -241,27 +790,27 @@ IsValidConsoleFont2(
         /* ... 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"),
-                lplf->lfPitchAndFamily);
+        DBGFNT("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;
     }
 
     /* Reject TrueType fonts that are not FF_MODERN */
     if ((FontType == TRUETYPE_FONTTYPE) && ((lplf->lfPitchAndFamily & 0xF0) != 
FF_MODERN))
     {
-        DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN 
(lfPitchAndFamily = %d)\n",
-                FaceName, lplf->lfPitchAndFamily);
+        DBGFNT("TrueType font '%S' rejected because it's not FF_MODERN 
(lfPitchAndFamily = %d)\n",
+               FaceName, lplf->lfPitchAndFamily);
         return FALSE;
     }
 
     /* Reject vertical fonts (tategaki) */
     if (FaceName[0] == L'@')
     {
-        DPRINT1("Font '%S' rejected because it's vertical\n", FaceName);
+        DBGFNT("Font '%S' rejected because it's vertical\n", FaceName);
         return FALSE;
     }
 
@@ -276,14 +825,10 @@ IsValidConsoleFont2(
              * 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
-               )
+            if (!IsCJKCharSet(lplf->lfCharSet))
             {
-                DPRINT1("TrueType font '%S' rejected because it's not Asian 
charset (lfCharSet = %d)\n",
-                        FaceName, lplf->lfCharSet);
+                DBGFNT("TrueType font '%S' rejected because it's not Asian 
charset (lfCharSet = %d)\n",
+                       FaceName, lplf->lfCharSet);
                 return FALSE;
             }
 
@@ -299,8 +844,8 @@ IsValidConsoleFont2(
             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);
+                DBGFNT("Cached TrueType font '%S' rejected because it claims a 
code page that is not Asian charset (lfCharSet = %d)\n",
+                       FaceName, lplf->lfCharSet);
                 return FALSE;
             }
         }
@@ -309,15 +854,15 @@ IsValidConsoleFont2(
             /* 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);
+                DBGFNT("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)
+            if (wcscmp(FaceName, TERMINAL_FACENAME) != 0)
             {
-                DPRINT1("Non-TrueType font '%S' rejected because it's not 
'Terminal'\n", FaceName);
+                DBGFNT("Non-TrueType font '%S' rejected because it's not 
'Terminal'\n", FaceName);
                 return FALSE;
             }
         }
@@ -332,8 +877,8 @@ IsValidConsoleFont2(
             (lplf->lfCharSet != DEFAULT_CHARSET) &&
             (lplf->lfCharSet != OEM_CHARSET))
         {
-            DPRINT1("Non-TrueType font '%S' rejected because it's not 
ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
-                    FaceName, lplf->lfCharSet);
+            DBGFNT("Non-TrueType font '%S' rejected because it's not 
ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
+                   FaceName, lplf->lfCharSet);
             return FALSE;
         }
     }
@@ -348,6 +893,9 @@ typedef struct _IS_VALID_CONSOLE_FONT_PARAM
     UINT CodePage;
 } IS_VALID_CONSOLE_FONT_PARAM, *PIS_VALID_CONSOLE_FONT_PARAM;
 
+/**
+ * @brief   EnumFontFamiliesEx() callback helper for IsValidConsoleFont().
+ **/
 static BOOL CALLBACK
 IsValidConsoleFontProc(
     _In_ PLOGFONTW lplf,
@@ -362,6 +910,23 @@ IsValidConsoleFontProc(
     return FALSE;
 }
 
+/**
+ * @brief
+ * Validates whether a given font can be supported in the console,
+ * under the specified code page.
+ *
+ * @param[in]   FaceName
+ * The face name of the font to validate.
+ *
+ * @param[in]   CodePage
+ * The code page the font has to support.
+ *
+ * @return
+ * @b TRUE if the font is valid and supported in the console,
+ * @b FALSE if not.
+ *
+ * @see IsValidConsoleFont2()
+ **/
 BOOL
 IsValidConsoleFont(
     // _In_reads_or_z_(LF_FACESIZE)
@@ -460,7 +1025,7 @@ InitTTFontCache(VOID)
         FontEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 
sizeof(*FontEntry));
         if (!FontEntry)
         {
-            DPRINT1("InitTTFontCache: Failed to allocate memory, 
continuing...\n");
+            DBGFNT1("InitTTFontCache: Failed to allocate memory, 
continuing...\n");
             continue;
         }
 
diff --git a/win32ss/user/winsrv/concfg/font.h 
b/win32ss/user/winsrv/concfg/font.h
index 870b3805a63..6faa59dad33 100644
--- a/win32ss/user/winsrv/concfg/font.h
+++ b/win32ss/user/winsrv/concfg/font.h
@@ -1,10 +1,9 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS Console Server DLL
- * FILE:            win32ss/user/winsrv/concfg/font.h
- * PURPOSE:         Console Fonts Management
- * PROGRAMMERS:     Hermes Belusca-Maito ([email protected])
- *                  Katayama Hirofumi MZ ([email protected])
+ * PROJECT:     ReactOS Console Server DLL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Console GDI Fonts Management.
+ * COPYRIGHT:   Copyright 2017-2022 Hermès Bélusca-Maïto
+ *              Copyright 2017 Katayama Hirofumi MZ 
([email protected])
  */
 
 #pragma once
@@ -13,6 +12,12 @@
 
 #define INVALID_CP  ((UINT)-1)
 
+#ifndef CP_UTF8
+#define CP_UTF8 65001
+#endif
+
+#define CP_USA      437  // United States (OEM)
+
 #define CP_SHIFTJIS 932  // Japanese Shift-JIS
 #define CP_HANGUL   949  // Korean Hangul/Wansung
 #define CP_JOHAB    1361 // Korean Johab
@@ -70,15 +75,27 @@ BYTE
 CodePageToCharSet(
     _In_ UINT CodePage);
 
+// FIXME: Will be redefined once we support a font cache.
+typedef struct _FONT_DATA
+{
+    _Inout_updates_z_(LF_FACESIZE) PWSTR FaceName;
+    ULONG Weight;
+    ULONG Family;
+    COORD Size;
+    BYTE  CharSet;
+} FONT_DATA, *PFONT_DATA;
+
 HFONT
 CreateConsoleFontEx(
     _In_     LONG Height,
     _In_opt_ LONG Width,
     _Inout_updates_z_(LF_FACESIZE)
          PWSTR FaceName,
-    _In_ ULONG FontFamily,
     _In_ ULONG FontWeight,
-    _In_ UINT  CodePage);
+    _In_ ULONG FontFamily,
+    _In_ UINT  CodePage,
+    _In_ BOOL  UseDefaultFallback,
+    _Out_ PFONT_DATA FontData);
 
 HFONT
 CreateConsoleFont2(
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c 
b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
index a1d180d5f93..8b6f67c7e9d 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
@@ -3,7 +3,7 @@
  * PROJECT:         ReactOS Console Server DLL
  * FILE:            win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
  * PURPOSE:         GUI Console Window Class
- * PROGRAMMERS:     G� van Geldorp
+ * PROGRAMMERS:     Gé van Geldorp
  *                  Johannes Anderwald
  *                  Jeffrey Morlan
  *                  Hermes Belusca-Maito ([email protected])
@@ -518,31 +518,54 @@ CreateDerivedFont(HFONT OrgFont,
 }
 
 BOOL
-InitFonts(PGUI_CONSOLE_DATA GuiData,
-          LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements.
-          ULONG  FontFamily,
-          COORD  FontSize,
-          ULONG  FontWeight)
+InitFonts(
+    _Inout_ PGUI_CONSOLE_DATA GuiData,
+    _In_reads_or_z_(LF_FACESIZE)
+         PCWSTR FaceName,
+    _In_ ULONG FontWeight,
+    _In_ ULONG FontFamily,
+    _In_ COORD FontSize,
+    _In_opt_ UINT CodePage,
+    _In_ BOOL UseDefaultFallback)
 {
     HDC hDC;
     HFONT hFont;
+    FONT_DATA FontData;
+    UINT OldCharWidth  = GuiData->CharWidth;
+    UINT OldCharHeight = GuiData->CharHeight;
+    COORD OldFontSize  = GuiData->GuiInfo.FontSize;
+    WCHAR NewFaceName[LF_FACESIZE];
+
+    /* Default to current code page if none has been provided */
+    if (!CodePage)
+        CodePage = GuiData->Console->OutputCodePage;
 
     /*
-     * Initialize a new NORMAL font and get its character cell size.
+     * Initialize a new NORMAL font.
      */
+
+    /* Copy the requested face name into the local buffer.
+     * It will be modified in output by CreateConsoleFontEx()
+     * to hold a possible fallback font face name. */
+    StringCchCopyNW(NewFaceName, ARRAYSIZE(NewFaceName),
+                    FaceName, LF_FACESIZE);
+
     /* NOTE: FontSize is always in cell height/width units (pixels) */
     hFont = CreateConsoleFontEx((LONG)(ULONG)FontSize.Y,
                                 (LONG)(ULONG)FontSize.X,
-                                FaceName,
-                                FontFamily,
+                                NewFaceName,
                                 FontWeight,
-                                GuiData->Console->OutputCodePage);
-    if (hFont == NULL)
+                                FontFamily,
+                                CodePage,
+                                UseDefaultFallback,
+                                &FontData);
+    if (!hFont)
     {
-        DPRINT1("InitFonts: CreateConsoleFontEx failed\n");
+        DPRINT1("InitFonts: CreateConsoleFontEx('%S') failed\n", NewFaceName);
         return FALSE;
     }
 
+    /* Retrieve its character cell size */
     hDC = GetDC(GuiData->hWindow);
     if (!GetFontCellSize(hDC, hFont, &GuiData->CharHeight, 
&GuiData->CharWidth))
     {
@@ -561,35 +584,43 @@ InitFonts(PGUI_CONSOLE_DATA GuiData,
     GuiData->Font[FONT_NORMAL] = hFont;
 
     /*
-     * Now build the other fonts (bold, underlined, mixed).
+     * Now build the optional fonts (bold, underlined, mixed).
+     * Do not error in case they fail to be created.
      */
     GuiData->Font[FONT_BOLD] =
         CreateDerivedFont(GuiData->Font[FONT_NORMAL],
-                          FontWeight < FW_BOLD ? FW_BOLD : FontWeight,
+                          max(FW_BOLD, FontData.Weight),
                           FALSE,
                           FALSE);
     GuiData->Font[FONT_UNDERLINE] =
         CreateDerivedFont(GuiData->Font[FONT_NORMAL],
-                          FontWeight,
+                          FontData.Weight,
                           TRUE,
                           FALSE);
     GuiData->Font[FONT_BOLD | FONT_UNDERLINE] =
         CreateDerivedFont(GuiData->Font[FONT_NORMAL],
-                          FontWeight < FW_BOLD ? FW_BOLD : FontWeight,
+                          max(FW_BOLD, FontData.Weight),
                           TRUE,
                           FALSE);
 
     /*
-     * Save the settings.
+     * Save the new font characteristics.
      */
-    if (FaceName != GuiData->GuiInfo.FaceName)
+    StringCchCopyNW(GuiData->GuiInfo.FaceName,
+                    ARRAYSIZE(GuiData->GuiInfo.FaceName),
+                    NewFaceName, ARRAYSIZE(NewFaceName));
+    GuiData->GuiInfo.FontWeight = FontData.Weight;
+    GuiData->GuiInfo.FontFamily = FontData.Family;
+    GuiData->GuiInfo.FontSize   = FontData.Size;
+
+    /* Resize the terminal, in case the new font has a different size */
+    if ((OldCharWidth  != GuiData->CharWidth)  ||
+        (OldCharHeight != GuiData->CharHeight) ||
+        (OldFontSize.X != FontData.Size.X ||
+         OldFontSize.Y != FontData.Size.Y))
     {
-        StringCchCopyNW(GuiData->GuiInfo.FaceName, 
ARRAYSIZE(GuiData->GuiInfo.FaceName),
-                        FaceName, LF_FACESIZE);
+        TermResizeTerminal(GuiData->Console);
     }
-    GuiData->GuiInfo.FontFamily = FontFamily;
-    GuiData->GuiInfo.FontSize   = FontSize;
-    GuiData->GuiInfo.FontWeight = FontWeight;
 
     return TRUE;
 }
@@ -615,14 +646,40 @@ OnNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
     /* Initialize the fonts */
     if (!InitFonts(GuiData,
                    GuiData->GuiInfo.FaceName,
+                   GuiData->GuiInfo.FontWeight,
                    GuiData->GuiInfo.FontFamily,
                    GuiData->GuiInfo.FontSize,
-                   GuiData->GuiInfo.FontWeight))
+                   0, FALSE))
     {
-        DPRINT1("GuiConsoleNcCreate: InitFonts failed\n");
-        GuiData->hWindow = NULL;
-        NtSetEvent(GuiData->hGuiInitEvent, NULL);
-        return FALSE;
+        /* Reset only the output code page if we don't have a suitable
+         * font for it, possibly falling back to "United States (OEM)". */
+        UINT AltCodePage = GetOEMCP();
+
+        if (AltCodePage == Console->OutputCodePage)
+            AltCodePage = CP_USA;
+
+        DPRINT1("Could not initialize font '%S' for code page %d - Resetting 
CP to %d\n",
+                GuiData->GuiInfo.FaceName, Console->OutputCodePage, 
AltCodePage);
+
+        CON_SET_OUTPUT_CP(Console, AltCodePage);
+
+        /* We will use a fallback font if we cannot find
+         * anything for this replacement code page. */
+        if (!InitFonts(GuiData,
+                       GuiData->GuiInfo.FaceName,
+                       GuiData->GuiInfo.FontWeight,
+                       GuiData->GuiInfo.FontFamily,
+                       GuiData->GuiInfo.FontSize,
+                       0, TRUE))
+        {
+            DPRINT1("Failed to initialize font '%S' for code page %d\n",
+                    GuiData->GuiInfo.FaceName, Console->OutputCodePage);
+
+            DPRINT1("GuiConsoleNcCreate: InitFonts failed\n");
+            GuiData->hWindow = NULL;
+            NtSetEvent(GuiData->hGuiInitEvent, NULL);
+            return FALSE;
+        }
     }
 
     /* Initialize the terminal framebuffer */
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c 
b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
index 1ee89ed8a47..38dec0bbd75 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
@@ -163,9 +163,9 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
         /* GUI Information */
         StringCchCopyNW(pSharedInfo->FaceName, 
ARRAYSIZE(pSharedInfo->FaceName),
                         GuiData->GuiInfo.FaceName, 
ARRAYSIZE(GuiData->GuiInfo.FaceName));
+        pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight;
         pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily;
         pSharedInfo->FontSize   = GuiData->GuiInfo.FontSize;
-        pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight;
         pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen;
         pSharedInfo->AutoPosition   = GuiData->GuiInfo.AutoPosition;
         pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin;
@@ -312,28 +312,29 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
 
         // TODO: Check that GuiData->hWindow == pConInfo->hWnd
 
-        /* Retrieve terminal informations */
-
         /* Console information */
 
         /*
          * Apply the settings
          */
 
-        /* Set the console informations */
+        /* Refresh the additional TrueType fonts cache now,
+         * as ConSrvApplyUserSettings() could change the output
+         * code page and trigger a font change in the terminal. */
+        RefreshTTFontCache();
+
+        /* Apply the generic console settings */
         ConSrvApplyUserSettings(Console, pConInfo);
 
-        /* Set the terminal informations */
+        /* Set the terminal settings */
 
-        /* Refresh the additional TrueType fonts cache and change the font */
-        RefreshTTFontCache();
+        /* Now, attempt to change the font to what the user specified */
         InitFonts(GuiData,
                   pConInfo->FaceName,
+                  pConInfo->FontWeight,
                   pConInfo->FontFamily,
                   pConInfo->FontSize,
-                  pConInfo->FontWeight);
-       // HACK, needed because changing font may change the size of the window
-       /**/TermResizeTerminal(Console);/**/
+                  0, FALSE);
 
         /* Move the window to the user's values */
         GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition;
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h 
b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h
index e67c537ee8f..71e968a57a6 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h
@@ -16,9 +16,9 @@
 typedef struct _GUI_CONSOLE_INFO
 {
     WCHAR FaceName[LF_FACESIZE];
+    ULONG FontWeight;
     ULONG FontFamily;
     COORD FontSize;
-    ULONG FontWeight;
 
     BOOL  FullScreen;       /* Whether the console is displayed in full-screen 
or windowed mode */
 //  ULONG HardwareState;    /* _GDI_MANAGED, _DIRECT */
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c 
b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
index 778b11073c1..0594ff4a0c8 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
@@ -3,7 +3,7 @@
  * PROJECT:         ReactOS Console Server DLL
  * FILE:            win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
  * PURPOSE:         GUI Terminal Front-End
- * PROGRAMMERS:     G� van Geldorp
+ * PROGRAMMERS:     Gé van Geldorp
  *                  Johannes Anderwald
  *                  Jeffrey Morlan
  *                  Hermes Belusca-Maito ([email protected])
@@ -1038,9 +1038,28 @@ static BOOL NTAPI
 GuiSetCodePage(IN OUT PFRONTEND This,
                UINT CodePage)
 {
-    // TODO: Find a suitable console font for the given code page,
-    // and set it if found; otherwise fail the call, or fall back
-    // to some default font...
+    PGUI_CONSOLE_DATA GuiData = This->Context;
+
+    /*
+     * Attempt to reinitialize the current font for the new code page,
+     * trying to keep the current font with the same characteristics.
+     * If the current font does not support the new code page, switch
+     * to a different font supporting the code page but having similar
+     * characteristics.
+     * If no font can be found for this code page, stay using the
+     * original font and refuse changing the code page.
+     */
+    if (!InitFonts(GuiData,
+                   GuiData->GuiInfo.FaceName,
+                   GuiData->GuiInfo.FontWeight,
+                   GuiData->GuiInfo.FontFamily,
+                   GuiData->GuiInfo.FontSize,
+                   CodePage, FALSE))
+    {
+        DPRINT1("Failed to initialize font '%S' for code page %d - Refuse CP 
change\n",
+                GuiData->GuiInfo.FaceName, CodePage);
+        return FALSE;
+    }
 
     return TRUE;
 }
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h 
b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
index 4ed6c1e8c19..e83f2a0cf96 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
+++ b/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
@@ -3,7 +3,7 @@
  * PROJECT:         ReactOS Console Server DLL
  * FILE:            win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
  * PURPOSE:         GUI Terminal Front-End
- * PROGRAMMERS:     G� van Geldorp
+ * PROGRAMMERS:     Gé van Geldorp
  *                  Johannes Anderwald
  *                  Jeffrey Morlan
  *                  Hermes Belusca-Maito ([email protected])
@@ -65,11 +65,16 @@ GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData);
 /* conwnd.c */
 
 BOOL
-InitFonts(PGUI_CONSOLE_DATA GuiData,
-          LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements.
-          ULONG  FontFamily,
-          COORD  FontSize,
-          ULONG  FontWeight);
+InitFonts(
+    _Inout_ PGUI_CONSOLE_DATA GuiData,
+    _In_reads_or_z_(LF_FACESIZE)
+         PCWSTR FaceName,
+    _In_ ULONG FontWeight,
+    _In_ ULONG FontFamily,
+    _In_ COORD FontSize,
+    _In_opt_ UINT CodePage,
+    _In_ BOOL UseDefaultFallback);
+
 VOID
 DeleteFonts(PGUI_CONSOLE_DATA GuiData);
 

Reply via email to