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