/*
worm.c
copyright 1989, Sarmad Adnan, adnan@rice.edu
copyright 1990, Sarmad Adnan, adnan@rice.edu
*/

#include <windows.h>
#include <math.h>
#include "worm.h"



HANDLE hInst;
HDC    screen;
POINT  segm[MAXSEG];
short  head= -1, tail=MAXSEG;
RECT   wormcage;


int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;


if(hPrevInstance)
    {
    MessageBox(NULL, "worm: your screen is already wormed", "Error", MB_OK);
    return(NULL);
    }

if(!WormInit(hInstance))
    {
    MessageBox(NULL, "Worm: class registration failed", "Error", MB_OK);
    return(NULL);
    }

hInst = hInstance;

hWnd = CreateWindow(
		WORM_APPNAME,
		WORM_TITLE,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0,
		0,
		NULL,
		NULL,
		hInstance,
		NULL
		);

if(!hWnd)
    {
    MessageBox(NULL, "worm: could not create window", "Error", MB_OK);
    return (NULL);
    }

if(!GetScreenSize())
    {
    MessageBox(hWnd, "worm: could not obtain screen handle", "Error", MB_OK);
    return(NULL);
    }

if(!SetTimer(hWnd, NULL, 200, NULL) )
    {
    MessageBox(hWnd, "worm: no timers available", "Error", MB_OK);
    return(NULL);
    }

ShowWindow(hWnd, SW_MINIMIZE);
UpdateWindow(hWnd);

while( GetMessage( &msg, NULL, NULL, NULL) )
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
return(msg.wParam);
}


BOOL WormInit(HANDLE hInstance)
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;

hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);

pWndClass->style = NULL;
pWndClass->lpfnWndProc = WormWndProc;
pWndClass->hInstance = hInstance;
pWndClass->hIcon = LoadIcon(hInstance, "worm");
pWndClass->hCursor = LoadCursor(NULL, IDC_CROSS);
pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
pWndClass->lpszMenuName = (LPSTR) NULL;
pWndClass->lpszClassName = (LPSTR) WORM_APPNAME;
bSuccess = RegisterClass(pWndClass);
LocalUnlock(hMemory);
LocalFree(hMemory);

return(bSuccess);
}






long FAR PASCAL WormWndProc(HWND hWnd, unsigned message, WORD wParam, LONG lParam)
{
FARPROC lpProcAbout;
HMENU hMenu;

switch(message) 
    {
    case WM_TIMER:
        WormUpdate(hWnd);
        break;
    case WM_SIZE:
        InvalidateRect(hWnd, NULL, TRUE);
        break;
    case WM_SYSCOMMAND:
        if(wParam == ID_ABOUT)
            {
            lpProcAbout = MakeProcInstance(About, hInst);
            DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
            FreeProcInstance(lpProcAbout);
            break;
	    }
        else
            return(DefWindowProc(hWnd, message, wParam, lParam));
    case WM_CREATE:
        hMenu = GetSystemMenu(hWnd, FALSE);
        ChangeMenu(hMenu, NULL, NULL, NULL, MF_APPEND | MF_SEPARATOR);
        ChangeMenu(hMenu, NULL, "A&bout Worm...", ID_ABOUT, MF_APPEND | MF_STRING);
        break;
    case WM_QUERYOPEN:
        return 0L;
    case WM_DESTROY:
        KillTimer(hWnd, NULL);
        DeleteDC(screen);
        PostQuitMessage(0);
        break;
    default:
        return (DefWindowProc(hWnd, message, wParam, lParam));
    }
return(NULL);
}


BOOL FAR PASCAL About(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
switch(message)
    {
    case WM_INITDIALOG:
        return (TRUE);
    case WM_COMMAND:
        if (wParam == IDOK) 
            {
            EndDialog(hDlg, NULL);
            return (TRUE);
	    }
        break;
    }
return(FALSE);
}



void WormUpdate(HWND hWnd)
{
HDC    hDc;
static double dir=0.0;
POINT  prev;


if(rand()<16384)
    dir+=INCREMENT;
else
    dir-=INCREMENT;


prev.x=segm[head].x;
prev.y=segm[head].y;
head--, tail--;
if(head<0) head=MAXSEG-1;
if(tail<0) tail=MAXSEG-1;

Ellipse(screen, segm[head].x-SIZE, segm[head].y-SIZE, segm[head].x+SIZE, segm[head].y+SIZE);
segm[head].x=prev.x+(int)(STEPSIZE*cos(dir));
segm[head].y=prev.y+(int)(STEPSIZE*sin(dir));
if(segm[head].x<wormcage.left)
    segm[head].x=wormcage.right-1;
if(segm[head].x>wormcage.right)
    segm[head].x=wormcage.left;
if(segm[head].y<wormcage.top)
    segm[head].y=wormcage.bottom-1;
if(segm[head].y>wormcage.bottom)
    segm[head].y=wormcage.top;

Ellipse(screen, segm[head].x-SIZE, segm[head].y-SIZE, segm[head].x+SIZE, segm[head].y+SIZE);
}



BOOL GetScreenSize()
{
POINT extent;
DWORD test;
int count;

screen=CreateDC("DISPLAY", NULL, NULL, NULL);
if(!screen)
    return(FALSE);

wormcage.right=GetDeviceCaps(screen, HORZRES);
wormcage.bottom=GetDeviceCaps(screen, VERTRES);

wormcage.top=0;
wormcage.left=0;

for(count=0; count<MAXSEG; count++)
    {
    segm[count].x=0;
    segm[count].y=0;
    }

SelectObject(screen, GetStockObject(BLACK_BRUSH) );
SetROP2(screen, R2_NOTXORPEN);
SelectObject(screen, GetStockObject(BLACK_PEN) );

return(TRUE);
}

