windows-nt/Source/XPSP1/NT/shell/osshell/control/console/fontdlg.c
2020-09-26 16:20:57 +08:00

1253 lines
36 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
fontdlg.dlg
Abstract:
This module contains the code for console font dialog
Author:
Therese Stowell (thereses) Feb-3-1992 (swiped from Win3.1)
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "fontdlg.h"
/* ----- Prototypes ----- */
int FontListCreate(
HWND hDlg,
LPTSTR ptszTTFace,
BOOL bNewFaceList
);
BOOL PreviewUpdate(
HWND hDlg,
BOOL bLB
);
int SelectCurrentSize(
HWND hDlg,
BOOL bLB,
int FontIndex);
BOOL PreviewInit(
HWND hDlg);
VOID DrawItemFontList(
const LPDRAWITEMSTRUCT lpdis);
/* ----- Globals ----- */
const TCHAR g_szPreviewText[] = \
TEXT("C:\\WINDOWS> dir \n") \
TEXT("SYSTEM <DIR> 10-01-99 5:00a\n") \
TEXT("SYSTEM32 <DIR> 10-01-99 5:00a\n") \
TEXT("README TXT 26926 10-01-99 5:00a\n") \
TEXT("WINDOWS BMP 46080 10-01-99 5:00a\n") \
TEXT("NOTEPAD EXE 337232 10-01-99 5:00a\n") \
TEXT("CLOCK AVI 39594 10-01-99 5:00p\n") \
TEXT("WIN INI 7005 10-01-99 5:00a\n");
HBITMAP hbmTT = NULL; // handle of TT logo bitmap
BITMAP bmTT; // attributes of TT source bitmap
int dyFacelistItem; // height of Item in Facelist listbox
BOOL gbPointSizeError = FALSE;
BOOL gbBold = FALSE;
#if defined(FE_SB)
BOOL fChangeCodePage = FALSE;
BOOL
SelectCurrentFont(
HWND hDlg,
int FontIndex
);
#endif
// Globals strings loaded from resource
TCHAR tszSelectedFont[CCH_SELECTEDFONT+1];
TCHAR tszRasterFonts[CCH_RASTERFONTS+1];
INT_PTR
APIENTRY
FontDlgProc(
HWND hDlg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Dialog proc for the font selection dialog box.
Returns the near offset into the far table of LOGFONT structures.
--*/
{
HWND hWndFocus;
HWND hWndList;
int FontIndex;
BOOL bLB;
TEXTMETRIC tm;
HDC hDC;
switch (wMsg) {
case WM_INITDIALOG:
/*
* Load the font description strings
*/
LoadString(ghInstance, IDS_RASTERFONT,
tszRasterFonts, NELEM(tszRasterFonts));
DBGPRINT(("tszRasterFonts = \"%ls\"\n", tszRasterFonts));
ASSERT(_tcslen(tszRasterFonts) < CCH_RASTERFONTS);
LoadString(ghInstance, IDS_SELECTEDFONT,
tszSelectedFont, NELEM(tszSelectedFont));
DBGPRINT(("tszSelectedFont = \"%ls\"\n", tszSelectedFont));
ASSERT(_tcslen(tszSelectedFont) < CCH_SELECTEDFONT);
/* Save current font size as dialog window's user data */
#if defined(FE_SB)
ASSERT(OEMCP != 0);
if (gfFESystem) {
SetWindowLongPtr(hDlg, GWLP_USERDATA,
MAKELONG(FontInfo[CurrentFontIndex].tmCharSet,
FontInfo[CurrentFontIndex].Size.Y));
} else {
#endif
SetWindowLongPtr(hDlg, GWLP_USERDATA,
MAKELONG(FontInfo[CurrentFontIndex].Size.X,
FontInfo[CurrentFontIndex].Size.Y));
#if defined(FE_SB)
}
#endif
/* Create the list of suitable fonts */
gbEnumerateFaces = TRUE;
bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
gbBold = IS_BOLD(gpStateInfo->FontWeight);
CheckDlgButton(hDlg, IDD_BOLDFONT, gbBold);
FontListCreate(hDlg, bLB ? NULL : gpStateInfo->FaceName, TRUE);
/* Initialize the preview window - selects current face & size too */
bLB = PreviewInit(hDlg);
PreviewUpdate(hDlg, bLB);
/* Make sure the list box has the focus */
hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
SetFocus(hWndList);
break;
case WM_FONTCHANGE:
gbEnumerateFaces = TRUE;
bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
FontListCreate(hDlg, NULL, TRUE);
FontIndex = FindCreateFont(gpStateInfo->FontFamily,
gpStateInfo->FaceName,
gpStateInfo->FontSize,
gpStateInfo->FontWeight,
gpStateInfo->CodePage);
SelectCurrentSize(hDlg, bLB, FontIndex);
return TRUE;
#if defined(FE_SB)
case WM_PAINT:
if (fChangeCodePage)
{
fChangeCodePage = FALSE;
/* Create the list of suitable fonts */
bLB = !TM_IS_TT_FONT(gpStateInfo->FontFamily);
FontIndex = FontListCreate(hDlg, !bLB ? NULL : gpStateInfo->FaceName, TRUE);
FontIndex = FontListCreate(hDlg, bLB ? NULL : gpStateInfo->FaceName, TRUE);
CurrentFontIndex = FontIndex;
FontIndex = SelectCurrentSize(hDlg, bLB, FontIndex);
SelectCurrentFont(hDlg, FontIndex);
PreviewUpdate(hDlg, bLB);
}
break;
#endif
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDD_BOLDFONT:
DBGPRINT(("WM_COMMAND to Bold Font checkbox %x\n", HIWORD(wParam)));
gbBold = IsDlgButtonChecked(hDlg, IDD_BOLDFONT);
goto RedoFontListAndPreview;
case IDD_FACENAME:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
RedoFontListAndPreview:
{
TCHAR atchNewFace[LF_FACESIZE];
LONG l;
DBGFONTS(("LBN_SELCHANGE from FACENAME\n"));
l = (LONG)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETCURSEL, 0, 0L);
bLB = (BOOL)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETITEMDATA, l, 0L);
if (!bLB) {
SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETTEXT, l, (LPARAM)atchNewFace);
DBGFONTS(("LBN_EDITUPDATE, got TT face \"%ls\"\n", atchNewFace));
}
FontIndex = FontListCreate(hDlg, bLB ? NULL : atchNewFace, FALSE);
FontIndex = SelectCurrentSize(hDlg, bLB, FontIndex);
PreviewUpdate(hDlg, bLB);
return TRUE;
}
}
break;
case IDD_POINTSLIST:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
DBGFONTS(("CBN_SELCHANGE from POINTSLIST\n"));
PreviewUpdate(hDlg, FALSE);
return TRUE;
case CBN_KILLFOCUS:
DBGFONTS(("CBN_KILLFOCUS from POINTSLIST\n"));
if (!gbPointSizeError) {
hWndFocus = GetFocus();
if (hWndFocus != NULL && IsChild(hDlg, hWndFocus) &&
hWndFocus != GetDlgItem(hDlg, IDCANCEL)) {
PreviewUpdate(hDlg, FALSE);
}
}
return TRUE;
default:
DBGFONTS(("unhandled CBN_%x from POINTSLIST\n",HIWORD(wParam)));
break;
}
break;
case IDD_PIXELSLIST:
switch (HIWORD(wParam)) {
case LBN_SELCHANGE:
DBGFONTS(("LBN_SELCHANGE from PIXELSLIST\n"));
PreviewUpdate(hDlg, TRUE);
return TRUE;
default:
break;
}
break;
default:
break;
}
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) {
case PSN_KILLACTIVE:
//
// If the TT combo box is visible, update selection
//
hWndList = GetDlgItem(hDlg, IDD_POINTSLIST);
if (hWndList != NULL && IsWindowVisible(hWndList)) {
if (!PreviewUpdate(hDlg, FALSE)) {
SetDlgMsgResult(hDlg, PSN_KILLACTIVE, TRUE);
return TRUE;
}
SetDlgMsgResult(hDlg, PSN_KILLACTIVE, FALSE);
}
FontIndex = CurrentFontIndex;
if (FontInfo[FontIndex].SizeWant.Y == 0) {
// Raster Font, so save actual size
gpStateInfo->FontSize = FontInfo[FontIndex].Size;
} else {
// TT Font, so save desired size
gpStateInfo->FontSize = FontInfo[FontIndex].SizeWant;
}
gpStateInfo->FontWeight = FontInfo[FontIndex].Weight;
gpStateInfo->FontFamily = FontInfo[FontIndex].Family;
wcscpy(gpStateInfo->FaceName, FontInfo[FontIndex].FaceName);
return TRUE;
case PSN_APPLY:
/*
* Write out the state values and exit.
*/
EndDlgPage(hDlg);
return TRUE;
}
break;
/*
* For WM_MEASUREITEM and WM_DRAWITEM, since there is only one
* owner-draw item (combobox) in the entire dialog box, we don't have
* to do a GetDlgItem to figure out who he is.
*/
case WM_MEASUREITEM:
/*
* Load the TrueType logo bitmap
*/
if (hbmTT == NULL) {
hbmTT = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_TRUETYPE));
GetObject(hbmTT, sizeof(BITMAP), &bmTT);
}
/*
* Compute the height of face name listbox entries
*/
if (dyFacelistItem == 0) {
HFONT hFont;
hDC = GetDC(hDlg);
hFont = GetWindowFont(hDlg);
if (hFont) {
hFont = SelectObject(hDC, hFont);
}
GetTextMetrics(hDC, &tm);
if (hFont) {
SelectObject(hDC, hFont);
}
ReleaseDC(hDlg, hDC);
dyFacelistItem = max(tm.tmHeight, bmTT.bmHeight);
}
((LPMEASUREITEMSTRUCT)lParam)->itemHeight = dyFacelistItem;
return TRUE;
case WM_DRAWITEM:
DrawItemFontList((LPDRAWITEMSTRUCT)lParam);
return TRUE;
case WM_DESTROY:
/*
* Delete the TrueType logo bitmap
*/
if (hbmTT != NULL) {
DeleteObject(hbmTT);
hbmTT = NULL;
}
return TRUE;
default:
break;
}
return CommonDlgProc(hDlg, wMsg, wParam, lParam);
}
int
FontListCreate(
HWND hDlg,
LPTSTR ptszTTFace,
BOOL bNewFaceList
)
/*++
Initializes the font list by enumerating all fonts and picking the
proper ones for our list.
Returns
FontIndex of selected font (LB_ERR if none)
--*/
{
TCHAR tszText[80];
LONG lListIndex;
ULONG i;
HWND hWndShow; // List or Combo box
HWND hWndHide; // Combo or List box
HWND hWndFaceCombo;
HANDLE hStockFont;
BOOL bLB;
int LastShowX = 0;
int LastShowY = 0;
int nSameSize = 0;
UINT CodePage = gpStateInfo->CodePage;
BOOL fDbcsCharSet = IS_ANY_DBCS_CHARSET( CodePageToCharSet( CodePage ) );
BOOL fFindTTFont = FALSE;
LPTSTR ptszAltTTFace = NULL;
LONG_PTR dwExStyle = 0L;
ASSERT(OEMCP != 0); // must be initialized
bLB = ((ptszTTFace == NULL) || (ptszTTFace[0] == TEXT('\0')));
if (! bLB) {
if (IsAvailableTTFont(ptszTTFace)) {
ptszAltTTFace = GetAltFaceName(ptszTTFace);
}
else {
ptszAltTTFace = ptszTTFace;
}
}
DBGFONTS(("FontListCreate %lx, %s, %s new FaceList\n", hDlg,
bLB ? "Raster" : "TrueType",
bNewFaceList ? "Make" : "No" ));
/*
* This only enumerates face names if necessary, and
* it only enumerates font sizes if necessary
*/
EnumerateFonts(bLB ? EF_OEMFONT : EF_TTFONT);
/* init the TTFaceNames */
DBGFONTS((" Create %s fonts\n", bLB ? "Raster" : "TrueType"));
if (bNewFaceList) {
PFACENODE panFace;
hWndFaceCombo = GetDlgItem(hDlg, IDD_FACENAME);
SendMessage(hWndFaceCombo, LB_RESETCONTENT, 0, 0);
lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0, (LPARAM)tszRasterFonts);
SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, TRUE);
DBGFONTS(("Added \"%ls\", set Item Data %d = TRUE\n", tszRasterFonts, lListIndex));
for (panFace = gpFaceNames; panFace; panFace = panFace->pNext) {
if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
continue;
}
if (!fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
continue;
}
if ((fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
(!fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, 0)))
{
if ( !bLB &&
(_tcscmp(ptszTTFace, panFace->atch) == 0 ||
_tcscmp(ptszAltTTFace, panFace->atch) == 0)
) {
fFindTTFont = TRUE;
}
lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0,
(LPARAM)panFace->atch);
SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, FALSE);
DBGFONTS(("Added \"%ls\", set Item Data %d = FALSE\n",
panFace->atch, lListIndex));
}
}
if (!bLB && !fFindTTFont) {
for (panFace = gpFaceNames; panFace; panFace = panFace->pNext) {
if ((panFace->dwFlag & (EF_TTFONT|EF_NEW)) != (EF_TTFONT|EF_NEW)) {
continue;
}
if (!fDbcsCharSet && (panFace->dwFlag & EF_DBCSFONT)) {
continue;
}
if (( fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
(!fDbcsCharSet && IsAvailableTTFontCP(panFace->atch, 0)))
{
if (_tcscmp(ptszTTFace, panFace->atch) != 0) {
_tcscpy(ptszTTFace, panFace->atch);
break;
}
}
}
}
} // if(bNewFaceList)
hWndShow = GetDlgItem(hDlg, IDD_BOLDFONT);
#if defined(FE_SB)
/*
* For JAPAN, We uses "MS Gothic" TT font.
* So, Bold of this font is not 1:2 width between SBCS:DBCS.
*/
if (fDbcsCharSet && IsDisableBoldTTFont(ptszTTFace)) {
EnableWindow(hWndShow, FALSE);
gbBold = FALSE;
CheckDlgButton(hDlg, IDD_BOLDFONT, FALSE);
} else {
#endif
CheckDlgButton(hDlg, IDD_BOLDFONT, (bLB || !gbBold) ? FALSE : TRUE);
EnableWindow(hWndShow, bLB ? FALSE : TRUE);
#if defined(FE_SB)
}
#endif
hWndHide = GetDlgItem(hDlg, bLB ? IDD_POINTSLIST : IDD_PIXELSLIST);
ShowWindow(hWndHide, SW_HIDE);
EnableWindow(hWndHide, FALSE);
hWndShow = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
// hStockFont = GetStockObject(SYSTEM_FIXED_FONT);
// SendMessage(hWndShow, WM_SETFONT, (DWORD)hStockFont, FALSE);
ShowWindow(hWndShow, SW_SHOW);
EnableWindow(hWndShow, TRUE);
#if defined(FE_SB)
if (bNewFaceList) {
lcbRESETCONTENT(hWndShow, bLB);
}
#endif
dwExStyle = GetWindowLongPtr(hWndShow, GWL_EXSTYLE);
if((dwExStyle & WS_EX_LAYOUTRTL) && !(dwExStyle & WS_EX_RTLREADING))
{
// if mirrored RTL Reading means LTR !!
SetWindowLongPtr(hWndShow, GWL_EXSTYLE, dwExStyle | WS_EX_RTLREADING);
}
/* Initialize hWndShow list/combo box */
for (i=0;i<NumberOfFonts;i++) {
int ShowX, ShowY;
if (!bLB == !TM_IS_TT_FONT(FontInfo[i].Family)) {
DBGFONTS((" Font %x not right type\n", i));
continue;
}
#if defined(FE_SB)
if (fDbcsCharSet) {
if (!IS_ANY_DBCS_CHARSET(FontInfo[i].tmCharSet)) {
DBGFONTS((" Font %x not right type for DBCS character set\n", i));
continue;
}
}
else {
if (IS_ANY_DBCS_CHARSET(FontInfo[i].tmCharSet)) {
DBGFONTS((" Font %x not right type for SBCS character set\n", i));
continue;
}
}
#endif
if (!bLB) {
if (_tcscmp(FontInfo[i].FaceName, ptszTTFace) != 0 &&
_tcscmp(FontInfo[i].FaceName, ptszAltTTFace) != 0
) {
/*
* A TrueType font, but not the one we're interested in,
* so don't add it to the list of point sizes.
*/
DBGFONTS((" Font %x is TT, but not %ls\n", i, ptszTTFace));
continue;
}
if (gbBold != IS_BOLD(FontInfo[i].Weight)) {
DBGFONTS((" Font %x has weight %d, but we wanted %sbold\n",
i, FontInfo[i].Weight, gbBold ? "" : "not "));
continue;
}
}
if (FontInfo[i].SizeWant.X > 0) {
ShowX = FontInfo[i].SizeWant.X;
} else {
ShowX = FontInfo[i].Size.X;
}
if (FontInfo[i].SizeWant.Y > 0) {
ShowY = FontInfo[i].SizeWant.Y;
} else {
ShowY = FontInfo[i].Size.Y;
}
/*
* Add the size description string to the end of the right list
*/
if (TM_IS_TT_FONT(FontInfo[i].Family)) {
// point size
wsprintf(tszText, TEXT("%2d"), FontInfo[i].SizeWant.Y);
} else {
// pixel size
if ((LastShowX == ShowX) && (LastShowY == ShowY)) {
nSameSize++;
} else {
LastShowX = ShowX;
LastShowY = ShowY;
nSameSize = 0;
}
/*
* The number nSameSize is appended to the string to distinguish
* between Raster fonts of the same size. It is not intended to
* be visible and exists off the edge of the list
*/
if(((dwExStyle & WS_EX_RIGHT) && !(dwExStyle & WS_EX_LAYOUTRTL))
|| (!(dwExStyle & WS_EX_RIGHT) && (dwExStyle & WS_EX_LAYOUTRTL))) {
// flip it so that the hidden part be at the far left
wsprintf(tszText, TEXT("#%d %2d x %2d"),
nSameSize, ShowX, ShowY);
} else {
wsprintf(tszText, TEXT("%2d x %2d #%d"),
ShowX, ShowY, nSameSize);
}
}
lListIndex = lcbFINDSTRINGEXACT(hWndShow, bLB, tszText);
if (lListIndex == LB_ERR) {
lListIndex = lcbADDSTRING(hWndShow, bLB, tszText);
}
DBGFONTS((" added %ls to %sSLIST(%lx) index %lx\n",
tszText,
bLB ? "PIXEL" : "POINT",
hWndShow, lListIndex));
lcbSETITEMDATA(hWndShow, bLB, (DWORD)lListIndex, i);
}
/*
* Get the FontIndex from the currently selected item.
* (i will be LB_ERR if no currently selected item).
*/
lListIndex = lcbGETCURSEL(hWndShow, bLB);
i = lcbGETITEMDATA(hWndShow, bLB, lListIndex);
DBGFONTS(("FontListCreate returns 0x%x\n", i));
return i;
}
/** DrawItemFontList
*
* Answer the WM_DRAWITEM message sent from the font list box or
* facename list box.
*
* Entry:
* lpdis -> DRAWITEMSTRUCT describing object to be drawn
*
* Returns:
* None.
*
* The object is drawn.
*/
VOID WINAPI
DrawItemFontList(const LPDRAWITEMSTRUCT lpdis)
{
HDC hDC, hdcMem;
DWORD rgbBack, rgbText, rgbFill;
TCHAR tszFace[LF_FACESIZE];
HBITMAP hOld;
int dy;
HBRUSH hbrFill;
HWND hWndItem;
BOOL bLB;
int dxttbmp;
if ((int)lpdis->itemID < 0)
return;
hDC = lpdis->hDC;
if (lpdis->itemAction & ODA_FOCUS) {
if (lpdis->itemState & ODS_SELECTED) {
DrawFocusRect(hDC, &lpdis->rcItem);
}
} else {
if (lpdis->itemState & ODS_SELECTED) {
rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_HIGHLIGHT));
} else {
rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
rgbBack = SetBkColor(hDC, rgbFill = GetSysColor(COLOR_WINDOW));
}
// draw selection background
hbrFill = CreateSolidBrush(rgbFill);
if (hbrFill) {
FillRect(hDC, &lpdis->rcItem, hbrFill);
DeleteObject(hbrFill);
}
// get the string
if (IsWindow(hWndItem = lpdis->hwndItem) == FALSE) {
return;
}
SendMessage(hWndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)tszFace);
bLB = (BOOL)SendMessage(hWndItem, LB_GETITEMDATA, lpdis->itemID, 0L);
dxttbmp = bLB ? 0 : bmTT.bmWidth;
DBGFONTS(("DrawItemFontList must redraw \"%ls\" %s\n", tszFace,
bLB ? "Raster" : "TrueType"));
// draw the text
TabbedTextOut(hDC, lpdis->rcItem.left + dxttbmp,
lpdis->rcItem.top, tszFace,
_tcslen(tszFace), 0, NULL, dxttbmp);
// and the TT bitmap if needed
if (!bLB) {
hdcMem = CreateCompatibleDC(hDC);
if (hdcMem) {
hOld = SelectObject(hdcMem, hbmTT);
dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - bmTT.bmHeight) / 2;
BitBlt(hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy,
dxttbmp, dyFacelistItem, hdcMem,
0, 0, SRCINVERT);
if (hOld)
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
}
}
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBack);
if (lpdis->itemState & ODS_FOCUS) {
DrawFocusRect(hDC, &lpdis->rcItem);
}
}
}
UINT
GetPointSizeInRange(
HWND hDlg,
INT Min,
INT Max)
/*++
Routine Description:
Get a size from the Point Size ComboBox edit field
Return Value:
Point Size - of the edit field limited by Min/Max size
0 - if the field is empty or invalid
--*/
{
TCHAR szBuf[90];
int nTmp = 0;
BOOL bOK;
if (GetDlgItemText(hDlg, IDD_POINTSLIST, szBuf, NELEM(szBuf))) {
nTmp = GetDlgItemInt(hDlg, IDD_POINTSLIST, &bOK, TRUE);
if (bOK && nTmp >= Min && nTmp <= Max) {
return nTmp;
}
}
return 0;
}
/* ----- Preview routines ----- */
LRESULT
FontPreviewWndProc(
HWND hWnd,
UINT wMessage,
WPARAM wParam,
LPARAM lParam
)
/* FontPreviewWndProc
* Handles the font preview window
*/
{
PAINTSTRUCT ps;
RECT rect;
HFONT hfontOld;
HBRUSH hbrNew;
HBRUSH hbrOld;
COLORREF rgbText;
COLORREF rgbBk;
switch (wMessage) {
case WM_ERASEBKGND:
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
/* Draw the font sample */
if (GetWindowLong(hWnd, GWL_ID) == IDD_COLOR_POPUP_COLORS) {
rgbText = GetNearestColor(ps.hdc, PopupTextColor(gpStateInfo));
rgbBk = GetNearestColor(ps.hdc, PopupBkColor(gpStateInfo));
} else {
rgbText = GetNearestColor(ps.hdc, ScreenTextColor(gpStateInfo));
rgbBk = GetNearestColor(ps.hdc, ScreenBkColor(gpStateInfo));
}
SetTextColor(ps.hdc, rgbText);
SetBkColor(ps.hdc, rgbBk);
GetClientRect(hWnd, &rect);
hfontOld = SelectObject(ps.hdc, FontInfo[CurrentFontIndex].hFont);
hbrNew = CreateSolidBrush(rgbBk);
hbrOld = SelectObject(ps.hdc, hbrNew);
PatBlt(ps.hdc, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
PATCOPY);
InflateRect(&rect, -2, -2);
DrawText(ps.hdc, g_szPreviewText, -1, &rect, 0);
SelectObject(ps.hdc, hbrOld);
DeleteObject(hbrNew);
SelectObject(ps.hdc, hfontOld);
EndPaint(hWnd, &ps);
break;
default:
return DefWindowProc(hWnd, wMessage, wParam, lParam);
}
return 0L;
}
/*
* Get the font index for a new font
* If necessary, attempt to create the font.
* Always return a valid FontIndex (even if not correct)
* Family: Find/Create a font with of this Family
* 0 - don't care
* ptszFace: Find/Create a font with this face name.
* NULL or TEXT("") - use DefaultFaceName
* Size: Must match SizeWant or actual Size.
*/
int
FindCreateFont(
DWORD Family,
LPTSTR ptszFace,
COORD Size,
LONG Weight,
UINT CodePage)
{
#define NOT_CREATED_NOR_FOUND -1
#define CREATED_BUT_NOT_FOUND -2
int i;
int FontIndex = NOT_CREATED_NOR_FOUND;
BOOL bFontOK;
TCHAR AltFaceName[LF_FACESIZE];
COORD AltFontSize;
BYTE AltFontFamily;
ULONG AltFontIndex = 0;
LPTSTR ptszAltFace = NULL;
BYTE CharSet = CodePageToCharSet(CodePage);
ASSERT(OEMCP != 0);
DBGFONTS(("FindCreateFont Family=%x %ls (%d,%d) %d %d %x\n",
Family, ptszFace, Size.X, Size.Y, Weight, CodePage, CharSet));
if (gfFESystem) {
if (IS_ANY_DBCS_CHARSET(CharSet)) {
if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
ptszFace = DefaultFaceName;
}
if (Size.Y == 0) {
Size = DefaultFontSize;
}
}
else {
MakeAltRasterFont(CodePage, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
ptszFace = AltFaceName;
}
if (Size.Y == 0) {
Size.X = AltFontSize.X;
Size.Y = AltFontSize.Y;
}
}
}
else {
if (ptszFace == NULL || *ptszFace == TEXT('\0')) {
ptszFace = DefaultFaceName;
}
if (Size.Y == 0) {
Size = DefaultFontSize;
}
}
if (IsAvailableTTFont(ptszFace)) {
ptszAltFace = GetAltFaceName(ptszFace);
}
else {
ptszAltFace = ptszFace;
}
/*
* Try to find the exact font
*/
TryFindExactFont:
for (i=0; i < (int)NumberOfFonts; i++) {
/*
* If looking for a particular Family, skip non-matches
*/
if ((Family != 0) &&
((BYTE)Family != FontInfo[i].Family)) {
continue;
}
/*
* Skip non-matching sizes
*/
if ((!SIZE_EQUAL(FontInfo[i].SizeWant, Size) &&
!SIZE_EQUAL(FontInfo[i].Size, Size))) {
continue;
}
/*
* Skip non-matching weights
*/
if ((Weight != 0) && (Weight != FontInfo[i].Weight)) {
continue;
}
#if defined(FE_SB)
if (!TM_IS_TT_FONT(FontInfo[i].Family) &&
FontInfo[i].tmCharSet != CharSet) {
continue;
}
#endif
/*
* Size (and maybe Family) match.
* If we don't care about the name, or if it matches, use this font.
* Else if name doesn't match and it is a raster font, consider it.
*/
if ((ptszFace == NULL) || (ptszFace[0] == TEXT('\0')) ||
(_tcscmp(FontInfo[i].FaceName, ptszFace) == 0) ||
(_tcscmp(FontInfo[i].FaceName, ptszAltFace) == 0)
) {
FontIndex = i;
goto FoundFont;
} else if (!TM_IS_TT_FONT(FontInfo[i].Family)) {
FontIndex = i;
}
}
if (FontIndex == NOT_CREATED_NOR_FOUND) {
/*
* Didn't find the exact font, so try to create it
*/
ULONG ulOldEnumFilter;
ulOldEnumFilter = SetFontEnumeration(0);
SetFontEnumeration(ulOldEnumFilter & ~FE_FILTER_TRUETYPE);
if (Size.Y < 0) {
Size.Y = -Size.Y;
}
bFontOK = DoFontEnum(NULL, ptszFace, &Size.Y, 1);
SetFontEnumeration(ulOldEnumFilter);
if (bFontOK) {
DBGFONTS(("FindCreateFont created font!\n"));
FontIndex = CREATED_BUT_NOT_FOUND;
goto TryFindExactFont;
} else {
DBGFONTS(("FindCreateFont failed to create font!\n"));
}
} else if (FontIndex >= 0) {
// a close Raster Font fit - only the name doesn't match.
goto FoundFont;
}
/*
* Failed to find exact match, even after enumeration, so now try
* to find a font of same family and same size or bigger
*/
for (i=0; i < (int)NumberOfFonts; i++) {
#if defined(FE_SB)
if (gfFESystem) {
if ((Family != 0) &&
((BYTE)Family != FontInfo[i].Family)) {
continue;
}
if (!TM_IS_TT_FONT(FontInfo[i].Family) &&
FontInfo[i].tmCharSet != CharSet) {
continue;
}
}
else {
#endif
if ((BYTE)Family != FontInfo[i].Family) {
continue;
}
#if defined(FE_SB)
}
#endif
if (FontInfo[i].Size.Y >= Size.Y &&
FontInfo[i].Size.X >= Size.X) {
// Same family, size >= desired.
FontIndex = i;
break;
}
}
if (FontIndex < 0) {
DBGFONTS(("FindCreateFont defaults!\n"));
#if defined(FE_SB)
if (gfFESystem) {
if (CodePage == OEMCP) {
FontIndex = DefaultFontIndex;
}
else {
FontIndex = AltFontIndex;
}
}
else {
#endif
FontIndex = DefaultFontIndex;
#if defined(FE_SB)
}
#endif
}
FoundFont:
DBGFONTS(("FindCreateFont returns %x : %ls (%d,%d)\n", FontIndex,
FontInfo[FontIndex].FaceName,
FontInfo[FontIndex].Size.X, FontInfo[FontIndex].Size.Y));
return FontIndex;
#undef NOT_CREATED_NOR_FOUND
#undef CREATED_BUT_NOT_FOUND
}
/*
* SelectCurrentSize - Select the right line of the Size listbox/combobox.
* bLB : Size controls is a listbox (TRUE for RasterFonts)
* FontIndex : Index into FontInfo[] cache
* If < 0 then choose a good font.
* Returns
* FontIndex : Index into FontInfo[] cache
*/
int
SelectCurrentSize(HWND hDlg, BOOL bLB, int FontIndex)
{
int iCB;
HWND hWndList;
DBGFONTS(("SelectCurrentSize %lx %s %x\n",
hDlg, bLB ? "Raster" : "TrueType", FontIndex));
hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
iCB = lcbGETCOUNT(hWndList, bLB);
DBGFONTS((" Count of items in %lx = %lx\n", hWndList, iCB));
if (FontIndex >= 0) {
/*
* look for FontIndex
*/
while (iCB > 0) {
iCB--;
if (lcbGETITEMDATA(hWndList, bLB, iCB) == FontIndex) {
lcbSETCURSEL(hWndList, bLB, iCB);
break;
}
}
} else {
/*
* look for a reasonable default size: looking backwards, find
* the first one same height or smaller.
*/
DWORD Size;
Size = GetWindowLong(hDlg, GWLP_USERDATA);
#if defined(FE_SB)
ASSERT(OEMCP != 0);
if (gfFESystem && bLB
&& (FontInfo[CurrentFontIndex].tmCharSet != LOBYTE(LOWORD(Size)))
)
{
TCHAR AltFaceName[LF_FACESIZE];
COORD AltFontSize;
BYTE AltFontFamily;
ULONG AltFontIndex = 0;
MakeAltRasterFont(gpStateInfo->CodePage, &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
while (iCB > 0) {
iCB--;
if (lcbGETITEMDATA(hWndList, bLB, iCB) == (int)AltFontIndex) {
lcbSETCURSEL(hWndList, bLB, iCB);
break;
}
}
}
else
#endif
while (iCB > 0) {
iCB--;
FontIndex = lcbGETITEMDATA(hWndList, bLB, iCB);
if (FontInfo[FontIndex].Size.Y <= HIWORD(Size)) {
lcbSETCURSEL(hWndList, bLB, iCB);
break;
}
}
}
DBGFONTS(("SelectCurrentSize returns %x\n", FontIndex));
return FontIndex;
}
BOOL
SelectCurrentFont(HWND hDlg, int FontIndex)
{
BOOL bLB;
DBGFONTS(("SelectCurrentFont hDlg=%lx, FontIndex=%x\n", hDlg, FontIndex));
bLB = !TM_IS_TT_FONT(FontInfo[FontIndex].Family);
SendDlgItemMessage(hDlg, IDD_FACENAME, LB_SELECTSTRING, (WPARAM)-1,
bLB ? (LPARAM)tszRasterFonts : (LPARAM)FontInfo[FontIndex].FaceName);
SelectCurrentSize(hDlg, bLB, FontIndex);
return bLB;
}
BOOL
PreviewInit(
HWND hDlg
)
/* PreviewInit
* Prepares the preview code, sizing the window and the dialog to
* make an attractive preview.
* Returns TRUE if Raster Fonts, FALSE if TT Font
*/
{
int nFont;
DBGFONTS(("PreviewInit hDlg=%lx\n", hDlg));
/*
* Set the current font
*/
nFont = FindCreateFont(gpStateInfo->FontFamily,
gpStateInfo->FaceName,
gpStateInfo->FontSize,
gpStateInfo->FontWeight,
gpStateInfo->CodePage);
DBGPRINT(("Changing Font Number from %d to %d\n",
CurrentFontIndex, nFont));
CurrentFontIndex = nFont;
return SelectCurrentFont(hDlg, nFont);
}
BOOL
PreviewUpdate(
HWND hDlg,
BOOL bLB
)
/*++
Does the preview of the selected font.
--*/
{
PFONT_INFO lpFont;
int FontIndex;
LONG lIndex;
HWND hWnd;
TCHAR tszText[60];
TCHAR tszFace[LF_FACESIZE + CCH_SELECTEDFONT];
HWND hWndList;
DBGFONTS(("PreviewUpdate hDlg=%lx, %s\n", hDlg,
bLB ? "Raster" : "TrueType"));
hWndList = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
/* When we select a font, we do the font preview by setting it into
* the appropriate list box
*/
lIndex = lcbGETCURSEL(hWndList, bLB);
DBGFONTS(("PreviewUpdate GETCURSEL gets %x\n", lIndex));
if ((lIndex < 0) && !bLB) {
COORD NewSize;
lIndex = (LONG)SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETCURSEL, 0, 0L);
SendDlgItemMessage(hDlg, IDD_FACENAME, LB_GETTEXT, lIndex, (LPARAM)tszFace);
NewSize.X = 0;
NewSize.Y = (SHORT)GetPointSizeInRange(hDlg, MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
if (NewSize.Y == 0) {
TCHAR tszBuf[60];
/*
* Use tszText, tszBuf to put up an error msg for bad point size
*/
gbPointSizeError = TRUE;
LoadString(ghInstance, IDS_FONTSIZE, tszBuf, NELEM(tszBuf));
wsprintf(tszText, tszBuf, MIN_PIXEL_HEIGHT, MAX_PIXEL_HEIGHT);
GetWindowText(hDlg, tszBuf, NELEM(tszBuf));
MessageBoxEx(hDlg, tszText, tszBuf, MB_OK|MB_ICONINFORMATION, 0L);
SetFocus(hWndList);
gbPointSizeError = FALSE;
return FALSE;
}
FontIndex = FindCreateFont(FF_MODERN|TMPF_VECTOR|TMPF_TRUETYPE,
tszFace, NewSize, 0,
gpStateInfo->CodePage);
} else {
FontIndex = lcbGETITEMDATA(hWndList, bLB, lIndex);
}
if (FontIndex < 0) {
FontIndex = DefaultFontIndex;
}
/*
* If we've selected a new font, tell the property sheet we've changed
*/
if (CurrentFontIndex != (ULONG)FontIndex) {
CurrentFontIndex = FontIndex;
}
lpFont = &FontInfo[FontIndex];
/* Display the new font */
_tcscpy(tszFace, tszSelectedFont);
_tcscat(tszFace, lpFont->FaceName);
SetDlgItemText(hDlg, IDD_GROUP, tszFace);
/* Put the font size in the static boxes */
wsprintf(tszText, TEXT("%u"), lpFont->Size.X);
hWnd = GetDlgItem(hDlg, IDD_FONTWIDTH);
SetWindowText(hWnd, tszText);
InvalidateRect(hWnd, NULL, TRUE);
wsprintf(tszText, TEXT("%u"), lpFont->Size.Y);
hWnd = GetDlgItem(hDlg, IDD_FONTHEIGHT);
SetWindowText(hWnd, tszText);
InvalidateRect(hWnd, NULL, TRUE);
/* Force the preview windows to repaint */
hWnd = GetDlgItem(hDlg, IDD_PREVIEWWINDOW);
SendMessage(hWnd, CM_PREVIEW_UPDATE, 0, 0);
hWnd = GetDlgItem(hDlg, IDD_FONTWINDOW);
InvalidateRect(hWnd, NULL, TRUE);
DBGFONTS(("Font %x, (%d,%d) %ls\n", FontIndex,
FontInfo[FontIndex].Size.X,
FontInfo[FontIndex].Size.Y,
FontInfo[FontIndex].FaceName));
return TRUE;
}