/* Fader.c
   source for Fader/Dissolve style controls

    Copyright 1990 by William R. Ross
*/

#include "windows.h"
#define FADER_MAIN
#include "fader.h"
#include <sys\types.h> /* for ftime() */
#include <sys\timeb.h> /* ditto */

#define FCN

static void FadeIn ();
static void Dissolve ();
static void FadeOut ();
static void Wait ();

/******************************************
* FaderInit ()
* registers Fader window class
*
*******************************************/
FCN BOOL FaderInit( hInstance )
HANDLE hInstance;
{
    PWNDCLASS   pClass;
 
    pClass = (PWNDCLASS)LocalAlloc( LPTR, sizeof(WNDCLASS) );

    /* this is the class for the FADER control */
    pClass->hCursor        = LoadCursor( NULL, IDC_ARROW );
    pClass->hIcon          = NULL;
    pClass->lpszMenuName   = (LPSTR)NULL;
    pClass->hbrBackground  = (HBRUSH)GetStockObject( WHITE_BRUSH );
    pClass->hInstance      = hInstance;
    pClass->style          = CS_HREDRAW | CS_VREDRAW;
    /* here's the interesting parts of the class... */
    pClass->lpfnWndProc    = FaderWndProc;
    pClass->lpszClassName  = (LPSTR)"FADER";
 
    if (!RegisterClass( (LPWNDCLASS)pClass ) )
        /* Initialization failed.
         * Windows will automatically deallocate all allocated memory.
         */
        return FALSE;
 
    LocalFree( (HANDLE)pClass );
    return TRUE;        /* Initialization succeeded */
} /* end of FaderInit */
 
/***************************************************
* FadeIn ()
* 
*
***************************************************/
FCN void FadeIn (hWnd, lpszText)
HWND hWnd;
LPSTR lpszText;
{
    HDC hDC, hMemDC;
    HBITMAP hBM;
    RECT rect;
    int nWidth, nHeight;
    int i;

    GetClientRect (hWnd, &rect);
    nWidth = rect.right - rect.left;
    nHeight = rect.bottom - rect.top;

    hDC = GetDC (hWnd);
    hMemDC = CreateCompatibleDC (hDC);
    hBM = CreateCompatibleBitmap (hDC, nWidth, nHeight);

    SelectObject (hMemDC, hBM);
    PatBlt (hMemDC, 0, 0, nWidth, nHeight, WHITENESS);
    DrawText (hMemDC, (LPSTR)lpszText, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDC, GetStockObject(LTGRAY_BRUSH));
    PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
    Wait(47);

     DrawText (hMemDC, (LPSTR)lpszText, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SelectObject(hMemDC, GetStockObject(GRAY_BRUSH));
     PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
     BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
    Wait(47);

     DrawText (hMemDC, (LPSTR)lpszText, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SelectObject(hMemDC, GetStockObject(DKGRAY_BRUSH));
     PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
     BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
     Wait(47);

     DrawText (hMemDC, (LPSTR)lpszText, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SelectObject(hMemDC, GetStockObject(BLACK_BRUSH));
     PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
     BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);


     DeleteDC (hMemDC);
     DeleteObject (hBM);
     ReleaseDC(hWnd, hDC);

    SetWindowText (hWnd, (LPSTR)lpszText);
} /* end of FadeIn */

/***************************************************
* Dissolve ()
* 
*
***************************************************/
FCN void Dissolve (hWnd, lpszNew, szOld)
HWND hWnd;
LPSTR lpszNew;
char *szOld;
{
    HDC hDC, hMemDCOld, hMemDCNew;
    HBITMAP hBMOld, hBMNew;
    RECT rect;
    int nWidth, nHeight;
    unsigned int i;

    GetClientRect (hWnd, &rect);
    nWidth = rect.right - rect.left;
    nHeight = rect.bottom - rect.top;

    hDC = GetDC (hWnd);
    hMemDCOld = CreateCompatibleDC (hDC);
    hMemDCNew = CreateCompatibleDC (hDC);
    hBMOld = CreateCompatibleBitmap (hDC, nWidth, nHeight);
    hBMNew = CreateCompatibleBitmap (hDC, nWidth, nHeight);

    SelectObject (hMemDCOld, hBMOld);
    SelectObject (hMemDCNew, hBMNew);
    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, WHITENESS);
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, WHITENESS);

    DrawText (hMemDCOld, (LPSTR)szOld, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCOld, GetStockObject(DKGRAY_BRUSH));
    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    DrawText (hMemDCNew, (LPSTR)lpszNew, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCNew, GetStockObject(LTGRAY_BRUSH));
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    BitBlt (hMemDCOld, 0, 0, nWidth, nHeight, hMemDCNew, 0, 0, (DWORD)0x8800C6);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDCOld, 0, 0, SRCCOPY);
    Wait(55);

    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, WHITENESS);
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, WHITENESS);

    DrawText (hMemDCOld, (LPSTR)szOld, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCOld, GetStockObject(GRAY_BRUSH));
    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    DrawText (hMemDCNew, (LPSTR)lpszNew, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCNew, GetStockObject(GRAY_BRUSH));
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    BitBlt (hMemDCOld, 0, 0, nWidth, nHeight, hMemDCNew, 0, 0, (DWORD)0x8800C6);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDCOld, 0, 0, SRCCOPY);
    Wait(55);

    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, WHITENESS);
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, WHITENESS);

    DrawText (hMemDCOld, (LPSTR)szOld, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCOld, GetStockObject(LTGRAY_BRUSH));
    PatBlt (hMemDCOld, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    DrawText (hMemDCNew, (LPSTR)lpszNew, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDCNew, GetStockObject(DKGRAY_BRUSH));
    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    BitBlt (hMemDCOld, 0, 0, nWidth, nHeight, hMemDCNew, 0, 0, (DWORD)0x8800C6);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDCOld, 0, 0, SRCCOPY);
    Wait(55);

    PatBlt (hMemDCNew, 0, 0, nWidth, nHeight, WHITENESS);

    DrawText (hMemDCNew, (LPSTR)lpszNew, -1, &rect,
             DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDCNew, 0, 0, SRCCOPY);

    DeleteDC (hMemDCOld);
    DeleteDC (hMemDCNew);
    DeleteObject (hBMOld);
    DeleteObject (hBMNew);
    ReleaseDC(hWnd, hDC);

    SetWindowText (hWnd, (LPSTR)lpszNew);
} /* end of Dissolve */

