mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
484 lines
16 KiB
C
484 lines
16 KiB
C
/*
|
|
* PROJECT: ReactOS Console Configuration DLL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/win32/console/font.c
|
|
* PURPOSE: Font dialog
|
|
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
|
*/
|
|
|
|
#include "console.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
//
|
|
// Some temporary code for future reference...
|
|
//
|
|
#if 0
|
|
/*
|
|
* This code comes from PuTTY
|
|
*/
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This code is from consrv.
|
|
*/
|
|
{
|
|
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;
|
|
|
|
/* Measure real char width more precisely if possible. */
|
|
if (GetTextExtentPoint32W(drawItem->hDC, L"R", 1, &CharSize))
|
|
GuiData->CharWidth = CharSize.cx;
|
|
}
|
|
|
|
/*
|
|
* See also: Display_SetTypeFace in applications/fontview/display.c
|
|
*/
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Font pixel heights for TrueType fonts
|
|
*/
|
|
static SHORT TrueTypePoints[] =
|
|
{
|
|
// 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
|
|
};
|
|
|
|
static BOOL CALLBACK
|
|
EnumFontNamesProc(PLOGFONTW lplf,
|
|
PNEWTEXTMETRICW lpntm,
|
|
DWORD FontType,
|
|
LPARAM lParam)
|
|
{
|
|
HWND hwndCombo = (HWND)lParam;
|
|
LPWSTR pszName = lplf->lfFaceName;
|
|
|
|
BOOL fFixed;
|
|
BOOL fTrueType;
|
|
|
|
/* Record the font's attributes (Fixedwidth and Truetype) */
|
|
fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
|
|
fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE;
|
|
|
|
/*
|
|
* 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 criteria:
|
|
* - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
|
|
* that can be italic and 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 support Asian criteria at the moment.
|
|
* - 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",
|
|
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;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* Reject non-TrueType fonts that are not OEM */
|
|
#if 0
|
|
if ((FontType != TRUETYPE_FONTTYPE) && (lplf->lfCharSet != OEM_CHARSET))
|
|
{
|
|
DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n", pszName, lplf->lfCharSet);
|
|
return TRUE;
|
|
}
|
|
#else // Improved criterium
|
|
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", pszName, lplf->lfCharSet);
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/* Reject fonts that are vertical (tategaki) */
|
|
if (pszName[0] == L'@')
|
|
{
|
|
DPRINT1("Font '%S' rejected because it's vertical\n", pszName);
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0 // For Asian installations only
|
|
/* Reject non-TrueType fonts that are not Terminal */
|
|
if ((FontType != TRUETYPE_FONTTYPE) && (wcscmp(pszName, L"Terminal") != 0))
|
|
{
|
|
DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", pszName);
|
|
return TRUE;
|
|
}
|
|
|
|
// TODO: Asian TrueType font must also be an Asian character set.
|
|
#endif
|
|
|
|
/* Make sure the font doesn't already exist in the list */
|
|
if (SendMessageW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)pszName) == LB_ERR)
|
|
{
|
|
/* Add the font */
|
|
INT idx = (INT)SendMessageW(hwndCombo, LB_ADDSTRING, 0, (LPARAM)pszName);
|
|
|
|
DPRINT1("Add font '%S' (lfPitchAndFamily = %d)\n", pszName, lplf->lfPitchAndFamily);
|
|
|
|
/* Store this information in the list-item's userdata area */
|
|
SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK
|
|
EnumFontSizesProc(PLOGFONTW lplf,
|
|
PNEWTEXTMETRICW lpntm,
|
|
DWORD FontType,
|
|
LPARAM lParam)
|
|
{
|
|
HWND hwndCombo = (HWND)lParam;
|
|
WCHAR FontSize[100];
|
|
|
|
if (FontType != TRUETYPE_FONTTYPE)
|
|
{
|
|
// int logsize = lpntm->tmHeight - lpntm->tmInternalLeading;
|
|
// LONG pointsize = MulDiv(logsize, 72, GetDeviceCaps(hdc, LOGPIXELSY));
|
|
|
|
// swprintf(FontSize, L"%2d (%d x %d)", pointsize, lplf->lfWidth, lplf->lfHeight);
|
|
swprintf(FontSize, L"%d x %d", lplf->lfWidth, lplf->lfHeight);
|
|
|
|
/* 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(lplf->lfWidth, lplf->lfHeight));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(TrueTypePoints) / sizeof(TrueTypePoints[0]); ++i)
|
|
{
|
|
swprintf(FontSize, L"%2d", TrueTypePoints[i]);
|
|
|
|
/* 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]));
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static VOID
|
|
FontSizeChange(HWND hwndDlg,
|
|
PGUI_CONSOLE_INFO GuiInfo);
|
|
|
|
static VOID
|
|
FontTypeChange(HWND hwndDlg,
|
|
PGUI_CONSOLE_INFO GuiInfo)
|
|
{
|
|
INT Length, nSel;
|
|
LPWSTR FaceName;
|
|
|
|
HDC hDC;
|
|
LOGFONTW lf;
|
|
|
|
nSel = (INT)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTTYPE,
|
|
LB_GETCURSEL, 0, 0);
|
|
if (nSel == LB_ERR) return;
|
|
|
|
Length = (INT)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTTYPE,
|
|
LB_GETTEXTLEN, nSel, 0);
|
|
if (Length == LB_ERR) return;
|
|
|
|
FaceName = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
(Length + 1) * sizeof(WCHAR));
|
|
if (FaceName == NULL) return;
|
|
|
|
Length = (INT)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTTYPE,
|
|
LB_GETTEXT, nSel, (LPARAM)FaceName);
|
|
FaceName[Length] = '\0';
|
|
|
|
Length = min(Length/*wcslen(FaceName) + 1*/, LF_FACESIZE); // wcsnlen
|
|
wcsncpy(GuiInfo->FaceName, FaceName, LF_FACESIZE);
|
|
GuiInfo->FaceName[Length] = L'\0';
|
|
DPRINT1("GuiInfo->FaceName = '%S'\n", GuiInfo->FaceName);
|
|
|
|
/* Enumerate the available sizes for the selected font */
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = DEFAULT_CHARSET; // OEM_CHARSET;
|
|
// lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
|
|
wcsncpy(lf.lfFaceName, FaceName, LF_FACESIZE);
|
|
lf.lfFaceName[Length] = L'\0';
|
|
|
|
hDC = GetDC(NULL);
|
|
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontSizesProc,
|
|
(LPARAM)GetDlgItem(hwndDlg, IDC_LBOX_FONTSIZE), 0);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
HeapFree(GetProcessHeap(), 0, FaceName);
|
|
|
|
// TODO: Select a default font size????
|
|
FontSizeChange(hwndDlg, GuiInfo);
|
|
|
|
// InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
|
|
// InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
|
|
}
|
|
|
|
static VOID
|
|
FontSizeChange(HWND hwndDlg,
|
|
PGUI_CONSOLE_INFO GuiInfo)
|
|
{
|
|
INT nSel;
|
|
ULONG FontSize;
|
|
WCHAR FontSizeStr[20];
|
|
|
|
nSel = (INT)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTSIZE,
|
|
LB_GETCURSEL, 0, 0);
|
|
if (nSel == LB_ERR) return;
|
|
|
|
/*
|
|
* Format:
|
|
* Width = FontSize.X = LOWORD(FontSize);
|
|
* Height = FontSize.Y = HIWORD(FontSize);
|
|
*/
|
|
FontSize = (ULONG)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTSIZE,
|
|
LB_GETITEMDATA, nSel, 0);
|
|
if (FontSize == LB_ERR) return;
|
|
|
|
GuiInfo->FontSize.X = LOWORD(FontSize);
|
|
GuiInfo->FontSize.Y = HIWORD(FontSize);
|
|
DPRINT1("GuiInfo->FontSize = (%d x %d)\n", GuiInfo->FontSize.X, GuiInfo->FontSize.Y);
|
|
|
|
InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
|
|
InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
|
|
|
|
swprintf(FontSizeStr, L"%2d", GuiInfo->FontSize.X);
|
|
SetWindowText(GetDlgItem(hwndDlg, IDC_FONT_SIZE_X), FontSizeStr);
|
|
swprintf(FontSizeStr, L"%2d", GuiInfo->FontSize.Y);
|
|
SetWindowText(GetDlgItem(hwndDlg, IDC_FONT_SIZE_Y), FontSizeStr);
|
|
}
|
|
|
|
|
|
INT_PTR
|
|
CALLBACK
|
|
FontProc(HWND hwndDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PCONSOLE_PROPS pConInfo = (PCONSOLE_PROPS)GetWindowLongPtr(hwndDlg, DWLP_USER);
|
|
PGUI_CONSOLE_INFO GuiInfo = (pConInfo ? pConInfo->TerminalInfo.TermInfo : NULL);
|
|
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HDC hDC;
|
|
LOGFONTW lf;
|
|
INT idx;
|
|
|
|
pConInfo = (PCONSOLE_PROPS)((LPPROPSHEETPAGE)lParam)->lParam;
|
|
GuiInfo = pConInfo->TerminalInfo.TermInfo;
|
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pConInfo);
|
|
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = DEFAULT_CHARSET; // OEM_CHARSET;
|
|
// lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
|
|
|
|
hDC = GetDC(NULL);
|
|
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontNamesProc,
|
|
(LPARAM)GetDlgItem(hwndDlg, IDC_LBOX_FONTTYPE), 0);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
DPRINT1("GuiInfo->FaceName = '%S'\n", GuiInfo->FaceName);
|
|
idx = (INT)SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTTYPE,
|
|
LB_FINDSTRINGEXACT, 0, (LPARAM)GuiInfo->FaceName);
|
|
if (idx != LB_ERR) SendDlgItemMessageW(hwndDlg, IDC_LBOX_FONTTYPE,
|
|
LB_SETCURSEL, (WPARAM)idx, 0);
|
|
|
|
FontTypeChange(hwndDlg, GuiInfo);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
|
|
|
|
if (drawItem->CtlID == IDC_STATIC_FONT_WINDOW_PREVIEW)
|
|
PaintConsole(drawItem, pConInfo);
|
|
else if (drawItem->CtlID == IDC_STATIC_SELECT_FONT_PREVIEW)
|
|
PaintText(drawItem, pConInfo, Screen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case PSN_APPLY:
|
|
{
|
|
if (!pConInfo->AppliedConfig)
|
|
{
|
|
return ApplyConsoleInfo(hwndDlg, pConInfo);
|
|
}
|
|
else
|
|
{
|
|
/* Options have already been applied */
|
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case LBN_SELCHANGE:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_LBOX_FONTTYPE:
|
|
{
|
|
FontTypeChange(hwndDlg, GuiInfo);
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
break;
|
|
}
|
|
|
|
case IDC_LBOX_FONTSIZE:
|
|
{
|
|
FontSizeChange(hwndDlg, GuiInfo);
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|