/******************************************************************
 *						Author:	Zhou Yundong
 *						Time: 20070401 12:44
 *
 * 2009年1月9日决定支持中断，思考时不允许编辑
 * 左盘的内容在思考前先送到思考盘，结果放在右盘
 ******************************************************************/
#include "StdAfx.h"
#include <commdlg.h>
#include "Sample.h"
#include "resource.h"
#include "time.h"
#include "Think.h"

BOOL CMainWin::PreCreateWindow(CREATESTRUCT	&cs)
{
	cs.dwExStyle = WS_EX_STATICEDGE;
	cs.style = WS_OVERLAPPED | WS_CAPTION |	WS_SYSMENU | WS_MINIMIZEBOX;

	CRect	rect(0,	0, 915, 444);
	::AdjustWindowRectEx(&rect,	cs.style, TRUE,	cs.dwExStyle);

	int	width =	rect.Width();
	int	height = rect.Height();

	CRect rcArea;
	SystemParametersInfo(SPI_GETWORKAREA, NULL,	&rcArea, NULL);

	int	x =	rcArea.left	+ (rcArea.Width() -	width) / 2;
	int	y =	rcArea.top + (rcArea.Height() -	height)	/ 2;

	cs.x = x;
	cs.y = y;
	cs.cx =	width;
	cs.cy =	height;
	cs.lpszClass = "MainWindow";

	if (!Application->RegisterWndClass(cs.lpszClass,
		CS_VREDRAW | CS_HREDRAW	| CS_OWNDC,	LoadCursor(NULL, IDC_ARROW),
		(HBRUSH)::GetStockObject(BLACK_BRUSH), Application->LoadIcon(IDI_ICON)))
		return FALSE;
	return TRUE;
}

LRESULT	CMainWin::WindowProc(UINT uMsg,	WPARAM wParam, LPARAM lParam)
{
	int xPos = LOWORD(lParam);
	int yPos = HIWORD(lParam);
	switch (uMsg) {
		case WM_CLOSE:
			OnClose();
			break;

		case WM_ERASEBKGND:
			return FALSE;
	  
		case WM_TIMER:
			OnTimer(wParam);
			break;

		case WM_KEYDOWN:
			OnKeyDown(wParam);
			break;

		case WM_KEYUP:
			OnKeyUp(wParam);
			break;

		case WM_LBUTTONDOWN:
			OnLButtonDown(wParam, CPoint(xPos, yPos));
			break;

		case WM_RBUTTONUP:
			OnRButtonUp(wParam, CPoint(xPos, yPos));
			break;

		case WM_MBUTTONUP:
			OnMButtonUp(wParam, CPoint(xPos, yPos));
			break;

		case WM_MOUSEMOVE:
			OnMouseMove(wParam, CPoint(xPos, yPos));
			break;

		case WM_MOUSEWHEEL:
			OnMouseWheel(wParam>>24);
			break;

		default:
			return CWindow::WindowProc(uMsg, wParam, lParam);
	}
	return 0L;
}

void CMainWin::OnCommand(UINT notifyCode, UINT id, HWND	ctrl)
{
	switch (id)
	{
		case ID_APP_OPENL:
			OnMenuOpenL();
			break;

		case ID_APP_OPENR:
			OnMenuOpenR();
			break;

		case ID_APP_ANSWER:
			OnMenuAnswer();
			break;

		case ID_APP_QUESTION:
			OnMenuQuestion();
			break;

		case ID_APP_SAVE:
			OnMenuSave();
			break;

		case ID_APP_QUIT:
			OnClose();
			break;

		case ID_APP_UP:
			OnMenuUp();
			break;

		case ID_APP_DOWN:
			OnMenuDown();
			break;

		case ID_APP_LEFT:
			OnMenuLeft();
			break;

		case ID_APP_RIGHT:
			OnMenuRight();
			break;

		case ID_APP_COPY:
			OnMenuCopy();
			break;

		case ID_APP_PASTE:
			OnMenuPaste();
			break;

		case ID_APP_CLEAN:
			OnMenuClean();
			break;

		case ID_APP_EMPTY:
			OnMenuEmpty();
			break;

		case ID_APP_LEGALCHECK:
			OnMenuCheck(false);
			break;

		case ID_APP_ANSWERCHECK:
			OnMenuCheck(true);
			break;

		case ID_APP_ANSWERS:
			OnMenuAnswers();
			break;

		case ID_APP_QUESTIONS:
			OnMenuQuestions();
			break;

		case ID_APP_UNIFIES:
			OnMenuUnifies();
			break;

		case ID_APP_UNIFY:
			OnMenuUnify();
			break;

		case ID_APP_SODOKU:
			OnMenuSodoku();
			break;

		case ID_APP_SOSUM:
			OnMenuSosum();
			break;

		case ID_APP_SOPARE:
			OnMenuSopare();
			break;

		case ID_APP_SOMIX:
			OnMenuSomix();
			break;

		case ID_APP_JIGSAW:
			OnMenuJigsaw();
			break;

		case ID_APP_SOEXTRA:
			OnMenuSoextra();
			break;
	}
}

