[CONSOLE.CPL]: Rewrite the way we deal with console font samples in the console prope...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 3 May 2017 23:56:35 +0000 (23:56 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 3 May 2017 23:56:35 +0000 (23:56 +0000)
- Remove the font helper functions that were already moved into concfg/font.c in r74462, and use the latter instead.
- Use a double list for listing the available font sizes for a given face:
  * a ListBox for raster fonts;
  * a ComboBox for TrueType fonts, allowing the user to specify a custom size.
  The raster ListBox is wrapped using the LIST_CTL structure so that we can use
  the bisection functions on it.
- Allow the user to specify TrueType font size either in pixels or in points. Raster font sizes however are always in pixels.
- Try to remember the nearest font size across different selected face changes.
- Try to support custom-sized TrueType fonts (using the ComboBox's edit field). May need more improvements!
- Retrieve the correct character cell height & width size in pixels when selecting a font (especially when it's a TrueType one).
- We now support bold console fonts too, see CORE-13122 (thanks Katayama!).
- Remove the commented-out "temporary code for future reference".
- Use a global cached font "hCurrentFont" that gets initialized when the console properties applet is created,
  so that we now can have a correct font in the screen samples when one directly views e.g. the "Color" tab,
  without going first in the "Font" tab. This current font is of course updated whenever one changes the font settings.

Tested with success on Windows 2003, Windows 7 and on ReactOS.

CORE-13122 CORE-13182 #resolve

svn path=/trunk/; revision=74469

reactos/dll/cpl/console/console.c
reactos/dll/cpl/console/console.h
reactos/dll/cpl/console/font.c
reactos/dll/cpl/console/layout.c

index d4fd181..0fd16b5 100644 (file)
@@ -88,7 +88,7 @@ VOID
 ApplyConsoleInfo(HWND hwndDlg)
 {
     static BOOL ConsoleInfoAlreadySaved = FALSE;
 ApplyConsoleInfo(HWND hwndDlg)
 {
     static BOOL ConsoleInfoAlreadySaved = FALSE;
-    
+
     /*
      * We already applied all the console properties (and saved if needed).
      * Nothing more needs to be done.
     /*
      * We already applied all the console properties (and saved if needed).
      * Nothing more needs to be done.
@@ -210,6 +210,11 @@ InitApplet(HANDLE hSectionOrWnd)
         InitDefaultConsoleInfo(ConInfo);
     }
 
         InitDefaultConsoleInfo(ConInfo);
     }
 
+    /* Initialize the font support */
+    hCurrentFont = CreateConsoleFont(ConInfo);
+    if (hCurrentFont == NULL)
+        DPRINT1("InitApplet: CreateConsoleFont failed\n");
+
     /* Initialize the property sheet structure */
     ZeroMemory(&psh, sizeof(psh));
     psh.dwSize = sizeof(psh);
     /* Initialize the property sheet structure */
     ZeroMemory(&psh, sizeof(psh));
     psh.dwSize = sizeof(psh);
@@ -250,8 +255,14 @@ InitApplet(HANDLE hSectionOrWnd)
     InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , LayoutProc );
     InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , ColorsProc );
 
     InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , LayoutProc );
     InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , ColorsProc );
 
+    /* Display the property sheet */
     Result = PropertySheetW(&psh);
     Result = PropertySheetW(&psh);
-    
+
+    /* First cleanup */
+    if (hCurrentFont) DeleteObject(hCurrentFont);
+    hCurrentFont = NULL;
+
+    /* Save the console settings */
     if (SetConsoleInfo)
     {
         HANDLE hSection;
     if (SetConsoleInfo)
     {
         HANDLE hSection;
@@ -286,9 +297,7 @@ InitApplet(HANDLE hSectionOrWnd)
         UnmapViewOfFile(pSharedInfo);
 
         /* Signal to CONSRV that it can apply the new configuration */
         UnmapViewOfFile(pSharedInfo);
 
         /* Signal to CONSRV that it can apply the new configuration */
-        SendMessage(ConInfo->hWnd,
-                    WM_SETCONSOLEINFO,
-                    (WPARAM)hSection, 0);
+        SendMessageW(ConInfo->hWnd, WM_SETCONSOLEINFO, (WPARAM)hSection, 0);
 
         /* Close the section and return */
         CloseHandle(hSection);
 
         /* Close the section and return */
         CloseHandle(hSection);
@@ -299,7 +308,7 @@ InitApplet(HANDLE hSectionOrWnd)
         /* Default settings saved when ConInfo->hWnd == NULL */
         ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL);
     }
         /* Default settings saved when ConInfo->hWnd == NULL */
         ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL);
     }
-    
+
 Quit:
     /* Cleanup */
     HeapFree(GetProcessHeap(), 0, ConInfo);
 Quit:
     /* Cleanup */
     HeapFree(GetProcessHeap(), 0, ConInfo);