/***************************************************
* FadeOut ()
* 
*
***************************************************/
FCN void FadeOut (hWnd, szOld)
HWND hWnd;
char *szOld;
{
    HDC hDC, hMemDC;
    HBITMAP hBM;
    RECT rect;
    int nWidth, nHeight;
    int i;

    GetClientRect (hWnd, &rect);
    nWidth = rect.right - rect.left;
    nHeight = rect.bottom - rect.top;

    hDC = GetDC (hWnd);
    hMemDC = CreateCompatibleDC (hDC);
    hBM = CreateCompatibleBitmap (hDC, nWidth, nHeight);

    SelectObject (hMemDC, hBM);
    PatBlt (hMemDC, 0, 0, nWidth, nHeight, WHITENESS);
    DrawText (hMemDC, (LPSTR)szOld, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    SelectObject(hMemDC, GetStockObject(DKGRAY_BRUSH));
    PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
    BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
    Wait(47);

     DrawText (hMemDC, (LPSTR)szOld, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SelectObject(hMemDC, GetStockObject(GRAY_BRUSH));
     PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
     BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
    Wait(47);

     DrawText (hMemDC, (LPSTR)szOld, -1, &rect,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SelectObject(hMemDC, GetStockObject(LTGRAY_BRUSH));
     PatBlt (hMemDC, 0, 0, nWidth, nHeight, (DWORD)0xFA0089);
     BitBlt (hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
    Wait(47);

    PatBlt (hDC, 0, 0, nWidth, nHeight, WHITENESS);

     DeleteDC (hMemDC);
     DeleteObject (hBM);
     ReleaseDC(hWnd, hDC);

    SetWindowText (hWnd, (LPSTR) '\0');
} /* end of FadeOut */

/***************************************************
* FaderWndProc ()
* window procedure for fader control
*
***************************************************/
FCN long FAR PASCAL FaderWndProc( hWnd, message, wParam, lParam )
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
    char szText [80];
    HDC hDC, hMemDC;
    HBITMAP hBM;
    RECT rect;

    switch (message)
    {
    case WM_FADER:
        GetWindowText (hWnd, szText, sizeof(szText));

        /* lParam is new text, szText is current text */
        if (!lParam && !szText)
            break; /* nothing to do */

        else if (lParam && !szText)
            FadeIn (hWnd, (LPSTR)lParam);

        else if (lParam && szText)
            Dissolve(hWnd, (LPSTR)lParam, szText);

        else if (!lParam && szText)
            FadeOut(hWnd, szText);

        break;

    case WM_PAINT:
        GetClientRect (hWnd, &rect);
        GetWindowText (hWnd, szText, sizeof(szText));
        hDC = GetDC (hWnd);
        DrawText (hDC, szText, -1, &rect,
                 DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        ReleaseDC (hWnd, hDC);
        ValidateRect (hWnd, (LPRECT)NULL);
        break;

    default:
        return DefWindowProc( hWnd, message, wParam, lParam );
        break;
    } /* switch */

    return(0L);
} /* end of FaderWndProc */

/***************************************************
* Wait ()
* wait for "interval" number of milliseconds
* use only for small intervals < 1000 ms
***************************************************/
FCN void Wait (int interval)
{
    struct timeb timebuffer;
    unsigned short startMS;

    ftime (&timebuffer);
    startMS = timebuffer.millitm;
    while (TRUE)
        {
        ftime (&timebuffer);
        if (startMS > timebuffer.millitm)
            timebuffer.millitm += 1000;

        if ((timebuffer.millitm - startMS) > interval)
            break;
        } /* while */

} /* end of Wait */
