/***********************************************************************
 * This program was originally written by Michael Harrison [76057,101] *
 * The only problem with the original that I could see was that it was *
 * somewhat of a memory hog.  The burst bitmap that gets popped up on  *
 * the screen was reloaded every time a burst was supposed to pop up.  *
 * Thus, the GDI ended up with about 100 copies of the bitmap (more if *
 * the user let it run after it asked if that was enough).  Even though*
 * this program is kinder to the victim in that it removes itself from *
 * memory after the user terminates it, only the last bitmap was       *
 * removed from the GDI resource pool.  I've cleaned this up a bit.    *
 * Perri Nelson [71401,2116]                                           *
 ***********************************************************************/
/*** Include files needed for definitions, declarations, etc.         ***/
#include <windows.h>  /* Required for all Windows programs              */
#include <stdlib.h>

/*** Forward declare functions                                        ***/
long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG);
void FAR PASCAL TimerProc(HWND, unsigned, WORD, LONG);

HANDLE    hInst;

    /* Moved from WndProc to make available to WinMain as well */
    static HANDLE hBitmap;


int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
    HANDLE      hInstance, hPrevInstance;
    LPSTR       lpszCmdLine;
    int         nCmdShow;
    {
    HWND        hWnd;
    MSG         msg;
    WNDCLASS    wndclass;
    FARPROC     lpfnTimerProc;

    if (!hPrevInstance)
        {
        wndclass.style          = CS_HREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = NULL;
        wndclass.hCursor        = LoadCursor (hInstance, IDC_ARROW);
        wndclass.hbrBackground  = GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = "Burst";

    if (!RegisterClass (&wndclass) )
        return FALSE;
        }
    else
        return FALSE;

    hInst=hInstance;
    hWnd = CreateWindow ("Burst", "Burst", WS_OVERLAPPEDWINDOW, 0, 0,
                        0,0, NULL, NULL, hInstance, NULL);

    lpfnTimerProc = MakeProcInstance( TimerProc, hInstance );

    if(!SetTimer(hWnd, 1, 60000, lpfnTimerProc))
        {
        MessageBox(hWnd, "Too many clocks or timers!", "Burst",
                   MB_ICONEXCLAMATION | MB_OK);
        return FALSE;
        }
                /* Moved from WndProc to make more memory efficient */
                hBitmap=LoadBitmap(hInst, "Burst");

    while (GetMessage(&msg, NULL, 0,0 ))
        {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        }
    return msg.wParam;
    }

long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
    HWND          hWnd;
    unsigned      iMessage;
    WORD          wParam;
    LONG          lParam;
    {
    BITMAP        bm;
    HDC           hDC,hMemDC;
    short         nRand;
    long          xStart, yStart;
    static char   cJunk=0;
    unsigned int  nIndex;
    static int    nNoise=0;


    switch (iMessage)
        {
        case WM_TIMER:
            if(rand() < 2000)
                {

                GetObject(hBitmap, sizeof(BITMAP), (LPSTR) &bm);

                hDC=CreateDC("DISPLAY", NULL, NULL, NULL);
                hMemDC=CreateCompatibleDC(hDC);
                SelectObject(hMemDC, hBitmap);

                xStart=rand() % GetSystemMetrics(SM_CXSCREEN);
                yStart=rand() % GetSystemMetrics(SM_CYSCREEN);
                BitBlt(hDC, (short)xStart, (short)yStart, bm.bmWidth, bm.bmHeight,
                       hMemDC, 0,0, SRCAND);

                DeleteDC(hDC);
                DeleteDC(hMemDC);

                OpenSound();
                StopSound();
                SetSoundNoise(nNoise++, 100);
                StartSound();
                for (nIndex=0; nIndex < 65535; nIndex++); /* pause      */
                StopSound();

                if ( cJunk == 100 ) {
                    cJunk = 0;
                    KillTimer( hWnd, 1 );
                    if ( MessageBox( hWnd, "Had enough?", "Burst by MSH",MB_YESNO | MB_ICONQUESTION ) == IDYES )
                        SendMessage( hWnd, WM_CLOSE, 0, 0L );
                    else
                        if(!SetTimer(hWnd, 1, 100, NULL))
                        {
                            MessageBox(hWnd, "Too many clocks or timers!", "Error",
                            MB_ICONEXCLAMATION | MB_OK);
                        }
                }
                else
                    cJunk++;
                }

            break;

        case WM_CREATE:
            OpenSound();
            srand((unsigned)GetTickCount());
            break;

        case WM_DESTROY:
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            CloseSound();
            StopSound();
            KillTimer( hWnd, 1 );
            break;

        default:
            return (DefWindowProc(hWnd, iMessage, wParam, lParam));
        }
    return 0L;
}


void FAR PASCAL TimerProc( hWnd, iMessage, wParam, lParam )
    HWND hWnd;
    unsigned iMessage;
    WORD wParam;
    long lParam;
{
    KillTimer( hWnd, 1 );
    if(!SetTimer(hWnd, 1, 50, NULL))
    {
        MessageBox(hWnd, "Too many clocks or timers!", "Error",
           MB_ICONEXCLAMATION | MB_OK);
        SendMessage( hWnd, WM_CLOSE, 0, 0L );
    }
}
