//THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
//ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
//THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE.
//
// Copyright © 1993, 1994  Microsoft Corporation.  All Rights Reserved.
//
//  MODULE:     Dialogs.c
//
//  PURPOSE:    Dialog procs and helper routines
//
//  PLATFORMS:  Chicago, NT, Win32s
//
//  FUNCTIONS:  
//      SetDlgItemValue() - set the edit control text with the given value
//      DlgEnumFontSizes() - font enumeration callback, stores sizes
//      DlgEnumFontNames() - font enumeration callback, stores names
//      SimpleDlgProc() - processes messages for the About box
//      CreateDlgProc() - processes messages for font creation dialog
//      MetricsDlgProc() - processes messages for the TEXTMETRICS dialog
//      FillEnumFields() - fills in TEXTMETRIC and LOGFONT info in the corresponding edit controls
//      DrawSample() - display a sample of the selected font
//      EnumDlgProc() - processes messages for the font enumeration dialog
//
//  SPECIAL INSTRUCTIONS: N/A
//

#define NOMINMAX

#include <windows.h>
#include "FontView.h"
#include <stdlib.h>

#if !defined (APIENTRY)
#define APIENTRY FAR PASCAL
#endif

// prototype
BOOL CenterWindow (HWND, HWND);

typedef struct FONTENUM {       // font info
    short       ft;
    TEXTMETRIC  tm;
    LOGFONT     lf;
} FONTSTRUCT;
typedef FONTSTRUCT      *PFONTSTRUCT;
typedef FONTSTRUCT NEAR *NPFONTSTRUCT;
typedef FONTSTRUCT FAR  *LPFONTSTRUCT;

typedef struct FONTLIST {       // enumerated fonts
    int     count;
    HANDLE  hList;
} FONTLIST;
typedef FONTLIST        *PFONTLIST;
typedef FONTLIST NEAR   *NPFONTLIST;
typedef FONTLIST FAR    *LPFONTLIST;


//
//  FUNCTION: SetDlgItemValue()
//
//  PURPOSE: set the edit control text with the given value
//

void SetDlgItemValue(HWND hDlg, int nIDDlgItem, int wValue, BOOL bSigned, int nBase)
{
    char szValue[20];

    switch (nBase) {
    case 8:
        wsprintf (szValue, "0o%o", wValue);
        SetDlgItemText (hDlg, nIDDlgItem, szValue);
        break;
    case 16:
        wsprintf (szValue, "0x%x", wValue);
        SetDlgItemText (hDlg, nIDDlgItem, szValue);
        break;
    default:
        SetDlgItemInt (hDlg, nIDDlgItem, wValue, bSigned);
        break;
    }
}


//
//  FUNCTION: DlgEnumFontSizes()
//
//  PURPOSE: This function will lock down the incoming handle, properly alloc, and
//           realloc the handle within it to hold the data of the fonts enumerated,
//           then unlock the handle.
//

int FAR PASCAL DlgEnumFontSizes(LPLOGFONT lpLogFont, LPTEXTMETRIC lpTextMetric, short nFontType, LPHANDLE lpData)
{
    HANDLE hFonts;
    LPFONTSTRUCT pFS;
    LPFONTLIST pFL;

    hFonts = *lpData;
    pFL = (LPFONTLIST)GlobalLock (hFonts);
    if (!pFL) {
        return FALSE;
    }
    else if (pFL->count == 0) {
        pFL->hList = GlobalAlloc (GHND, sizeof(FONTSTRUCT));
    }
    else {
        pFL->hList = GlobalReAlloc (pFL->hList, sizeof(FONTSTRUCT)*(1+pFL->count), GMEM_MOVEABLE);
    }

    if (pFL->hList) {
        pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
        if (pFS) {
            pFS[pFL->count].ft = nFontType;
            pFS[pFL->count].tm = *lpTextMetric;
            pFS[pFL->count].lf = *lpLogFont;
            GlobalUnlock (pFL->hList);
            pFL->count++;
        }
        GlobalUnlock (hFonts);
    }
    else {
        GlobalUnlock (hFonts);
        return FALSE;
    }

    return TRUE;
}


//
//  FUNCTION: DlgEnumFontNames()
//
//  PURPOSE: This function is just a pass through. For each face encountered, it will
//           in turn enumerate all sizes available. the lpData, which is a FAR * to a
//           FONTSTRUCT structure will simply be passed on to the second enumeration
//           procedure which will fill it in.
//

