

/*
 * I. ARIT 1992 Hidirbeyli,AYDIN,TR.  09400 Golden,    CO,   USA. 80401 
 *
 *
 * Copyright (C) 1992 Ismail ARIT 
 *
 * This file is distributed in the hope that it will be useful,but without any
 * warranty.  No author or distributor accepts responsibility to anyone for
 * the consequences of using it or for whether it serves any particular
 * purpose or works at all. 
 *
 *
 * Everyone is granted permission to copy, modify and redistribute this file
 * under the following conditions: 
 *
 * Permission is granted to anyone to make or distribute copies of the source
 * code, either as received or modified, in any medium, provided that all
 * copyright notices, permission and nonwarranty notices are preserved, and
 * that the distributor grants the recipient permission for further
 * redistribution as permitted by this document. 
 *
 * No part of this program can be used in any commercial product. 
 */






#include <windows.h>
#include <commdlg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <math.h>

#include "definiti.h"




int             xClient = 550, yClient = 400;
int             xStart = 0, yStart = 0;



HANDLE          hInst;		/* hInstance of application */
HWND            hWndMain;	/* hWnd of main window */

HWND  DialogWinHandle;



static char     AppName[20];	/* name of application */

/* at the beginning */
int             WhiteBallOut = NO;
int             BlackBallOut = NO;

int             YourScore = 0, MyScore = 0;
/* these are for stick position */
int             StartX, StartY, NewX, NewY;

Space           PlayGround={72.0,42.0,510.0,320.0};

Timing          PlayTime;

/* this is the big guy, controlling everything */
Coordinator    *Dept_Head;

Stick          *PoolStick;
Stick          *Trajectory;

Ball           *WhiteBall, *BlackBall;
Ball           *DottedWhiteBall;/* we'll use it for 3-ball pool */
Ball           *MyBalls[7];
Ball           *YourBalls[7];

int             gameType, HowManyBalls;
extern int      WantsTrajectory;








int             WLeft = 10, WTop = 10, WRight = 550, WBottom = 400;
int             TableTop = 20, TableLeft = 50;
int             PocDiameter = 40;
int             MouseX, MouseY;
int             LeftButton = FALSE;
int             PressedBefore = FALSE;
int             MouseMessage = FALSE;

HPEN            StickPen;
HPEN            TrajPen;
Stick          *PoolStick;
Stick          *Trajectory;


HBITMAP         MyBitmapHandle;
HBITMAP         BallDel, Balls[16];
HDC             hDCBall[16];
HDC             hDCBallDel;

BITMAP          BitmapDim;




HBRUSH          hbrTable, hbrPocket, hbrSurface;
HPEN            hpenBorder, hpenSurBorder;






int             PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance,
	LPSTR lpszCmdLine, int cmdShow);

void
InitApp(HANDLE hInstance, HANDLE hPrevInstance,
	LPSTR lpszCmdLine, int cmdShow);



long FAR        PASCAL
AppWndProc(HWND hWnd, WORD message,
	   WORD wParam, LONG lParam);

void
BuildTheTable(HDC hDC);

void
MoveTheBall(HDC hdc);


void
LayTheFloor(HDC hdc);
extern Stick   *
new__Stick(int type);




extern int      oldx, oldy, oldxx, oldyy;
extern int      ButtonPressedBefore;
extern int      pane_x, pane_y;
extern 
handle_stick(HDC hdc, int button);
extern void 
handle_white_ball(HDC hdc, int button);

extern void     MainSetup();


/* file open dialog */
char            szDirName[256];
char            szFile[256], szFileTitle[256];
UINT            i, cbString;
char            chReplace;	/* string separator for szFilter */
char            szFilter[256];
HFILE           hf;
OPENFILENAME    ofn;
FILE *filehandle;


extern BOOL FAR PASCAL 
PlayersHandleDlgProc(HWND hDlg, WORD iMessage, WORD wParam, LONG lParam);
extern int 
GetPlayersName(HANDLE hinst, HWND hwnd);

