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 } 923