--- /dev/null
+/*
+ * 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 (hermes.belusca@sfr.fr)
+ * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "precomp.h"
+#include <winuser.h>
+
+#include "settings.h"
+#include "font.h"
+// #include "concfg.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* FUNCTIONS ******************************************************************/
+
+/* Retrieves the character set associated with a given code page */
+BYTE
+CodePageToCharSet(
+ IN UINT CodePage)
+{
+ CHARSETINFO CharInfo;
+ if (TranslateCharsetInfo((LPDWORD)CodePage, &CharInfo, TCI_SRCCODEPAGE))
+ return CharInfo.ciCharset;
+ else
+ return DEFAULT_CHARSET;
+}
+
+HFONT
+CreateConsoleFontEx(
+ IN LONG Height,
+ IN LONG Width OPTIONAL,
+ IN OUT LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements
+ IN ULONG FontFamily,
+ IN ULONG FontWeight,
+ IN UINT CodePage)
+{
+ LOGFONTW lf;
+
+ RtlZeroMemory(&lf, sizeof(lf));
+
+ lf.lfHeight = Height;
+ lf.lfWidth = Width;
+
+ 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.lfCharSet = CodePageToCharSet(CodePage);
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = (BYTE)(FIXED_PITCH | FontFamily);
+
+ if (!IsValidConsoleFont(FaceName, CodePage))
+ StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal");
+
+ StringCchCopyNW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName),
+ FaceName, LF_FACESIZE);
+
+ return CreateFontIndirectW(&lf);
+}
+
+HFONT
+CreateConsoleFont2(
+ IN LONG Height,
+ IN LONG Width OPTIONAL,
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
+{
+ return CreateConsoleFontEx(Height,
+ Width,
+ ConsoleInfo->FaceName,
+ ConsoleInfo->FontFamily,
+ ConsoleInfo->FontWeight,
+ ConsoleInfo->CodePage);
+}
+
+HFONT
+CreateConsoleFont(
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
+{
+ /*
+ * Format:
+ * Width = FontSize.X = LOWORD(FontSize);
+ * 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);
+}
+
+BOOL
+GetFontCellSize(
+ IN HDC hDC OPTIONAL,
+ IN HFONT hFont,
+ OUT PUINT Height,
+ OUT PUINT Width)
+{
+ BOOL Success = FALSE;
+ HDC hOrgDC = hDC;
+ HFONT hOldFont;
+ // LONG LogSize, PointSize;
+ LONG CharWidth, CharHeight;
+ TEXTMETRICW tm;
+ // SIZE CharSize;
+
+ if (!hDC)
+ hDC = GetDC(NULL);
+
+ hOldFont = SelectObject(hDC, hFont);
+ if (hOldFont == NULL)
+ {
+ DPRINT1("GetFontCellSize: SelectObject failed\n");
+ goto Quit;
+ }
+
+/*
+ * See also: Display_SetTypeFace in applications/fontview/display.c
+ */
+
+ /*
+ * Note that the method with GetObjectW just returns
+ * the original parameters with which the font was created.
+ */
+ if (!GetTextMetricsW(hDC, &tm))
+ {
+ DPRINT1("GetFontCellSize: GetTextMetrics failed\n");
+ goto Cleanup;
+ }
+
+ CharHeight = tm.tmHeight + tm.tmExternalLeading;
+
+#if 0
+ /* Measure real char width more precisely if possible */
+ if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
+ CharWidth = CharSize.cx;
+#else
+ CharWidth = tm.tmAveCharWidth; // tm.tmMaxCharWidth;
+#endif
+
+#if 0
+ /*** Logical to Point size ***/
+ LogSize = tm.tmHeight - tm.tmInternalLeading;
+ PointSize = MulDiv(LogSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
+ /*****************************/
+#endif
+
+ *Height = (UINT)CharHeight;
+ *Width = (UINT)CharWidth;
+ Success = TRUE;
+
+Cleanup:
+ SelectObject(hDC, hOldFont);
+Quit:
+ if (!hOrgDC)
+ ReleaseDC(NULL, hDC);
+
+ return Success;
+}
+
+BOOL
+IsValidConsoleFont2(
+ IN PLOGFONTW lplf,
+ IN PNEWTEXTMETRICW lpntm,
+ IN DWORD FontType,
+ IN UINT CodePage)
+{
+ LPCWSTR FaceName = lplf->lfFaceName;
+
+ /* Record the font's attributes (Fixedwidth and Truetype) */
+ // BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
+ // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
+
+ /*
+ * According to: http://support.microsoft.com/kb/247815
+ * the criteria for console-eligible fonts are:
+ * - 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
+ */
+
+ /*
+ * 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
+ )
+ {
+ DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
+ FaceName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
+ : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
+ : " is broken"),
+ lplf->lfPitchAndFamily);
+ return FALSE;
+ }
+
+ /* 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);
+ return FALSE;
+ }
+
+ /* Is the current code page Chinese, Japanese or Korean? */
+ if (IsCJKCodePage(CodePage))
+ {
+ /* It's Asian */
+ if (FontType == TRUETYPE_FONTTYPE)
+ {
+ if (lplf->lfCharSet != CodePageToCharSet(CodePage))
+ {
+ DPRINT1("TrueType font '%S' rejected because it's not user Asian charset (lfCharSet = %d)\n",
+ FaceName, lplf->lfCharSet);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Reject non-TrueType fonts that are not Terminal */
+ if (wcscmp(FaceName, L"Terminal") != 0)
+ {
+ DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", FaceName);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* Not CJK */
+ if ((FontType != TRUETYPE_FONTTYPE) &&
+ (lplf->lfCharSet != ANSI_CHARSET) &&
+ (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);
+ return FALSE;
+ }
+ }
+
+ /* Reject fonts that are vertical (tategaki) */
+ if (FaceName[0] == L'@')
+ {
+ DPRINT1("Font '%S' rejected because it's vertical\n", FaceName);
+ return FALSE;
+ }
+
+ /* All good */
+ return TRUE;
+}
+
+typedef struct _IS_VALID_CONSOLE_FONT_PARAM
+{
+ BOOL IsValidFont;
+ UINT CodePage;
+} IS_VALID_CONSOLE_FONT_PARAM, *PIS_VALID_CONSOLE_FONT_PARAM;
+
+static BOOL CALLBACK
+IsValidConsoleFontProc(
+ IN PLOGFONTW lplf,
+ IN PNEWTEXTMETRICW lpntm,
+ IN DWORD FontType,
+ IN LPARAM lParam)
+{
+ PIS_VALID_CONSOLE_FONT_PARAM Param = (PIS_VALID_CONSOLE_FONT_PARAM)lParam;
+ Param->IsValidFont = IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage);
+
+ /* Stop the enumeration now */
+ return FALSE;
+}
+
+BOOL
+IsValidConsoleFont(
+ IN LPCWSTR FaceName,
+ IN UINT CodePage)
+{
+ IS_VALID_CONSOLE_FONT_PARAM Param;
+ HDC hDC;
+ LOGFONTW lf;
+
+ Param.IsValidFont = FALSE;
+ Param.CodePage = CodePage;
+
+ RtlZeroMemory(&lf, sizeof(lf));
+ lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
+ // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+ StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
+
+ hDC = GetDC(NULL);
+ EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)IsValidConsoleFontProc, (LPARAM)&Param, 0);
+ ReleaseDC(NULL, hDC);
+
+ return Param.IsValidFont;
+}
+
+/* EOF */
/* INCLUDES *******************************************************************/
-/* PSDK/NDK Headers */
-
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
-
-#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h> // For LF_FACESIZE
-#include <wincon.h>
-#include <winnls.h>
-#include <winreg.h>
-// #include <winuser.h>
-// #include <imm.h>
+#include "precomp.h"
// /* Undocumented user definitions */
// #include <undocuser.h>
-#define NTOS_MODE_USER
-// #include <ndk/cmfuncs.h>
-// #include <ndk/exfuncs.h>
-#include <ndk/obfuncs.h>
-// #include <ndk/psfuncs.h>
-#include <ndk/rtlfuncs.h>
-
#include "settings.h"
-#include <stdio.h> // for swprintf
-#include <strsafe.h>
-
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
/* Default cursor size -- see conio_winsrv.h */
+// #define SMALL_SIZE 25
#define CSR_DEFAULT_CURSOR_SIZE 25
/* Default attributes -- see conio.h */
RGB(255, 255, 0), // GREEN | RED | INTENSITY
RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
};
-// /* Default attributes */
-// #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
-// #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | /
- // BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
-// /* Cursor size */
-// #define CSR_DEFAULT_CURSOR_SIZE 25
/* FUNCTIONS ******************************************************************/
static VOID
-TranslateConsoleName(OUT LPWSTR DestString,
- IN LPCWSTR ConsoleName,
- IN UINT MaxStrLen)
+TranslateConsoleName(
+ OUT LPWSTR DestString,
+ IN LPCWSTR ConsoleName,
+ IN UINT MaxStrLen)
{
#define PATH_SEPARATOR L'\\'
}
BOOLEAN
-ConCfgOpenUserSettings(LPCWSTR ConsoleTitle,
- PHKEY hSubKey,
- REGSAM samDesired,
- BOOLEAN Create)
+ConCfgOpenUserSettings(
+ IN LPCWSTR ConsoleTitle,
+ OUT PHKEY phSubKey,
+ IN REGSAM samDesired,
+ IN BOOLEAN Create)
{
BOOLEAN Success = TRUE;
NTSTATUS Status;
REG_OPTION_NON_VOLATILE,
samDesired,
NULL,
- hSubKey,
+ phSubKey,
NULL) == ERROR_SUCCESS);
}
else
szBuffer,
0,
samDesired,
- hSubKey) == ERROR_SUCCESS);
+ phSubKey) == ERROR_SUCCESS);
}
/* Close the parent key and return success or not */
}
BOOLEAN
-ConCfgReadUserSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
- IN BOOLEAN DefaultSettings)
+ConCfgReadUserSettings(
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
+ IN BOOLEAN DefaultSettings)
{
BOOLEAN Success = FALSE;
HKEY hKey;
}
else if (!wcscmp(szValueName, L"FaceName"))
{
- wcsncpy(ConsoleInfo->FaceName, szValue, LF_FACESIZE);
- ConsoleInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL;
+ StringCchCopyNW(ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName),
+ szValue, ARRAYSIZE(szValue));
Success = TRUE;
}
else if (!wcscmp(szValueName, L"FontFamily"))
}
BOOLEAN
-ConCfgWriteUserSettings(IN PCONSOLE_STATE_INFO ConsoleInfo,
- IN BOOLEAN DefaultSettings)
+ConCfgWriteUserSettings(
+ IN PCONSOLE_STATE_INFO ConsoleInfo,
+ IN BOOLEAN DefaultSettings)
{
HKEY hKey;
DWORD Storage = 0;
}
VOID
-ConCfgInitDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
+ConCfgInitDefaultSettings(
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
{
if (ConsoleInfo == NULL) return;
// wcsncpy(ConsoleInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
// ConsoleInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
- // ConsoleInfo->FontSize = MAKELONG(16, 16); // font is 16x16
- wcsncpy(ConsoleInfo->FaceName, L"VGA", LF_FACESIZE); // HACK: !!
+ StringCchCopyW(ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName), L"VGA"); // HACK: !!
// ConsoleInfo->FaceName[0] = UNICODE_NULL;
+ // ConsoleInfo->FontSize.X = 8;
+ // ConsoleInfo->FontSize.Y = 12;
+ ConsoleInfo->FontSize.X = 0; // HACK: !!
+ ConsoleInfo->FontSize.Y = 16; // HACK: !!
ConsoleInfo->FontFamily = FF_DONTCARE;
- ConsoleInfo->FontSize.X = 0;
- ConsoleInfo->FontSize.Y = 0;
- ConsoleInfo->FontWeight = FW_NORMAL; // HACK: !!
- // ConsoleInfo->FontWeight = FW_DONTCARE;
+ ConsoleInfo->FontWeight = FW_NORMAL; // FW_DONTCARE;
/* Initialize the default properties */
ConsoleInfo->WindowPosition.x = 0;
ConsoleInfo->WindowPosition.y = 0;
- ConsoleInfo->CursorSize = CSR_DEFAULT_CURSOR_SIZE; // #define SMALL_SIZE 25
+ ConsoleInfo->CursorSize = CSR_DEFAULT_CURSOR_SIZE;
ConsoleInfo->ScreenAttributes = DEFAULT_SCREEN_ATTRIB;
ConsoleInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB;
}
VOID
-ConCfgGetDefaultSettings(IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
+ConCfgGetDefaultSettings(
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
{
if (ConsoleInfo == NULL) return;