int FAR PASCAL DlgEnumFontNames(LPLOGFONT lpLogFont, LPTEXTMETRIC lpTextMetric, short nFontType, LPHANDLE lpData)
{
    HDC  hdc;
    HWND hwnd;
    HANDLE hInst;
    FARPROC lpFontEnumProc;

    hwnd = GetFocus();
#if defined (WIN16)
    hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#else
    hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#endif

    lpFontEnumProc = MakeProcInstance((FARPROC)DlgEnumFontSizes, hInst);
    if (lpFontEnumProc) {
        hdc  = GetDC(hwnd);
        EnumFonts (hdc, lpLogFont->lfFaceName, (FONTENUMPROC)lpFontEnumProc, (LPARAM)lpData);
        ReleaseDC(hwnd, hdc);
        FreeProcInstance (lpFontEnumProc);
    }
    else {
        MessageBox (GetFocus(), "Couldn't create a proc instance", "FontView", MB_OK);
        return FALSE;
    }
    return TRUE;

    lpTextMetric;  // unreferenced formal parameter
    nFontType;     // unreferenced formal parameter
}


//
//  FUNCTION: SimpleDlgProc()
//
//  PURPOSE: processes messages for the About box
//

BOOL APIENTRY SimpleDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    int wmId;
    static HBITMAP hbmFontView;
    static BITMAP bmFontView;
    RECT rect;
    HDC hdc, hdcSrc;
    HBITMAP hbmOld;
    PAINTSTRUCT ps;
    HANDLE hInst;

#if defined (_WIN32)
    hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#elif defined (WIN16)
    hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#endif

    switch (msg) {
    case WM_INITDIALOG:
        CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
        hbmFontView = LoadBitmap (hInst, "FONTVIEW");
        GetObject (hbmFontView,sizeof(BITMAP), &bmFontView);
        if (!hbmFontView) MessageBeep(0);
        return (TRUE);

    case WM_DESTROY:
        DeleteObject (hbmFontView);
        break;

    case WM_PAINT:
        hdc = BeginPaint (hwnd, &ps);
        GetWindowRect (hwnd, &rect);
        ScreenToClient (hwnd, (LPPOINT)&rect.left);
        ScreenToClient (hwnd, (LPPOINT)&rect.right);
        hdc = GetDC (hwnd);
        hdcSrc = CreateCompatibleDC (hdc);
        hbmOld = SelectObject (hdcSrc, hbmFontView);
        if (!BitBlt (hdc, 0, 0, bmFontView.bmWidth, bmFontView.bmHeight, hdcSrc, 0, 0, SRCCOPY)) {
            MessageBeep(0);
        }
        SelectObject (hdcSrc, hbmOld);
        DeleteDC (hdcSrc);
        EndPaint (hwnd, &ps);
        break;

    case WM_COMMAND:
#if defined (_WIN32)
        wmId = LOWORD(wParam);
#elif defined (WIN16)
        wmId = wParam;
#endif
        switch (wmId) {
        case IDOK:
            EndDialog(hwnd, TRUE);
            return (TRUE);

        case IDCANCEL:
            EndDialog(hwnd, TRUE);
            return (TRUE);
        }
        break;
    }
    return (FALSE);

    lParam; // unreferenced formal parameter
}


//
//  FUNCTION: CreateDlgProc()
//
//  PURPOSE: This dialog will present edit controls for all the parameters of
//           a CreateFont call. The user can put any value in any of the fields,
//           no validation is done. These parameters are then used to create a font
//           with, and that will be the font that will be displayed.
//