extern TwoPlayer My;


extern BOOL FAR PASCAL
ScoresHandleDlgProc(HWND hDlg, WORD iMessage, WORD wParam, LONG lParam);
extern int
GetScores(HANDLE hinst, HWND hwnd);











int             PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance,
	LPSTR lpszCmdLine, int cmdShow)
{
	MSG             msg;
	/* this is the name of the application */
	strcpy(AppName, "Win Pool");

	hInst = hInstance;	/* init this application. */
	InitApp(hInstance, hPrevInstance, lpszCmdLine, cmdShow);

	/* Get and dispatch messages for this applicaton. */

	while (GetMessage(&msg, NULL, 0, 0)) {
	 if(DialogWinHandle==NULL || !IsDialogMessage(DialogWinHandle,&msg)){

		TranslateMessage(&msg);
		DispatchMessage(&msg);
		    }
	}


	return (msg.wParam);
}



void
InitApp(HANDLE hInstance, HANDLE hPrevInstance,
	LPSTR lpszCmdLine, int cmdShow)
{
	WNDCLASS        wcAppClass;

	if (!hPrevInstance) {	/* if no previous instance, this is first */
		/* Define the window class for this application. */
		wcAppClass.lpszClassName = (LPSTR) AppName;
		wcAppClass.hInstance = hInstance;
		wcAppClass.lpfnWndProc = AppWndProc;
		wcAppClass.hCursor = LoadCursor(NULL, IDC_ARROW);
		wcAppClass.hIcon = LoadIcon(hInstance, "Pool");
		wcAppClass.lpszMenuName = NULL ;  /*"POOL";   */
		wcAppClass.hbrBackground = GetStockObject(WHITE_BRUSH);
		wcAppClass.style = CS_HREDRAW | CS_VREDRAW;
		wcAppClass.cbClsExtra = 0;
		wcAppClass.cbWndExtra = 0;

		/* Register the class */
		RegisterClass(&wcAppClass);
	}
	/* Create applications main window. */
	hWndMain = CreateWindowEx(0L,
				AppName,
				AppName,
				WS_OVERLAPPEDWINDOW,
				CW_USEDEFAULT,
				0,
				550,
				410,
				NULL,
				NULL,
				hInstance,
				NULL
		);

	/* Update display of main window. */
	ShowWindow(hWndMain, cmdShow);
	UpdateWindow(hWndMain);
}


float           XXX, YYY;
int             tx, ty;
LPARAM          lParaM;

	FARPROC         lpfnHandleDlgProc;


      extern	BOOL FAR PASCAL FloatHandleDlgProc(HWND hDlg, WORD iMessage, WORD wParam, LONG lParam);