index 442cd92..eaea53d 100644 (file)
@@ -2,17 +2,20 @@
 #define CONSOLE_H__
 
 #include <stdio.h>
 #define CONSOLE_H__
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <wchar.h>
 
 #define WIN32_NO_STATUS
 
 #include <windef.h>
 #include <winbase.h>
 #include <wchar.h>
 
 #define WIN32_NO_STATUS
 
 #include <windef.h>
 #include <winbase.h>
+
+#include <wincon.h>
 #include <wingdi.h>
 #include <winnls.h>
 #include <winreg.h>
 #include <wingdi.h>
 #include <winnls.h>
 #include <winreg.h>
+
 #include <winuser.h>
 #include <winuser.h>
-#include <wincon.h>
 #include <commctrl.h>
 #include <cpl.h>
 
 #include <commctrl.h>
 #include <cpl.h>
 
@@ -24,7 +27,7 @@
     EnableWindow(GetDlgItem((hDlg), (nID)), (bEnable))
 
 /* Shared header with the GUI Terminal Front-End from consrv.dll */
     EnableWindow(GetDlgItem((hDlg), (nID)), (bEnable))
 
 /* Shared header with the GUI Terminal Front-End from consrv.dll */
-#include "settings.h" // in /winsrv/concfg/
+#include "concfg.h" // in /winsrv/concfg/
 
 typedef enum _TEXT_TYPE
 {
 
 typedef enum _TEXT_TYPE
 {
@@ -33,12 +36,22 @@ typedef enum _TEXT_TYPE
 } TEXT_TYPE;
 
 /* Globals */
 } TEXT_TYPE;
 
 /* Globals */
+extern HINSTANCE hApplet;
 extern PCONSOLE_STATE_INFO ConInfo;
 extern PCONSOLE_STATE_INFO ConInfo;
+extern HFONT hCurrentFont;
 
 VOID ApplyConsoleInfo(HWND hwndDlg);
 
 VOID ApplyConsoleInfo(HWND hwndDlg);
-BYTE CodePageToCharSet(UINT CodePage);
-VOID PaintConsole(LPDRAWITEMSTRUCT drawItem, PCONSOLE_STATE_INFO pConInfo);
-BOOL PaintText(LPDRAWITEMSTRUCT drawItem, PCONSOLE_STATE_INFO pConInfo, TEXT_TYPE TextMode);
+
+VOID
+PaintConsole(
+    IN LPDRAWITEMSTRUCT drawItem,
+    IN PCONSOLE_STATE_INFO pConInfo);
+
+BOOL
+PaintText(
+    IN LPDRAWITEMSTRUCT drawItem,
+    IN PCONSOLE_STATE_INFO pConInfo,
+    IN TEXT_TYPE TextMode);
 
 
 struct _LIST_CTL;
 
 
 struct _LIST_CTL;
index e84896f..83c8a23 100644 (file)
 #include <debug.h>
 
 
 #include <debug.h>
 
 
-//
-// Some temporary code for future reference...
-//
-#if 0
 /*
 /*
- * This code comes from PuTTY
+ * Current active font, corresponding to the active console font,
+ * and used for painting the text samples.
  */
  */
-{
-    CHOOSEFONT cf;
-    LOGFONT lf;
-    HDC hdc;
-    FontSpec *fs = (FontSpec *)c->data;
-
-    hdc = GetDC(0);
-    lf.lfHeight = -MulDiv(fs->height,
-              GetDeviceCaps(hdc, LOGPIXELSY), 72);
-    ReleaseDC(0, hdc);
-    lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
-    lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
-    lf.lfWeight = (fs->isbold ? FW_BOLD : 0);
-    lf.lfCharSet = fs->charset;
-    lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
-    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
-    lf.lfQuality = DEFAULT_QUALITY;
-    lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
-    strncpy(lf.lfFaceName, fs->name,
-        sizeof(lf.lfFaceName) - 1);
-    lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
-
-    cf.lStructSize = sizeof(cf);
-    cf.hwndOwner = dp->hwnd;
-    cf.lpLogFont = &lf;
-    cf.Flags = (dp->fixed_pitch_fonts ? CF_FIXEDPITCHONLY : 0) |
-            CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
-
-    if (ChooseFont(&cf)) {
-            fs = fontspec_new(lf.lfFaceName, (lf.lfWeight == FW_BOLD),
-                              cf.iPointSize / 10, lf.lfCharSet);
-    dlg_fontsel_set(ctrl, dp, fs);
-            fontspec_free(fs);
-
-    ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
-    }
-}
+HFONT hCurrentFont = NULL;
+
 
 /*
 
 /*
- * This code is from consrv.
+ * Standard font pixel/point heights for TrueType fonts
  */
  */