BOOL APIENTRY CreateDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    int wmId, i;
    BOOL bDone;
    static LOGFONT lfDlg;
    static LPLOGFONT lplf;

    switch (msg) {
    case WM_INITDIALOG:
        CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
        lplf = (LOGFONT *)lParam;
        lfDlg = *lplf;
        SetDlgItemInt (hwnd, CFD_HEIGHT, (int)lfDlg.lfHeight, TRUE);
        SetDlgItemInt (hwnd, CFD_WIDTH, (int)lfDlg.lfWidth, TRUE);
        SetDlgItemInt (hwnd, CFD_ESCAPEMENT, (int)lfDlg.lfEscapement, TRUE);
        SetDlgItemInt (hwnd, CFD_ORIENTATION, (int)lfDlg.lfOrientation, TRUE);
        SetDlgItemInt (hwnd, CFD_WEIGHT, (int)lfDlg.lfWeight, FALSE);
        SetDlgItemInt (hwnd, CFD_ITALIC, (int)lfDlg.lfItalic, FALSE);
        SetDlgItemInt (hwnd, CFD_UNDERLINE, (int)lfDlg.lfUnderline, FALSE);
        SetDlgItemInt (hwnd, CFD_STRIKEOUT, (int)lfDlg.lfStrikeOut, FALSE);
        SetDlgItemInt (hwnd, CFD_CHARSET, (int)lfDlg.lfCharSet, FALSE);
        SetDlgItemInt (hwnd, CFD_OUTPUTPRECISION, (int)lfDlg.lfOutPrecision, FALSE);
        SetDlgItemInt (hwnd, CFD_CLIPPRECISION, (int)lfDlg.lfClipPrecision, FALSE);
        SetDlgItemInt (hwnd, CFD_QUALITY, (int)lfDlg.lfQuality, FALSE);
        SetDlgItemInt (hwnd, CFD_PITCHANDFAMILY, (int)lfDlg.lfPitchAndFamily, FALSE);
        SetDlgItemText(hwnd, CFD_FACENAME, lfDlg.lfFaceName);
        return (TRUE);

    case WM_COMMAND:
#if defined (_WIN32)
        wmId = LOWORD(wParam);
#elif defined (WIN16)
        wmId = wParam;
#endif
        switch (wmId) {
        case CFD_DEFAULT:
            // Set all elements to ZERO. This will give us a 'default' font
            for (i=CFD_BASE; i<=CFD_PITCHANDFAMILY; i++) {
                SetDlgItemInt (hwnd, i, 0, FALSE);
            }
            SetDlgItemText (hwnd, CFD_FACENAME, "");
            break;

        case IDOK:
            // Get the data from the edit control, we will then use this for a 'CreatFont' call
            lfDlg.lfHeight = GetDlgItemInt (hwnd, CFD_HEIGHT, &bDone, TRUE);
            lfDlg.lfWidth = GetDlgItemInt (hwnd, CFD_WIDTH, &bDone, TRUE);
            lfDlg.lfEscapement = GetDlgItemInt (hwnd, CFD_ESCAPEMENT, &bDone, TRUE);
            lfDlg.lfOrientation = GetDlgItemInt (hwnd, CFD_ORIENTATION, &bDone, TRUE);
            lfDlg.lfWeight = GetDlgItemInt (hwnd, CFD_WEIGHT, &bDone, FALSE);
            lfDlg.lfItalic = (BYTE)GetDlgItemInt (hwnd, CFD_ITALIC, &bDone, FALSE);
            lfDlg.lfUnderline = (BYTE)GetDlgItemInt (hwnd, CFD_UNDERLINE, &bDone, FALSE);
            lfDlg.lfStrikeOut = (BYTE)GetDlgItemInt (hwnd, CFD_STRIKEOUT, &bDone, FALSE);
            lfDlg.lfCharSet = (BYTE)GetDlgItemInt (hwnd, CFD_CHARSET, &bDone, FALSE);
            lfDlg.lfOutPrecision = (BYTE)GetDlgItemInt (hwnd, CFD_OUTPUTPRECISION, &bDone, FALSE);
            lfDlg.lfClipPrecision = (BYTE)GetDlgItemInt (hwnd, CFD_CLIPPRECISION, &bDone, FALSE);
            lfDlg.lfQuality = (BYTE)GetDlgItemInt (hwnd, CFD_QUALITY, &bDone, FALSE);
            lfDlg.lfPitchAndFamily = (BYTE)GetDlgItemInt (hwnd, CFD_PITCHANDFAMILY, &bDone, FALSE);
            GetDlgItemText(hwnd, CFD_FACENAME, lfDlg.lfFaceName,20);
            // and copy the data into our external structure
            *lplf = lfDlg;
            EndDialog(hwnd, TRUE);
            return (TRUE);

        case IDCANCEL:
            // Exit without changing anything
            EndDialog(hwnd, TRUE);
            return (TRUE);

        }
        break;
    }
    return (FALSE);

    lParam; //unreferenced formal paramter
}


//
//  FUNCTION: MetricsDlgProc()
//
//  PURPOSE: This dialog will display the TEXTMETRIC data that is retrieved
//           from a 'GetTextMetric' call. If the 'Select' button is clicked,
//           then the current CreateFont data will be replaced with as much
//           data from TEXTMETRIC as possible.
//

