2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/console/font.c
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
17 // Some temporary code for future reference...
21 * This code comes from PuTTY
27 FontSpec
*fs
= (FontSpec
*)c
->data
;
30 lf
.lfHeight
= -MulDiv(fs
->height
,
31 GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
33 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
34 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
35 lf
.lfWeight
= (fs
->isbold
? FW_BOLD
: 0);
36 lf
.lfCharSet
= fs
->charset
;
37 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
38 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
39 lf
.lfQuality
= DEFAULT_QUALITY
;
40 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
41 strncpy(lf
.lfFaceName
, fs
->name
,
42 sizeof(lf
.lfFaceName
) - 1);
43 lf
.lfFaceName
[sizeof(lf
.lfFaceName
) - 1] = '\0';
45 cf
.lStructSize
= sizeof(cf
);
46 cf
.hwndOwner
= dp
->hwnd
;
48 cf
.Flags
= (dp
->fixed_pitch_fonts
? CF_FIXEDPITCHONLY
: 0) |
49 CF_FORCEFONTEXIST
| CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
51 if (ChooseFont(&cf
)) {
52 fs
= fontspec_new(lf
.lfFaceName
, (lf
.lfWeight
== FW_BOLD
),
53 cf
.iPointSize
/ 10, lf
.lfCharSet
);
54 dlg_fontsel_set(ctrl
, dp
, fs
);
57 ctrl
->generic
.handler(ctrl
, dp
, dp
->data
, EVENT_VALCHANGE
);
62 * This code is from consrv.
65 if (!GetTextMetricsW(drawItem
->hDC
, &Metrics
))
67 DPRINT1("PaintText: GetTextMetrics failed\n");
68 SelectObject(drawItem
->hDC
, OldFont
);
72 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
73 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
75 /* Measure real char width more precisely if possible */
76 if (GetTextExtentPoint32W(drawItem
->hDC
, L
"R", 1, &CharSize
))
77 GuiData
->CharWidth
= CharSize
.cx
;
81 * See also: Display_SetTypeFace in applications/fontview/display.c
87 * Font pixel heights for TrueType fonts
89 static SHORT TrueTypePoints
[] =
91 // 8, 9, 10, 11, 12, 14, 16, 18, 20,
92 // 22, 24, 26, 28, 36, 48, 72
93 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 36, 72
97 EnumFontNamesProc(PLOGFONTW lplf
,
98 PNEWTEXTMETRICW lpntm
,
102 HWND hwndCombo
= (HWND
)lParam
;
103 LPWSTR pszName
= lplf
->lfFaceName
;
105 /* Record the font's attributes (Fixedwidth and Truetype) */
106 // BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
107 // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
110 * According to: http://support.microsoft.com/kb/247815
111 * the criteria for console-eligible fonts are:
112 * - The font must be a fixed-pitch font.
113 * - The font cannot be an italic font.
114 * - The font cannot have a negative A or C space.
115 * - If it is a TrueType font, it must be FF_MODERN.
116 * - If it is not a TrueType font, it must be OEM_CHARSET.
118 * Non documented: vertical fonts are forbidden (their name start with a '@').
120 * Additional criteria for Asian installations:
121 * - If it is not a TrueType font, the face name must be "Terminal".
122 * - If it is an Asian TrueType font, it must also be an Asian character set.
124 * To install additional TrueType fonts to be available for the console,
125 * add entries of type REG_SZ named "0", "00" etc... in:
126 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
127 * The names of the fonts listed there should match those in:
128 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
132 * In ReactOS, we relax some criteria:
133 * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
134 * that can be italic and have negative A or C space.
135 * - If it is not a TrueType font, it can be from another character set
137 * - We do not support Asian criteria at the moment.
138 * - We do not look into the magic registry key mentioned above.
141 /* Reject variable width fonts */
142 if (((lplf
->lfPitchAndFamily
& 0x03) != FIXED_PITCH
)
143 #if 0 /* Reject italic and TrueType fonts with negative A or C space */
145 || !(lpntm
->ntmFlags
& NTM_NONNEGATIVE_AC
)
149 DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
150 pszName
, !(lplf
->lfPitchAndFamily
& FIXED_PITCH
) ? "'s not FIXED_PITCH" : (!(lpntm
->ntmFlags
& NTM_NONNEGATIVE_AC
) ? " has negative A or C space" : " is broken"),
151 lplf
->lfPitchAndFamily
);
155 /* Reject TrueType fonts that are not FF_MODERN */
156 if ((FontType
== TRUETYPE_FONTTYPE
) && ((lplf
->lfPitchAndFamily
& 0xF0) != FF_MODERN
))
158 DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n",
159 pszName
, lplf
->lfPitchAndFamily
);
163 /* Reject non-TrueType fonts that are not OEM */
165 if ((FontType
!= TRUETYPE_FONTTYPE
) && (lplf
->lfCharSet
!= OEM_CHARSET
))
167 DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n",
168 pszName
, lplf
->lfCharSet
);
171 #else // Improved criterium
172 if ((FontType
!= TRUETYPE_FONTTYPE
) &&
173 ((lplf
->lfCharSet
!= ANSI_CHARSET
) && (lplf
->lfCharSet
!= DEFAULT_CHARSET
) && (lplf
->lfCharSet
!= OEM_CHARSET
)))
175 DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
176 pszName
, lplf
->lfCharSet
);
181 /* Reject fonts that are vertical (tategaki) */
182 if (pszName
[0] == L
'@')
184 DPRINT1("Font '%S' rejected because it's vertical\n", pszName
);
188 #if 0 // For Asian installations only
189 /* Reject non-TrueType fonts that are not Terminal */
190 if ((FontType
!= TRUETYPE_FONTTYPE
) && (wcscmp(pszName
, L
"Terminal") != 0))
192 DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", pszName
);
196 // TODO: Asian TrueType font must also be an Asian character set.
199 /* Make sure the font doesn't already exist in the list */
200 if (SendMessageW(hwndCombo
, LB_FINDSTRINGEXACT
, 0, (LPARAM
)pszName
) == LB_ERR
)
203 INT idx
= (INT
)SendMessageW(hwndCombo
, LB_ADDSTRING
, 0, (LPARAM
)pszName
);
205 DPRINT1("Add font '%S' (lfPitchAndFamily = %d)\n", pszName
, lplf
->lfPitchAndFamily
);
207 /* Store this information in the list-item's userdata area */
208 // SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType));
209 SendMessageW(hwndCombo
, LB_SETITEMDATA
, idx
, (WPARAM
)FontType
);
216 EnumFontSizesProc(PLOGFONTW lplf
,
217 PNEWTEXTMETRICW lpntm
,
221 HWND hwndCombo
= (HWND
)lParam
;
224 if (FontType
!= TRUETYPE_FONTTYPE
)
226 // int logsize = lpntm->tmHeight - lpntm->tmInternalLeading;
227 // LONG pointsize = MulDiv(logsize, 72, GetDeviceCaps(hdc, LOGPIXELSY));
229 // swprintf(FontSize, L"%2d (%d x %d)", pointsize, lplf->lfWidth, lplf->lfHeight);
230 swprintf(FontSize
, L
"%d x %d", lplf
->lfWidth
, lplf
->lfHeight
);
232 /* Make sure the size doesn't already exist in the list */
233 if (SendMessageW(hwndCombo
, LB_FINDSTRINGEXACT
, 0, (LPARAM
)FontSize
) == LB_ERR
)
236 INT idx
= (INT
)SendMessageW(hwndCombo
, LB_ADDSTRING
, 0, (LPARAM
)FontSize
);
239 * Store this information in the list-item's userdata area.
241 * Width = FontSize.X = LOWORD(FontSize);
242 * Height = FontSize.Y = HIWORD(FontSize);
244 SendMessageW(hwndCombo
, LB_SETITEMDATA
, idx
, MAKEWPARAM(lplf
->lfWidth
, lplf
->lfHeight
));
252 for (i
= 0; i
< sizeof(TrueTypePoints
) / sizeof(TrueTypePoints
[0]); ++i
)
254 swprintf(FontSize
, L
"%2d", TrueTypePoints
[i
]);
256 /* Make sure the size doesn't already exist in the list */
257 if (SendMessageW(hwndCombo
, LB_FINDSTRINGEXACT
, 0, (LPARAM
)FontSize
) == LB_ERR
)
260 INT idx
= (INT
)SendMessageW(hwndCombo
, LB_ADDSTRING
, 0, (LPARAM
)FontSize
);
263 * Store this information in the list-item's userdata area.
265 * Width = FontSize.X = LOWORD(FontSize);
266 * Height = FontSize.Y = HIWORD(FontSize);
268 SendMessageW(hwndCombo
, LB_SETITEMDATA
, idx
, MAKEWPARAM(0, TrueTypePoints
[i
]));
278 FontSizeChange(HWND hwndDlg
,
279 PGUI_CONSOLE_INFO GuiInfo
);
282 FontTypeChange(HWND hwndDlg
,
283 PGUI_CONSOLE_INFO GuiInfo
)
291 nSel
= (INT
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTTYPE
,
293 if (nSel
== LB_ERR
) return;
295 Length
= (INT
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTTYPE
,
296 LB_GETTEXTLEN
, nSel
, 0);
297 if (Length
== LB_ERR
) return;
299 FaceName
= HeapAlloc(GetProcessHeap(),
301 (Length
+ 1) * sizeof(WCHAR
));
302 if (FaceName
== NULL
) return;
304 Length
= (INT
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTTYPE
,
305 LB_GETTEXT
, nSel
, (LPARAM
)FaceName
);
306 FaceName
[Length
] = '\0';
308 Length
= min(Length
/*wcslen(FaceName) + 1*/, LF_FACESIZE
); // wcsnlen
309 wcsncpy(GuiInfo
->FaceName
, FaceName
, LF_FACESIZE
);
310 GuiInfo
->FaceName
[Length
] = L
'\0';
311 DPRINT1("GuiInfo->FaceName = '%S'\n", GuiInfo
->FaceName
);
313 /* Enumerate the available sizes for the selected font */
314 ZeroMemory(&lf
, sizeof(lf
));
315 lf
.lfCharSet
= DEFAULT_CHARSET
; // OEM_CHARSET;
316 // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
317 wcsncpy(lf
.lfFaceName
, FaceName
, LF_FACESIZE
);
318 lf
.lfFaceName
[Length
] = L
'\0';
321 EnumFontFamiliesExW(hDC
, &lf
, (FONTENUMPROCW
)EnumFontSizesProc
,
322 (LPARAM
)GetDlgItem(hwndDlg
, IDC_LBOX_FONTSIZE
), 0);
323 ReleaseDC(NULL
, hDC
);
325 HeapFree(GetProcessHeap(), 0, FaceName
);
327 // TODO: Select a default font size????
328 FontSizeChange(hwndDlg
, GuiInfo
);
330 // InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
331 // InvalidateRect(GetDlgItem(hwndDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
335 FontSizeChange(HWND hwndDlg
,
336 PGUI_CONSOLE_INFO GuiInfo
)
340 WCHAR FontSizeStr
[20];
342 nSel
= (INT
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTSIZE
,
344 if (nSel
== LB_ERR
) return;
348 * Width = FontSize.X = LOWORD(FontSize);
349 * Height = FontSize.Y = HIWORD(FontSize);
351 FontSize
= (ULONG
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTSIZE
,
352 LB_GETITEMDATA
, nSel
, 0);
353 if (FontSize
== LB_ERR
) return;
355 GuiInfo
->FontSize
.X
= LOWORD(FontSize
);
356 GuiInfo
->FontSize
.Y
= HIWORD(FontSize
);
357 DPRINT1("GuiInfo->FontSize = (%d x %d)\n", GuiInfo
->FontSize
.X
, GuiInfo
->FontSize
.Y
);
359 InvalidateRect(GetDlgItem(hwndDlg
, IDC_STATIC_FONT_WINDOW_PREVIEW
), NULL
, TRUE
);
360 InvalidateRect(GetDlgItem(hwndDlg
, IDC_STATIC_SELECT_FONT_PREVIEW
), NULL
, TRUE
);
362 swprintf(FontSizeStr
, L
"%2d", GuiInfo
->FontSize
.X
);
363 SetWindowText(GetDlgItem(hwndDlg
, IDC_FONT_SIZE_X
), FontSizeStr
);
364 swprintf(FontSizeStr
, L
"%2d", GuiInfo
->FontSize
.Y
);
365 SetWindowText(GetDlgItem(hwndDlg
, IDC_FONT_SIZE_Y
), FontSizeStr
);
371 FontProc(HWND hwndDlg
,
376 PCONSOLE_PROPS pConInfo
= (PCONSOLE_PROPS
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
377 PGUI_CONSOLE_INFO GuiInfo
= (pConInfo
? pConInfo
->TerminalInfo
.TermInfo
: NULL
);
379 UNREFERENCED_PARAMETER(wParam
);
389 pConInfo
= (PCONSOLE_PROPS
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
390 GuiInfo
= pConInfo
->TerminalInfo
.TermInfo
;
391 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pConInfo
);
393 ZeroMemory(&lf
, sizeof(lf
));
394 lf
.lfCharSet
= DEFAULT_CHARSET
; // OEM_CHARSET;
395 // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
398 EnumFontFamiliesExW(hDC
, &lf
, (FONTENUMPROCW
)EnumFontNamesProc
,
399 (LPARAM
)GetDlgItem(hwndDlg
, IDC_LBOX_FONTTYPE
), 0);
400 ReleaseDC(NULL
, hDC
);
402 DPRINT1("GuiInfo->FaceName = '%S'\n", GuiInfo
->FaceName
);
403 idx
= (INT
)SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTTYPE
,
404 LB_FINDSTRINGEXACT
, 0, (LPARAM
)GuiInfo
->FaceName
);
405 if (idx
!= LB_ERR
) SendDlgItemMessageW(hwndDlg
, IDC_LBOX_FONTTYPE
,
406 LB_SETCURSEL
, (WPARAM
)idx
, 0);
408 FontTypeChange(hwndDlg
, GuiInfo
);
415 LPDRAWITEMSTRUCT drawItem
= (LPDRAWITEMSTRUCT
)lParam
;
417 if (drawItem
->CtlID
== IDC_STATIC_FONT_WINDOW_PREVIEW
)
418 PaintConsole(drawItem
, pConInfo
);
419 else if (drawItem
->CtlID
== IDC_STATIC_SELECT_FONT_PREVIEW
)
420 PaintText(drawItem
, pConInfo
, Screen
);
427 switch (((LPNMHDR
)lParam
)->code
)
431 if (!pConInfo
->AppliedConfig
)
433 return ApplyConsoleInfo(hwndDlg
, pConInfo
);
437 /* Options have already been applied */
438 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
450 switch (HIWORD(wParam
))
454 switch (LOWORD(wParam
))
456 case IDC_LBOX_FONTTYPE
:
458 FontTypeChange(hwndDlg
, GuiInfo
);
459 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
463 case IDC_LBOX_FONTSIZE
:
465 FontSizeChange(hwndDlg
, GuiInfo
);
466 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);