long FAR        PASCAL
AppWndProc(HWND hWnd, WORD message,
	   WORD wParam, LONG lParam)
{
	HDC             hDC;
	PAINTSTRUCT     ps;
	int             i;



	switch (message) {



	case WM_CREATE:


	lpfnHandleDlgProc = MakeProcInstance(FloatHandleDlgProc, hInst);

	DialogWinHandle = CreateDialog(hInst, "FLOATDIALOG", hWnd, lpfnHandleDlgProc);

	 ShowWindow(DialogWinHandle,SW_SHOW);



		strcpy(My.Player1String, "Player I");
		strcpy(My.Player2String, "Player II");


		MainSetup();


		hDC = GetDC(hWnd);

		PoolStick = new__Stick(STICK);
		Trajectory = new__Stick(TRAJECTORY);

		MyBitmapHandle = LoadBitmap(hInst, "Tile");

		BallDel = LoadBitmap(hInst, "BALLDEL");
		hDCBallDel = CreateCompatibleDC(hDC);
		SelectObject(hDCBallDel, BallDel);

		/* load other bitmaps here too */
		Balls[0] = LoadBitmap(hInst, "BALL0");
		Balls[1] = LoadBitmap(hInst, "BALL8");
		Balls[2] = LoadBitmap(hInst, "BALL2");
		Balls[3] = LoadBitmap(hInst, "BALL3");
		Balls[4] = LoadBitmap(hInst, "BALL4");
		Balls[5] = LoadBitmap(hInst, "BALL5");
		Balls[6] = LoadBitmap(hInst, "BALL6");
		Balls[7] = LoadBitmap(hInst, "BALL7");
		Balls[8] = LoadBitmap(hInst, "BALL1");
		Balls[9] = LoadBitmap(hInst, "BALL9");
		Balls[10] = LoadBitmap(hInst, "BALL10");
		Balls[11] = LoadBitmap(hInst, "BALL11");
		Balls[12] = LoadBitmap(hInst, "BALL12");
		Balls[13] = LoadBitmap(hInst, "BALL13");
		Balls[14] = LoadBitmap(hInst, "BALL14");
		Balls[15] = LoadBitmap(hInst, "BALL15");



		/* create space to put bitmaps */
		for (i = 0; i < 16; i++) {
			hDCBall[i] = CreateCompatibleDC(hDC);
			SelectObject(hDCBall[i], Balls[i]);

		}

		/* get the size of a bitmap */
		GetObject(Balls[1], sizeof(BITMAP), &BitmapDim);



		StickPen = CreatePen(PS_SOLID, 3, RGB(255, 255, 255));
		TrajPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));


		/* trying to get blue */
		hbrTable = CreateSolidBrush(RGB(0, 126, 255));
		hpenBorder = CreatePen(PS_SOLID, 6, RGB(255, 0, 0));

		/* let's change the brush */
		hbrPocket = CreateSolidBrush(RGB(0, 0, 0));

		hbrSurface = CreateSolidBrush(RGB(0, 0, 255));

		hpenSurBorder = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));



		/*
		 * PoolTable.left = TableLeft; PoolTable.top  = TableTop;
		 * PoolTable.bottom = WRight-20; PoolTable.right =
		 * WBottom-20; 
		 *
		 */
		Dept_Head->InitConfig(Dept_Head, hDC);

		ReleaseDC(hWnd, hDC);

		break;



	case WM_PAINT:


		BeginPaint(hWnd, (LPPAINTSTRUCT) & ps);
		hDC = ps.hdc;
		BuildTheTable(hDC);

		for (i = 0; i < Dept_Head->NumberOfObjects; i++)
			Dept_Head->Objects[i]->ShowOut = NO;
		Dept_Head->ShowStaticPosition(Dept_Head, hDC);



		EndPaint(hWnd, (LPPAINTSTRUCT) & ps);
		break;

	case WM_LBUTTONDOWN:

                SetCapture(hWnd);
		break;

	case WM_MOUSEMOVE:

		/* case WM_LBUTTONDOWN : */

		pane_x = (int) LOWORD(lParam);
		pane_y = (int) HIWORD(lParam);
		lParaM = lParam;

		if (wParam == MK_LBUTTON)
			LeftButton = TRUE;
		else
			LeftButton = FALSE;


		hDC = GetDC(hWnd);
		tx = abs(pane_x - (int) Dept_Head->Objects[0]->CurrentL.x);
		ty = abs(pane_y - (int) Dept_Head->Objects[0]->CurrentL.y);


		XXX = tx * tx;
		YYY = ty * ty;



		/* let's see what the hell player wants to do.. */
		if ((tx < Dept_Head->Objects[0]->radius) && (ty < Dept_Head->Objects[0]->radius))
			handle_white_ball(hDC, LeftButton);	/* wants to move the
								 * white ball */
		else
			handle_stick(hDC, LeftButton);	/* wants to move stick */
		/*
		 * note that if you move your mouse fast, blt will not be
		 * able to catch up with you, so you are gonna end up moving
		 * the stick not the white ball. 
		 */
		ReleaseDC(hWnd, hDC);



		break;


	case WM_LBUTTONUP:

		if (ButtonPressedBefore)
			SendMessage(hWnd, WM_MOUSEMOVE, 0, lParaM);
                ReleaseCapture();
		break;


	case WM_SIZE:

		/* Save size of window client area. */
		if (lParam) {
			yClient = HIWORD(lParam);
			xClient = LOWORD(lParam);
		}
	case WM_COMMAND:

		switch (wParam) {

		case NewGame:

			hDC = GetDC(hWnd);
			BuildTheTable(hDC);
			Dept_Head->InitConfig(Dept_Head, hDC);
			ReleaseDC(hWnd, hDC);
			/* to delete balls at the outside */
			/* SendMessage(hWnd,WM_PAINT,0,0L); */

			break;



		case LoadGame:


			/*
			 * Get the system directory name, and store in
			 * szDirName 
			 */
			GetSystemDirectory(szDirName, sizeof(szDirName));
			szFile[0] = '\0';
			if ((cbString = LoadString(hInst, IDS_FILTERSTRING,
					szFilter, sizeof(szFilter))) == 0) {

				MessageBox(hWnd, "Can't Read Resources!...\nAborting... ", "Error", MB_OK);

				return 0L;
			}
			chReplace = szFilter[cbString - 1];	/* retrieve wildcard */
			for (i = 0; szFilter[i] != '\0'; i++) {
				if (szFilter[i] == chReplace)
					szFilter[i] = '\0';
			}
			/* Set all structure members to zero. */
			memset(&ofn, 0, sizeof(OPENFILENAME));
			ofn.lStructSize = sizeof(OPENFILENAME);
			ofn.hwndOwner = hWnd;
			ofn.lpstrFilter = szFilter;
			ofn.nFilterIndex = 1;
			ofn.lpstrFile = szFile;
			ofn.nMaxFile = sizeof(szFile);
			ofn.lpstrFileTitle = szFileTitle;
			ofn.nMaxFileTitle = sizeof(szFileTitle);
			ofn.lpstrInitialDir = szDirName;
			ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
			if (GetOpenFileName(&ofn)) {

			     if ((filehandle = fopen(ofn.lpstrFile,"r"))==NULL)
					MessageBox(hWnd, "Can't Read From a File!...\nAborting...", "Error", MB_OK);
			     else
					fscanf(filehandle,"%s  %s  %d  %d",My.Player1String,My.Player2String,&My.Player1Score,&My.Player2Score);

			       close(filehandle);

			} else
			     ;  //	MessageBox(hWnd, "Can't Open File To Read!...\nAborting...", "Error", MB_OK);

			break;
			/* Fileopen */

		case SaveIt:

			/*
			 * Get the system directory name, and store in
			 * szDirName
			 */
			GetSystemDirectory(szDirName, sizeof(szDirName));
			szFile[0] = '\0';
			if ((cbString = LoadString(hInst, IDS_FILTERSTRING,
					szFilter, sizeof(szFilter))) == 0) {

				MessageBox(hWnd, "Can't Read Resources!...\nAborting... ", "Error", MB_OK);

				return 0L;
			}
			chReplace = szFilter[cbString - 1];	/* retrieve wildcard */
			for (i = 0; szFilter[i] != '\0'; i++) {
				if (szFilter[i] == chReplace)
					szFilter[i] = '\0';
			}
			/* Set all structure members to zero. */
			memset(&ofn, 0, sizeof(OPENFILENAME));
			ofn.lStructSize = sizeof(OPENFILENAME);
			ofn.hwndOwner = hWnd;
			ofn.lpstrFilter = szFilter;
			ofn.nFilterIndex = 1;
			ofn.lpstrFile = szFile;
			ofn.nMaxFile = sizeof(szFile);
			ofn.lpstrFileTitle = szFileTitle;
			ofn.nMaxFileTitle = sizeof(szFileTitle);
			ofn.lpstrInitialDir = szDirName;
			ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
			if (GetSaveFileName(&ofn)) {


			    if ((filehandle = fopen(ofn.lpstrFile,"w"))==NULL)
					MessageBox(hWnd, "Can't Read From a File!...\nAborting...", "Error", MB_OK);
			     else
					fprintf(filehandle,"%s  %s  %d  %d",My.Player1String,My.Player2String,My.Player1Score,My.Player2Score);

			       close(filehandle);

			} else
			      ; //	MessageBox(hWnd, "Can't Open File To Save!...\nAborting...", "Error", MB_OK);






			break;


		case Players:

			GetPlayersName(hInst, hWnd);

			break;


		case Scores:

			GetScores(hInst, hWnd);

			break;




		case TrajectoryMode:
			WantsTrajectory = !WantsTrajectory;

			if (WantsTrajectory == YES)
				CheckMenuItem(GetMenu(hWnd), TrajectoryMode, MF_CHECKED);
			else
				CheckMenuItem(GetMenu(hWnd), TrajectoryMode, MF_UNCHECKED);


			break;


		case ExitThisApp:
			/* User selected Quit on menu */
			PostMessage(hWnd, WM_CLOSE, 0, 0L);

			break;

		case AboutBox:
			MessageBox(hWnd,
				   "Win Pool 1992 Version 1.0\nCopyright Ismail ARIT\nKusadasi,AYDIN,TURKIYE. 09400\n(Please read 'readme.txt or readme.wri'\nfor more info...)\n",
				   "About ",
				   MB_OK | MB_ICONINFORMATION);
			break;



		default:
			break;
		}
		break;

	case WM_DESTROY:
		for (i = 0; i < 16; i++)
			DeleteDC(hDCBall[i]);

		/* This is the end if we were closed by a DestroyWindow call. */
		PostQuitMessage(0);	/* this is the end...     */
		break;

	case WM_CLOSE:
		/* Tell windows to destroy our window. */
		FreeProcInstance(lpfnHandleDlgProc);

		DestroyWindow(hWnd);
		break;

	default:
		/* Let windows handle all messages we choose to ignore. */
		return (DefWindowProc(hWnd, message, wParam, lParam));
	}

	return (0L);
}




