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