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
;
108 /* Record the font's attributes (Fixedwidth and Truetype) */
109 fFixed
= ((lplf
->lfPitchAndFamily
& 0x03) == FIXED_PITCH
);
110 fTrueType
= (lplf
->lfOutPrecision
== OUT_STROKE_PRECIS
) ? TRUE
: FALSE
;
113 * According to: http://support.microsoft.com/kb/247815
114 * the criteria for console-eligible fonts are:
115 * - The font must be a fixed-pitch font.
116 * - The font cannot be an italic font.
117 * - The font cannot have a negative A or C space.
118 * - If it is a TrueType font, it must be FF_MODERN.
119 * - If it is not a TrueType font, it must be OEM_CHARSET.
121 * Non documented: vertical fonts are forbidden (their name start with a '@').
123 * Additional criteria for Asian installations:
124 * - If it is not a TrueType font, the face name must be "Terminal".
125 * - If it is an Asian TrueType font, it must also be an Asian character set.
127 * To install additional TrueType fonts to be available for the console,
128 * add entries of type REG_SZ named "0", "00" etc... in:
129 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
130 * The names of the fonts listed there should match those in:
131 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
135 * In ReactOS, we relax some criteria:
136 * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
137 * that can be italic and have negative A or C space.
138 * - If it is not a TrueType font, it can be from another character set
140 * - We do not support Asian criteria at the moment.
141 * - We do not look into the magic registry key mentioned above.
144 /* Reject variable width fonts */
145 if (((lplf
->lfPitchAndFamily
& 0x03) != FIXED_PITCH
)
146 #if 0 /* Reject italic and TrueType fonts with negative A or C space */
148 || !(lpntm
->ntmFlags
& NTM_NONNEGATIVE_AC
)
152 DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
153 pszName
, !(lplf
->lfPitchAndFamily
& FIXED_PITCH
) ? "'s not FIXED_PITCH" : (!(lpntm
->ntmFlags
& NTM_NONNEGATIVE_AC
) ? " has negative A or C space" : " is broken"),
154 lplf
->lfPitchAndFamily
);
158 /* Reject TrueType fonts that are not FF_MODERN */
159 if ((FontType
== TRUETYPE_FONTTYPE
) && ((lplf
->lfPitchAndFamily
& 0xF0) != FF_MODERN
))
161 DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n", pszName
, lplf
->lfPitchAndFamily
);
165 /* Reject non-TrueType fonts that are not OEM */
167 if ((FontType
!= TRUETYPE_FONTTYPE
) && (lplf
->lfCharSet
!= OEM_CHARSET
))
169 DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n", pszName
, lplf
->lfCharSet
);
172 #else // Improved criterium
173 if ((FontType
!= TRUETYPE_FONTTYPE
) &&
174 ((lplf
->lfCharSet
!= ANSI_CHARSET
) && (lplf
->lfCharSet
!= DEFAULT_CHARSET
) && (lplf
->lfCharSet
!= OEM_CHARSET
)))
176 DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n", 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
));
215 EnumFontSizesProc(PLOGFONTW lplf
,
216 PNEWTEXTMETRICW lpntm
,
220 HWND hwndCombo
= (HWND
)lParam
;
223 if (FontType
!= TRUETYPE_FONTTYPE
)
225 // int logsize = lpntm->tmHeight - lpntm->tmInternalLeading;
226 // LONG pointsize = MulDiv(logsize, 72, GetDeviceCaps(hdc, LOGPIXELSY));
228 // swprintf(FontSize, L"%2d (%d x %d)", pointsize, lplf->lfWidth, lplf->lfHeight);
229 swprintf(FontSize
, L
"%d x %d", lplf
->lfWidth
, lplf
->lfHeight
);
231 /* Make sure the size doesn't already exist in the list */
232 if (SendMessageW(hwndCombo
, LB_FINDSTRINGEXACT
, 0, (LPARAM
)FontSize
) == LB_ERR
)
235 INT idx
= (INT
)SendMessageW(hwndCombo
, LB_ADDSTRING
, 0, (LPARAM
)FontSize
);
238 * Store this information in the list-item's userdata area.
240 * Width = FontSize.X = LOWORD(FontSize);
241 * Height = FontSize.Y = HIWORD(FontSize);
243 SendMessageW(hwndCombo
, LB_SETITEMDATA
, idx
, MAKEWPARAM(lplf
->lfWidth
, lplf
->lfHeight
));
251 for (i
= 0; i
< sizeof(TrueTypePoints
) / sizeof(TrueTypePoints
[0]); ++i
)
253 swprintf(FontSize
, L
"%2d", TrueTypePoints
[i
]);
255 /* Make sure the size doesn't already exist in the list */
256 if (SendMessageW(hwndCombo
, LB_FINDSTRINGEXACT
, 0, (LPARAM
)FontSize
) == LB_ERR
)
259 INT idx
= (INT
)SendMessageW(hwndCombo
, LB_ADDSTRING
, 0, (LPARAM
)FontSize
);
262 * Store this information in the list-item's userdata area.
264 * Width = FontSize.X = LOWORD(FontSize);
265 * Height = FontSize.Y = HIWORD(FontSize);
267 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
);