void
LayTheFloor(HDC hdc)
{
	/* hInst is the handle for this instance */
	HDC             hDCMem;
	BITMAP         *MyBitmap;
	POINT           Original, Normal;

	hDCMem = CreateCompatibleDC(hdc);
	SelectObject(hDCMem, MyBitmapHandle);
	SetMapMode(hDCMem, GetMapMode(hdc));

	GetObject(MyBitmapHandle, sizeof(BITMAP), (LPSTR) MyBitmap);
	Normal.x = MyBitmap->bmWidth;
	Normal.y = MyBitmap->bmHeight;
	DPtoLP(hdc, &Normal, 1);

	Original.x = 0;
	Original.y = 0;

	DPtoLP(hDCMem, &Original, 1);



	StretchBlt(hdc, xStart, yStart, xClient, yClient,
		   hDCMem, Original.x, Original.y, Normal.x,
		   Normal.y, SRCCOPY);

	DeleteDC(hDCMem);


}

void
MoveTheBall(HDC hdc)
{

	int             i;
	long            j;
	float           s;

	for (i = 0; i < 400; i += 20) {
		/*
		 *
		 * BitBlt(hdc,i+100,200,BitmapDim.bmWidth,BitmapDim.bmHeight,h
		 * DCBallDel, 0,0,SRCCOPY); 
		 */


		for (j = 0; j < 16; j++)
			BitBlt(hdc, i + 100, 50 + j * 16, BitmapDim.bmWidth, BitmapDim.bmHeight, hDCBall[j],
			       0, 0, SRCCOPY);



	}


};