BOOL APIENTRY MetricsDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    static LOGFONT lfDlg;
    static LPLOGFONT lplf;
    static TEXTMETRIC tm;
    static char szFacename[LF_FACESIZE];
    int wmId;
    BOOL bDone;
    TEXTMETRIC tmTmp;
    HFONT hfont, hfontPrev;
    HDC   hdc;
    char szBuffer[LF_FACESIZE+15];

    switch (msg) {
    case WM_INITDIALOG:
        CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
        lplf = (LOGFONT *)lParam;
        lfDlg = *lplf;

        hfont = CreateFontIndirect (&lfDlg);
        hdc = GetDC (hwnd);
        hfontPrev = SelectObject (hdc, hfont);
        GetTextMetrics (hdc, &tm);
        GetTextFace    (hdc, sizeof(szFacename), szFacename);
        SelectObject (hdc, hfontPrev);
        DeleteObject (hfont);
        ReleaseDC (hwnd, hdc);

        wsprintf (szBuffer, "TextMetrics: %s", (LPSTR)szFacename);
        SetWindowText (hwnd, szBuffer);

        SetDlgItemInt (hwnd, TMD_HEIGHT, (int)tm.tmHeight, TRUE);
        SetDlgItemInt (hwnd, TMD_ASCENT, (int)tm.tmAscent, TRUE);
        SetDlgItemInt (hwnd, TMD_DESCENT, (int)tm.tmDescent, TRUE);
        SetDlgItemInt (hwnd, TMD_INTERNAL, (int)tm.tmInternalLeading, TRUE);
        SetDlgItemInt (hwnd, TMD_EXTERNAL, (int)tm.tmExternalLeading, TRUE);
        SetDlgItemInt (hwnd, TMD_AVEWIDTH, (int)tm.tmAveCharWidth, TRUE);
        SetDlgItemInt (hwnd, TMD_MAXWIDTH, (int)tm.tmMaxCharWidth, TRUE);
        SetDlgItemInt (hwnd, TMD_WEIGHT, (int)tm.tmWeight, TRUE);
        SetDlgItemInt (hwnd, TMD_ITALIC, (int)tm.tmItalic, FALSE);
        SetDlgItemInt (hwnd, TMD_UNDERLINE, (int)tm.tmUnderlined, FALSE);
        SetDlgItemInt (hwnd, TMD_STRUCKOUT, (int)tm.tmStruckOut, FALSE);
        SetDlgItemInt (hwnd, TMD_FIRSTCHAR, (int)tm.tmFirstChar, FALSE);
        SetDlgItemInt (hwnd, TMD_LASTCHAR, (int)tm.tmLastChar, FALSE);
        SetDlgItemInt (hwnd, TMD_DEFAULTCHAR, (int)tm.tmDefaultChar, FALSE);
        SetDlgItemInt (hwnd, TMD_BREAKCHAR, (int)tm.tmBreakChar, FALSE);
        SetDlgItemInt (hwnd, TMD_PITCHANDFAMILY, (int)tm.tmPitchAndFamily, FALSE);
        SetDlgItemInt (hwnd, TMD_CHARSET, (int)tm.tmCharSet, FALSE);
        SetDlgItemInt (hwnd, TMD_OVERHANG, (int)tm.tmOverhang, TRUE);
        SetDlgItemInt (hwnd, TMD_DIGITIZEDASPECTX, (int)tm.tmDigitizedAspectX, TRUE);
        SetDlgItemInt (hwnd, TMD_DIGITIZEDASPECTY, (int)tm.tmDigitizedAspectY, TRUE);
        return (TRUE);

    case WM_COMMAND:
#if defined (_WIN32)
        wmId = LOWORD(wParam);
#elif defined (WIN16)
        wmId = wParam;
#endif
        switch (wmId) {
        case IDOK:
            // Lets pull in as much data from the TEXTMETRIC structure as possible...
            lfDlg.lfHeight         = tm.tmHeight;
            lfDlg.lfWidth          = tm.tmAveCharWidth;
            //lfDlg.lfEscapement - No Use
            //lfDlg.lfOrientation - No Use
            lfDlg.lfWeight         = tm.tmWeight;
            lfDlg.lfItalic         = tm.tmItalic;
            lfDlg.lfUnderline      = tm.tmUnderlined;
            lfDlg.lfStrikeOut      = tm.tmStruckOut;
            lfDlg.lfCharSet        = tm.tmCharSet;
            //lfDlg.lfOutPrecision - No Use
            //lfDlg.lfClipPrecision - No Use
            //lfDlg.lfQuality - No Use
            lfDlg.lfPitchAndFamily = tm.tmPitchAndFamily;
            lstrcpy(lfDlg.lfFaceName, szFacename);

            // Lets create a font with this new data
            hfont = CreateFontIndirect (&lfDlg);
            hdc = GetDC (hwnd);
            hfontPrev = SelectObject (hdc, hfont);
            GetTextMetrics (hdc, &tmTmp);
            // Get the face name
            GetTextFace    (hdc, sizeof(szBuffer), szBuffer);
            SelectObject (hdc, hfontPrev);
            DeleteObject (hfont);
            ReleaseDC (hwnd, hdc);

            // And verify that we did indeed get the same font.
            bDone = TRUE;
            bDone = bDone && (tm.tmHeight==tmTmp.tmHeight);
            bDone = bDone && (tm.tmAscent==tmTmp.tmAscent);
            bDone = bDone && (tm.tmDescent==tmTmp.tmDescent);
            bDone = bDone && (tm.tmInternalLeading==tmTmp.tmInternalLeading);
            bDone = bDone && (tm.tmExternalLeading==tmTmp.tmExternalLeading);
            bDone = bDone && (tm.tmAveCharWidth==tmTmp.tmAveCharWidth);
            bDone = bDone && (tm.tmMaxCharWidth==tmTmp.tmMaxCharWidth);
            bDone = bDone && (tm.tmWeight==tmTmp.tmWeight);
            bDone = bDone && (tm.tmItalic==tmTmp.tmItalic);
            bDone = bDone && (tm.tmUnderlined==tmTmp.tmUnderlined);
            bDone = bDone && (tm.tmStruckOut==tmTmp.tmStruckOut);
            bDone = bDone && (tm.tmFirstChar==tmTmp.tmFirstChar);
            bDone = bDone && (tm.tmLastChar==tmTmp.tmLastChar);
            bDone = bDone && (tm.tmDefaultChar==tmTmp.tmDefaultChar);
            bDone = bDone && (tm.tmBreakChar==tmTmp.tmBreakChar);
            bDone = bDone && (tm.tmPitchAndFamily==tmTmp.tmPitchAndFamily);
            bDone = bDone && (tm.tmCharSet==tmTmp.tmCharSet);
            // Did it work?
            if (bDone) {
                *lplf = lfDlg;
                EndDialog(hwnd, TRUE);
                return (TRUE);
            }
            else {
                // We need to take a close look at the font verification
                // code. Currently, it sometimes will report that the
                // font didn't get properly selected, even if it did.
                *lplf = lfDlg;
                            EndDialog(hwnd, TRUE);
                return (TRUE);

                // This is what we want to do once we beef up the font
                // verification code:
                lfDlg = *lplf;
                MessageBox (GetFocus(),
                    "Unable to re-create font from TextMetrics",
                    "FontView", MB_OK);
            }
            break;

        case IDCANCEL:
            EndDialog(hwnd, TRUE);
            return (TRUE);

        }
        break;
    }
    return (FALSE);

    // Just For Reference
    lParam;
}


