/******************************************************************************* * * 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 #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 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 || nTmpnSizeMin)) { 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