+static const SHORT TrueTypePoints[] =
 {
 {
-    if (!GetTextMetricsW(drawItem->hDC, &Metrics))
-    {
-        DPRINT1("PaintText: GetTextMetrics failed\n");
-        SelectObject(drawItem->hDC, OldFont);
-        DeleteObject(Font);
-        return;
-    }
-    GuiData->CharWidth  = Metrics.tmMaxCharWidth;
-    GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
+    5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
+};
 
 
-    /* Measure real char width more precisely if possible */
-    if (GetTextExtentPoint32W(drawItem->hDC, L"R", 1, &CharSize))
-        GuiData->CharWidth = CharSize.cx;
+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
+
+
+// PLIST_GETCOUNT
+static INT
+RasterSizeList_GetCount(
+    IN PLIST_CTL ListCtl)
+{
+    return (INT)SendMessageW(ListCtl->hWndList, LB_GETCOUNT, 0, 0);
 }
 
 }
 
-/*
- * See also: Display_SetTypeFace in applications/fontview/display.c
- */
-#endif
+// 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);
+}
 
 
 
 
-/*
- * Font pixel heights for TrueType fonts
- */
-static SHORT TrueTypePoints[] =
+INT
+LogicalSizeToPointSize(
+    IN HDC hDC OPTIONAL,
+    IN UINT LogicalSize)
 {
 {
-    // 8, 9, 10, 11, 12, 14, 16, 18, 20,
-    // 22, 24, 26, 28, 36, 48, 72
-    5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
-};
+    INT PointSize;
+    HDC hOrgDC = hDC;
+
+    if (!hDC)
+        hDC = GetDC(NULL);
 
 
-#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)
+    // LogicalSize = tm.tmHeight - tm.tmInternalLeading;
+    PointSize = MulDiv(LogicalSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
 
 
-/* IsFarEastCP(CodePage) */
-#define IsCJKCodePage(CodePage) \
-    ((CodePage) == CP_SHIFTJIS || (CodePage) == CP_HANGUL || \
-     (CodePage) == CP_BIG5     || (CodePage) == CP_GB2312)
+    if (!hOrgDC)
+        ReleaseDC(NULL, hDC);
+
+    return PointSize;
+}
+
+INT
+PointSizeToLogicalSize(
+    IN HDC hDC OPTIONAL,
+    IN INT PointSize)
+{
+    INT LogicalSize;
+    HDC hOrgDC = hDC;
 
 
-/* Retrieves the character set associated with a given code page */
-BYTE CodePageToCharSet(UINT CodePage)
+    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)
 {
 {
-    CHARSETINFO CharInfo;
-    if (TranslateCharsetInfo((LPDWORD)CodePage, &CharInfo, TCI_SRCCODEPAGE))
-        return CharInfo.ciCharset;
+    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 = SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
+        if (nSel == CB_ERR)
+        {
+            nSel = (UINT)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;
+    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
     else
-        return DEFAULT_CHARSET;
+    {
+        /* 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.
+             */
+            nSel = SendMessageW(SizeList->hWndTTSizeList, CB_GETCURSEL, 0, 0);
+            SendMessageW(SizeList->hWndTTSizeList, CB_GETLBTEXT, nSel, (LPARAM)szFontSize);
+        }
+        else
+        {
+            /* Read the ComboBox edit string, as the user has entered a custom size */
+            // ComboBox_GetText(...)
+            GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
+
+            // HACK???
+            nSel = SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
+            if (nSel == CB_ERR)
+            {
+                nSel = (UINT)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;
+
+        /* If _wtol fails and returns 0, the font size is considered invalid */
+        // FontSize = wcstoul(szFontSize, &pszNext, 10); if (!*pszNext) { /* Error */ }
+        FontSize = _wtol(szFontSize);
+        if (FontSize == 0) return 0;
+
+        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,
 }
 
 
 static VOID
 AddFontToList(
     IN HWND hWndList,
-    IN LPCWSTR pszFontName,
+    IN LPCWSTR pszFaceName,
     IN DWORD FontType)
 {
     IN DWORD FontType)
 {
-    INT idx;
+    INT iItem;
 
     /* Make sure the font doesn't already exist in the list */
 
     /* Make sure the font doesn't already exist in the list */
-    if (SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)pszFontName) != LB_ERR)
+    if (SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)pszFaceName) != LB_ERR)
         return;
 
     /* Add the font */
         return;
 
     /* Add the font */
-    idx = (INT)SendMessageW(hWndList, LB_ADDSTRING, 0, (LPARAM)pszFontName);
-    if (idx == LB_ERR)
+    iItem = (INT)SendMessageW(hWndList, LB_ADDSTRING, 0, (LPARAM)pszFaceName);
+    if (iItem == LB_ERR)
     {
     {
-        DPRINT1("Failed to add font '%S'\n", pszFontName);
+        DPRINT1("Failed to add font '%S'\n", pszFaceName);
         return;
     }
 
         return;
     }
 
-    DPRINT1("Add font '%S'\n", pszFontName);
+    DPRINT1("Add font '%S'\n", pszFaceName);
 
     /* Store this information in the list-item's userdata area */
 
     /* Store this information in the list-item's userdata area */
-    // SendMessageW(hWndList, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType));
-    SendMessageW(hWndList, LB_SETITEMDATA, idx, (WPARAM)FontType);
+    // SendMessageW(hWndList, LB_SETITEMDATA, idx, MAKELPARAM(fFixed, fTrueType));
+    SendMessageW(hWndList, LB_SETITEMDATA, iItem, (LPARAM)FontType);
 }
 
 }
 