//
//  FUNCTION: FillEnumFields()
//
//  PURPOSE: fills in TEXTMETRIC and LOGFONT info in the corresponding edit controls
//

BOOL FillEnumFields(HWND hwnd, int iType, LPTEXTMETRIC ptm, LPLOGFONT plf, int nBase)
{
    SetDlgItemValue (hwnd, TMD_HEIGHT, (int)ptm->tmHeight, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_ASCENT, (int)ptm->tmAscent, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_DESCENT, (int)ptm->tmDescent, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_INTERNAL, (int)ptm->tmInternalLeading, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_EXTERNAL, (int)ptm->tmExternalLeading, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_AVEWIDTH, (int)ptm->tmAveCharWidth, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_MAXWIDTH, (int)ptm->tmMaxCharWidth, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_WEIGHT, (int)ptm->tmWeight, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_ITALIC, (int)ptm->tmItalic, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_UNDERLINE, (int)ptm->tmUnderlined, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_STRUCKOUT, (int)ptm->tmStruckOut, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_FIRSTCHAR, (int)ptm->tmFirstChar, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_LASTCHAR, (int)ptm->tmLastChar, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_DEFAULTCHAR, (int)ptm->tmDefaultChar, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_BREAKCHAR, (int)ptm->tmBreakChar, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_PITCHANDFAMILY, (int)ptm->tmPitchAndFamily, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_CHARSET, (int)ptm->tmCharSet, FALSE, nBase);
    SetDlgItemValue (hwnd, TMD_OVERHANG, (int)ptm->tmOverhang, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_DIGITIZEDASPECTX, (int)ptm->tmDigitizedAspectX, TRUE, nBase);
    SetDlgItemValue (hwnd, TMD_DIGITIZEDASPECTY, (int)ptm->tmDigitizedAspectY, TRUE, nBase);
    
    SetDlgItemValue (hwnd, CFD_HEIGHT, (int)plf->lfHeight, TRUE, nBase);
    SetDlgItemValue (hwnd, CFD_WIDTH, (int)plf->lfWidth, TRUE, nBase);
    SetDlgItemValue (hwnd, CFD_ESCAPEMENT, (int)plf->lfEscapement, TRUE, nBase);
    SetDlgItemValue (hwnd, CFD_ORIENTATION, (int)plf->lfOrientation, TRUE, nBase);
    SetDlgItemValue (hwnd, CFD_WEIGHT, (int)plf->lfWeight, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_ITALIC, (int)plf->lfItalic, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_UNDERLINE, (int)plf->lfUnderline, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_STRIKEOUT, (int)plf->lfStrikeOut, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_CHARSET, (int)plf->lfCharSet, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_OUTPUTPRECISION, (int)plf->lfOutPrecision, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_CLIPPRECISION, (int)plf->lfClipPrecision, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_QUALITY, (int)plf->lfQuality, FALSE, nBase);
    SetDlgItemValue (hwnd, CFD_PITCHANDFAMILY, (int)plf->lfPitchAndFamily, FALSE, nBase);
    SetDlgItemText(hwnd, CFD_FACENAME, plf->lfFaceName);
    
    SetDlgItemValue (hwnd, ED_TYPE, (int)iType, FALSE, nBase);
    
    return TRUE;
}


