1962 lines
63 KiB
C
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
|
||
|
|