-static BOOL CALLBACK
-EnumFontNamesProc(PLOGFONTW lplf,
-                  PNEWTEXTMETRICW lpntm,
-                  DWORD  FontType,
-                  LPARAM lParam)
+typedef struct _FACE_NAMES_PROC_PARAM
 {
 {
-    HWND hwndCombo = (HWND)lParam;
-    LPWSTR pszName = lplf->lfFaceName;
+    HWND hWndList;
+    UINT CodePage;
+} FACE_NAMES_PROC_PARAM, *PFACE_NAMES_PROC_PARAM;
 
 
-    /* Record the font's attributes (Fixedwidth and Truetype) */
-    // BOOL fFixed    = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
-    // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
+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;
 
     /*
 
     /*
-     * According to: http://support.microsoft.com/kb/247815
-     * the criteria for console-eligible fonts are:
-     * - 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.
-     * - If it is a TrueType font, it must be FF_MODERN.
-     * - If it is not a TrueType font, it must be OEM_CHARSET.
-     *
-     * Non documented: vertical fonts are forbidden (their name start with a '@').
-     *
-     * Additional criteria for Asian installations:
-     * - 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.
-     *
      * 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
      */
      * 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
      */
-
-     /*
-      * 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)
-#endif
-        )
+    if (IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
     {
     {
-        DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
-                pszName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
-                                                                 : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
-                                                                                                            : " is broken"),
-                lplf->lfPitchAndFamily);
-        return TRUE;
+        /* Add the font to the list */
+        AddFontToList(Param->hWndList, lplf->lfFaceName, FontType);
     }
 
     }
 
