windows-nt/Source/XPSP1/NT/base/mvdm/wow16/commdlg/font.c
2020-09-26 16:20:57 +08:00

1962 lines
63 KiB
C

/*******************************************************************************
*
* MODULE : Font.c
*
* DESCRIPTION : Font selection dialog routines and related functions.
*
* HISTORY : 11/13/90 - by L.Raman.
* HISTORY : 4/30/91 - reworked for new super font dialog
*
* Copyright (c) Microsoft Corporation, 1990-
*
* some notes:
*
* under 3.0 sending a CB_SETCURSEL message to an owner draw
* combo wipes out the exit text (in this case that means the
* face and size combos).
*
******************************************************************************/
#define NOCOMM
#define NOWH
#include <windows.h>
#include "privcomd.h"
#include "font.h"
typedef struct {
HWND hwndFamily;
HWND hwndStyle;
HWND hwndSizes;
HDC hDC;
DWORD dwFlags;
WORD nFontType;
BOOL bFillSize;
BOOL bPrinterFont;
LPCHOOSEFONT lpcf;
} ENUM_FONT_DATA, FAR *LPENUM_FONT_DATA;
#define CBN_MYSELCHANGE (WM_USER + 500)
#define CBN_MYEDITUPDATE (WM_USER + 501)
#define DEF_POINT_SIZE 10
HBITMAP NEAR PASCAL LoadBitmaps(int id);
BOOL FAR PASCAL FormatCharDlgProc(HWND, unsigned, WORD, LONG);
void NEAR PASCAL FreeFonts(HWND hwnd);
BOOL NEAR PASCAL ProcessDlgCtrlCommand(HWND hDlg, LPCHOOSEFONT lpcf, WORD wParam, LONG lParam);
BOOL NEAR PASCAL DrawColorComboItem(LPDRAWITEMSTRUCT lpdis);
BOOL NEAR PASCAL DrawFamilyComboItem(LPDRAWITEMSTRUCT lpdis);
BOOL NEAR PASCAL DrawSizeComboItem(LPDRAWITEMSTRUCT lpdis);
BOOL NEAR PASCAL FillInFont(HWND hDlg, LPCHOOSEFONT lpcf, LPLOGFONT lplf, BOOL bSetBits);
void NEAR PASCAL FillColorCombo(HWND hDlg);
void NEAR PASCAL ComputeSampleTextRectangle(HWND hDlg);
void NEAR PASCAL SelectStyleFromLF(HWND hwnd, LPLOGFONT lplf);
void NEAR PASCAL DrawSampleText(HWND hDlg, LPCHOOSEFONT lpcf, HDC hDC);
int NEAR PASCAL GetPointString(LPSTR buf, HDC hdc, int height);
BOOL NEAR PASCAL GetFontFamily(HWND hDlg, HDC hDC, DWORD dwEnumCode);
BOOL NEAR PASCAL GetFontStylesAndSizes(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bFillSizes);
int NEAR PASCAL CBSetTextFromSel(HWND hwnd);
int NEAR PASCAL CBSetSelFromText(HWND hwnd, LPSTR lpszString);
int NEAR PASCAL CBFindString(HWND hwnd, LPSTR lpszString);
int NEAR PASCAL CBGetTextAndData(HWND hwnd, LPSTR lpszString, int iSize, LPDWORD lpdw);
void NEAR PASCAL InitLF(LPLOGFONT lplf);
#if 0
int NEAR PASCAL atoi(LPSTR sz);
#endif
/* color table used for colors combobox
the order of these values must match the names in sz.src */
DWORD rgbColors[CCHCOLORS] = {
RGB( 0, 0, 0), /* Black */
RGB(128, 0, 0), /* Dark red */
RGB( 0, 128, 0), /* Dark green */
RGB(128, 128, 0), /* Dark yellow */
RGB( 0, 0, 128), /* Dark blue */
RGB(128, 0, 128), /* Dark purple */
RGB( 0, 128, 128), /* Dark aqua */
RGB(128, 128, 128), /* Dark grey */
RGB(192, 192, 192), /* Light grey */
RGB(255, 0, 0), /* Light red */
RGB( 0, 255, 0), /* Light green */
RGB(255, 255, 0), /* Light yellow */
RGB( 0, 0, 255), /* Light blue */
RGB(255, 0, 255), /* Light purple */
RGB( 0, 255, 255), /* Light aqua */
RGB(255, 255, 255), /* White */
};
RECT rcText;
WORD nLastFontType;
HBITMAP hbmFont = NULL;
#define DX_BITMAP 20
#define DY_BITMAP 12
char szRegular[CCHSTYLE];
char szBold[CCHSTYLE];
char szItalic[CCHSTYLE];
char szBoldItalic[CCHSTYLE];
#if 0
char szEnumFonts31[] = "EnumFontFamilies";
char szEnumFonts30[] = "EnumFonts";
#else
#define szEnumFonts30 MAKEINTRESOURCE(70)
#define szEnumFonts31 MAKEINTRESOURCE(330)
#endif
char szGDI[] = "GDI";
char szPtFormat[] = "%d";
UINT (FAR PASCAL *glpfnFontHook)(HWND, UINT, WPARAM, LPARAM) = 0;
void NEAR PASCAL SetStyleSelection(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bInit)
{
if (!(lpcf->Flags & CF_NOSTYLESEL)) {
if (bInit && (lpcf->Flags & CF_USESTYLE))
{
PLOGFONT plf;
short iSel;
iSel = (short)CBSetSelFromText(GetDlgItem(hDlg, cmb2), lpcf->lpszStyle);
if (iSel >= 0)
{
plf = (PLOGFONT)(WORD)SendDlgItemMessage(hDlg, cmb2,
CB_GETITEMDATA, iSel, 0L);
lpcf->lpLogFont->lfWeight = plf->lfWeight;
lpcf->lpLogFont->lfItalic = plf->lfItalic;
}
else
{
lpcf->lpLogFont->lfWeight = FW_NORMAL;
lpcf->lpLogFont->lfItalic = 0;
}
}
else
SelectStyleFromLF(GetDlgItem(hDlg, cmb2), lpcf->lpLogFont);
CBSetTextFromSel(GetDlgItem(hDlg, cmb2));
}
}
void NEAR PASCAL HideDlgItem(HWND hDlg, int id)
{
EnableWindow(GetDlgItem(hDlg, id), FALSE);
ShowWindow(GetDlgItem(hDlg, id), SW_HIDE);
}
// fix the ownerdraw combos to match the heigh of the non owner draw combo
// this only works on 3.1
void NEAR PASCAL FixComboHeights(HWND hDlg)
{
int height;
height = (int)SendDlgItemMessage(hDlg, cmb2, CB_GETITEMHEIGHT, (WPARAM)-1, 0L);
SendDlgItemMessage(hDlg, cmb1, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)height);
SendDlgItemMessage(hDlg, cmb3, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)height);
}
/****************************************************************************
*
* FormatCharDlgProc
*
* PURPOSE : Handles dialog messages for the font picker dialog.
*
* RETURNS : Normal dialog function values.
*
* ASSUMES :
* chx1 - " " "Underline" checkbox
* chx2 - " " "Strikeout" checkbox
* psh4 - " " "Help..." pushbutton
*
* COMMENTS : The CHOOSEFONT struct is accessed via lParam during a
* WM_INITDIALOG, and stored in the window's property list. If
* a hook function has been specified, it is invoked AFTER the
* current function has processed WM_INITDIALOG. For all other
* messages, control is passed directly to the hook function.
* Depending on the latter's return value, the message is also
* processed by this function.
*
****************************************************************************/
BOOL FAR PASCAL FormatCharDlgProc(HWND hDlg, unsigned wMsg, WORD wParam, LONG lParam)
{
PAINTSTRUCT ps;
TEXTMETRIC tm;
HDC hDC; /* handle to screen DC */
LPCHOOSEFONT lpcf = NULL; /* ptr. to struct. passed to ChooseFont() */
LPCHOOSEFONT *plpcf; /* ptr. to above */
HWND hWndHelp; /* handle to Help... pushbutton */
short nIndex; /* At init, see if color matches */
char szPoints[10];
HDC hdc;
HFONT hFont;
DWORD dw;
WORD wRet;
/* If the CHOOSEFONT. struct has already been accessed and if a hook fn. is
* specified, let it do the processing.
*/
plpcf = (LPCHOOSEFONT *)GetProp(hDlg, FONTPROP);
if (plpcf) {
lpcf = (LPCHOOSEFONT)*plpcf++;
if (lpcf->Flags & CF_ENABLEHOOK) {
if ((wRet = (WORD)(*lpcf->lpfnHook)(hDlg, wMsg, wParam, lParam)) != 0)
return wRet;
}
}
else if (glpfnFontHook && (wMsg != WM_INITDIALOG)) {
if ((wRet = (WORD)(* glpfnFontHook)(hDlg, wMsg,wParam,lParam)) != 0) {
return(wRet);
}
}
switch(wMsg){
case WM_INITDIALOG:
if (!LoadString(hinsCur, iszRegular, (LPSTR)szRegular, CCHSTYLE) ||
!LoadString(hinsCur, iszBold, (LPSTR)szBold, CCHSTYLE) ||
!LoadString(hinsCur, iszItalic, (LPSTR)szItalic, CCHSTYLE) ||
!LoadString(hinsCur, iszBoldItalic, (LPSTR)szBoldItalic, CCHSTYLE))
{
dwExtError = CDERR_LOADSTRFAILURE;
EndDialog(hDlg, FALSE);
return FALSE;
}
lpcf = (LPCHOOSEFONT)lParam;
if ((lpcf->Flags & CF_LIMITSIZE) &&
(lpcf->nSizeMax < lpcf->nSizeMin))
{
dwExtError = CFERR_MAXLESSTHANMIN;
EndDialog(hDlg, FALSE);
return FALSE;
}
/* Save the pointer to the CHOOSEFONT struct. in the dialog's
* property list. Also, allocate for a temporary LOGFONT struct.
* to be used for the length of the dlg. session, the contents of
* which will be copied over to the final LOGFONT (pointed to by
* CHOOSEFONT) only if <OK> is selected.
*/
plpcf = (LPCHOOSEFONT *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(LPCHOOSEFONT));
if (!plpcf) {
dwExtError = CDERR_MEMALLOCFAILURE;
EndDialog(hDlg, FALSE);
return FALSE;
}
SetProp(hDlg, FONTPROP, (HANDLE)plpcf);
glpfnFontHook = 0;
lpcf = *(LPCHOOSEFONT FAR *)plpcf = (LPCHOOSEFONT)lParam;
if (!hbmFont)
hbmFont = LoadBitmaps(BMFONT);
if (!(lpcf->Flags & CF_APPLY))
HideDlgItem(hDlg, psh3);
if (!(lpcf->Flags & CF_EFFECTS)) {
HideDlgItem(hDlg, stc4);
HideDlgItem(hDlg, cmb4);
} else {
// fill color list
FillColorCombo(hDlg);
for (nIndex = CCHCOLORS - 1; nIndex > 0; nIndex--) {
dw = SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, nIndex, 0L);
if (lpcf->rgbColors == dw)
break;
}
SendDlgItemMessage(hDlg, cmb4, CB_SETCURSEL, nIndex, 0L);
}
ComputeSampleTextRectangle(hDlg);
FixComboHeights(hDlg);
// init our LOGFONT
if (!(lpcf->Flags & CF_INITTOLOGFONTSTRUCT)) {
InitLF(lpcf->lpLogFont);
#if 0
*lpcf->lpLogFont->lfFaceName = 0;
lpcf->lpLogFont->lfWeight = FW_NORMAL;
lpcf->lpLogFont->lfHeight = 0;
lpcf->lpLogFont->lfItalic = 0;
lpcf->lpLogFont->lfStrikeOut = 0;
lpcf->lpLogFont->lfUnderline = 0;
#endif
}
// init effects
if (!(lpcf->Flags & CF_EFFECTS)) {
HideDlgItem(hDlg, grp1);
HideDlgItem(hDlg, chx1);
HideDlgItem(hDlg, chx2);
} else {
CheckDlgButton(hDlg, chx1, lpcf->lpLogFont->lfStrikeOut);
CheckDlgButton(hDlg, chx2, lpcf->lpLogFont->lfUnderline);
}
nLastFontType = 0;
if (!GetFontFamily(hDlg, lpcf->hDC, lpcf->Flags)) {
dwExtError = CFERR_NOFONTS;
EndDialog(hDlg, FALSE);
RemoveProp(hDlg, FONTPROP);
if (lpcf->Flags & CF_ENABLEHOOK)
glpfnFontHook = lpcf->lpfnHook;
return FALSE;
}
if (!(lpcf->Flags & CF_NOFACESEL) && *lpcf->lpLogFont->lfFaceName) {
CBSetSelFromText(GetDlgItem(hDlg, cmb1), lpcf->lpLogFont->lfFaceName);
CBSetTextFromSel(GetDlgItem(hDlg, cmb1));
}
GetFontStylesAndSizes(hDlg, lpcf, TRUE);
if (!(lpcf->Flags & CF_NOSTYLESEL)) {
SetStyleSelection(hDlg, lpcf, TRUE);
}
if (!(lpcf->Flags & CF_NOSIZESEL) && lpcf->lpLogFont->lfHeight) {
hdc = GetDC(NULL);
GetPointString(szPoints, hdc, lpcf->lpLogFont->lfHeight);
ReleaseDC(NULL, hdc);
CBSetSelFromText(GetDlgItem(hDlg, cmb3), szPoints);
SetDlgItemText(hDlg, cmb3, szPoints);
}
/* Hide the help button if it isn't needed */
if (!(lpcf->Flags & CF_SHOWHELP)) {
ShowWindow (hWndHelp = GetDlgItem(hDlg, pshHelp), SW_HIDE);
EnableWindow (hWndHelp, FALSE);
}
SendDlgItemMessage(hDlg, cmb1, CB_LIMITTEXT, LF_FACESIZE-1, 0L);
SendDlgItemMessage(hDlg, cmb2, CB_LIMITTEXT, LF_FACESIZE-1, 0L);
SendDlgItemMessage(hDlg, cmb3, CB_LIMITTEXT, 4, 0L);
// if hook function has been specified, let it do any additional
// processing of this message.
if (lpcf->Flags & CF_ENABLEHOOK)
return (*lpcf->lpfnHook)(hDlg, wMsg, wParam, lParam);
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case WM_PAINT:
if (BeginPaint(hDlg, &ps)) {
DrawSampleText(hDlg, lpcf, ps.hdc);
EndPaint(hDlg, &ps);
}
break;
case WM_MEASUREITEM:
hDC = GetDC(hDlg);
hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
if (hFont)
hFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
if (hFont)
SelectObject(hDC, hFont);
ReleaseDC(hDlg, hDC);
if (((LPMEASUREITEMSTRUCT)lParam)->itemID != -1)
((LPMEASUREITEMSTRUCT)lParam)->itemHeight = max(tm.tmHeight, DY_BITMAP);
else
// this is for 3.0. since in 3.1 the CB_SETITEMHEIGH
// will fix this. note, this is off by one on 8514
((LPMEASUREITEMSTRUCT)lParam)->itemHeight = tm.tmHeight + 1;
break;
case WM_DRAWITEM:
#define lpdis ((LPDRAWITEMSTRUCT)lParam)
if (lpdis->itemID == 0xFFFF)
break;
if (lpdis->CtlID == cmb4)
DrawColorComboItem(lpdis);
else if (lpdis->CtlID == cmb1)
DrawFamilyComboItem(lpdis);
else
DrawSizeComboItem(lpdis);
break;
#undef lpdis
case WM_SYSCOLORCHANGE:
DeleteObject(hbmFont);
hbmFont = LoadBitmaps(BMFONT);
break;
case WM_COMMAND:
return ProcessDlgCtrlCommand(hDlg, lpcf, wParam, lParam);
break;
case WM_CHOOSEFONT_GETLOGFONT:
return FillInFont(hDlg, lpcf, (LPLOGFONT)lParam, TRUE);
default:
return FALSE;
}
return TRUE;
}
// given a logfont select the closest match in the style list
void NEAR PASCAL SelectStyleFromLF(HWND hwnd, LPLOGFONT lplf)
{
int i, count, iSel;
LPLOGFONT plf;
int weight_delta, best_weight_delta = 1000;
BOOL bIgnoreItalic;
count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
iSel = 0;
bIgnoreItalic = FALSE;
TryAgain:
for (i = 0; i < count; i++) {
plf = (LPLOGFONT)SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
if (bIgnoreItalic ||
(plf->lfItalic && lplf->lfItalic) ||
(!plf->lfItalic && !lplf->lfItalic)) {
weight_delta = lplf->lfWeight - plf->lfWeight;
if (weight_delta < 0)
weight_delta = -weight_delta;
if (weight_delta < best_weight_delta) {
best_weight_delta = weight_delta;
iSel = i;
}
}
}
if (!bIgnoreItalic && iSel == 0) {
bIgnoreItalic = TRUE;
goto TryAgain;
}
SendMessage(hwnd, CB_SETCURSEL, iSel, 0L);
}
// make the currently selected item the edit text for a combobox
int NEAR PASCAL CBSetTextFromSel(HWND hwnd)
{
int iSel;
char szFace[LF_FACESIZE];
iSel = (int)SendMessage(hwnd, CB_GETCURSEL, 0, 0L);
if (iSel >= 0) {
SendMessage(hwnd, CB_GETLBTEXT, iSel, (LONG)(LPSTR)szFace);
SetWindowText(hwnd, szFace);
}
return iSel;
}
// set the selection based on lpszString. send notification
// messages if bNotify is TRUE
int NEAR PASCAL CBSetSelFromText(HWND hwnd, LPSTR lpszString)
{
int iInd;
iInd = CBFindString(hwnd, lpszString);
if (iInd >= 0) {
SendMessage(hwnd, CB_SETCURSEL, iInd, 0L);
}
return iInd;
}
// return the text and item data for a combo box based on the current
// edit text. if the current edit text does not match anything in the
// listbox return CB_ERR
int NEAR PASCAL CBGetTextAndData(HWND hwnd, LPSTR lpszString, int iSize, LPDWORD lpdw)
{
int iSel;
GetWindowText(hwnd, lpszString, iSize);
iSel = CBFindString(hwnd, lpszString);
if (iSel < 0)
return iSel;
*lpdw = SendMessage(hwnd, CB_GETITEMDATA, iSel, 0L);
return iSel;
}
// do an exact string find and return the index
int NEAR PASCAL CBFindString(HWND hwnd, LPSTR lpszString)
{
int iItem, iCount;
char szFace[LF_FACESIZE];
iCount = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
for (iItem = 0; iItem < iCount; iItem++) {
SendMessage(hwnd, CB_GETLBTEXT, iItem, (LONG)(LPSTR)szFace);
if (!lstrcmpi(szFace, lpszString))
return iItem;
}
return CB_ERR;
}
#define GPS_COMPLAIN 0x0001
#define GPS_SETDEFSIZE 0x0002
// make sure the point size edit field is in range.
//
// returns:
// the point size of the edit field limitted by the min/max size
// 0 if the field is empty
BOOL NEAR PASCAL GetPointSizeInRange(HWND hDlg, LPCHOOSEFONT lpcf, LPINT pts,
WORD wFlags)
{
char szBuffer[90];
char szTitle[90];
int nTmp;
BOOL bOK;
*pts = 0;
if (GetDlgItemText(hDlg, cmb3, szBuffer, sizeof(szBuffer))) {
nTmp = GetDlgItemInt(hDlg, cmb3, &bOK, TRUE);
if (!bOK)
nTmp = 0;
} else if (wFlags & GPS_SETDEFSIZE) {
nTmp = DEF_POINT_SIZE;
bOK = TRUE;
} else {
/* We're just returning with 0 in *pts
*/
return(FALSE);
}
/* Check that we got a number in range
*/
if (wFlags & GPS_COMPLAIN) {
if ((lpcf->Flags&CF_LIMITSIZE) &&
(!bOK || nTmp>lpcf->nSizeMax || nTmp<lpcf->nSizeMin)) {
bOK = FALSE;
LoadString(hinsCur, iszSizeRange, szTitle, sizeof(szTitle));
wsprintf(szBuffer, szTitle, lpcf->nSizeMin, lpcf->nSizeMax);
} else if (!bOK)
LoadString(hinsCur, iszSizeNumber, szBuffer, sizeof(szBuffer));
if (!bOK) {
GetWindowText(hDlg, szTitle, sizeof(szTitle));
MessageBox(hDlg, szBuffer, szTitle, MB_OK | MB_ICONINFORMATION);
return(FALSE);
}
}
*pts = nTmp;
return(TRUE);
}
/****************************************************************************
*
* ProcessDlgCtrlCommand
*
* PURPOSE : Handles all WM_COMMAND messages for the font picker dialog
*
* ASSUMES : cmb1 - ID of font facename combobox
* cmb2 - " " style
* cmb3 - " " size
* chx1 - " " "Underline" checkbox
* chx2 - " " "Strikeout" checkbox
* stc5 - " " frame around text preview area
* psh4 - " " button that invokes the Help application
* IDOK - " " OK button to end dialog, retaining information
* IDCANCEL" " button to cancel dialog, not doing anything.
*
* RETURNS : TRUE if message is processed succesfully, FALSE otherwise.
*
* COMMENTS : if the OK button is selected, all the font information is
* written into the CHOOSEFONT structure.
*
****************************************************************************/
BOOL NEAR PASCAL ProcessDlgCtrlCommand(HWND hDlg, LPCHOOSEFONT lpcf, WORD wParam, LONG lParam)
{
int iSel;
char szPoints[10];
char szStyle[LF_FACESIZE];
DWORD dw;
WORD wCmbId;
char szMsg[160], szTitle[160];
switch (wParam) {
case IDABORT:
// this is how a hook can cause the dialog to go away
FreeFonts(GetDlgItem(hDlg, cmb2));
EndDialog(hDlg, LOWORD(lParam));
RemoveProp(hDlg, FONTPROP);
if (lpcf->Flags & CF_ENABLEHOOK)
glpfnFontHook = lpcf->lpfnHook;
break;
case IDOK:
if (!GetPointSizeInRange(hDlg, lpcf, &iSel,
GPS_COMPLAIN|GPS_SETDEFSIZE)) {
PostMessage(hDlg, WM_NEXTDLGCTL, GetDlgItem(hDlg, cmb3), 1L);
break;
}
lpcf->iPointSize = iSel * 10;
FillInFont(hDlg, lpcf, lpcf->lpLogFont, TRUE);
if (lpcf->Flags & CF_FORCEFONTEXIST)
{
if (lpcf->Flags & CF_NOFACESEL)
wCmbId = cmb1;
else if (lpcf->Flags & CF_NOSTYLESEL)
wCmbId = cmb2;
else
wCmbId = NULL;
if (wCmbId) /* Error found */
{
LoadString(hinsCur, (wCmbId == cmb1) ? iszNoFaceSel
: iszNoStyleSel, szMsg, sizeof(szMsg));
GetWindowText(hDlg, szTitle, sizeof(szTitle));
MessageBox(hDlg, szMsg, szTitle, MB_OK|MB_ICONINFORMATION);
PostMessage(hDlg,WM_NEXTDLGCTL,GetDlgItem(hDlg,wCmbId),1L);
break;
}
}
if (lpcf->Flags & CF_EFFECTS) {
// Get currently selected item in color combo box and the 32 bit
// color rgb value associated with it
iSel = (int)SendDlgItemMessage(hDlg, cmb4, CB_GETCURSEL, 0, 0L);
lpcf->rgbColors= (DWORD)SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, iSel, 0L);
}
CBGetTextAndData(GetDlgItem(hDlg, cmb2), szStyle, sizeof(szStyle), &dw);
lpcf->nFontType = HIWORD(dw);
if (lpcf->Flags & CF_USESTYLE)
lstrcpy(lpcf->lpszStyle, szStyle);
// fall through
case IDCANCEL:
FreeFonts(GetDlgItem(hDlg, cmb2));
EndDialog(hDlg, wParam == IDOK);
RemoveProp(hDlg, FONTPROP);
if (lpcf->Flags & CF_ENABLEHOOK)
glpfnFontHook = lpcf->lpfnHook;
break;
case cmb1: // facenames combobox
switch (HIWORD(lParam)) {
case CBN_SELCHANGE:
CBSetTextFromSel(LOWORD(lParam));
FillStyles:
// try to mainting the current point size and style
GetDlgItemText(hDlg, cmb3, szPoints, sizeof(szPoints));
GetFontStylesAndSizes(hDlg, lpcf, FALSE);
SetStyleSelection(hDlg, lpcf, FALSE);
// preserv the point size selection or put it in the
// edit control if it is not in the list for this font
iSel = CBFindString(GetDlgItem(hDlg, cmb3), szPoints);
if (iSel < 0) {
SetDlgItemText(hDlg, cmb3, szPoints);
} else {
SendDlgItemMessage(hDlg, cmb3, CB_SETCURSEL, iSel, 0L);
// 3.0 wipes out the edit text in the above call
if (wWinVer < 0x030A)
CBSetTextFromSel(GetDlgItem(hDlg, cmb3));
}
if (wWinVer < 0x030A)
PostMessage(hDlg, WM_COMMAND, cmb1, MAKELONG(LOWORD(lParam), CBN_MYSELCHANGE));
goto DrawSample;
break;
case CBN_MYSELCHANGE: // for 3.0
CBSetTextFromSel(LOWORD(lParam));
SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, 0xFFFF0000);
break;
case CBN_EDITUPDATE:
PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYEDITUPDATE));
break;
// case CBN_EDITCHANGE:
// case CBN_EDITUPDATE:
case CBN_MYEDITUPDATE:
GetWindowText(LOWORD(lParam), szStyle, sizeof(szStyle));
iSel = CBFindString(LOWORD(lParam), szStyle);
if (iSel >= 0) {
SendMessage(LOWORD(lParam), CB_SETCURSEL, iSel, 0L);
// 3.0 wipes out the edit text in the above call
if (wWinVer < 0x030A)
CBSetTextFromSel(LOWORD(lParam));
SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, -1L);
goto FillStyles;
}
break;
}
break;
case cmb3: // point sizes combobox
case cmb2: // styles combobox
switch (HIWORD(lParam)) {
case CBN_EDITUPDATE:
PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYEDITUPDATE));
break;
// case CBN_EDITCHANGE:
// case CBN_EDITUPDATE:
case CBN_MYEDITUPDATE:
if (wParam == cmb2) {
GetWindowText(LOWORD(lParam), szStyle, sizeof(szStyle));
iSel = CBFindString(LOWORD(lParam), szStyle);
if (iSel >= 0) {
SendMessage(LOWORD(lParam), CB_SETCURSEL, iSel, 0L);
// 3.0 wipes out the edit text in the above call
if (wWinVer < 0x030A)
CBSetTextFromSel(LOWORD(lParam));
SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, -1L);
goto DrawSample;
}
}
break;
case CBN_SELCHANGE:
iSel = CBSetTextFromSel(LOWORD(lParam));
if (iSel >= 0) {
// make the style selection stick
if (wParam == cmb2) {
PLOGFONT plf = (PLOGFONT)(WORD)SendMessage(LOWORD(lParam), CB_GETITEMDATA, iSel, 0L);
lpcf->lpLogFont->lfWeight = plf->lfWeight;
lpcf->lpLogFont->lfItalic = plf->lfItalic;
}
}
if (wWinVer < 0x030A)
PostMessage(hDlg, WM_COMMAND, wParam, MAKELONG(LOWORD(lParam), CBN_MYSELCHANGE));
goto DrawSample;
case CBN_MYSELCHANGE: // for 3.0
CBSetTextFromSel(LOWORD(lParam));
SendMessage(LOWORD(lParam), CB_SETEDITSEL, 0, 0xFFFF0000);
break;
case CBN_KILLFOCUS:
DrawSample:
// force redraw of preview text for any size change
InvalidateRect(hDlg, &rcText, FALSE);
UpdateWindow(hDlg);
}
break;
case cmb4:
if (HIWORD(lParam) != CBN_SELCHANGE)
break;
// fall through
case chx1: // bold
case chx2: // italic
goto DrawSample;
case pshHelp: // help
if (msgHELP && lpcf->hwndOwner)
SendMessage(lpcf->hwndOwner, msgHELP, hDlg, (DWORD) lpcf);
break;
default:
return (FALSE);
}
return TRUE;
}
//
// this returns the best of the 2 font types.
// the values of the font type bits are monotonic except the low
// bit (RASTER_FONTTYPE). so we flip that bit and then can compare
// the words directly.
//
int NEAR PASCAL CmpFontType(WORD ft1, WORD ft2)
{
ft1 &= ~(SCREEN_FONTTYPE | PRINTER_FONTTYPE);
ft2 &= ~(SCREEN_FONTTYPE | PRINTER_FONTTYPE);
ft1 ^= RASTER_FONTTYPE; // flip these so we can compare
ft2 ^= RASTER_FONTTYPE;
return (int)ft1 - (int)ft2;
}
// nFontType bits
//
// SCALABLE DEVICE RASTER
// (TT) (not GDI) (not scalable)
// 0 0 0 vector, ATM screen
// 0 0 1 GDI raster font
// 0 1 0 PS/LJ III, ATM printer, ATI/LaserMaster
// 0 1 1 non scalable device font
// 1 0 x TT screen font
// 1 1 x TT dev font
int FAR PASCAL FontFamilyEnumProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, WORD nFontType, LPENUM_FONT_DATA lpData)
{
int iItem;
WORD nOldType, nNewType;
lptm = lptm;
// bounce non TT fonts
if ((lpData->dwFlags & CF_TTONLY) &&
!(nFontType & TRUETYPE_FONTTYPE))
return TRUE;
// bounce non scalable fonts
if ((lpData->dwFlags & CF_SCALABLEONLY) &&
(nFontType & RASTER_FONTTYPE))
return TRUE;
// bounce non ANSI fonts
if ((lpData->dwFlags & CF_ANSIONLY) &&
(lplf->lfCharSet != ANSI_CHARSET))
return TRUE;
// bounce proportional fonts
if ((lpData->dwFlags & CF_FIXEDPITCHONLY) &&
(lplf->lfPitchAndFamily & VARIABLE_PITCH))
return TRUE;
// bounce vector fonts
if ((lpData->dwFlags & CF_NOVECTORFONTS) &&
(lplf->lfCharSet == OEM_CHARSET))
return TRUE;
if (lpData->bPrinterFont)
nFontType |= PRINTER_FONTTYPE;
else
nFontType |= SCREEN_FONTTYPE;
// test for a name collision
iItem = CBFindString(lpData->hwndFamily, lplf->lfFaceName);
if (iItem >= 0) {
nOldType = (WORD)SendMessage(lpData->hwndFamily, CB_GETITEMDATA, iItem, 0L);
/* If we don't want screen fonts, but do want printer fonts,
* the old font is a screen font and the new font is a
* printer font, take the new font regardless of other flags.
* Note that this means if a printer wants TRUETYPE fonts, it
* should enumerate them. Bug 9675, 12-12-91, Clark Cyr
*/
if (!(lpData->dwFlags & CF_SCREENFONTS) &&
(lpData->dwFlags & CF_PRINTERFONTS) &&
(nFontType & PRINTER_FONTTYPE) &&
(nOldType & SCREEN_FONTTYPE) )
{
nOldType = 0; /* for setting nNewType below */
goto SetNewType;
}
if (CmpFontType(nFontType, nOldType) > 0) {
SetNewType:
nNewType = nFontType;
SendMessage(lpData->hwndFamily, CB_INSERTSTRING, iItem, (LONG)(LPSTR)lplf->lfFaceName);
SendMessage(lpData->hwndFamily, CB_DELETESTRING, iItem + 1, 0L);
} else {
nNewType = nOldType;
}
// accumulate the printer/screen ness of these fonts
nNewType |= (nFontType | nOldType) & (SCREEN_FONTTYPE | PRINTER_FONTTYPE);
SendMessage(lpData->hwndFamily, CB_SETITEMDATA, iItem, MAKELONG(nNewType, 0));
return TRUE;
}
iItem = (int)SendMessage(lpData->hwndFamily, CB_ADDSTRING, 0, (LONG)(LPSTR)lplf->lfFaceName);
if (iItem < 0)
return FALSE;
SendMessage(lpData->hwndFamily, CB_SETITEMDATA, iItem, MAKELONG(nFontType, 0));
return TRUE;
}
/****************************************************************************
*
* GetFontFamily
*
* PURPOSE : Fills the screen and/or printer font facenames into the font
* facenames combobox, depending on the CF_?? flags passed in.
*
* ASSUMES : cmb1 - ID of font facename combobox
*
* RETURNS : TRUE if succesful, FALSE otherwise.
*
* COMMENTS : Both screen and printer fonts are listed into the same combo
* box.
*
****************************************************************************/
BOOL NEAR PASCAL GetFontFamily(HWND hDlg, HDC hDC, DWORD dwEnumCode)
{
ENUM_FONT_DATA data;
HANDLE hMod;
int iItem, iCount;
WORD nFontType;
char szMsg[100], szTitle[40];
WORD (FAR PASCAL *lpEnumFonts)(HDC, LPSTR, FARPROC, VOID FAR *);
hMod = GetModuleHandle(szGDI);
if (wWinVer < 0x030A)
lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts30);
else
lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts31);
if (!lpEnumFonts)
return FALSE;
data.hwndFamily = GetDlgItem(hDlg, cmb1);
data.dwFlags = dwEnumCode;
// this is a bit strage. we have to get all the screen fonts
// so if they ask for the printer fonts we can tell which
// are really printer fonts. that is so we don't list the
// vector and raster fonts as printer device fonts
data.hDC = GetDC(NULL);
data.bPrinterFont = FALSE;
(*lpEnumFonts)(data.hDC, NULL, FontFamilyEnumProc, &data);
ReleaseDC(NULL, data.hDC);
/* list out printer font facenames */
if (dwEnumCode & CF_PRINTERFONTS) {
data.hDC = hDC;
data.bPrinterFont = TRUE;
(*lpEnumFonts)(hDC, NULL, FontFamilyEnumProc, &data);
}
// now we have to remove those screen fonts if they didn't
// ask for them.
if (!(dwEnumCode & CF_SCREENFONTS)) {
iCount = (int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L);
for (iItem = iCount - 1; iItem >= 0; iItem--) {
nFontType = (WORD)SendMessage(data.hwndFamily, CB_GETITEMDATA, iItem, 0L);
if ((nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE)) == SCREEN_FONTTYPE)
SendMessage(data.hwndFamily, CB_DELETESTRING, iItem, 0L);
}
}
// for WYSIWYG mode we delete all the fonts that don't exist
// on the screen and the printer
if (dwEnumCode & CF_WYSIWYG) {
iCount = (int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L);
for (iItem = iCount - 1; iItem >= 0; iItem--) {
nFontType = (WORD)SendMessage(data.hwndFamily, CB_GETITEMDATA, iItem, 0L);
if ((nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE)) != (SCREEN_FONTTYPE | PRINTER_FONTTYPE))
SendMessage(data.hwndFamily, CB_DELETESTRING, iItem, 0L);
}
}
if ((int)SendMessage(data.hwndFamily, CB_GETCOUNT, 0, 0L) <= 0) {
LoadString(hinsCur, iszNoFontsTitle, szTitle, sizeof(szTitle));
LoadString(hinsCur, iszNoFontsMsg, szMsg, sizeof(szMsg));
MessageBox(hDlg, szMsg, szTitle, MB_OK | MB_ICONINFORMATION);
return FALSE;
}
return TRUE;
}
void NEAR PASCAL CBAddSize(HWND hwnd, int pts, LPCHOOSEFONT lpcf)
{
int iInd;
char szSize[10];
int count, test_size;
if ((lpcf->Flags & CF_LIMITSIZE) && ((pts > lpcf->nSizeMax) || (pts < lpcf->nSizeMin)))
return;
wsprintf(szSize, szPtFormat, pts);
count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
test_size = -1;
for (iInd = 0; iInd < count; iInd++) {
test_size = (int)SendMessage(hwnd, CB_GETITEMDATA, iInd, 0L);
if (pts <= test_size)
break;
}
if (pts == test_size) /* don't add duplicates */
return;
iInd = (int)SendMessage(hwnd, CB_INSERTSTRING, iInd, (LONG)(LPSTR)szSize);
if (iInd >= 0)
SendMessage(hwnd, CB_SETITEMDATA, iInd, MAKELONG(pts, 0));
}
// sort styles by weight first, then italicness
// returns:
// the index of the place this was inserted
int NEAR PASCAL InsertStyleSorted(HWND hwnd, LPSTR lpszStyle, LPLOGFONT lplf)
{
int count, i;
LPLOGFONT plf;
count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
for (i = 0; i < count; i++) {
plf = (LPLOGFONT)SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
if (lplf->lfWeight < plf->lfWeight) {
break;
} else if (lplf->lfWeight == plf->lfWeight) {
if (lplf->lfItalic && !plf->lfItalic)
i++;
break;
}
}
return (int)SendMessage(hwnd, CB_INSERTSTRING, i, (LONG)lpszStyle);
}
PLOGFONT NEAR PASCAL CBAddStyle(HWND hwnd, LPSTR lpszStyle, WORD nFontType, LPLOGFONT lplf)
{
int iItem;
PLOGFONT plf;
// don't add duplicates
if (CBFindString(hwnd, lpszStyle) >= 0)
return NULL;
iItem = (int)InsertStyleSorted(hwnd, lpszStyle, lplf);
if (iItem < 0)
return NULL;
plf = (PLOGFONT)LocalAlloc(LMEM_FIXED, sizeof(LOGFONT));
if (!plf) {
SendMessage(hwnd, CB_DELETESTRING, iItem, 0L);
return NULL;
}
*plf = *lplf;
SendMessage(hwnd, CB_SETITEMDATA, iItem, MAKELONG(plf, nFontType));
return plf;
}
// generate simulated forms from those that we have
//
// reg -> bold
// reg -> italic
// bold || italic || reg -> bold italic
void NEAR PASCAL FillInMissingStyles(HWND hwnd)
{
PLOGFONT plf, plf_reg, plf_bold, plf_italic;
WORD nFontType;
int i, count;
BOOL bBold, bItalic, bBoldItalic;
DWORD dw;
LOGFONT lf;
bBold = bItalic = bBoldItalic = FALSE;
plf_reg = plf_bold = plf_italic = NULL;
count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
for (i = 0; i < count; i++) {
dw = SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
plf = (PLOGFONT)LOWORD(dw);
nFontType = HIWORD(dw);
if ((nFontType & BOLD_FONTTYPE) && (nFontType & ITALIC_FONTTYPE)) {
bBoldItalic = TRUE;
} else if (nFontType & BOLD_FONTTYPE) {
bBold = TRUE;
plf_bold = plf;
} else if (nFontType & ITALIC_FONTTYPE) {
bItalic = TRUE;
plf_italic = plf;
} else
plf_reg = plf;
}
nFontType |= SIMULATED_FONTTYPE;
if (!bBold && plf_reg) {
lf = *plf_reg;
lf.lfWeight = FW_BOLD;
CBAddStyle(hwnd, szBold, nFontType | BOLD_FONTTYPE, &lf);
}
if (!bItalic && plf_reg) {
lf = *plf_reg;
lf.lfItalic = TRUE;
CBAddStyle(hwnd, szItalic, nFontType | ITALIC_FONTTYPE, &lf);
}
if (!bBoldItalic && (plf_bold || plf_italic || plf_reg)) {
if (plf_italic)
plf = plf_italic;
else if (plf_bold)
plf = plf_bold;
else
plf = plf_reg;
lf = *plf;
lf.lfItalic = TRUE;
lf.lfWeight = FW_BOLD;
CBAddStyle(hwnd, szBoldItalic, nFontType | BOLD_FONTTYPE | ITALIC_FONTTYPE, &lf);
}
}
void NEAR PASCAL FillScalableSizes(HWND hwnd, LPCHOOSEFONT lpcf)
{
CBAddSize(hwnd, 8, lpcf);
CBAddSize(hwnd, 9, lpcf);
CBAddSize(hwnd, 10, lpcf);
CBAddSize(hwnd, 11, lpcf);
CBAddSize(hwnd, 12, lpcf);
CBAddSize(hwnd, 14, lpcf);
CBAddSize(hwnd, 16, lpcf);
CBAddSize(hwnd, 18, lpcf);
CBAddSize(hwnd, 20, lpcf);
CBAddSize(hwnd, 22, lpcf);
CBAddSize(hwnd, 24, lpcf);
CBAddSize(hwnd, 26, lpcf);
CBAddSize(hwnd, 28, lpcf);
CBAddSize(hwnd, 36, lpcf);
CBAddSize(hwnd, 48, lpcf);
CBAddSize(hwnd, 72, lpcf);
}
#define GDI_FONTTYPE_STUFF (RASTER_FONTTYPE | DEVICE_FONTTYPE | TRUETYPE_FONTTYPE)
int FAR PASCAL FontStyleEnumProc(LPLOGFONT lplf, LPNEWTEXTMETRIC lptm, WORD nFontType, LPENUM_FONT_DATA lpData)
{
int height, pts;
char buf[10];
// filter for a font type match (the font type of the selected face
// must be the same as that enumerated)
if (nFontType != (WORD)(GDI_FONTTYPE_STUFF & lpData->nFontType))
return TRUE;
if (!(nFontType & RASTER_FONTTYPE)) {
// vector or TT font
if (lpData->bFillSize &&
(int)SendMessage(lpData->hwndSizes, CB_GETCOUNT, 0, 0L) == 0) {
FillScalableSizes(lpData->hwndSizes, lpData->lpcf);
}
} else {
height = lptm->tmHeight - lptm->tmInternalLeading;
pts = GetPointString(buf, lpData->hDC, height);
// filter devices same size of multiple styles
if (CBFindString(lpData->hwndSizes, buf) < 0)
CBAddSize(lpData->hwndSizes, pts, lpData->lpcf);
}
// keep the printer/screen bits from the family list here too
nFontType |= (lpData->nFontType & (SCREEN_FONTTYPE | PRINTER_FONTTYPE));
if (nFontType & TRUETYPE_FONTTYPE) {
// if (lptm->ntmFlags & NTM_REGULAR)
if (!(lptm->ntmFlags & (NTM_BOLD | NTM_ITALIC)))
nFontType |= REGULAR_FONTTYPE;
if (lptm->ntmFlags & NTM_ITALIC)
nFontType |= ITALIC_FONTTYPE;
if (lptm->ntmFlags & NTM_BOLD)
nFontType |= BOLD_FONTTYPE;
// after the LOGFONT.lfFaceName there are 2 more names
// lfFullName[LF_FACESIZE * 2]
// lfStyle[LF_FACESIZE]
CBAddStyle(lpData->hwndStyle, lplf->lfFaceName + 3 * LF_FACESIZE, nFontType, lplf);
} else {
if ((lplf->lfWeight >= FW_BOLD) && lplf->lfItalic)
CBAddStyle(lpData->hwndStyle, szBoldItalic, nFontType | BOLD_FONTTYPE | ITALIC_FONTTYPE, lplf);
else if (lplf->lfWeight >= FW_BOLD)
CBAddStyle(lpData->hwndStyle, szBold, nFontType | BOLD_FONTTYPE, lplf);
else if (lplf->lfItalic)
CBAddStyle(lpData->hwndStyle, szItalic, nFontType | ITALIC_FONTTYPE, lplf);
else
CBAddStyle(lpData->hwndStyle, szRegular, nFontType | REGULAR_FONTTYPE, lplf);
}
return TRUE;
}
void NEAR PASCAL FreeFonts(HWND hwnd)
{
DWORD dw;
int i, count;
count = (int)SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
for (i = 0; i < count; i++) {
dw = SendMessage(hwnd, CB_GETITEMDATA, i, 0L);
LocalFree((HANDLE)LOWORD(dw));
}
SendMessage(hwnd, CB_RESETCONTENT, 0, 0L);
}
// initalize a LOGFONT strucuture to some base generic regular type font
void NEAR PASCAL InitLF(LPLOGFONT lplf)
{
HDC hdc;
lplf->lfEscapement = 0;
lplf->lfOrientation = 0;
lplf->lfCharSet = ANSI_CHARSET;
lplf->lfOutPrecision = OUT_DEFAULT_PRECIS;
lplf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
lplf->lfQuality = DEFAULT_QUALITY;
lplf->lfPitchAndFamily = DEFAULT_PITCH;
lplf->lfItalic = 0;
lplf->lfWeight = FW_NORMAL;
lplf->lfStrikeOut = 0;
lplf->lfUnderline = 0;
lplf->lfWidth = 0; // otherwise we get independant x-y scaling
lplf->lfFaceName[0] = 0;
hdc = GetDC(NULL);
lplf->lfHeight = -MulDiv(DEF_POINT_SIZE, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
ReleaseDC(NULL, hdc);
}
/****************************************************************************
*
* GetFontStylesAndSizes
*
* PURPOSE : Fills the point sizes combo box with the point sizes for the
* current selection in the facenames combobox.
*
* ASSUMES : cmb1 - ID of font facename combobox
*
* RETURNS : TRUE if succesful, FALSE otherwise.
*
****************************************************************************/
BOOL NEAR PASCAL GetFontStylesAndSizes(HWND hDlg, LPCHOOSEFONT lpcf, BOOL bForceSizeFill)
{
ENUM_FONT_DATA data;
char szFace[LF_FACESIZE];
WORD nFontType;
int iSel;
int iMapMode;
DWORD dwViewportExt, dwWindowExt;
HANDLE hMod;
LOGFONT lf;
WORD (FAR PASCAL *lpEnumFonts)(HDC, LPSTR, FARPROC, VOID FAR *);
bForceSizeFill = bForceSizeFill;
hMod = GetModuleHandle(szGDI);
if (wWinVer < 0x030A)
lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts30);
else
lpEnumFonts = (WORD (FAR PASCAL *)(HDC, LPSTR, FARPROC, VOID FAR *))GetProcAddress(hMod, szEnumFonts31);
if (!lpEnumFonts)
return FALSE;
FreeFonts(GetDlgItem(hDlg, cmb2));
data.hwndStyle = GetDlgItem(hDlg, cmb2);
data.hwndSizes = GetDlgItem(hDlg, cmb3);
data.dwFlags = lpcf->Flags;
data.lpcf = lpcf;
iSel = (int)SendDlgItemMessage(hDlg, cmb1, CB_GETCURSEL, 0, 0L);
if (iSel < 0) {
// if we don't have a face name selected we will synthisize
// the standard font styles...
InitLF(&lf);
CBAddStyle(data.hwndStyle, szRegular, REGULAR_FONTTYPE, &lf);
lf.lfWeight = FW_BOLD;
CBAddStyle(data.hwndStyle, szBold, BOLD_FONTTYPE, &lf);
lf.lfWeight = FW_NORMAL;
lf.lfItalic = TRUE;
CBAddStyle(data.hwndStyle, szItalic, ITALIC_FONTTYPE, &lf);
lf.lfWeight = FW_BOLD;
CBAddStyle(data.hwndStyle, szBoldItalic, BOLD_FONTTYPE | ITALIC_FONTTYPE, &lf);
FillScalableSizes(data.hwndSizes, lpcf);
return TRUE;
}
nFontType = (WORD)SendDlgItemMessage(hDlg, cmb1, CB_GETITEMDATA, iSel, 0L);
data.nFontType = nFontType;
#if 0
data.bFillSize = bForceSizeFill ||
(nLastFontType & RASTER_FONTTYPE) != (nFontType & RASTER_FONTTYPE) ||
(nFontType & RASTER_FONTTYPE);
/* This does the same thing as above, i.e. if either or both fonts are
* raster fonts, update the sizes combobox. If they're both non-raster,
* don't update the combobox.
*/
data.bFillSize = bForceSizeFill ||
(nLastFontType & RASTER_FONTTYPE) ||
(nFontType & RASTER_FONTTYPE) ||
(SendMessage(data.hwndSizes, CB_GETCOUNT, 0, 0L) <= 0);
#else
data.bFillSize = TRUE;
#endif
if (data.bFillSize) {
SendMessage(data.hwndSizes, CB_RESETCONTENT, 0, 0L);
SendMessage(data.hwndSizes, WM_SETREDRAW, FALSE, 0L);
}
SendMessage(data.hwndStyle, WM_SETREDRAW, FALSE, 0L);
GetDlgItemText(hDlg, cmb1, szFace, sizeof(szFace));
if (lpcf->Flags & CF_SCREENFONTS) {
data.hDC = GetDC(NULL);
data.bPrinterFont = FALSE;
(*lpEnumFonts)(data.hDC, szFace, FontStyleEnumProc, &data);
ReleaseDC(NULL, data.hDC);
}
if (lpcf->Flags & CF_PRINTERFONTS) {
/* Bug #10619: Save and restore the DC's mapping mode (and extents if
* needed) if it's been set by the app to something other than MM_TEXT.
* 3 January 1992 Clark Cyr
*/
if ((iMapMode = GetMapMode(lpcf->hDC)) != MM_TEXT)
{
if ((iMapMode == MM_ISOTROPIC) || (iMapMode == MM_ANISOTROPIC))
{
dwViewportExt = GetViewportExt(lpcf->hDC);
dwWindowExt = GetWindowExt(lpcf->hDC);
}
SetMapMode(lpcf->hDC, MM_TEXT);
}
data.hDC = lpcf->hDC;
data.bPrinterFont = TRUE;
(*lpEnumFonts)(lpcf->hDC, szFace, FontStyleEnumProc, &data);
if (iMapMode != MM_TEXT)
{
SetMapMode(lpcf->hDC, iMapMode);
if ((iMapMode == MM_ISOTROPIC) || (iMapMode == MM_ANISOTROPIC))
{
SetWindowExt(lpcf->hDC, LOWORD(dwWindowExt),
HIWORD(dwWindowExt));
SetViewportExt(lpcf->hDC, LOWORD(dwViewportExt),
HIWORD(dwViewportExt));
}
}
}
if (!(lpcf->Flags & CF_NOSIMULATIONS))
FillInMissingStyles(data.hwndStyle);
SendMessage(data.hwndStyle, WM_SETREDRAW, TRUE, 0L);
if (wWinVer < 0x030A)
InvalidateRect(data.hwndStyle, NULL, TRUE);
if (data.bFillSize) {
SendMessage(data.hwndSizes, WM_SETREDRAW, TRUE, 0L);
if (wWinVer < 0x030A)
InvalidateRect(data.hwndSizes, NULL, TRUE);
}
return TRUE;
}
/****************************************************************************
*
* FillColorCombo
*
* PURPOSE : Adds the color name strings to the colors combobox.
*
* ASSUMES : cmb4 - ID of colors combobox
*
* COMMENTS : The color rectangles are drawn later in response to
* WM_DRAWITEM messages
*
****************************************************************************/
void NEAR PASCAL FillColorCombo(HWND hDlg)
{
int iT, item;
char szT[CCHCOLORNAMEMAX];
for (iT = 0; iT < CCHCOLORS; ++iT)
{
*szT = 0;
LoadString(hinsCur, iszBlack + iT, szT, sizeof(szT));
item = (int)SendDlgItemMessage(hDlg, cmb4, CB_INSERTSTRING, iT, (LONG)(LPSTR)szT);
if (item >= 0)
SendDlgItemMessage(hDlg, cmb4, CB_SETITEMDATA, item, rgbColors[iT]);
}
}
/****************************************************************************
*
* ComputeSampleTextRectangle
*
* PURPOSE : Determines the bounding rectangle for the text preview area,
* and fills in rcText.
*
* ASSUMES : stc5 - ID preview text rectangle
*
* COMMENTS : The coordinates are calculated w.r.t the dialog.
*
****************************************************************************/
void NEAR PASCAL ComputeSampleTextRectangle(HWND hDlg)
{
GetWindowRect(GetDlgItem (hDlg, stc5), &rcText);
ScreenToClient(hDlg, (LPPOINT)&rcText.left);
ScreenToClient(hDlg, (LPPOINT)&rcText.right);
}
BOOL NEAR PASCAL DrawSizeComboItem(LPDRAWITEMSTRUCT lpdis)
{
HDC hDC;
DWORD rgbBack, rgbText;
char szFace[10];
hDC = lpdis->hDC;
if (lpdis->itemState & ODS_SELECTED) {
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
} else {
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
}
SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szFace);
ExtTextOut(hDC, lpdis->rcItem.left + GetSystemMetrics(SM_CXBORDER), lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, szFace, lstrlen(szFace), NULL);
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBack);
return TRUE;
}
BOOL NEAR PASCAL DrawFamilyComboItem(LPDRAWITEMSTRUCT lpdis)
{
HDC hDC, hdcMem;
DWORD rgbBack, rgbText;
char szFace[LF_FACESIZE + 10];
HBITMAP hOld;
int dy, x;
hDC = lpdis->hDC;
if (lpdis->itemState & ODS_SELECTED) {
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
} else {
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
rgbText = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
}
// wsprintf(szFace, "%4.4X", LOWORD(lpdis->itemData));
SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szFace);
ExtTextOut(hDC, lpdis->rcItem.left + DX_BITMAP, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, szFace, lstrlen(szFace), NULL);
hdcMem = CreateCompatibleDC(hDC);
if (hdcMem) {
if (hbmFont) {
hOld = SelectObject(hdcMem, hbmFont);
if (lpdis->itemData & TRUETYPE_FONTTYPE)
x = 0;
else if ((lpdis->itemData & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) == (PRINTER_FONTTYPE | DEVICE_FONTTYPE))
// this may be a screen and printer font but
// we will call it a printer font here
x = DX_BITMAP;
else
goto SkipBlt;
dy = ((lpdis->rcItem.bottom - lpdis->rcItem.top) - DY_BITMAP) / 2;
BitBlt(hDC, lpdis->rcItem.left, lpdis->rcItem.top + dy, DX_BITMAP, DY_BITMAP, hdcMem,
x, lpdis->itemState & ODS_SELECTED ? DY_BITMAP : 0, SRCCOPY);
SkipBlt:
SelectObject(hdcMem, hOld);
}
DeleteDC(hdcMem);
}
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBack);
return TRUE;
}
/****************************************************************************
*
* DrawColorComboItem
*
* PURPOSE : Called by main dialog fn. in response to a WM_DRAWITEM
* message, computes and draws the color combo items.
*
* RETURNS : TRUE if succesful, FALSE otherwise.
*
* COMMENTS : All color name strings have already loaded and filled into
* combobox.
*
****************************************************************************/
BOOL NEAR PASCAL DrawColorComboItem(LPDRAWITEMSTRUCT lpdis)
{
HDC hDC;
HBRUSH hbr;
WORD dx, dy;
RECT rc;
char szColor[CCHCOLORNAMEMAX];
DWORD rgbBack, rgbText, dw;
hDC = lpdis->hDC;
if (lpdis->itemState & ODS_SELECTED) {
rgbBack = SetBkColor(hDC, GetSysColor (COLOR_HIGHLIGHT));
rgbText = SetTextColor(hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
} else {
rgbBack = SetBkColor(hDC, GetSysColor (COLOR_WINDOW));
rgbText = SetTextColor(hDC, GetSysColor (COLOR_WINDOWTEXT));
}
ExtTextOut(hDC, lpdis->rcItem.left, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, NULL, 0, NULL);
/* compute coordinates of color rectangle and draw it */
dx = (WORD)GetSystemMetrics(SM_CXBORDER);
dy = (WORD)GetSystemMetrics(SM_CYBORDER);
rc.top = lpdis->rcItem.top + dy;
rc.bottom = lpdis->rcItem.bottom - dy;
rc.left = lpdis->rcItem.left + dx;
rc.right = rc.left + 2 * (rc.bottom - rc.top);
if (wWinVer < 0x030A)
dw = SendMessage(lpdis->hwndItem, CB_GETITEMDATA, lpdis->itemID, 0L);
else
dw = lpdis->itemData;
hbr = CreateSolidBrush(dw);
if (!hbr)
return FALSE;
hbr = SelectObject (hDC, hbr);
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
DeleteObject(SelectObject(hDC, hbr));
/* shift the color text right by the width of the color rectangle */
*szColor = 0;
SendMessage(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LONG)(LPSTR)szColor);
TextOut(hDC, 2 * dx + rc.right, lpdis->rcItem.top, szColor, lstrlen(szColor));
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBack);
return TRUE;
}
/****************************************************************************
*
* DrawSampleText
*
* PURPOSE : To display the sample text with the given attributes
*
* COMMENTS : Assumes rcText holds the coordinates of the area within the
* frame (relative to dialog client) which text should be drawn in
*
****************************************************************************/
void NEAR PASCAL DrawSampleText(HWND hDlg, LPCHOOSEFONT lpcf, HDC hDC)
{
DWORD rgbText;
DWORD rgbBack;
int iItem;
HFONT hFont, hTemp;
char szSample[50];
LOGFONT lf;
int len, x, y, dx, dy;
TEXTMETRIC tm;
BOOL bCompleteFont;
bCompleteFont = FillInFont(hDlg, lpcf, &lf, FALSE);
hFont = CreateFontIndirect(&lf);
if (!hFont)
return;
hTemp = SelectObject(hDC, hFont);
rgbBack = SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
if (lpcf->Flags & CF_EFFECTS) {
iItem = (int)SendDlgItemMessage(hDlg, cmb4, CB_GETCURSEL, 0, 0L);
if (iItem != CB_ERR)
rgbText = SendDlgItemMessage(hDlg, cmb4, CB_GETITEMDATA, iItem, 0L);
else
goto GetWindowTextColor;
}
else
{
GetWindowTextColor:
rgbText = GetSysColor(COLOR_WINDOWTEXT);
}
rgbText = SetTextColor(hDC, rgbText);
if (bCompleteFont)
GetDlgItemText(hDlg, stc5, szSample, sizeof(szSample));
else
szSample[0] = 0;
GetTextMetrics(hDC, &tm);
len = lstrlen(szSample);
dx = (int)GetTextExtent(hDC, szSample, len);
dy = tm.tmAscent - tm.tmInternalLeading;
if ((dx >= (rcText.right - rcText.left)) || (dx <= 0))
x = rcText.left;
else
x = rcText.left + ((rcText.right - rcText.left) - (int)dx) / 2;
y = min(rcText.bottom, rcText.bottom - ((rcText.bottom - rcText.top) - (int)dy) / 2);
ExtTextOut(hDC, x, y - (tm.tmAscent), ETO_OPAQUE | ETO_CLIPPED, &rcText, szSample, len, NULL);
SetBkColor(hDC, rgbBack);
SetTextColor(hDC, rgbText);
if (hTemp)
DeleteObject(SelectObject(hDC, hTemp));
}
// fill in the LOGFONT strucuture based on the current selection
//
// in:
// bSetBits if TRUE the Flags fields in the lpcf are set to
// indicate what parts (face, style, size) are not
// selected
// out:
// lplf filled in LOGFONT
//
// returns:
// TRUE if there was an unambigious selection
// (the LOGFONT is filled as per the enumeration in)
// FALSE there was not a complete selection
// (fields set in the LOGFONT with default values)
BOOL NEAR PASCAL FillInFont(HWND hDlg, LPCHOOSEFONT lpcf, LPLOGFONT lplf, BOOL bSetBits)
{
HDC hdc;
int iSel, id, pts;
DWORD dw;
WORD nFontType;
PLOGFONT plf;
char szStyle[LF_FACESIZE];
char szMessage[128];
BOOL bFontComplete = TRUE;
InitLF(lplf);
GetDlgItemText(hDlg, cmb1, lplf->lfFaceName, sizeof(lplf->lfFaceName));
if (CBFindString(GetDlgItem(hDlg, cmb1), lplf->lfFaceName) >= 0) {
if (bSetBits)
lpcf->Flags &= ~CF_NOFACESEL;
} else {
bFontComplete = FALSE;
if (bSetBits)
lpcf->Flags |= CF_NOFACESEL;
}
iSel = CBGetTextAndData(GetDlgItem(hDlg, cmb2), szStyle, sizeof(szStyle), &dw);
if (iSel >= 0) {
nFontType = HIWORD(dw);
plf = (PLOGFONT)LOWORD(dw);
*lplf = *plf; // copy the LOGFONT
lplf->lfWidth = 0; // 1:1 x-y scaling
if (bSetBits)
lpcf->Flags &= ~CF_NOSTYLESEL;
} else {
bFontComplete = FALSE;
if (bSetBits)
lpcf->Flags |= CF_NOSTYLESEL;
nFontType = 0;
}
// now make sure the size is in range; pts will be 0 if not
GetPointSizeInRange(hDlg, lpcf, &pts, 0);
hdc = GetDC(NULL);
if (pts) {
lplf->lfHeight = -MulDiv(pts, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
if (bSetBits)
lpcf->Flags &= ~CF_NOSIZESEL;
} else {
lplf->lfHeight = -MulDiv(DEF_POINT_SIZE, GetDeviceCaps(hdc, LOGPIXELSY), POINTS_PER_INCH);
bFontComplete = FALSE;
if (bSetBits)
lpcf->Flags |= CF_NOSIZESEL;
}
ReleaseDC(NULL, hdc);
// and the attributes we control
lplf->lfStrikeOut = (BYTE)IsDlgButtonChecked(hDlg, chx1);
lplf->lfUnderline = (BYTE)IsDlgButtonChecked(hDlg, chx2);
if (nFontType != nLastFontType) {
if (lpcf->Flags & CF_PRINTERFONTS) {
if (nFontType & SIMULATED_FONTTYPE) {
id = iszSynth;
} else if (nFontType & TRUETYPE_FONTTYPE) {
id = iszTrueType;
} else if ((nFontType & (PRINTER_FONTTYPE | SCREEN_FONTTYPE)) == SCREEN_FONTTYPE) {
id = iszGDIFont;
} else if ((nFontType & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) == (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) {
// may be both screen and printer (ATM) but we'll just
// call this a printer font
id = iszPrinterFont;
} else {
szMessage[0] = 0;
goto SetText;
}
LoadString(hinsCur, id, szMessage, sizeof(szMessage));
SetText:
SetDlgItemText(hDlg, stc6, szMessage);
}
}
nLastFontType = nFontType;
return bFontComplete;
}
/****************************************************************************
*
* TermFont
*
* PURPOSE : To release any data required by functions in this module
* Called from WEP on exit from DLL
*
****************************************************************************/
void FAR PASCAL TermFont(void)
{
if (hbmFont)
DeleteObject(hbmFont);
}
/****************************************************************************
*
* GetPointString
*
* PURPOSE : Converts font height into a string of digits repr. pointsize
*
* RETURNS : size in points and fills in buffer with string
*
****************************************************************************/
int NEAR PASCAL GetPointString(LPSTR buf, HDC hDC, int height)
{
int pts;
pts = MulDiv((height < 0) ? -height : height, 72, GetDeviceCaps(hDC, LOGPIXELSY));
wsprintf(buf, szPtFormat, pts);
return pts;
}
//
// BOOL FAR PASCAL LoadBitmaps()
//
// this routine loads DIB bitmaps, and "fixes up" their color tables
// so that we get the desired result for the device we are on.
//
// this routine requires:
// the DIB is a 16 color DIB authored with the standard windows colors
// bright blue (00 00 FF) is converted to the background color!
// light grey (C0 C0 C0) is replaced with the button face color
// dark grey (80 80 80) is replaced with the button shadow color
//
// this means you can't have any of these colors in your bitmap
//
#define BACKGROUND 0x000000FF // bright blue
#define BACKGROUNDSEL 0x00FF00FF // bright blue
#define BUTTONFACE 0x00C0C0C0 // bright grey
#define BUTTONSHADOW 0x00808080 // dark grey
DWORD NEAR PASCAL FlipColor(DWORD rgb)
{
return RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb));
}
HBITMAP NEAR PASCAL LoadBitmaps(int id)
{
HDC hdc;
HANDLE h;
DWORD FAR *p;
LPSTR lpBits;
HANDLE hRes;
LPBITMAPINFOHEADER lpBitmapInfo;
int numcolors;
DWORD rgbSelected;
DWORD rgbUnselected;
HBITMAP hbm;
rgbSelected = FlipColor(GetSysColor(COLOR_HIGHLIGHT));
rgbUnselected = FlipColor(GetSysColor(COLOR_WINDOW));
h = FindResource(hinsCur, MAKEINTRESOURCE(id), RT_BITMAP);
hRes = LoadResource(hinsCur, h);
/* Lock the bitmap and get a pointer to the color table. */
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
if (!lpBitmapInfo)
return FALSE;
p = (DWORD FAR *)((LPSTR)(lpBitmapInfo) + lpBitmapInfo->biSize);
/* Search for the Solid Blue entry and replace it with the current
* background RGB.
*/
numcolors = 16;
while (numcolors-- > 0) {
if (*p == BACKGROUND)
*p = rgbUnselected;
else if (*p == BACKGROUNDSEL)
*p = rgbSelected;
#if 0
else if (*p == BUTTONFACE)
*p = FlipColor(GetSysColor(COLOR_BTNFACE));
else if (*p == BUTTONSHADOW)
*p = FlipColor(GetSysColor(COLOR_BTNSHADOW));
#endif
p++;
}
UnlockResource(hRes);
/* Now create the DIB. */
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hRes);
/* First skip over the header structure */
lpBits = (LPSTR)(lpBitmapInfo + 1);
/* Skip the color table entries, if any */
lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
/* Create a color bitmap compatible with the display device */
hdc = GetDC(NULL);
hbm = CreateDIBitmap(hdc, lpBitmapInfo, (DWORD)CBM_INIT, lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
ReleaseDC(NULL, hdc);
MySetObjectOwner(hbm);
GlobalUnlock(hRes);
FreeResource(hRes);
return hbm;
}
#if 0
#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
int NEAR PASCAL atoi(LPSTR sz)
{
int n = 0;
BOOL bNeg = FALSE;
if (*sz == '-') {
bNeg = TRUE;
sz++;
}
while (ISDIGIT(*sz)) {
n *= 10;
n += *sz - '0';
sz++;
}
return bNeg ? -n : n;
}
#endif