//
//  FUNCTION: DrawSample()
//
//  PURPOSE: display a sample of the selected font
//

BOOL DrawSample(HWND hwnd, LPLOGFONT plf)
{
    HFONT hfont, hfontPrev;
    HDC  hdc;
    RECT r;

    hfont = CreateFontIndirect (plf);
    hdc = GetDC (hwnd);
    hfontPrev = SelectObject (hdc, hfont);
    GetWindowRect (hwnd, &r);
    ScreenToClient (hwnd, (LPPOINT)&r.left);
    ScreenToClient (hwnd, (LPPOINT)&r.right);

    Rectangle (hdc, r.left, r.top, r.right, r.bottom);

    InflateRect (&r, -1, -1);
    SetTextAlign (hdc, TA_BOTTOM | TA_CENTER);
    ExtTextOut (hdc, r.left + ((r.right-r.left)/2), r.bottom, ETO_CLIPPED, &r,"AaBbCcDdEe 012345", 17, NULL);

    SelectObject (hdc, hfontPrev);
    DeleteObject (hfont);
    ReleaseDC (hwnd, hdc);
    return TRUE;
}


//
//  FUNCTION: EnumDlgProc()
//
//  PURPOSE: Display a dialog that the user can use to enumerate through
//           all of the fonts in the system. Show him not only all of the
//           metrics for the font, but a sample of the font as well. If the
//           user picks the 'Select' button, then the Metrics of this font
//           will be used for the CreateFont call.
//