-    /* 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",
-                pszName, lplf->lfPitchAndFamily);
-        return TRUE;
-    }
+    /* Continue the font enumeration */
+    return TRUE;
+}
 
 
-    /* Is the current code page Chinese, Japanese or Korean? */
-    if (IsCJKCodePage(ConInfo->CodePage))
+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)
     {
     {
-        /* It's Asian */
-        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)
         {
         {
-            if (lplf->lfCharSet != CodePageToCharSet(ConInfo->CodePage))
-            {
-                DPRINT1("TrueType font '%S' rejected because it's not user Asian charset (lfCharSet = %d)\n",
-                        pszName, lplf->lfCharSet);
-                return TRUE;
-            }
-        }
-        else
-        {
-            /* Reject non-TrueType fonts that are not Terminal */
-            if (wcscmp(pszName, L"Terminal") != 0)
-            {
-                DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", pszName);
-                return TRUE;
-            }
+            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
     {
     }
     else
     {
-        /* Not CJK */
-        if ((FontType != TRUETYPE_FONTTYPE) &&
-            (lplf->lfCharSet != ANSI_CHARSET) &&
-            (lplf->lfCharSet != DEFAULT_CHARSET) &&
-            (lplf->lfCharSet != OEM_CHARSET))
+        /* TrueType or vectored font: list all the hardcoded font points */
+        ULONG i;
+        for (i = 0; i < ARRAYSIZE(TrueTypePoints); ++i)
         {
         {
-            DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
-                    pszName, lplf->lfCharSet);
-            return TRUE;
+            // _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;
+
+    Param.hWndList = hWndList;
+    Param.CodePage = CodePage;
+
+    ZeroMemory(&lf, sizeof(lf));
+    lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
+    // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
 
 
-    /* Reject fonts that are vertical (tategaki) */
-    if (pszName[0] == L'@')
+    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)
     {
     {
-        DPRINT1("Font '%S' rejected because it's vertical\n", pszName);
-        return TRUE;
+        /* We have found some fonts and filled the list, we are fine! */
+        return;
     }
 
     }
 
-    /* Add the font to the list */
-    AddFontToList(hwndCombo, pszName, /* MAKEWPARAM(fFixed, fTrueType) */ FontType);
+    /* No fonts were found. Manually add default ones into the list. */
+    DPRINT1("The ideal console fonts were not found; manually add default ones.\n");
 
 
-    return TRUE;
+    AddFontToList(hWndList, L"Terminal", RASTER_FONTTYPE);
+    AddFontToList(hWndList, L"Lucida Console", TRUETYPE_FONTTYPE);
+    if (CodePageToCharSet(CodePage) != DEFAULT_CHARSET)
+        AddFontToList(hWndList, L"Droid Sans Fallback", TRUETYPE_FONTTYPE);
 }
 
 }
 
-static BOOL CALLBACK
-EnumFontSizesProc(PLOGFONTW lplf,
-                  PNEWTEXTMETRICW lpntm,
-                  DWORD  FontType,
-                  LPARAM lParam)
+static VOID
+FaceNameList_SelectFaceName(
+    IN HWND hWndList,
+    IN LPCWSTR FaceName)
 {
 {
-    HWND hwndCombo = (HWND)lParam;
-    WCHAR FontSize[100];
+    INT iItem;
 
 
-    if (FontType != TRUETYPE_FONTTYPE)
+    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);
+
+    // return iItem;
+}
+
+static VOID
+UpdateFontSizeList(
+    IN HWND hDlg,
+    IN PFONTSIZE_LIST_CTL SizeList)
+{
+    HWND hDlgItem;
+
+    if (SizeList->UseRasterOrTTList)
     {
     {
-        // int logsize     = lpntm->tmHeight - lpntm->tmInternalLeading;
-        // LONG pointsize  = MulDiv(logsize, 72, GetDeviceCaps(hdc, LOGPIXELSY));
+        /*
+         * Raster font: show the Raster size list, and
+         * hide the TrueType size list and the units.
+         */
 
 
-        // swprintf(FontSize, L"%2d (%d x %d)", pointsize, lplf->lfWidth, lplf->lfHeight);
-        swprintf(FontSize, L"%d x %d", lplf->lfWidth, lplf->lfHeight);
+        // EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, FALSE);
 
 
-        /* Make sure the size doesn't already exist in the list */
-        if (SendMessageW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)FontSize) == LB_ERR)
-        {
-            /* Add the size */
-            INT idx = (INT)SendMessageW(hwndCombo, LB_ADDSTRING, 0, (LPARAM)FontSize);
+        hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
+        ShowWindow(hDlgItem, SW_HIDE);
+        EnableWindow(hDlgItem, FALSE);
 
 
-            /*
-             * Store this information in the list-item's userdata area.
-             * Format:
-             * Width  = FontSize.X = LOWORD(FontSize);
-             * Height = FontSize.Y = HIWORD(FontSize);
-             */
-            SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(lplf->lfWidth, lplf->lfHeight));
-        }
+        hDlgItem = GetDlgItem(hDlg, IDC_RADIO_POINT_UNIT);
+        ShowWindow(hDlgItem, SW_HIDE);
+        EnableWindow(hDlgItem, FALSE);
 
 
-        return TRUE;
+        hDlgItem = SizeList->hWndTTSizeList;
+        ShowWindow(hDlgItem, SW_HIDE);
+        EnableWindow(hDlgItem, FALSE);
+
+        hDlgItem = SizeList->RasterSizeList.hWndList;
+        EnableWindow(hDlgItem, TRUE);
+        ShowWindow(hDlgItem, SW_SHOW);
     }
     else
     {
     }
     else
     {
-        ULONG i;
-        for (i = 0; i < ARRAYSIZE(TrueTypePoints); ++i)
-        {
-            swprintf(FontSize, L"%2d", TrueTypePoints[i]);
+        /*
+         * TrueType font: show the TrueType size list
+         * and the units, and hide the Raster size list.
+         */
 
 
-            /* Make sure the size doesn't already exist in the list */
-            if (SendMessageW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)FontSize) == LB_ERR)
-            {
-                /* Add the size */
-                INT idx = (INT)SendMessageW(hwndCombo, LB_ADDSTRING, 0, (LPARAM)FontSize);
-
-                /*
-                 * Store this information in the list-item's userdata area.
-                 * Format:
-                 * Width  = FontSize.X = LOWORD(FontSize);
-                 * Height = FontSize.Y = HIWORD(FontSize);
-                 */
-                SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(0, TrueTypePoints[i]));
-            }
-        }
+        // EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, TRUE);
 
 
-        return FALSE;
-    }
-}
+        hDlgItem = SizeList->RasterSizeList.hWndList;
+        ShowWindow(hDlgItem, SW_HIDE);
+        EnableWindow(hDlgItem, FALSE);
 
 
+        hDlgItem = SizeList->hWndTTSizeList;
+        EnableWindow(hDlgItem, TRUE);
+        ShowWindow(hDlgItem, SW_SHOW);
 
 
-static VOID
-FontSizeChange(HWND hwndDlg,
-               PCONSOLE_STATE_INFO pConInfo);
+        hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
+        EnableWindow(hDlgItem, TRUE);
+        ShowWindow(hDlgItem, SW_SHOW);
 
 
-static VOID
-FontTypeChange(HWND hwndDlg,
-               PCONSOLE_STATE_INFO pConInfo)
+        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 hListBox = GetDlgItem(hwndDlg, IDC_LBOX_FONTTYPE);
+    HWND hListBox = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
     INT Length, nSel;
     INT Length, nSel;
