[CONSOLE][CONCFG][CONSRV] Provide support for specified additional TrueType fonts...
[reactos.git] / dll / cpl / console / font.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/console/font.c
5 * PURPOSE: Font dialog
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
9 */
10
11 #include "console.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 /*
18 * Current active font, corresponding to the active console font,
19 * and used for painting the text samples.
20 */
21 FONT_PREVIEW FontPreview = {NULL, 0, 0};
22
23
24 /*
25 * Standard font pixel/point heights for TrueType fonts
26 */
27 static const SHORT TrueTypePoints[] =
28 {
29 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
30 };
31
32 typedef struct _FONTSIZE_LIST_CTL
33 {
34 LIST_CTL RasterSizeList; // ListBox for Raster font sizes; needs to handle bisection.
35 HWND hWndTTSizeList; // ComboBox for TrueType font sizes.
36 BOOL bIsTTSizeDirty; // TRUE or FALSE depending on whether we have edited the edit zone.
37 BOOL UseRasterOrTTList; // TRUE: Use the Raster size list; FALSE: Use the TrueType size list.
38 BOOL TTSizePixelUnit; // TRUE: Size in pixels (default); FALSE: Size in points.
39 LONG CurrentRasterSize;
40 LONG CurrentTTSize; // In whatever unit (pixels or points) currently selected.
41 } FONTSIZE_LIST_CTL, *PFONTSIZE_LIST_CTL;
42
43 /* Used by FontTypeChange() only */
44 static INT CurrentSelFont = LB_ERR;
45 static DWORD CurrentFontType = (DWORD)-1; // Invalid font type
46
47
48 VOID
49 RefreshFontPreview(
50 IN FONT_PREVIEW* Preview,
51 IN PCONSOLE_STATE_INFO pConInfo)
52 {
53 if (Preview->hFont) DeleteObject(Preview->hFont);
54 Preview->hFont = CreateConsoleFont(pConInfo);
55 if (Preview->hFont == NULL)
56 DPRINT1("RefreshFontPreview: CreateConsoleFont() failed\n");
57 GetFontCellSize(NULL, Preview->hFont, &Preview->CharHeight, &Preview->CharWidth);
58 }
59
60 VOID
61 UpdateFontPreview(
62 IN FONT_PREVIEW* Preview,
63 IN HFONT hFont,
64 IN UINT CharWidth,
65 IN UINT CharHeight)
66 {
67 if (Preview->hFont) DeleteObject(Preview->hFont);
68 Preview->hFont = hFont;
69 Preview->CharWidth = CharWidth;
70 Preview->CharHeight = CharHeight;
71 }
72
73 // PLIST_GETCOUNT
74 static INT
75 RasterSizeList_GetCount(
76 IN PLIST_CTL ListCtl)
77 {
78 return (INT)SendMessageW(ListCtl->hWndList, LB_GETCOUNT, 0, 0);
79 }
80
81 // PLIST_GETDATA
82 static ULONG_PTR
83 RasterSizeList_GetData(
84 IN PLIST_CTL ListCtl,
85 IN INT Index)
86 {
87 return (ULONG_PTR)SendMessageW(ListCtl->hWndList, LB_GETITEMDATA, (WPARAM)Index, 0);
88 }
89
90
91 INT
92 LogicalSizeToPointSize(
93 IN HDC hDC OPTIONAL,
94 IN UINT LogicalSize)
95 {
96 INT PointSize;
97 HDC hOrgDC = hDC;
98
99 if (!hDC)
100 hDC = GetDC(NULL);
101
102 // LogicalSize = tm.tmHeight - tm.tmInternalLeading;
103 PointSize = MulDiv(LogicalSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
104
105 if (!hOrgDC)
106 ReleaseDC(NULL, hDC);
107
108 return PointSize;
109 }
110
111 INT
112 PointSizeToLogicalSize(
113 IN HDC hDC OPTIONAL,
114 IN INT PointSize)
115 {
116 INT LogicalSize;
117 HDC hOrgDC = hDC;
118
119 if (!hDC)
120 hDC = GetDC(NULL);
121
122 LogicalSize = MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
123
124 if (!hOrgDC)
125 ReleaseDC(NULL, hDC);
126
127 return LogicalSize;
128 }
129
130
131 static VOID
132 FontSizeList_SelectFontSize(
133 IN PFONTSIZE_LIST_CTL SizeList,
134 IN ULONG FontSize)
135 {
136 INT nSel;
137 WCHAR szFontSize[100];
138
139 //
140 // FIXME: Check whether FontSize == 0
141 // (or in the case of raster font maybe, whether HIWORD(FontSize) == Height == 0) ??
142 //
143
144 /* Find and select the best font size in the list corresponding to the current size */
145 if (SizeList->UseRasterOrTTList)
146 {
147 INT idx;
148
149 /* Raster font size (in pixels) */
150 SizeList->CurrentRasterSize = FontSize;
151
152 nSel = BisectListSortedByValue(&SizeList->RasterSizeList, FontSize, NULL, FALSE);
153 idx = (INT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_GETCOUNT, 0, 0);
154 if (nSel == LB_ERR)
155 {
156 /* Not found, select the first element of the list */
157 nSel = 0;
158 }
159 else if (nSel >= idx)
160 {
161 /*
162 * We got an index beyond the end of the list (as per Bisect* functionality),
163 * so instead, select the last element of the list.
164 */
165 nSel = idx-1;
166 }
167 SendMessageW(SizeList->RasterSizeList.hWndList, LB_SETCURSEL, (WPARAM)nSel, 0);
168 }
169 else
170 {
171 /* TrueType font size (in pixels or points) */
172 SizeList->CurrentTTSize = FontSize;
173
174 // _ultow(szFontSize, FontSize, 10);
175 StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", FontSize);
176
177 /* Find the font size in the list, or add it both in the ComboBox list, sorted by size value (string), and its edit box */
178 nSel = SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
179 if (nSel == CB_ERR)
180 {
181 nSel = (UINT)SendMessageW(SizeList->hWndTTSizeList, CB_ADDSTRING, -1, (LPARAM)szFontSize);
182 // ComboBox_SetText(...)
183 SetWindowTextW(SizeList->hWndTTSizeList, szFontSize);
184 SizeList->bIsTTSizeDirty = TRUE;
185 }
186 SendMessageW(SizeList->hWndTTSizeList, CB_SETCURSEL, (WPARAM)nSel, 0);
187 }
188 }
189
190 static LONG
191 FontSizeList_GetSelectedFontSize(
192 IN PFONTSIZE_LIST_CTL SizeList)
193 {
194 INT nSel;
195 LONG FontSize;
196 PWCHAR pszNext = NULL;
197 WCHAR szFontSize[100];
198
199 if (SizeList->UseRasterOrTTList)
200 {
201 /* Raster font size (in pixels) */
202
203 nSel = (INT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_GETCURSEL, 0, 0);
204 if (nSel == LB_ERR) return 0;
205
206 FontSize = (LONG)SizeList->RasterSizeList.GetData(&SizeList->RasterSizeList, nSel);
207 if (FontSize == LB_ERR) return 0;
208
209 SizeList->CurrentRasterSize = FontSize;
210 }
211 else
212 {
213 /* TrueType font size (in pixels or points) */
214
215 if (!SizeList->bIsTTSizeDirty)
216 {
217 /*
218 * The user just selected an existing size, read the ComboBox selection.
219 *
220 * See: https://support.microsoft.com/en-us/help/66365/how-to-process-a-cbn-selchange-notification-message
221 * for more details.
222 */
223 nSel = SendMessageW(SizeList->hWndTTSizeList, CB_GETCURSEL, 0, 0);
224 SendMessageW(SizeList->hWndTTSizeList, CB_GETLBTEXT, nSel, (LPARAM)szFontSize);
225
226 /* Validate the font size */
227 FontSize = wcstoul(szFontSize, &pszNext, 10);
228 if ((FontSize == 0) || (*pszNext))
229 return 0;
230 }
231 else
232 {
233 /* Read the ComboBox edit string, as the user has entered a custom size */
234 // ComboBox_GetText(...)
235 GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
236
237 /* Validate the font size */
238 FontSize = wcstoul(szFontSize, &pszNext, 10);
239 if ((FontSize == 0) || (*pszNext))
240 return 0;
241
242 /* Find if the font size already exists in the list; if not, add it */
243 nSel = SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize);
244 if (nSel == CB_ERR)
245 {
246 nSel = (UINT)SendMessageW(SizeList->hWndTTSizeList, CB_ADDSTRING, -1, (LPARAM)szFontSize);
247 //// ComboBox_SetText(...)
248 //SetWindowTextW(SizeList->hWndTTSizeList, szFontSize);
249 //SizeList->bIsTTSizeDirty = TRUE;
250 }
251 SendMessageW(SizeList->hWndTTSizeList, CB_SETCURSEL, (WPARAM)nSel, 0);
252 }
253
254 SizeList->bIsTTSizeDirty = FALSE;
255
256 SizeList->CurrentTTSize = FontSize;
257
258 /*
259 * If the font size is given in points, instead of pixels,
260 * convert it into logical size.
261 */
262 if (!SizeList->TTSizePixelUnit)
263 FontSize = -PointSizeToLogicalSize(NULL, FontSize);
264 }
265
266 return FontSize;
267 }
268
269
270 static VOID
271 AddFontToList(
272 IN HWND hWndList,
273 IN LPCWSTR pszFaceName,
274 IN DWORD FontType)
275 {
276 INT iItem;
277
278 /* Make sure the font doesn't already exist in the list */
279 if (SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)pszFaceName) != LB_ERR)
280 return;
281
282 /* Add the font */
283 iItem = (INT)SendMessageW(hWndList, LB_ADDSTRING, 0, (LPARAM)pszFaceName);
284 if (iItem == LB_ERR)
285 {
286 DPRINT1("Failed to add font '%S'\n", pszFaceName);
287 return;
288 }
289
290 DPRINT1("Add font '%S'\n", pszFaceName);
291
292 /* Store this information in the list-item's userdata area */
293 // SendMessageW(hWndList, LB_SETITEMDATA, idx, MAKELPARAM(fFixed, fTrueType));
294 SendMessageW(hWndList, LB_SETITEMDATA, iItem, (LPARAM)FontType);
295 }
296
297 typedef struct _FACE_NAMES_PROC_PARAM
298 {
299 HWND hWndList;
300 UINT CodePage;
301 } FACE_NAMES_PROC_PARAM, *PFACE_NAMES_PROC_PARAM;
302
303 static BOOL CALLBACK
304 EnumFaceNamesProc(
305 IN PLOGFONTW lplf,
306 IN PNEWTEXTMETRICW lpntm,
307 IN DWORD FontType,
308 IN LPARAM lParam)
309 {
310 PFACE_NAMES_PROC_PARAM Param = (PFACE_NAMES_PROC_PARAM)lParam;
311
312 if (IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
313 {
314 /* Add the font to the list */
315 AddFontToList(Param->hWndList, lplf->lfFaceName, FontType);
316 }
317
318 /* Continue the font enumeration */
319 return TRUE;
320 }
321
322 static BOOL CALLBACK
323 EnumFontSizesProc(
324 IN PLOGFONTW lplf,
325 IN PNEWTEXTMETRICW lpntm,
326 IN DWORD FontType,
327 IN LPARAM lParam)
328 {
329 PFONTSIZE_LIST_CTL SizeList = (PFONTSIZE_LIST_CTL)lParam;
330 UINT iItem, iDupItem;
331 WCHAR szFontSize[100];
332
333 if (FontType != TRUETYPE_FONTTYPE)
334 {
335 WPARAM FontSize;
336
337 /*
338 * Format:
339 * Width = FontSize.X = LOWORD(FontSize);
340 * Height = FontSize.Y = HIWORD(FontSize);
341 */
342
343 StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d x %d", lplf->lfWidth, lplf->lfHeight);
344 FontSize = MAKEWPARAM(lplf->lfWidth, lplf->lfHeight);
345
346 /* Add the font size into the list, sorted by size value. Avoid any duplicates. */
347 /* Store this information in the list-item's userdata area */
348 iDupItem = LB_ERR;
349 iItem = BisectListSortedByValue(&SizeList->RasterSizeList, FontSize, &iDupItem, TRUE);
350 if (iItem == LB_ERR)
351 iItem = 0;
352 if (iDupItem == LB_ERR)
353 {
354 iItem = (UINT)SendMessageW(SizeList->RasterSizeList.hWndList, LB_INSERTSTRING, iItem, (LPARAM)szFontSize);
355 if (iItem != LB_ERR && iItem != LB_ERRSPACE)
356 iItem = SendMessageW(SizeList->RasterSizeList.hWndList, LB_SETITEMDATA, iItem, FontSize);
357 }
358
359 return TRUE;
360 }
361 else
362 {
363 /* TrueType or vectored font: list all the hardcoded font points */
364 ULONG i;
365 for (i = 0; i < ARRAYSIZE(TrueTypePoints); ++i)
366 {
367 // _ultow(szFontSize, TrueTypePoints[i], 10);
368 StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", TrueTypePoints[i]);
369
370 /* Add the font size into the list, sorted by size value (string). Avoid any duplicates. */
371 if (SendMessageW(SizeList->hWndTTSizeList, CB_FINDSTRINGEXACT, 0, (LPARAM)szFontSize) == CB_ERR)
372 iItem = (UINT)SendMessageW(SizeList->hWndTTSizeList, CB_INSERTSTRING, -1, (LPARAM)szFontSize);
373 }
374
375 /* Stop the enumeration now */
376 return FALSE;
377 }
378 }
379
380 static VOID
381 FaceNameList_Initialize(
382 IN HWND hWndList,
383 IN UINT CodePage)
384 {
385 FACE_NAMES_PROC_PARAM Param;
386 HDC hDC;
387 LOGFONTW lf;
388 INT idx;
389
390 Param.hWndList = hWndList;
391 Param.CodePage = CodePage;
392
393 ZeroMemory(&lf, sizeof(lf));
394 lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
395 // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
396
397 hDC = GetDC(NULL);
398 EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFaceNamesProc, (LPARAM)&Param, 0);
399 ReleaseDC(NULL, hDC);
400
401 idx = (INT)SendMessageW(hWndList, LB_GETCOUNT, 0, 0);
402 if (idx != LB_ERR && idx != 0)
403 {
404 /* We have found some fonts and filled the list, we are fine! */
405 return;
406 }
407
408 /* No fonts were found. Manually add default ones into the list. */
409 DPRINT1("The ideal console fonts were not found; manually add default ones.\n");
410
411 AddFontToList(hWndList, L"Terminal", RASTER_FONTTYPE);
412 AddFontToList(hWndList, L"Lucida Console", TRUETYPE_FONTTYPE);
413 if (CodePageToCharSet(CodePage) != DEFAULT_CHARSET)
414 AddFontToList(hWndList, L"Droid Sans Fallback", TRUETYPE_FONTTYPE);
415 }
416
417 static VOID
418 FaceNameList_SelectFont(
419 IN HWND hDlg,
420 IN HWND hWndList,
421 IN PFONTSIZE_LIST_CTL SizeList,
422 IN LPCWSTR FaceName,
423 IN ULONG FontFamily,
424 IN ULONG FontWeight,
425 IN COORD FontSize)
426 {
427 INT iItem;
428
429 iItem = (INT)SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)FaceName);
430 if (iItem == LB_ERR)
431 iItem = (INT)SendMessageW(hWndList, LB_FINDSTRINGEXACT, 0, (LPARAM)L"Terminal");
432 if (iItem == LB_ERR)
433 iItem = 0;
434 SendMessageW(hWndList, LB_SETCURSEL, (WPARAM)iItem, 0);
435
436 if (FontWeight >= FW_BOLD)
437 CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_CHECKED);
438 else
439 CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_UNCHECKED);
440
441 /* Select the current font size */
442 /*
443 * Format:
444 * Width = FontSize.X = LOWORD(FontSize);
445 * Height = FontSize.Y = HIWORD(FontSize);
446 */
447 SizeList->CurrentRasterSize = MAKELONG(FontSize.X, FontSize.Y);
448 SizeList->CurrentTTSize = FontSize.Y;
449 // FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
450
451 // return iItem;
452 }
453
454 static VOID
455 UpdateFontSizeList(
456 IN HWND hDlg,
457 IN PFONTSIZE_LIST_CTL SizeList)
458 {
459 HWND hDlgItem;
460
461 if (SizeList->UseRasterOrTTList)
462 {
463 /*
464 * Raster font: show the Raster size list, and
465 * hide the TrueType size list and the units.
466 */
467
468 // EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, FALSE);
469
470 hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
471 ShowWindow(hDlgItem, SW_HIDE);
472 EnableWindow(hDlgItem, FALSE);
473
474 hDlgItem = GetDlgItem(hDlg, IDC_RADIO_POINT_UNIT);
475 ShowWindow(hDlgItem, SW_HIDE);
476 EnableWindow(hDlgItem, FALSE);
477
478 hDlgItem = SizeList->hWndTTSizeList;
479 ShowWindow(hDlgItem, SW_HIDE);
480 EnableWindow(hDlgItem, FALSE);
481
482 hDlgItem = SizeList->RasterSizeList.hWndList;
483 EnableWindow(hDlgItem, TRUE);
484 ShowWindow(hDlgItem, SW_SHOW);
485 }
486 else
487 {
488 /*
489 * TrueType font: show the TrueType size list
490 * and the units, and hide the Raster size list.
491 */
492
493 // EnableDlgItem(hDlg, IDC_CHECK_BOLD_FONTS, TRUE);
494
495 hDlgItem = SizeList->RasterSizeList.hWndList;
496 ShowWindow(hDlgItem, SW_HIDE);
497 EnableWindow(hDlgItem, FALSE);
498
499 hDlgItem = SizeList->hWndTTSizeList;
500 EnableWindow(hDlgItem, TRUE);
501 ShowWindow(hDlgItem, SW_SHOW);
502
503 hDlgItem = GetDlgItem(hDlg, IDC_RADIO_PIXEL_UNIT);
504 EnableWindow(hDlgItem, TRUE);
505 ShowWindow(hDlgItem, SW_SHOW);
506
507 hDlgItem = GetDlgItem(hDlg, IDC_RADIO_POINT_UNIT);
508 EnableWindow(hDlgItem, TRUE);
509 ShowWindow(hDlgItem, SW_SHOW);
510 }
511 }
512
513 static BOOL
514 FontSizeChange(
515 IN HWND hDlg,
516 IN PFONTSIZE_LIST_CTL SizeList,
517 IN OUT PCONSOLE_STATE_INFO pConInfo);
518
519 static BOOL
520 FontTypeChange(
521 IN HWND hDlg,
522 IN PFONTSIZE_LIST_CTL SizeList,
523 IN OUT PCONSOLE_STATE_INFO pConInfo)
524 {
525 HWND hListBox = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
526 INT Length, nSel;
527 LPWSTR FaceName;
528 DWORD FontType;
529 LPCWSTR FontGrpBoxLabelTpl = NULL;
530 WCHAR FontGrpBoxLabel[260];
531
532 nSel = (INT)SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
533 if (nSel == LB_ERR) return FALSE;
534
535 /*
536 * This is disabled, because there can be external parameters
537 * that may have changed (e.g. ConInfo->FontWeight, code page, ...)
538 * and that we don't control here, and that need a font refresh.
539 */
540 #if 0
541 /* Check whether the selection has changed */
542 if (nSel == CurrentSelFont)
543 return FALSE;
544 #endif
545
546 Length = (INT)SendMessageW(hListBox, LB_GETTEXTLEN, nSel, 0);
547 if (Length == LB_ERR) return FALSE;
548
549 FaceName = HeapAlloc(GetProcessHeap(),
550 HEAP_ZERO_MEMORY,
551 (Length + 1) * sizeof(WCHAR));
552 if (FaceName == NULL) return FALSE;
553
554 Length = (INT)SendMessageW(hListBox, LB_GETTEXT, nSel, (LPARAM)FaceName);
555 FaceName[Length] = L'\0';
556
557 StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
558 DPRINT("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
559
560 /*
561 * Retrieve the read-only font group box label string template,
562 * and set the group box label to the name of the selected font.
563 */
564 Length = LoadStringW(hApplet, IDS_GROUPBOX_FONT_NAME, (LPWSTR)&FontGrpBoxLabelTpl, 0);
565 if (FontGrpBoxLabelTpl && Length > 0)
566 {
567 StringCchCopyNW(FontGrpBoxLabel, ARRAYSIZE(FontGrpBoxLabel), FontGrpBoxLabelTpl, Length);
568 StringCchCatW(FontGrpBoxLabel, ARRAYSIZE(FontGrpBoxLabel), FaceName);
569 SetDlgItemTextW(hDlg, IDC_GROUPBOX_FONT_NAME, FontGrpBoxLabel);
570 }
571
572 HeapFree(GetProcessHeap(), 0, FaceName);
573
574 /*
575 * Reset the font size list, only:
576 * - if we have changed the type of font, or
577 * - if the font type is the same and is RASTER but the font has changed.
578 * Otherwise, if the font type is not RASTER and has not changed,
579 * we always display the TrueType default sizes and we don't need to
580 * recreate the list when we change between different TrueType fonts.
581 */
582 FontType = SendMessageW(hListBox, LB_GETITEMDATA, nSel, 0);
583 if (FontType != LB_ERR)
584 {
585 SizeList->UseRasterOrTTList = (FontType == RASTER_FONTTYPE);
586
587 /* Display the correct font size list (if needed) */
588 if (CurrentFontType != FontType)
589 UpdateFontSizeList(hDlg, SizeList);
590
591 /* Enumerate the available sizes for the selected font */
592 if ((CurrentFontType != FontType) ||
593 (FontType == RASTER_FONTTYPE && CurrentSelFont != nSel))
594 {
595 LOGFONTW lf;
596 HDC hDC;
597
598 if (SizeList->UseRasterOrTTList)
599 SendMessageW(SizeList->RasterSizeList.hWndList, LB_RESETCONTENT, 0, 0);
600 else
601 SendMessageW(SizeList->hWndTTSizeList, CB_RESETCONTENT, 0, 0);
602
603 ZeroMemory(&lf, sizeof(lf));
604 lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
605 // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
606 StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), pConInfo->FaceName);
607
608 hDC = GetDC(NULL);
609 EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontSizesProc, (LPARAM)SizeList, 0);
610 ReleaseDC(NULL, hDC);
611
612 /* Re-select the current font size */
613 if (SizeList->UseRasterOrTTList)
614 FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
615 else
616 FontSizeList_SelectFontSize(SizeList, SizeList->CurrentTTSize);
617 }
618 }
619 else
620 {
621 /* We failed, display the raster fonts size list */
622 SizeList->UseRasterOrTTList = TRUE;
623 UpdateFontSizeList(hDlg, SizeList);
624 }
625 CurrentFontType = FontType;
626 CurrentSelFont = nSel;
627
628 FontSizeChange(hDlg, SizeList, pConInfo);
629 return TRUE;
630 }
631
632 static BOOL
633 FontSizeChange(
634 IN HWND hDlg,
635 IN PFONTSIZE_LIST_CTL SizeList,
636 IN OUT PCONSOLE_STATE_INFO pConInfo)
637 {
638 LONG FontSize;
639 UINT CharWidth, CharHeight;
640 HFONT hFont;
641 WCHAR szFontSize[100];
642
643 /*
644 * Retrieve the current selected font size.
645 * - If SizeList->UseRasterOrTTList is TRUE, or if it is FALSE but
646 * if SizeList->TTSizePixelUnit is TRUE, then the font size is in pixels;
647 * - If SizeList->TTSizePixelUnit is FALSE, then the font size is in points.
648 */
649 FontSize = FontSizeList_GetSelectedFontSize(SizeList);
650 if (FontSize == 0)
651 return FALSE; // We have got an invalid font size...
652
653 /*
654 * For TrueType fonts we set the requested width to zero
655 * so as to obtain a default aspect-ratio width.
656 */
657 CharHeight = (UINT)(SizeList->UseRasterOrTTList ? HIWORD(FontSize) : FontSize);
658 CharWidth = (UINT)(SizeList->UseRasterOrTTList ? LOWORD(FontSize) : 0);
659
660 hFont = CreateConsoleFont2((LONG)CharHeight, (LONG)CharWidth, pConInfo);
661 if (hFont == NULL)
662 DPRINT1("FontSizeChange: CreateConsoleFont2() failed\n");
663
664 /* Retrieve the real character size in pixels */
665 GetFontCellSize(NULL, hFont, &CharHeight, &CharWidth);
666
667 /*
668 * Update the font preview as well, and store the font handle. It will be
669 * freed at later update or when the font preview is refreshed or reset.
670 * For TrueType fonts, the preview will show the actual character width.
671 */
672 UpdateFontPreview(&FontPreview, hFont, CharWidth, CharHeight);
673
674 /*
675 * Format:
676 * Width = FontSize.X = LOWORD(FontSize);
677 * Height = FontSize.Y = HIWORD(FontSize);
678 */
679 pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? CharWidth : 0);
680 pConInfo->FontSize.Y = (SHORT)CharHeight;
681
682 DPRINT("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x %d)\n",
683 pConInfo->FontSize.X, pConInfo->FontSize.Y, CharWidth, CharHeight);
684
685 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
686 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
687
688 StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharWidth);
689 SetDlgItemText(hDlg, IDC_FONT_SIZE_X, szFontSize);
690 StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharHeight);
691 SetDlgItemText(hDlg, IDC_FONT_SIZE_Y, szFontSize);
692
693 return TRUE;
694 }
695
696
697 INT_PTR
698 CALLBACK
699 FontProc(HWND hDlg,
700 UINT uMsg,
701 WPARAM wParam,
702 LPARAM lParam)
703 {
704 PFONTSIZE_LIST_CTL SizeList;
705
706 SizeList = (PFONTSIZE_LIST_CTL)GetWindowLongPtrW(hDlg, DWLP_USER);
707
708 switch (uMsg)
709 {
710 case WM_INITDIALOG:
711 {
712 HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
713
714 SizeList = (PFONTSIZE_LIST_CTL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*SizeList));
715 if (!SizeList)
716 {
717 EndDialog(hDlg, 0);
718 return (INT_PTR)TRUE;
719 }
720 SizeList->RasterSizeList.hWndList = GetDlgItem(hDlg, IDC_LBOX_FONTSIZE);
721 SizeList->RasterSizeList.GetCount = RasterSizeList_GetCount;
722 SizeList->RasterSizeList.GetData = RasterSizeList_GetData;
723 SizeList->hWndTTSizeList = GetDlgItem(hDlg, IDC_CBOX_FONTSIZE);
724 SizeList->bIsTTSizeDirty = FALSE;
725 SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)SizeList);
726
727 /* By default show the raster font size list */
728 SizeList->UseRasterOrTTList = TRUE;
729
730 /* By default show the font sizes in pixel units */
731 CheckRadioButton(hDlg, IDC_RADIO_PIXEL_UNIT, IDC_RADIO_POINT_UNIT, IDC_RADIO_PIXEL_UNIT);
732 SizeList->TTSizePixelUnit = TRUE;
733
734 UpdateFontSizeList(hDlg, SizeList);
735
736 /* Initialize the font list */
737 FaceNameList_Initialize(hFontList, ConInfo->CodePage);
738
739 /* Select the current font */
740 DPRINT1("ConInfo->FaceName = '%S'\n", ConInfo->FaceName);
741 FaceNameList_SelectFont(hDlg, hFontList,
742 SizeList,
743 ConInfo->FaceName,
744 ConInfo->FontFamily,
745 ConInfo->FontWeight,
746 ConInfo->FontSize);
747
748 /* Refresh everything */
749 FontTypeChange(hDlg, SizeList, ConInfo);
750
751 return TRUE;
752 }
753
754 case WM_DESTROY:
755 {
756 if (SizeList)
757 HeapFree(GetProcessHeap(), 0, SizeList);
758 return (INT_PTR)TRUE;
759 }
760
761 case WM_DRAWITEM:
762 {
763 LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
764
765 if (drawItem->CtlID == IDC_STATIC_SELECT_FONT_PREVIEW)
766 PaintText(drawItem, ConInfo, Screen);
767
768 return TRUE;
769 }
770
771 case WM_DISPLAYCHANGE:
772 {
773 /* Retransmit to the preview window */
774 SendDlgItemMessageW(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW,
775 WM_DISPLAYCHANGE, wParam, lParam);
776 break;
777 }
778
779 #if 0
780 case PSM_QUERYSIBLINGS:
781 {
782 /*
783 * If this is a notification from the "Options" dialog because we
784 * changed the code page, treat it using the WM_FONTCHANGE case,
785 * otherwise ignore it.
786 */
787 if (wParam != IDL_CODEPAGE)
788 return FALSE;
789
790 /* Fall through */
791 }
792 #endif
793
794 case WM_FONTCHANGE:
795 {
796 /* The pool of font resources has changed, re-enumerate the fonts */
797 HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
798
799 /* Initialize the font list */
800 FaceNameList_Initialize(hFontList, ConInfo->CodePage);
801
802 /* Select the current font */
803 FaceNameList_SelectFont(hDlg, hFontList,
804 SizeList,
805 ConInfo->FaceName,
806 ConInfo->FontFamily,
807 ConInfo->FontWeight,
808 ConInfo->FontSize);
809
810 /* Refresh everything */
811 FontTypeChange(hDlg, SizeList, ConInfo);
812 break;
813 }
814
815 case WM_NOTIFY:
816 {
817 switch (((LPNMHDR)lParam)->code)
818 {
819 case PSN_APPLY:
820 {
821 ApplyConsoleInfo(hDlg);
822 return TRUE;
823 }
824 }
825
826 break;
827 }
828
829 case WM_COMMAND:
830 {
831 if (HIWORD(wParam) == LBN_SELCHANGE /* || CBN_SELCHANGE */)
832 {
833 switch (LOWORD(wParam))
834 {
835 case IDC_LBOX_FONTTYPE:
836 {
837 /* Change the property sheet state only if the font has really changed */
838 if (FontTypeChange(hDlg, SizeList, ConInfo))
839 PropSheet_Changed(GetParent(hDlg), hDlg);
840 break;
841 }
842
843 case IDC_LBOX_FONTSIZE:
844 case IDC_CBOX_FONTSIZE:
845 {
846 /* Change the property sheet state only if the font has really changed */
847 if (FontSizeChange(hDlg, SizeList, ConInfo))
848 PropSheet_Changed(GetParent(hDlg), hDlg);
849 break;
850 }
851 }
852 }
853 /* NOTE: CBN_EDITUPDATE is sent first, and is followed by CBN_EDITCHANGE */
854 else if (HIWORD(wParam) == CBN_EDITUPDATE && LOWORD(wParam) == IDC_CBOX_FONTSIZE)
855 {
856 ULONG FontSize;
857 PWCHAR pszNext = NULL;
858 WCHAR szFontSize[100];
859 WCHAR szMessage[260];
860
861 /* Read the ComboBox edit string, as the user has entered a custom size */
862 GetWindowTextW(SizeList->hWndTTSizeList, szFontSize, ARRAYSIZE(szFontSize));
863
864 /* Validate the font size */
865 FontSize = wcstoul(szFontSize, &pszNext, 10);
866 if ((FontSize == 0) || (*pszNext))
867 {
868 // FIXME: Localize!
869 StringCchPrintfW(szMessage, ARRAYSIZE(szMessage), L"\"%s\" is not a valid font size.", szFontSize);
870 MessageBoxW(hDlg, szMessage, L"Error", MB_ICONINFORMATION | MB_OK);
871 }
872 /**/SizeList->bIsTTSizeDirty = TRUE;/**/
873 }
874 else if (HIWORD(wParam) == CBN_KILLFOCUS && LOWORD(wParam) == IDC_CBOX_FONTSIZE)
875 {
876 /* Change the property sheet state only if the font has really changed */
877 if (FontSizeChange(hDlg, SizeList, ConInfo))
878 PropSheet_Changed(GetParent(hDlg), hDlg);
879 }
880 else
881 if (HIWORD(wParam) == BN_CLICKED)
882 {
883 switch (LOWORD(wParam))
884 {
885 case IDC_CHECK_BOLD_FONTS:
886 {
887 if (IsDlgButtonChecked(hDlg, IDC_CHECK_BOLD_FONTS) == BST_CHECKED)
888 ConInfo->FontWeight = FW_BOLD;
889 else
890 ConInfo->FontWeight = FW_NORMAL;
891
892 FontTypeChange(hDlg, SizeList, ConInfo);
893 PropSheet_Changed(GetParent(hDlg), hDlg);
894 break;
895 }
896
897 case IDC_RADIO_PIXEL_UNIT:
898 case IDC_RADIO_POINT_UNIT:
899 {
900 SizeList->TTSizePixelUnit = (LOWORD(wParam) == IDC_RADIO_PIXEL_UNIT);
901
902 /* The call is valid only for TrueType fonts */
903 if (CurrentFontType != TRUETYPE_FONTTYPE)
904 break;
905
906 /* Change the property sheet state only if the font has really changed */
907 if (FontSizeChange(hDlg, SizeList, ConInfo))
908 PropSheet_Changed(GetParent(hDlg), hDlg);
909 break;
910 }
911 }
912 }
913
914 break;
915 }
916
917 default:
918 break;
919 }
920
921 return FALSE;
922 }