BOOL APIENTRY EnumDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    static HANDLE /*TO FONTLIST*/ hFonts;
    static int iLoc=0;
    static int count=0;
    static BOOL bHex = FALSE;
    static LOGFONT *lplf;
    static LOGFONT lfDlg;
    int wmId, i, j;
    HANDLE hInst;
    HWND   hwndItem;
    HDC hdc;
    FARPROC lpEnumFonts;
    LPFONTLIST    pFL;
    LPFONTSTRUCT  pFS;
    char szTmp[80];
    HFONT hfont, hfontPrev;
    BOOL bDone;
    TEXTMETRIC tmTmp;

    switch (msg) {
    case WM_INITDIALOG:
        lplf = (LOGFONT *)lParam;
        lfDlg = *lplf;
        iLoc = 0;
        count = 0;
        bHex = FALSE;
        // First, lets enumerate ALL fonts, and store them in our list
        hFonts = GlobalAlloc (GHND, sizeof(FONTLIST));
        if (hFonts) {

#if defined (_WIN32)
            hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#elif defined (WIN16)
            hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#endif

            lpEnumFonts = MakeProcInstance((FARPROC)DlgEnumFontNames, hInst);
            if (lpEnumFonts) {
                hdc  = GetDC(hwnd);
                // The enumeration function will lock down the handle
                EnumFonts (hdc, NULL, (FONTENUMPROC)lpEnumFonts, (LPARAM)&hFonts);
                // The handle will come back to us properly unlocked
                ReleaseDC(hwnd, hdc);
                FreeProcInstance (lpEnumFonts);
            }
        }
        pFL = (LPFONTLIST)GlobalLock (hFonts);
        if (pFL) {
            pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
            if (pFS) {
                iLoc = 0;
                j = 100;
                for (i=0; i<pFL->count; i++) {
                    if (lstrcmp(lfDlg.lfFaceName, pFS[i].lf.lfFaceName) == 0) {
                        if (abs(lfDlg.lfHeight-pFS[i].lf.lfHeight) < j) {
                            j = abs(lfDlg.lfHeight-pFS[i].lf.lfHeight);
                            iLoc = i;
                        }
                    }
                }
                FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
                hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
                DrawSample (hwndItem, &pFS[iLoc].lf);
                GlobalUnlock (pFL->hList);
            }
            count = pFL->count;
            GlobalUnlock (hFonts);

        }
        // now fill in the dialog values
        wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
        SetWindowText (hwnd, szTmp);
        CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));

        return TRUE;

    case WM_PAINT:
        pFL = (LPFONTLIST)GlobalLock (hFonts);
        if (pFL) {
            pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
            if (pFS) {
                FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
                hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
                DrawSample (hwndItem, &pFS[iLoc].lf);
                GlobalUnlock (pFL->hList);
            }
            GlobalUnlock (hFonts);
        }
        return 0;

    case WM_COMMAND:
#if defined (WIN16)
        wmId = wParam;
#else
        wmId = LOWORD(wParam);
