/* font2.cpp   Use a new font, add edit caret, & use keyboard accelerator table */

#include <windows.h>
#include "font2.h"

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
    int nCmdShow)
{
    HWND        hWnd ;      /* the window's "handle" */
    MSG         msg ;       /* a message structure */
    WNDCLASS    wndclass ;  /* window class structure */
    HANDLE      hAccel ;    /* handle to the accelerator table */

        wndclass.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
        wndclass.lpfnWndProc    = WndProc ;
        wndclass.cbClsExtra     = 0 ;
        wndclass.cbWndExtra     = 0 ;
        wndclass.hInstance      = hInstance ;
        wndclass.hIcon          = NULL ;
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW) ;
        wndclass.hbrBackground  = GetStockObject (WHITE_BRUSH) ;
        wndclass.lpszMenuName   = "MYMENU" ;
        wndclass.lpszClassName  = "MyClass" ;
                        /* register the window class */
        if (!RegisterClass (&wndclass))
            return 0 ;
 
    hWnd = CreateWindow ("MyClass","Type Something!", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,  CW_USEDEFAULT,  CW_USEDEFAULT,  CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL) ;
    ShowWindow (hWnd, nCmdShow) ;   /* display the window */
    UpdateWindow (hWnd) ;

    hAccel = LoadAccelerators (hInstance, "MYACCEL") ;  /* load accel. table */

    while (GetMessage (&msg, NULL, 0, 0))   /* message loop */
    {
        if (!TranslateAccelerator (hWnd, hAccel, &msg)) /* translate accel. */
        {
            TranslateMessage (&msg) ;   /* translate keyboard messages */
            DispatchMessage (&msg) ;    /* send message to WndProc() */
        }
    }
    return (msg.wParam) ;
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT wMessage, 
                                   WPARAM wParam, LPARAM lParam)
{
    static  char    cBuf [LINELONG] ;
    static  int     nCurPos = 0 ;
    PAINTSTRUCT     ps ;
    HDC             hDC ;
    static  HFONT   hFont ;
    static  int     nFontChoice = IDM_SWISS, nXCaret = 0, nYCaret = 0,
                    nCaretTall, nCaretWide, nClientWide  ;
    TEXTMETRIC      tm ;
        SIZE            size; 


    switch (wMessage)                       /* process windows messages */
    {
        case WM_CREATE:
            hFont = CreateFont (36, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
                OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                VARIABLE_PITCH | FF_SWISS, "Swiss") ;
            break ;
        case WM_COMMAND:
            switch (LOWORD(wParam))     /* menu items and/or accelerators */
            {
                case IDM_NOMENU:        /* keyboard accelerator, not menu item */
                    MessageBox (hWnd, "Got IDM_NOMENU WM_COMMAND message.",
                        "Accelerator Only", MB_OK) ;
                    break ;
                case IDM_ANSI:          /* remember font choice */
                    nFontChoice = IDM_ANSI ;
                    InvalidateRect (hWnd, NULL, TRUE) ; /* force WM_PAINT */
                    break ;
                case IDM_OEM:
                    nFontChoice = IDM_OEM ;
                    InvalidateRect (hWnd, NULL, TRUE) ; /* force WM_PAINT */
                    break ;
                case IDM_SWISS:
                    nFontChoice = IDM_SWISS ;
                    InvalidateRect (hWnd, NULL, TRUE) ; /* force WM_PAINT */
                    break ;
                case IDM_QUIT:
                    DestroyWindow (hWnd) ;  /* destroy window, */
                    break ;                 /* terminating application */
            }
            break ;
        case WM_PAINT:
            hDC = BeginPaint (hWnd, &ps) ;
            SetTextColor (hDC, RGB (0, 0, 255)) ;    /* blue letters */
            switch (nFontChoice)
            {                               /* select a font into DC */
                case IDM_ANSI:
                    SelectObject (hDC, GetStockObject (ANSI_VAR_FONT)) ;
                    break ;
                case IDM_OEM:
                    SelectObject (hDC, GetStockObject (OEM_FIXED_FONT)) ;
                    break ;
                case IDM_SWISS:
                    SelectObject (hDC, hFont) ;
                    break ;
            }
            GetTextMetrics (hDC, &tm) ;     /* get font height to size caret */
            nCaretTall = tm.tmHeight + tm.tmExternalLeading ;
                                    /* window border width * 2 = caret width */
            nCaretWide = 2 * GetSystemMetrics (SM_CXBORDER) ;
            DestroyCaret () ;
            CreateCaret (hWnd, NULL, nCaretWide, nCaretTall) ;
                                    /* get width of string to position caret */
            GetTextExtentPoint32 (hDC, cBuf, lstrlen (cBuf), &size) ;
            nXCaret = size.cx ;
            SetCaretPos (nXCaret, nYCaret) ;
            TextOut (hDC, 0, 0, cBuf, lstrlen (cBuf)) ;
            EndPaint (hWnd, &ps) ;
            break ;
        case WM_CHAR:                           /* char input */
            if (nCurPos < LINELONG &&           /* or punctuation */
                (IsCharAlphaNumeric ((char) wParam) || IsAnsiPunc ((char) wParam)))
            {
                cBuf [nCurPos++] = (char) wParam ;  /* add new letter */
                cBuf [nCurPos] = 0 ;                /* null term. string */
                InvalidateRect (hWnd, NULL, TRUE) ; /* force WM_PAINT */
            }
            break ;
        case WM_KEYDOWN:                        /* non ANSI key input */
            switch (wParam)
            {
                case VK_BACK:                   /* backspace key */
                    if (nCurPos > 0)
                    {
                        nCurPos-- ;            /* back up one char */
                        cBuf [nCurPos] = 0 ;   /* replace with null */
                        InvalidateRect (hWnd, NULL, TRUE) ;
                    }
            }
            break ;
        case WM_SETFOCUS:                       /* window gained focus */
            CreateCaret (hWnd, NULL, nCaretWide, nCaretTall) ;
            SetCaretPos (nXCaret, nYCaret) ;
            break ;
        case WM_KILLFOCUS:                      /* window lost focus */
            DestroyCaret () ;
            break ;
        case WM_DESTROY:                        /* stop application */
            DeleteObject (hFont) ;              /* remove font from memory */
            PostQuitMessage (0) ;
            break ;
        default:        /* default windows message processing */
            return DefWindowProc (hWnd, wMessage, wParam, lParam) ;
    }
    return (0) ;
}

BOOL IsAnsiPunc (WORD wChar)    /* returns true if wChar is punctuation char */
{
    if ((wChar >= ' ' && wChar <= '@') || (wChar >= '[' && wChar <= '`') ||
        (wChar >= '{' && wChar <= '~') || (wChar >= 0xA0 && wChar <= 0xBF))
        return (TRUE) ;
    else
        return (FALSE) ;
}