void
BuildTheTable(HDC hDC)
{


	HPEN            hpenOld;
	HBRUSH          hbrOld;


	RECT            PoolTable, PoolSurface, TopLeftPoc, TopRightPoc, TopMiddlePoc, BottomLeftPoc, BottomRightPoc, BottomMiddlePoc;




	PoolTable.left = TableLeft;
	PoolTable.top = TableTop;
	PoolTable.bottom = WBottom - 60;
	PoolTable.right = WRight - 20;

	PoolSurface.left = PoolTable.left + PocDiameter / 2;
	PoolSurface.top = PoolTable.top + PocDiameter / 2;
	PoolSurface.bottom = PoolTable.bottom - PocDiameter / 2;
	PoolSurface.right = PoolTable.right - PocDiameter / 2;


	/* first lay the floor */
	LayTheFloor(hDC);



	hbrOld = SelectObject(hDC, hbrTable);
	/* let's create the table corners */
	FillRect(hDC, (RECT FAR *) & PoolTable, hbrTable);


	hpenOld = SelectObject(hDC, hpenBorder);
	/* let's draw the borders */
	Rectangle(hDC, PoolTable.left, PoolTable.top,
		  PoolTable.right, PoolTable.bottom);


	SelectObject(hDC, hbrPocket);

	BottomLeftPoc.left = PoolTable.left;
	BottomLeftPoc.top = PoolTable.bottom - PocDiameter;
	BottomLeftPoc.right = PoolTable.left + PocDiameter;
	BottomLeftPoc.bottom = PoolTable.bottom;
	Ellipse(hDC, BottomLeftPoc.left, BottomLeftPoc.top,
		BottomLeftPoc.right, BottomLeftPoc.bottom);


	BottomRightPoc.left = PoolTable.right - PocDiameter;
	BottomRightPoc.top = PoolTable.bottom - PocDiameter;
	BottomRightPoc.right = PoolTable.right;
	BottomRightPoc.bottom = PoolTable.bottom;
	Ellipse(hDC, BottomRightPoc.left, BottomRightPoc.top,
		BottomRightPoc.right, BottomRightPoc.bottom);


	BottomMiddlePoc.left = PoolTable.left + ((PoolTable.right - PoolTable.left) - PocDiameter) / 2;
	BottomMiddlePoc.top = PoolTable.bottom - PocDiameter;
	BottomMiddlePoc.right = PoolTable.left + ((PoolTable.right - PoolTable.left) + PocDiameter) / 2;
	BottomMiddlePoc.bottom = PoolTable.bottom;
	Ellipse(hDC, BottomMiddlePoc.left, BottomMiddlePoc.top,
		BottomMiddlePoc.right, BottomMiddlePoc.bottom);


	TopLeftPoc.left = PoolTable.left;
	TopLeftPoc.top = PoolTable.top;
	TopLeftPoc.right = PoolTable.left + PocDiameter;
	TopLeftPoc.bottom = PoolTable.top + PocDiameter;
	Ellipse(hDC, TopLeftPoc.left, TopLeftPoc.top,
		TopLeftPoc.right, TopLeftPoc.bottom);


	TopRightPoc.left = PoolTable.right - PocDiameter;
	TopRightPoc.top = PoolTable.top;
	TopRightPoc.right = PoolTable.right;
	TopRightPoc.bottom = PoolTable.top + PocDiameter;
	Ellipse(hDC, TopRightPoc.left, TopRightPoc.top,
		TopRightPoc.right, TopRightPoc.bottom);


	TopMiddlePoc.left = PoolTable.left + ((PoolTable.right - PoolTable.left) - PocDiameter) / 2;
	TopMiddlePoc.top = PoolTable.top;
	TopMiddlePoc.right = PoolTable.left + ((PoolTable.right - PoolTable.left) + PocDiameter) / 2;
	TopMiddlePoc.bottom = PoolTable.top + PocDiameter;
	Ellipse(hDC, TopMiddlePoc.left, TopMiddlePoc.top,
		TopMiddlePoc.right, TopMiddlePoc.bottom);


	SelectObject(hDC, hbrSurface);
	FillRect(hDC, (RECT FAR *) & PoolSurface, hbrSurface);


	SelectObject(hDC, hpenSurBorder);
	/* let's draw the borders for surface */
	Rectangle(hDC, PoolSurface.left, PoolSurface.top,
		  PoolSurface.right, PoolSurface.bottom);

	/* let's restore the original pen and brush here */
	SelectObject(hDC, hpenOld);
	SelectObject(hDC, hbrOld);



};