#endif
        switch (wmId) {
            case ED_HEX:
                // Display the data in either Hex mode or Dec mode.
                bHex = !bHex;
                CheckDlgButton (hwnd, wmId, bHex);
                pFL = (LPFONTLIST)GlobalLock (hFonts);
                if (pFL) {
                    pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
                    if (pFS) {
                        FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
                        if (GlobalUnlock (pFL->hList)) {
                            MessageBox (GetFocus(), "In HEX", "Unlock pFL->hList", MB_OK);
                        }
                    }
                    if (GlobalUnlock (hFonts)) {
                        MessageBox (GetFocus(), "In HEX", "Unlock hFonts", MB_OK);
                    }

                }
                break;

            case ED_PREV:
                pFL = (LPFONTLIST)GlobalLock (hFonts);
                if (pFL) {
                    if (iLoc > 0) {
                        iLoc--;
                        pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
                        if (pFS) {
                            FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
                            hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
                            DrawSample (hwndItem, &pFS[iLoc].lf);
                            GlobalUnlock (pFL->hList);
                        }
                    }
                    GlobalUnlock (hFonts);
                }
                wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
                SetWindowText (hwnd, szTmp);
                break;

            case ED_NEXT:
                pFL = (LPFONTLIST)GlobalLock (hFonts);
                if (pFL) {
                    if ((pFL->count-1) > iLoc) {
                        iLoc++;
                        pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
                        if (pFS) {
                            FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
                            hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
                            DrawSample (hwndItem, &pFS[iLoc].lf);
                            GlobalUnlock (pFL->hList);
                        }

                    }
                    GlobalUnlock (hFonts);
                }
                wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
                SetWindowText (hwnd, szTmp);
                break;

            case IDOK:
                // Copy the LOGFONT structure from the enumeration list, into our private LF
                pFL = (LPFONTLIST)GlobalLock (hFonts);
                bDone = FALSE;
                if (pFL) {
                    if ((pFL->count-1) >= iLoc) {
                        pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
                        if (pFS) {
                            lfDlg = pFS[iLoc].lf;

                            // Lets create a font with this new data
                            hfont = CreateFontIndirect (&lfDlg);
                            hdc = GetDC (hwnd);
                            hfontPrev = SelectObject (hdc, hfont);
                            GetTextMetrics (hdc, &tmTmp);

                            // Get the face name
                            GetTextFace    (hdc, sizeof(szTmp), szTmp);
                            SelectObject (hdc, hfontPrev);
                            DeleteObject (hfont);
                            ReleaseDC (hwnd, hdc);

                            // And verify that we did indeed get the same font.
                            bDone = TRUE;
                            bDone = bDone && (pFS[iLoc].tm.tmHeight==tmTmp.tmHeight);
                            bDone = bDone && (pFS[iLoc].tm.tmAscent==tmTmp.tmAscent);
                            bDone = bDone && (pFS[iLoc].tm.tmDescent==tmTmp.tmDescent);
                            bDone = bDone && (pFS[iLoc].tm.tmInternalLeading==tmTmp.tmInternalLeading);
                            bDone = bDone && (pFS[iLoc].tm.tmExternalLeading==tmTmp.tmExternalLeading);
                            bDone = bDone && (pFS[iLoc].tm.tmAveCharWidth==tmTmp.tmAveCharWidth);
                            bDone = bDone && (pFS[iLoc].tm.tmMaxCharWidth==tmTmp.tmMaxCharWidth);
                            bDone = bDone && (pFS[iLoc].tm.tmWeight==tmTmp.tmWeight);
                            bDone = bDone && (pFS[iLoc].tm.tmItalic==tmTmp.tmItalic);
                            bDone = bDone && (pFS[iLoc].tm.tmUnderlined==tmTmp.tmUnderlined);
                            bDone = bDone && (pFS[iLoc].tm.tmStruckOut==tmTmp.tmStruckOut);
                            bDone = bDone && (pFS[iLoc].tm.tmFirstChar==tmTmp.tmFirstChar);
                            bDone = bDone && (pFS[iLoc].tm.tmLastChar==tmTmp.tmLastChar);
                            bDone = bDone && (pFS[iLoc].tm.tmDefaultChar==tmTmp.tmDefaultChar);
                            bDone = bDone && (pFS[iLoc].tm.tmBreakChar==tmTmp.tmBreakChar);
                            bDone = bDone && (pFS[iLoc].tm.tmPitchAndFamily==tmTmp.tmPitchAndFamily);
                            bDone = bDone && (pFS[iLoc].tm.tmCharSet==tmTmp.tmCharSet);

                            // Did it work?
                            if (bDone) {
                                *lplf = lfDlg;
                                //EndDialog(hwnd, TRUE);
                                //return (TRUE);
                            }
                            else {
                                // Again, font verification code is'nt quite up to
                                // snuff yet, so just Select the font anyway:
                                *lplf = lfDlg;
            
                                // ...and this is what we want to do once we fix the
                                // font verification code:
                                //lfDlg = *lplf;
                                //MessageBox (GetFocus(),
                                //    "Unable to re-create font from TextMetrics",
                                //    "FontView", MB_OK);
                            }
                            GlobalUnlock (pFL->hList);
                        }
                    }
                    GlobalUnlock (hFonts);
                }

                // Now set our master lf to this value. This way, we 'could' verify that the
                // LOGFONT structure will in fact select this particular font, we just aren't yet
                // *lplf = lfDlg;

                pFL = (LPFONTLIST)GlobalLock (hFonts);
                if (pFL) {
                    if (GlobalFree (pFL->hList))
                        MessageBox (GetFocus(), "Failed To Free", "pFL->hList", MB_OK);
                    else {
                        GlobalUnlock (hFonts);
                        if (GlobalFree (hFonts))
                            MessageBox (GetFocus(), "Failed To Free", "hFonts", MB_OK);
                    }
                }
                EndDialog(hwnd, TRUE);
                return (bDone);

            case IDCANCEL:
                pFL = (LPFONTLIST)GlobalLock (hFonts);
                if (pFL) {
                    if (GlobalFree (pFL->hList))
                        MessageBox (GetFocus(), "Failed To Free", "pFL->hList", MB_OK);
                    else {
                        GlobalUnlock (hFonts);
                        if (GlobalFree (hFonts))
                            MessageBox (GetFocus(), "Failed To Free", "hFonts", MB_OK);
                    }
                }
                EndDialog(hwnd, TRUE);
                return (TRUE);
            }
            break;
    }
    return (FALSE);

    lParam; // unreferenced formal parameter
}