-    LPWSTR FaceName;
-    HDC hDC;
     LOGFONTW lf;
     LOGFONTW lf;
+    LPWSTR FaceName;
+    DWORD FontType;
+    LPCWSTR FontGrpBoxLabelTpl = NULL;
+    WCHAR FontGrpBoxLabel[260];
 
     nSel = (INT)SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
 
     nSel = (INT)SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
-    if (nSel == LB_ERR) return;
+    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(hListBox, LB_GETTEXTLEN, nSel, 0);
 
     Length = (INT)SendMessageW(hListBox, LB_GETTEXTLEN, nSel, 0);
-    if (Length == LB_ERR) return;
+    if (Length == LB_ERR) return FALSE;
 
     FaceName = HeapAlloc(GetProcessHeap(),
                          HEAP_ZERO_MEMORY,
                          (Length + 1) * sizeof(WCHAR));
 
     FaceName = HeapAlloc(GetProcessHeap(),
                          HEAP_ZERO_MEMORY,
                          (Length + 1) * sizeof(WCHAR));
-    if (FaceName == NULL) return;
+    if (FaceName == NULL) return FALSE;
 
     Length = (INT)SendMessageW(hListBox, LB_GETTEXT, nSel, (LPARAM)FaceName);
     FaceName[Length] = L'\0';
 
     Length = (INT)SendMessageW(hListBox, LB_GETTEXT, nSel, (LPARAM)FaceName);
     FaceName[Length] = L'\0';
@@ -353,107 +514,204 @@ FontTypeChange(HWND hwndDlg,
     StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
     DPRINT1("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
 
     StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
     DPRINT1("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
 
-    /* Enumerate the available sizes for the selected font */
     ZeroMemory(&lf, sizeof(lf));
     lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
     // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
     StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), 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);
 
-    hDC = GetDC(NULL);
-    EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontSizesProc,
-                        (LPARAM)GetDlgItem(hwndDlg, IDC_LBOX_FONTSIZE), 0);
-    ReleaseDC(NULL, hDC);
+    /*
+     * 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);
 
 
     HeapFree(GetProcessHeap(), 0, FaceName);
 
-    // TODO: Select a default font size????
-    FontSizeChange(hwndDlg, pConInfo);
+    /*
+     * 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 = SendMessageW(hListBox, 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))
+        {
+            HDC hDC;
+
+            if (SizeList->UseRasterOrTTList)
+                SendMessageW(SizeList->RasterSizeList.hWndList, LB_RESETCONTENT, 0, 0);
+            else
+                SendMessageW(SizeList->hWndTTSizeList, CB_RESETCONTENT, 0, 0);
 
 
-    // InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
-    // InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
+            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 VOID
-FontSizeChange(HWND hwndDlg,
-               PCONSOLE_STATE_INFO pConInfo)
+static BOOL
+FontSizeChange(
+    IN HWND hDlg,
+    IN PFONTSIZE_LIST_CTL SizeList,
+    IN OUT PCONSOLE_STATE_INFO pConInfo)
 {
 {
-    HWND hListBox = GetDlgItem(hwndDlg, IDC_LBOX_FONTSIZE);
-    INT nSel;
-    ULONG FontSize;
-    WCHAR FontSizeStr[20];
+    HDC hDC;
+    LONG CharWidth, CharHeight, FontSize;
+    WCHAR szFontSize[100];
 
 
-    nSel = (INT)SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
-    if (nSel == LB_ERR) return;
+    /*
+     * 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);
+    CharHeight = (SizeList->UseRasterOrTTList ? (LONG)HIWORD(FontSize) : FontSize);
+    CharWidth  = (SizeList->UseRasterOrTTList ? (LONG)LOWORD(FontSize) : 0);
+
+    if (hCurrentFont) DeleteObject(hCurrentFont);
+    hCurrentFont = CreateConsoleFont2(CharHeight, CharWidth, pConInfo);
+    if (hCurrentFont == NULL)
+        DPRINT1("FontSizeChange: CreateConsoleFont2 failed\n");
+
+    /* Retrieve the real character size in pixels */
+    hDC = GetDC(NULL);
+    GetFontCellSize(hDC, hCurrentFont, (PUINT)&CharHeight, (PUINT)&CharWidth);
+    ReleaseDC(NULL, hDC);
 
     /*
      * Format:
      * Width  = FontSize.X = LOWORD(FontSize);
      * Height = FontSize.Y = HIWORD(FontSize);
      */
 
     /*
      * Format:
      * Width  = FontSize.X = LOWORD(FontSize);
      * Height = FontSize.Y = HIWORD(FontSize);
      */