//
// WM_CREATE
//
BOOL CMainWin::OnCreate(CREATESTRUCT *cs)
{
	LoadAccelTable(IDC_APPACCEL);
	CClientDC	dc(this);
	char pathName[256];
	char strErrMsg[400];

	loadGame();

	if (!ViewImage.Create(dc, 915, 444)) {
		MessageBox("Can not create window with mode 915, 444!"
			"Written by ZhouYundong Dec 14 2008!");
		return FALSE;
	}

	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\sodoku.bmp");
		CFile	file(pathName);
		if (!file || !Back.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\number.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageNumbers.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\led.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageLeds.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\smallnumber.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageLittleNumber.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\greyword.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageGrayWord.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\cover.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageCover.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\compare.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageCompare.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\sawedge.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageSawedge.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	{
		sprintf(pathName, "%s\\%s", basePath, "bmp\\extra.bmp");
		CFile	file(pathName);
		if (!file || !SpriteImageExtra.LoadBMP(file)) {
			sprintf(strErrMsg, "%s does not exist !", pathName);
			MessageBox(strErrMsg);
			return FALSE;
		}
	}
	ViewImage.Copy(&Back);
	XCaret = 0;
	YCaret = 0;
	ShowMyCaret();
	return TRUE;
}

void CMainWin::OnClose()
{
	::DestroyWindow(hWnd);
}

void CMainWin::OnTimer(WPARAM wParam)
{
	if(wParam == THINKOUT)
	{
		if(!underThinking)
		{
			KillTimer(THINKOUT);
			underThinking = false;
			InvalidateRect(NULL, TRUE);
		}
	}
}

void CMainWin::OnLButtonDown(UINT nFlags, CPoint point)
{
	int x, y;
	bool flagIntoEditing;
	if(underThinking) return;
	bool shiftDown = false, ctrlDown = false;
	if(point.x >= 1 && point.x <= 440 && point.y >= 1 && point.y <= 440)
	{
		rightStatus = 0;
		x = point.x / 49;
		y = point.y / 49;

		if(GetAsyncKeyState(VK_LSHIFT) < 0 || GetAsyncKeyState(VK_RSHIFT) < 0)
		{
			shiftDown = true;
		}
		if(GetAsyncKeyState(VK_LCONTROL) < 0 || GetAsyncKeyState(VK_RCONTROL) < 0)
		{
			ctrlDown = true;
		}
		if(gameKind == 0)
		{
			XCaret = x;
			YCaret = y;
			ShowMyCaret();
		}
		else if(gameKind == 1)
		{
			if(shiftDown && !ctrlDown)
			{
				flagIntoEditing = !underSumEditing;
				underSumEditing = true;
				updateIdxShift(x+mult9[y], flagIntoEditing);
				if(!underSumEditing)
				{
					ShowMyCaret();
				}
				getEndPoint();
			}
			else if(ctrlDown && !shiftDown)
			{
				if(glidingPare != 144)
				{
					leftPare[glidingPare] = (leftPare[glidingPare]+1) % 3;
					InvalidateRect(NULL, TRUE);
					return;
				}
				flagIntoEditing = !underSumEditing;
				underSumEditing = true;
				updateIdxCtrl(x+mult9[y], flagIntoEditing);
				if(!underSumEditing)
				{
					ShowMyCaret();
				}
				getEndPoint();
			}
			else if(!ctrlDown && !shiftDown)
			{
				glidingPare = 144;
				terminateSumEdit();
				getEndPoint();
				XCaret = x;
				YCaret = y;
				ShowMyCaret();
			}
		}
		else if(gameKind == 2)
		{
			if(ctrlDown && !shiftDown)
			{
				if(glidingPare != 144)
				{
					leftPare[glidingPare] = (leftPare[glidingPare]+1) % 3;
				}
			}
			else if(!ctrlDown && !shiftDown)
			{
				glidingPare = 144;
				XCaret = x;
				YCaret = y;
				ShowMyCaret();
			}
		}
		else if(gameKind == 3)
		{
			if(shiftDown && !ctrlDown)
			{
				if(glidingKilpare != 144)
				{
					leftKilpare[glidingKilpare] = (leftKilpare[glidingKilpare]+1) % 4;
					InvalidateRect(NULL, TRUE);
					return;
				}				
				if(editKind == 1)
				{
					flagIntoEditing = !underSumEditing;
					underSumEditing = true;
					updateIdxShift(x+mult9[y], flagIntoEditing);
				}
				else if(editKind == 2)
				{
					underSawEditing = true;
					updateSawShift(x+mult9[y]);
				}
				else if(editKind == 3)
				{
					underExtraEditing = true;
					updateExtraShift(x+mult9[y]);
				}
				if(!underSumEditing)
				{
					ShowMyCaret();
				}
				getEndPoint();
				getColorSaw();
			}
			else if(ctrlDown && !shiftDown)
			{
				if(glidingPare != 144)
				{
					leftPare[glidingPare] = (leftPare[glidingPare]+1) % 3;
					InvalidateRect(NULL, TRUE);
					return;
				}
				if(editKind == 1)
				{
					flagIntoEditing = !underSumEditing;
					underSumEditing = true;
					updateIdxCtrl(x+mult9[y], flagIntoEditing);
				}
				else if(editKind == 2)
				{
					underSawEditing = true;
					updateSawCtrl(x+mult9[y]);
				}
				else if(editKind == 3)
				{
					underExtraEditing = true;
					updateExtraCtrl(x+mult9[y]);
				}
				if(!underSumEditing)
				{
					ShowMyCaret();
				}
				getEndPoint();
				getColorSaw();
			}
			else if(!ctrlDown && !shiftDown)
			{
				glidingPare = 144;
				glidingKilpare = 144;
				terminateSumEdit();
				terminateSawEdit();
				terminateExtraEdit();
				getEndPoint();
				getColorSaw();
				XCaret = x;
				YCaret = y;
				ShowMyCaret();
			}
		}
		else if(gameKind == 4)
		{
			if(shiftDown && !ctrlDown)
			{
				underSawEditing = true;
				updateSawShift(x+mult9[y]);
				getColorSaw();
			}
			else if(ctrlDown && !shiftDown)
			{
				underSawEditing = true;
				updateSawCtrl(x+mult9[y]);
				getColorSaw();
			}
			else if(!ctrlDown && !shiftDown)
			{
				terminateSawEdit();
				getColorSaw();
				XCaret = x;
				YCaret = y;
				ShowMyCaret();
			}
		}
		else if(gameKind == 5)
		{
			if(shiftDown && !ctrlDown)
			{
				underExtraEditing = true;
				updateExtraShift(x+mult9[y]);
			}
			else if(ctrlDown && !shiftDown)
			{
				underExtraEditing = true;
				updateExtraCtrl(x+mult9[y]);
			}
			else if(!ctrlDown && !shiftDown)
			{
				terminateExtraEdit();
				XCaret = x;
				YCaret = y;
				ShowMyCaret();
			}
		}
		InvalidateRect(NULL, TRUE);
	}
	else if(point.x >= 443 && point.x <= 469)
	{
		if(point.y >= 57 && point.y <= 83)
		{
			// 求解
			OnMenuAnswer();
		}
		else if(point.y >= 99 && point.y <= 125)
		{
			// 左盘到右盘
			rightStatus = 2;
			gameKindRight = gameKind;
			terminateSumEdit();
			terminateSawEdit();
			terminateExtraEdit();
			getEndPoint();
			getColorSaw();
			ShowMyCaret();
			moveBoard('l', 'r'); // leftBoard to rightBoard
			moveSum('l', 'r'); // leftSum to rightSum
			moveIdx('l', 'r'); // leftIdx to rightIdx
			moveUniq('l', 'r'); // leftUniq to rightUniq
			movePare('l', 'r'); // leftPare to rightPare
			moveKilpare('l', 'r'); // leftKilpare to rightKilpare
			moveEndPoint('l', 'r'); // left dotted line to right dotted line
			moveSaw('l', 'r');
			moveColorSaw('l', 'r');
			moveExtra('l', 'r');
			rightKind = 1;
			InvalidateRect(NULL, TRUE);
		}
		else if(point.y >= 127 && point.y <= 153)
		{
			// 右盘到左盘
			if(gameKindRight == 0)
			{
				editKind = 0;
			}
			else if(gameKindRight == 1 || gameKindRight == 3)
			{
				editKind = 1;
			}
			else if(gameKindRight == 4)
			{
				editKind = 2;
			}
			else if(gameKindRight == 5)
			{
				editKind = 3;
			}
			rightStatus = 2;
			gameKind = gameKindRight;
			terminateSumEdit();
			terminateSawEdit();
			terminateExtraEdit();
			moveBoard('r', 'l'); // rightBoard to leftBoard
			moveSum('r', 'l'); // rightSum to leftSum
			moveIdx('r', 'l'); // rightIdx to leftIdx
			movePare('r', 'l'); // rightPare to leftPare
			moveKilpare('r', 'l'); // rightKilpare to leftKilpare
			updateHeadUniq();
			getEndPoint();
			moveSaw('r', 'l');
			moveColorSaw('r', 'l');
			moveExtra('r', 'l');
			InvalidateRect(NULL, TRUE);
		}
		else if(point.y >= 169 && point.y <= 195)
		{
			// 求题
			OnMenuQuestion();
		}
		else if(point.y >= 231 && point.y <= 257)
		{
			// 禁止自动求解
			autoSolute = !autoSolute;
			rightStatus = 0;
			InvalidateRect(NULL, TRUE);
		}
		else if(point.y >= 280 && point.y <= 306)
		{
			if(editKind == 1 && gameKind == 3)
			{
				editKind = 2;
				terminateSumEdit();
				getEndPoint();
				InvalidateRect(NULL, TRUE);
			}
			else if(editKind == 2 && gameKind == 3)
			{
				editKind = 3;
				terminateSawEdit();
				getColorSaw();
				InvalidateRect(NULL, TRUE);
			}
			else if(editKind == 3 && gameKind == 3)
			{
				editKind = 1;
				terminateExtraEdit();
				InvalidateRect(NULL, TRUE);
			}
		}
		if(point.y >= 328 && point.y <= 354)
		{
			// 检
			OnMenuCheck(false);
		}
		if(point.y >= 375 && point.y <= 401)
		{
			// 验
			OnMenuCheck(true);
		}
	}
}

void CMainWin::OnRButtonUp(UINT nFlags, CPoint point)
{
	int x, y;
	if(underThinking) return;
	if(point.x >= 1 && point.x <= 440 && point.y >= 1 && point.y <= 440)
	{
		x = point.x / 49;
		y = point.y / 49;
		XCaret = x;
		YCaret = y;
		ShowMyCaret();
		leftBoard[x+mult9[y]] = 0;
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
		OnMenuAnswer();
	}
}

void CMainWin::OnMButtonUp(UINT nFlags, CPoint point)
{
	int x, y;
	int index;
	if(underThinking) return;
	if(point.x >= 1 && point.x <= 440 && point.y >= 1 && point.y <= 440)
	{
		x = point.x / 49;
		y = point.y / 49;
		index = x + mult9[y];
		if(leftBoard[index] != 0)
		{
			fixation[index] = !fixation[index];
		}
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
	}
}

void CMainWin::OnMouseMove(UINT nFlags, CPoint point)
{
	int x, y;
	int m, n;
	int oldGlidingPare;
	int oldGlidingKilpare;
	if(underThinking) return;
	x = point.x;
	y = point.y;
	if(GetAsyncKeyState(VK_LCONTROL) < 0 || GetAsyncKeyState(VK_RCONTROL) < 0)
	{
		// ctrl键处于按下的状态
		if(x >= 8 && x <= 432 && y >= 8 && y <= 432 && (gameKind == 2 || gameKind == 3))
		{
			oldGlidingPare = glidingPare;
			glidingPare = 144;
			m = (x-46) / 49;
			if(46+mult49[m] <= x && x <= 52+mult49[m])
			{
				n = (y-15) / 49;
				if(15+mult49[n] <= y && y <= 33+mult49[n])
				{
					glidingPare = m + n*8;
					if(glidingPare == oldGlidingPare) return;
				}
			}
			m = (x-15) / 49;
			if(15+mult49[m] <= x && x <= 33+mult49[m])
			{
				n = (y-46) / 49;
				if(46+mult49[n] <= y && y <= 52+mult49[n])
				{
					glidingPare = m + n*9 +72;
					if(glidingPare == oldGlidingPare) return;
				}
			}
			InvalidateRect(NULL, TRUE);
		}
		else if(gameKind == 2 || gameKind == 3)
		{
			glidingPare = 144;
			InvalidateRect(NULL, TRUE);
		}
	}
	else if(GetAsyncKeyState(VK_LSHIFT) < 0 || GetAsyncKeyState(VK_RSHIFT) < 0)
	{
		// shift键处于按下的状态
		if(x >= 8 && x <= 432 && y >= 8 && y <= 432 && gameKind == 3)
		{
			oldGlidingKilpare = glidingKilpare;
			glidingKilpare = 144;
			m = (x-45) / 49;
			if(45+mult49[m] <= x && x <= 53+mult49[m])
			{
				n = (y-8) / 49;
				if(8+mult49[n] <= y && y <= 40+mult49[n])
				{
					glidingKilpare = m + n*8;
					if(glidingKilpare == oldGlidingKilpare) return;
				}
			}
			m = (x-8) / 49;
			if(8+mult49[m] <= x && x <= 40+mult49[m])
			{
				n = (y-45) / 49;
				if(45+mult49[n] <= y && y <= 53+mult49[n])
				{
					glidingKilpare = m + n*9 +72;
					if(glidingKilpare == oldGlidingKilpare) return;
				}
			}
			InvalidateRect(NULL, TRUE);
		}
		else if(gameKind == 3)
		{
			glidingKilpare = 144;
			InvalidateRect(NULL, TRUE);
		}
	}
}

void CMainWin::OnMouseWheel(int zDelta)
{
	if(underThinking) return;
	if(underSumEditing)
	{
		if(zDelta == 255)
		{
			leftSum[editingHead]++;
			if(leftSum[editingHead] > 99)
			{
				leftSum[editingHead] = 0;
			}
		}
		else
		{
			leftSum[editingHead]--;
			if(leftSum[editingHead] < 0)
			{
				leftSum[editingHead] = 99;
			}
		}
		InvalidateRect(NULL, TRUE);
	}
	else
	{
		if(zDelta == 255)
		{
			if(leftBoard[XCaret+mult9[YCaret]] < 9)
			{
				leftBoard[XCaret+mult9[YCaret]]++;
			}
			else
			{
				leftBoard[XCaret+mult9[YCaret]] = 0;
			}
		}
		else
		{
			if(leftBoard[XCaret+mult9[YCaret]] > 0)
			{
				leftBoard[XCaret+mult9[YCaret]]--;
			}
			else
			{
				leftBoard[XCaret+mult9[YCaret]] = 9;
			}
		}
		TerminateAll();
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
		OnMenuAnswer();
	}
}

void CMainWin::OnMenuUp()
{
	if(underSumEditing || underSawEditing) return;
	if(YCaret > 0)
	{
		YCaret--;
	}
	rightStatus = 0;
	ShowMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuDown()
{
	if(underSumEditing || underSawEditing) return;
	if(YCaret < 8)
	{
		YCaret++;
	}
	rightStatus = 0;
	ShowMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuLeft()
{
	if(underSumEditing || underSawEditing) return;
	if(XCaret > 0)
	{
		XCaret--;
	}
	rightStatus = 0;
	ShowMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuRight()
{
	if(underSumEditing || underSawEditing) return;
	if(XCaret < 8)
	{
		XCaret++;
	}
	rightStatus = 0;
	ShowMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::ShowMyCaret()
{
	if(CreateCaret(hWnd, NULL, 1, 21))
	{
		SetCaretPos(mult49[XCaret]+19, mult49[YCaret]+15);
		ShowCaret(hWnd);
	}
}

void CMainWin::OnMenuOpenL()
{
	if(underThinking) return;
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] =
		TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_READONLY;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetOpenFileName(&ofn))
		return;

	// 读取文件
	if(readFile(szFileName) == 0)
	{
		rightStatus = 4;
		InvalidateRect(NULL, TRUE);
		return;
	}
	flushSosumLeft();
	flushJigsawLeft();
	InitMyCaret();
	editKind = 1;
	gameKind = 3;
	rightStatus = 0;
	flagAnswer = -1;

	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuOpenR()
{
	if(underThinking) return;
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] =
		TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_READONLY;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetOpenFileName(&ofn))
		return;

	// 读取文件
	if(readFileR(szFileName) == 0)
	{
		rightStatus = 4;
		InvalidateRect(NULL, TRUE);
		return;
	}
	moveSum('0', 'r');
	moveIdx('0', 'r');
	movePare('0', 'r');
	moveKilpare('0', 'r');
	moveHead('0', 'r');
	moveUniq('0', 'r');
	moveSaw('0', 'r');
	for(int i=0; i<81; i++)
	{
		for(int j=0; j<4; j++)
		{
			colorSawRight[i][j] = 10;
		}
	}
	moveExtra('0', 'r');
	gameKindRight = 0;
	rightStatus = 0;
	flagAnswer = -1;
	pRightCircle = 0;
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSave()
{
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] = TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_CREATEPROMPT;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetSaveFileName(&ofn))
		return;
	// 保存文件
	if(!writeFile(szFileName))
	{
		MessageBox("Failed to save file!");
		return;
	}
	rightStatus = 0;
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnKeyDown(WPARAM wParam)
{
	if(underThinking) return;
	if(underSumEditing)
	{	
		if(wParam >= 48 && wParam <= 57)
		{
			if(leftSum[editingHead] < 10)
			{
				leftSum[editingHead] = leftSum[editingHead]*10 + wParam - 48;
			}
			else // must be 10 ~ 99
			{
				leftSum[editingHead] = wParam - 48;
			}
		}
		else if(wParam >= 96 && wParam <= 105)
		{
			if(leftSum[editingHead] < 10)
			{
				leftSum[editingHead] = leftSum[editingHead]*10 + wParam - 96;
			}
			else // must be 10 ~ 99
			{
				leftSum[editingHead] = wParam - 96;
			}
		}
		else if(wParam == 13)
		{
			terminateSumEdit();
			getEndPoint();
			ShowMyCaret();
		}
		else if(wParam == 46 || wParam == 8)
		{
			leftSum[editingHead] = 0;
		}
		else
		{
			return;
		}
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
	}
	else
	{
		if(wParam >= 48 && wParam <= 57)
		{
			leftBoard[XCaret+mult9[YCaret]] = wParam - 48;
			TerminateAll();
			OnMenuAnswer();
		}
		else if(wParam >= 96 && wParam <= 105)
		{
			leftBoard[XCaret+mult9[YCaret]] = wParam - 96;
			TerminateAll();
			OnMenuAnswer();
		}
		else if(wParam == 46 || wParam == 8)
		{
			leftBoard[XCaret+mult9[YCaret]] = 0;
			TerminateAll();
			OnMenuAnswer();
		}
		else if(wParam == 13)
		{
			TerminateAll();
			OnMenuAnswer();
		}
	}
}

void CMainWin::OnKeyUp(WPARAM wParam)
{
	if(underThinking) return;
	if(wParam == 16)
	{
		// shift按键动作为放开
		glidingKilpare = 144;
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
	}
	else if(wParam == 17)
	{
		// ctrl按键动作为放开
		glidingPare = 144;
		rightStatus = 0;
		InvalidateRect(NULL, TRUE);
	}
}

void CMainWin::OnMenuAnswer()
{
	if(!autoSolute || underThinking) return;
	underThinking = true;
	// 必须用现在的左盘
	for(int i=0; i<81; i++)
	{
		oldFix[i] = leftBoard[i] != 0;
	}
	moveBoard('l', 'b'); // leftBoard to board
	switch(gameKind)
	{
		case 0:
			runThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handleAnswer, NULL, 0, 0);
			break;
		case 1:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 2:
			runThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handleAnswerPare, NULL, 0, 0);
			break;
		case 3:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 4:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 5:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
	}
	SetTimer(THINKOUT, 1);
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuQuestion()
{
	if(!autoSolute || underThinking) return;
	underThinking = true;
	// 必须用现在的左盘
	switch(gameKind)
	{
		case 0:
			runThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handleQuestion, NULL, 0, 0);
			break;
		case 1:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 2:
			runThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handleQuestionPare, NULL, 0, 0);
			break;
		case 3:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 4:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
		case 5:
			MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
			return;
	}
	SetTimer(THINKOUT, 100);
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuCopy()
{
	char str[1000];
	if(!OpenClipboard(NULL))
	{
		MessageBox("Can not open clipboard !");
		return;
	}
	if(!EmptyClipboard())
	{
		MessageBox("Can not clear clipboard !");
		return;
	}
	HGLOBAL hData = GlobalAlloc(LMEM_FIXED|LMEM_ZEROINIT, 1000);
	{
		char *p = (char*)GlobalLock(hData);
		sprintf(p, "%s", writeStr(str));
		GlobalUnlock(hData);
	}
	if(SetClipboardData(CF_TEXT, hData) == NULL)
	{
		MessageBox("Can not copy left board to clipboard !");
		CloseClipboard();
		return;
	}
	rightStatus = 4;
	CloseClipboard();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuPaste()
{
	if(underThinking) return;
	if(!IsClipboardFormatAvailable(CF_TEXT))
	{
		MessageBox("Data format in clipboard is not text!");
	}
	if(!OpenClipboard(NULL))
	{
		MessageBox("Can not open clipboard !");
		return;
	}
	HGLOBAL hMem = GetClipboardData(CF_TEXT);
	if(hMem != NULL)
	{
		char *str = (char *)GlobalLock(hMem);
		if(str != NULL)
		{
			if(!readStr(str))
			{
				rightStatus = 4;
				GlobalUnlock(hMem);
				CloseClipboard();
				InvalidateRect(NULL, TRUE);
				return;
			}
			flushSosumLeft();
			flushJigsawLeft();
			InitMyCaret();
			GlobalUnlock(hMem);
		}
	}
	CloseClipboard();
	editKind = 1;
	gameKind = 3;
	rightStatus = 0;
	flagAnswer = -1;
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuClean()
{
	int i;
	if(underThinking) return;
	for(i=0; i<81; i++)
	{
		if(!fixation[i])
		{
			leftBoard[i] = 0;
		}
	}
	rightStatus = 0;
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuEmpty()
{
	if(underThinking) return;
	moveBoard('0', 'l'); // 0 to leftBoard
	initialSodoku();
	initialCommon();
	flushSosumLeft();
	flushJigsawLeft();
	terminateExtraEdit();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuAnswers()
{
	if(underThinking || !autoSolute) return;
	FILE *fp, *fp2;
	char str[1000];
	char fileName[255];
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] =
		TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_READONLY;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetOpenFileName(&ofn))
		return;

	// 读取文件
	if((fp=fopen(szFileName, "r")) == NULL)
	{
		MessageBox("Failed to open file!");
		return;
	}
	sprintf(fileName, "%s\\answer_%s", basePath, szTitleName);
	underThinking = true;
	// 重写一遍是因为这里屏蔽了leftBoard
	while(fgets(str, 1000, fp))
	{
		if((fp2=fopen(fileName, "a+")) == NULL)
		{
			MessageBox("Failed to open file!");
			underThinking = false;
			return;
		}
		readStrBoard(str);
		switch(gameKind)
		{
			case 0:
				getAnswer();
				break;
			case 1:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				return;
			case 2:
				getAnswerPare();
				movePare('p', 'a');
				break;
			case 3:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				break;
			case 4:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				break;
			case 5:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				break;
		}
		writeStrAnswer(str);
		if(flagAnswer == 1)
		{
			fputs(str, fp2);
			fputs("\n", fp2);
		}
		else
		{
			sprintf(str, "########################################%d########################################\n", flagAnswer);
			fputs(str, fp2);
		}
		fclose(fp2);
	}
	underThinking = false;
	fclose(fp);
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuQuestions()
{
	if(underThinking || !autoSolute) return;
	FILE *fp;
	char str[1000];
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] = TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_CREATEPROMPT;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetSaveFileName(&ofn))
		return;
	underThinking = true;
	while(true)
	{
		if((fp=fopen(szFileName, "a+")) == NULL)
		{
			MessageBox("Failed to open file!");
			return;
		}
		switch(gameKind)
		{
			case 0:
				handleQuestions();
				break;
			case 1:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				return;
			case 2:
				handleQuestionPares();
				return;
			case 3:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				return;
			case 4:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				return;
			case 5:
				MessageBox("还不支持这个功能！"); underThinking = false; InvalidateRect(NULL, TRUE);
				return;
		}
		writeStrAnswer(str);
		fputs(str, fp);
		fputs("\n", fp);
		fclose(fp);
	}
}

void CMainWin::OnMenuUnify()
{
	if(underThinking || !autoSolute) return;
	/*
	moveBoard('l', 'b'); // leftBoard to board
	underThinking = true;
	if(!handleUnify())
	{
		MessageBox("Not single solution!", "Written by ZhouYundong Dec 14 2008!");
		underThinking = false;
		return;
	}
	moveBoard('b', 'r'); // board to rightBoard
	underThinking = false;
	*/
	MessageBox("统一化功能没有实现！", "Written by ZhouYundong Dec 14 2008!");
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuUnifies()
{
	if(underThinking || !autoSolute) return;
	int result;
	FILE *fp, *fp2;
	char str[83];
	char fileName[255];
	static OPENFILENAME ofn;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static TCHAR szFilter[] =
		TEXT(".txt\0*.txt\0");

	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.Flags = OFN_READONLY;
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = szFilter;
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = szTitleName;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrDefExt = TEXT("txt");
	if (!GetOpenFileName(&ofn))
		return;

	// 读取文件
	if((fp=fopen(szFileName, "r")) == NULL)
	{
		MessageBox("Failed to open file!");
		return;
	}
	sprintf(fileName, "%s\\unify_%s", basePath, szTitleName);
	underThinking = true;
	// 重写一遍是因为这里屏蔽了leftBoard
	while(fgets(str, 83, fp))
	{
		if((fp2=fopen(fileName, "a+")) == NULL)
		{
			MessageBox("Failed to open file!");
			underThinking = false;
			return;
		}
		readStrBoard(str);
		result = handleUnify();
		moveBoard('b', 'a'); // board to answerBoard
		writeStrAnswer(str);
		if(result)
		{
			fputs(str, fp2);
			fputs("\n", fp2);
		}
		else
		{
			sprintf(str, "########################################%d########################################\n", flagAnswer);
			fputs(str, fp2);
		}
		fclose(fp2);
	}
	underThinking = false;
	fclose(fp);
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSodoku()
{
	if(underThinking) return;
	initialSodoku();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSosum()
{
	if(underThinking) return;
	initialSosum();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSopare()
{
	if(underThinking) return;
	initialSopare();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSomix()
{
	if(underThinking) return;
	initialSomix();
	setInitSaw();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuJigsaw()
{
	if(underThinking) return;
	initialJigsaw();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuSoextra()
{
	if(underThinking) return;
	initialSoextra();
	initialCommon();
	InitMyCaret();
	InvalidateRect(NULL, TRUE);
}

void CMainWin::InitMyCaret()
{
	XCaret = 0;
	YCaret = 0;
	ShowMyCaret();
}

void CMainWin::TerminateAll()
{
	rightStatus = 0;
	if(underSumEditing)
	{
		terminateSumEdit();
		getEndPoint();
	}
	else if(underSawEditing)
	{
		terminateSawEdit();
		getColorSaw();
	}
	else if(underExtraEditing)
	{
		terminateExtraEdit();
	}
	InvalidateRect(NULL, TRUE);
}

void CMainWin::OnMenuCheck(bool flag)
{
	int errKind;
	if(underThinking) return;
	if(!getFinishAll())
	{
		MessageBox("数扭规定必须是9组，每组必须是9个格子；数超规定必须是9格一组！");
		return;
	}
	if(flag)
	{
		errKind = finishCheckAll();
		if(errKind != -1)
		{
			MessageBox("右盘不是左盘的解！");
		}
		else
		{
			MessageBox("右盘是左盘的解！", "周运栋作于2008年10月15日", MB_OK);
		}
	}
	else
	{
		errKind = legalCheckAll();
		switch(errKind)
		{
			case 0:
				MessageBox("组内数重复！");
				break;
			case 1:
				MessageBox("数和不合法！");
				break;
			case 2:
				MessageBox("数比规定两边不允许都是已知数，不允许大数比小数小，不允许1>，不允许9<！");
				break;
			case 3:
				MessageBox("紫比规定两边必须都是和形式，并且不允许两边都是给定和，等号时两边和都必须未指定！");
				break;
			case 4:
				MessageBox("数扭规定必须是9组，每组必须是9个格子！");
				break;
			case 5:
				MessageBox("数超规定必须是9格一组！");
				break;
			case 6:
				MessageBox("右盘数字不全满");
				break;
			default:
				MessageBox("合法！", "周运栋作于2008年10月15日", MB_OK);
				break;
		}
	}
}