-    FontSize = (ULONG)SendMessageW(hListBox, LB_GETITEMDATA, nSel, 0);
-    if (FontSize == LB_ERR) return;
+    pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? CharWidth : 0);
+    pConInfo->FontSize.Y = (SHORT)CharHeight;
 
 
-    pConInfo->FontSize.X = LOWORD(FontSize);
-    pConInfo->FontSize.Y = HIWORD(FontSize);
-    DPRINT1("pConInfo->FontSize = (%d x %d)\n", pConInfo->FontSize.X, pConInfo->FontSize.Y);
+    DPRINT1("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x %d)\n",
+            pConInfo->FontSize.X, pConInfo->FontSize.Y, CharWidth, CharHeight);
 
 
-    InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
-    InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
+    InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
+    InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
 
 
-    swprintf(FontSizeStr, L"%2d", pConInfo->FontSize.X);
-    SetDlgItemText(hwndDlg, IDC_FONT_SIZE_X, FontSizeStr);
-    swprintf(FontSizeStr, L"%2d", pConInfo->FontSize.Y);
-    SetDlgItemText(hwndDlg, IDC_FONT_SIZE_Y, FontSizeStr);
+    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
 }
 
 
 INT_PTR
 CALLBACK
-FontProc(HWND hwndDlg,
+FontProc(HWND hDlg,
          UINT uMsg,
          WPARAM wParam,
          LPARAM lParam)
 {
          UINT uMsg,
          WPARAM wParam,
          LPARAM lParam)
 {
-    UNREFERENCED_PARAMETER(wParam);
+    PFONTSIZE_LIST_CTL SizeList;
+
+    SizeList = (PFONTSIZE_LIST_CTL)GetWindowLongPtrW(hDlg, DWLP_USER);
 
     switch (uMsg)
     {
         case WM_INITDIALOG:
         {
 
     switch (uMsg)
     {
         case WM_INITDIALOG:
         {
-            HWND hListBox = GetDlgItem(hwndDlg, IDC_LBOX_FONTTYPE);
-            HDC  hDC;
-            LOGFONTW lf;
-            INT idx;
+            HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
 
 
-            ZeroMemory(&lf, sizeof(lf));
-            lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(ConInfo->CodePage);
-            // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+            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);
 
 
-            hDC = GetDC(NULL);
-            EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontNamesProc, (LPARAM)hListBox, 0);
-            ReleaseDC(NULL, hDC);
+            /* By default show the raster font size list */
+            SizeList->UseRasterOrTTList = TRUE;
 
 
-            idx = (INT)SendMessageW(hListBox, LB_GETCOUNT, 0, 0);
-            if ((idx == 0) || (idx == LB_ERR))
-            {
-                DPRINT1("The ideal console fonts are not found; manually add default ones.\n");
+            /* 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;
 
 
-                /* This world is not ideal. We have to do it realistically. */
-                AddFontToList(hListBox, L"Lucida Console", TRUETYPE_FONTTYPE);
-                if (CodePageToCharSet(ConInfo->CodePage) != DEFAULT_CHARSET)
-                    AddFontToList(hListBox, L"Droid Sans Fallback", TRUETYPE_FONTTYPE);
-            }
+            UpdateFontSizeList(hDlg, SizeList);
+
+            /* Initialize the font list */
+            FaceNameList_Initialize(hFontList, ConInfo->CodePage);
 
 
+            /* Select the current font */
             DPRINT1("ConInfo->FaceName = '%S'\n", ConInfo->FaceName);
             DPRINT1("ConInfo->FaceName = '%S'\n", ConInfo->FaceName);
-            idx = (INT)SendMessageW(hListBox, LB_FINDSTRINGEXACT, 0, (LPARAM)ConInfo->FaceName);
-            if (idx != LB_ERR)
-                SendMessageW(hListBox, LB_SETCURSEL, (WPARAM)idx, 0);
+            FaceNameList_SelectFaceName(hFontList, ConInfo->FaceName);
 
 
-            FontTypeChange(hwndDlg, ConInfo);
+            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);
+
+            /* Refresh everything */
+            FontTypeChange(hDlg, SizeList, ConInfo);
 
             return TRUE;
         }
 
 
             return TRUE;
         }
 
+        case WM_DESTROY:
+        {
+            if (SizeList)
+                HeapFree(GetProcessHeap(), 0, SizeList);
+            return (INT_PTR)TRUE;
+        }
+
         case WM_DRAWITEM:
         {
             LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
         case WM_DRAWITEM:
         {
             LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
@@ -472,7 +730,7 @@ FontProc(HWND hwndDlg,
             {
                 case PSN_APPLY:
                 {
             {
                 case PSN_APPLY:
                 {
-                    ApplyConsoleInfo(hwndDlg);
+                    ApplyConsoleInfo(hDlg);
                     return TRUE;
                 }
             }
                     return TRUE;
                 }
             }
@@ -482,29 +740,85 @@ FontProc(HWND hwndDlg,
 
         case WM_COMMAND:
         {
 
         case WM_COMMAND:
         {
-            switch (HIWORD(wParam))
+            if (HIWORD(wParam) == LBN_SELCHANGE /* || CBN_SELCHANGE */)
             {
             {
-                case LBN_SELCHANGE:
+                switch (LOWORD(wParam))
                 {
                 {
-                    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:
                     {
                     {
-                        case IDC_LBOX_FONTTYPE:
-                        {
-                            FontTypeChange(hwndDlg, ConInfo);
-                            PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
-                            break;
-                        }
-
-                        case IDC_LBOX_FONTSIZE:
-                        {
-                            FontSizeChange(hwndDlg, ConInfo);
-                            PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
-                            break;
-                        }
+                        /* 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];
+
+                GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
+                FontSize = wcstoul(szFontSize, &pszNext, 10);
+                if (!*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);
+                    FontSizeList_SelectFontSize(SizeList, FontSize);
+                }
+                /**/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;
                 }
                     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;
             }
 
             break;
index cf92b5d..3724a7b 100644 (file)
@@ -105,9 +105,7 @@ PaintText(
     COLORREF pbkColor, ptColor;
     COLORREF nbkColor, ntColor;
     HBRUSH hBrush;
     COLORREF pbkColor, ptColor;
     COLORREF nbkColor, ntColor;
     HBRUSH hBrush;
-    HFONT Font, OldFont;
-
-    COORD FontSize = pConInfo->FontSize;
+    HFONT hOldFont;
 
     if (TextMode == Screen)
         CurrentAttrib = pConInfo->ScreenAttributes;
 
     if (TextMode == Screen)
         CurrentAttrib = pConInfo->ScreenAttributes;
@@ -122,37 +120,12 @@ PaintText(
     hBrush = CreateSolidBrush(nbkColor);
     if (!hBrush) return FALSE;
 
     hBrush = CreateSolidBrush(nbkColor);
     if (!hBrush) return FALSE;
 
-    FontSize.Y = FontSize.Y > 0 ? -MulDiv(FontSize.Y, GetDeviceCaps(drawItem->hDC, LOGPIXELSY), 72)
-                                : FontSize.Y;
-
-    Font = CreateFontW(FontSize.Y,
-                       FontSize.X,
-                       0,
-                       TA_BASELINE,
-                       pConInfo->FontWeight,
-                       FALSE,
-                       FALSE,
-                       FALSE,
-                       CodePageToCharSet(pConInfo->CodePage),
-                       OUT_DEFAULT_PRECIS,
-                       CLIP_DEFAULT_PRECIS,
-                       DEFAULT_QUALITY,
-                       FIXED_PITCH | pConInfo->FontFamily,
-                       pConInfo->FaceName);
-    if (Font == NULL)
-    {
-        DPRINT1("PaintText: CreateFont failed\n");
-        DeleteObject(hBrush);
-        return FALSE;
-    }
-
-    OldFont = SelectObject(drawItem->hDC, Font);
-    if (OldFont == NULL)
-    {
-        DeleteObject(Font);
-        DeleteObject(hBrush);
-        return FALSE;
-    }
+    hOldFont = SelectObject(drawItem->hDC, hCurrentFont);
+    //if (hOldFont == NULL)
+    //{
+    //    DeleteObject(hBrush);
+    //    return FALSE;
+    //}
 
     FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
 
 
     FillRect(drawItem->hDC, &drawItem->rcItem, hBrush);
 
@@ -161,10 +134,10 @@ PaintText(
     DrawTextW(drawItem->hDC, szPreviewText, wcslen(szPreviewText), &drawItem->rcItem, 0);
     SetTextColor(drawItem->hDC, ptColor);
     SetBkColor(drawItem->hDC, pbkColor);
     DrawTextW(drawItem->hDC, szPreviewText, wcslen(szPreviewText), &drawItem->rcItem, 0);
     SetTextColor(drawItem->hDC, ptColor);
     SetBkColor(drawItem->hDC, pbkColor);
-    DeleteObject(hBrush);
 
 
-    SelectObject(drawItem->hDC, OldFont);
-    DeleteObject(Font);
+    SelectObject(drawItem->hDC, hOldFont);
+
+    DeleteObject(hBrush);
 
     return TRUE;
 }
 
     return TRUE;
 }