//------------------------------------------------------------------
LRESULT CALLBACK WndMainProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i, notif;
	Tsquare *t;

	switch(message){
		case WM_PAINT:
		{
			static PAINTSTRUCT ps;
			BeginPaint(hWnd, &ps);
			paint(ps.hdc, &ps.rcPaint);
			EndPaint(hWnd, &ps);
		}
			break;
		case WM_LBUTTONDOWN:
			lbutton(lParam);
			break;
		case WM_RBUTTONDOWN:
			rbutton(lParam);
			break;
		case WM_LBUTTONUP:
			if(inserting){
				ReleaseCapture();
				inserting=false;
				insertGroup();
				resetSolution();
			}
			break;
		case WM_MOUSEMOVE:
			if(inserting){
				t= hitTest(lParam);
				if(t && t!=insSquares[insLen-1] && insLen<Nsymbol){
					insSquares[insLen++]=t;
				}
			}
#ifdef _DEBUGM
			mousemove(lParam);
#endif
			break;

		case WM_TIMER:
			if(!IsIconic(hWin)){
				playtime++;
				statusTime();
				checkShowErr(false);
			}
			break;
		case WM_KEYDOWN:
			key(wParam);
			break;
		case WM_GETMINMAXINFO:
		{
			LPMINMAXINFO lpmm = (LPMINMAXINFO)lParam;
			lpmm->ptMinTrackSize.x = 250;
			lpmm->ptMinTrackSize.y = 200+toolH;
			break;
		}
		case WM_SIZE:
			width=LOWORD(lParam);
			height=HIWORD(lParam);
			SendMessage(toolbar, TB_AUTOSIZE, 0, 0);
			SendMessage(statusbar, WM_SIZE, 0, 0);
			onMoved();
			invalidate();
			break;
		case WM_MOVE:
			onMoved();
			break;
		case WM_CLOSE:
			SendMessage(hWin, WM_COMMAND, ID_EXIT, 0);
			break;
		case WM_QUERYENDSESSION:
			writeini();
			return TRUE;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;

		case WM_COMMAND:
			notif=HIWORD(wParam);
			wParam=LOWORD(wParam);
			if(setLang(wParam)) break;
			if(wParam>=ID_SYMBOL && wParam<unsigned(ID_SYMBOL+size)){
				select(wParam-ID_SYMBOL);
				break;
			}
			if(wParam>=ID_SIZE+4 && wParam<=ID_SIZE+Msize){
				if(askNew()) break;
				size=wParam-ID_SIZE;
				newGameFormat();
				numButtons();
				break;
			}
			if(wParam>=ID_MULTI && wParam<ID_MULTI+sizeA(gameTypeA)-1){
				if(askNew()) break;
				gameType=wParam-ID_MULTI;
				newGameFormat();
				break;
			}

			switch(wParam){
				case ID_CLEAR:
					noScore=true;
					init(false);
					invalidate();
					break;
				case ID_CLEAR_ALL:
					noScore=true;
					initSquare(false);
					invalidate();
					break;
				case ID_EDITOR:
					if(!editor){
						if((undoPos==0 || done==Nsquare) && isGenerated()){
							initSquare(false);
						}
						editor=true;
						playtime=0;
						noScore=true;
						editorChanged();
					}
					break;
				case ID_EDITOR_END:
					if(editor){
						endEditor();
						editor=false;
						editorChanged();
					}
					break;
				case ID_SOLVE:
				case ID_SOLVE1:
					if(testTotal()) break;
					noScore=true;
					if(done<Nsquare){
						waitOn();
#ifdef _DEBUG
						DWORD time=getTickCount();
#endif
						Nsolution=0;
						curSolution=-1; //find all solutions (up to Msolution)
						undoAllPos=undoPos;
						if(wParam==ID_SOLVE1) resolve1(); else resolve();
						freeGroups();
#ifdef _DEBUG
						status(4, _T("%d ms"), getTickCount()-time);
#endif
						waitOff();
					}
					if(Nsolution>0){
						i=curSolution;
						curSolution++;
						if(curSolution>=Nsolution) curSolution=0;
						if(Nsolution>1){
							if(i<0){
								status(4, _T("%d %s"), Nsolution, lng(662, "solutions"));
							}
							else{
								status(4, _T("%d/%d"), curSolution+1, Nsolution);
							}
						}
						rdSolution();
					}
					else{ //easy solution (without recurse) or not solvable
						curSolution=0;
						status(4, _T(""));
					}
					checkErr();
					invalidate();
					break;
				case ID_CHEAT:
					noScore=true;
					if(errTime<0){
						waitOn();
						hint();
						waitOff();
					}
					checkShowErr(true);
					break;
				case ID_UNDO:
					undo();
					checkErr();
					break;
				case ID_REDO:
					redo();
					checkErr();
					break;
				case ID_UNDO_SYMBOL:
					undoSymbol();
					checkErr();
					break;
				case ID_REDO_SYMBOL:
					redoSymbol();
					checkErr();
					break;
				case ID_UNDO_ALL:
					undoAll();
					checkErr();
					break;
				case ID_REDO_ALL:
					while(redo());
					checkErr();
					break;
				case ID_DEL:
					select(-1);
					break;
				case ID_INS:
					select(-2);
					break;
				case ID_SIGN:
					select(-3);
					break;
				case ID_CONS:
					select(-4);
					break;
				case ID_EVEN:
					select(-5);
					break;
				case ID_EXIT:
					writeini();
					DestroyWindow(hWin);
					break;
				case ID_DIAGONAL:
					if(askNew()) break;
					diag=!diag;
					newGameFormat();
					break;
				case ID_SYMETRIC:
					if(askNew()) break;
					symetric=!symetric;
					newGameFormat();
					break;
				case ID_LEVEL:
					if(DialogBox(inst, MAKEINTRESOURCE(IDD_LEVEL), hWnd, (DLGPROC)LevelProc)){
						if(!editor) newGame();
					}
					break;
				case ID_SHOWERR:
					DialogBox(inst, MAKEINTRESOURCE(IDD_ERRTIME), hWnd, (DLGPROC)ShowErrProc);
					break;
				case ID_KILLER:
					if(askNew()) break;
					killer=!killer;
					newGameFormat();
					numButtons();
					break;
				case ID_GREATER:
					if(askNew()) break;
					greater=!greater;
					newGameFormat();
					break;
				case ID_CONSECUTIVE:
					if(askNew()) break;
					consecutive=!consecutive;
					newGameFormat();
					if(selectedNum==-4 && !consecutive) select(-1);
					break;
				case ID_ODDEVEN:
					if(askNew()) break;
					oddeven=!oddeven;
					newGameFormat();
					if(selectedNum==-5 && !oddeven) select(-1);
					break;
				case ID_DIGITS:
				case ID_LETTERS:
				case ID_COLORS:
					symbol0=wParam-350;
					checkMenus();
					invalidate();
					numButtons();
					break;
				case ID_NEWGAME:
					if(editor) SendMessage(hWnd, WM_COMMAND, ID_EDITOR_END, 0);
					else newGame();
					break;
				case ID_DELINI:
					delreg=true;
					break;
				case ID_DELHISCORE:
					if(MessageBox(hWnd,
						lng(799, "Do you really want to delete all hiscores ?"), title,
						MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDYES){
						for(TscoreTab *tab=score; tab;){
							TscoreTab *t1= tab->next;
							delete tab;
							tab=t1;
						}
						score=0;
						writeScore();
					}
					break;
				case ID_BEST_SCORES:
					DialogBox(inst, MAKEINTRESOURCE(IDD_HISCORE), hWnd, (DLGPROC)ScoreProc);
					break;
				case ID_COLORDLG:
					DialogBox(inst, MAKEINTRESOURCE(IDD_COLORS), hWin, (DLGPROC)ColorProc);
					break;
				case ID_ABOUT:
					DialogBox(inst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)AboutProc);
					break;
				case ID_HELP_README:
				{
					TCHAR *buf=(TCHAR*)_alloca(2*MAX_PATH);
					getExeDir(buf, lng(13, "readme.txt"));
					if(ShellExecute(0, _T("open"), buf, 0, 0, SW_SHOWNORMAL)==(HINSTANCE)ERROR_FILE_NOT_FOUND){
						msglng(730, "Cannot open %s", buf);
					}
				}
					break;
				case ID_WRBMP:
					if(saveFileDlg(&bmpOfn, hWnd, 0)){
						wrBmp(bmpFn, bmpOfn.nFilterIndex);
					}
					break;
				case ID_SAVE:
					if(saveFileDlg(&gameOfn, hWnd, OFN_OVERWRITEPROMPT)){
						save(gameFn);
					}
					break;
				case ID_OPEN:
					if(openFileDlg(&gameOfn, hWnd, OFN_FILEMUSTEXIST|OFN_HIDEREADONLY)){
						open(gameFn);
						checkErr();
					}
					break;
				case ID_CLEAR_GRP:
					resetSolution();
					for(i=0; i<Ngroup; i++){
						delGroup(&group[i]);
					}
					invalidate();
					break;
				case ID_CLEAR_SGN:
				case ID_CLEAR_CONS:
					resetSolution();
					for(i=0; i<Nboard; i++){
						if(wParam==ID_CLEAR_SGN){
							putSign(0, &board[i], 0);
							putSign(0, &board[i], 1);
						}
						if(wParam==ID_CLEAR_CONS){
							putCons(false, &board[i], 0);
							putCons(false, &board[i], 1);
						}
					}
					invalidate();
					break;
				case ID_MARKS:
					noScore=true;
					showMarks();
					break;
				case ID_DELMARKS:
					delAllMarks();
					break;
				case ID_PDF:
					if(askNew()) break;
					DialogBox(inst, MAKEINTRESOURCE(IDD_PDF), hWnd, (DLGPROC)PdfProc);
					numButtons();
					break;
			}
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
Exemple #2
0
DWORD WINAPI netGameLoop(void *param)
{
	int len, c, x, y;
	Psquare p;
	TnetGameSettings *b;
	char *m, *u, *a;
	hostent *h;
	char buf[256];

	if(!param){
		buf[0]=(BYTE)C_INIT1;
		buf[1]=NETGAME_VERSION;
		wr(buf, 2);
		c=rd1();
		if(c!=C_INIT2) goto le;
		c=rd1();
		if(c<1) goto le;
		netGameVersion=c;
		SetForegroundWindow(hWin);
		h= gethostbyaddr((char*)&netGameIP.sin_addr, 4, netGameIP.sin_family);
		a= inet_ntoa(netGameIP.sin_addr);
		if(msg1(MB_YESNO|MB_ICONQUESTION,
			lng(868, "Do you want to play with %s [%s] ?"),
			(h && h->h_name) ? h->h_name : "???", a ? a : "???")!=IDYES){
			wr1(C_INIT_DENY);
			goto le;
		}
		buf[0]=(BYTE)C_INFO;
		buf[1]=sizeof(TnetGameSettings);
		b= (TnetGameSettings*)(buf+2);
		b->width=(char)width;
		b->height=(char)height;
		b->begin= (player==1);
		b->rule5=(char)ruleFive;
		b->cont=(char)continuous;
		if(netGameVersion<2) b->rule5=b->cont=0;
		wr(buf, 2+sizeof(TnetGameSettings));
		if(rd1()!=C_INFO_OK) goto le;
		b->begin= !b->begin;
	}
	else{
		buf[0]=(BYTE)C_INIT2;
		buf[1]=NETGAME_VERSION;
		wr(buf, 2);
		c=rd1();
		if(c==C_BUSY) wrLog(lng(874, "The other player is already playing with someone else"));
		if(c!=C_INIT1) goto le;
		c=rd1();
		if(c<1) goto le;
		netGameVersion=c;
		wrLog(lng(871, "Connection established. Waiting for response..."));
		c=rd1();
		if(c==C_INIT_DENY) wrLog(lng(870, "The other player doesn't want to play with you !"));
		if(c!=C_INFO) goto le;
		len=rd1();
		b= (TnetGameSettings*)buf;
		memset(buf, 0, sizeof(TnetGameSettings));
		if(len<2 || rd(buf, len)<0) goto le;
		wr1(C_INFO_OK);
	}
	SendMessage(hWin, WM_COMMAND, 992, (LPARAM)b);
	undoRequest=0;

	for(;;){
		x=rd1();
		switch(x){
			case C_MSG: //message
				len=rd2();
				if(len<=0) goto le;
				u=new char[2*len];
				if(rd(u, 2*len)>=0){
					m=new char[len+1];
					WideCharToMultiByte(CP_ACP, 0, (WCHAR*)u, len, m, len, 0, 0);
					m[len]='\0';
					wrLog("--->  %s", m);
					delete[] m;
					SetWindowPos(logDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_ASYNCWINDOWPOS|SWP_NOACTIVATE|SWP_SHOWWINDOW);
				}
				delete[] u;
				break;
			case C_UNDO_REQUEST:
				y=rd2();
				if(y<=0 || y>moves) goto le;
				if(undoRequest){
					//both players pressed undo simultaneously
					if(undoRequest<0) undoRequest=y;
					amax(undoRequest, y);
					postUndo();
				}
				else{
					c=msg1(MB_YESNO|MB_ICONQUESTION,
						lng(876, "The other player wants to UNDO the last move.\r\nDo you agree ?"));
					if(c==IDYES){
						undoRequest=y;
						wr1(C_UNDO_YES);
						postUndo();
					}
					else{
						wr1(C_UNDO_NO);
					}
				}
				break;
			case C_NEW_REQUEST:
				if(undoRequest){
					if(undoRequest<0){
						//both players pressed NewGame simultaneously
						postNewGame();
					}
					else{
						postUndo();
					}
				}
				else{
					c=msg1(MB_YESNO|MB_ICONQUESTION,
						lng(877, "The other player wants to start a NEW game.\r\nDo you agree ?"));
					if(c==IDYES){
						undoRequest=-1;
						wr1(C_NEW_YES);
						postNewGame();
					}
					else{
						wr1(C_NEW_NO);
					}
				}
				break;
			case C_UNDO_YES:
				if(undoRequest<=0) goto le;
				postUndo();
				break;
			case C_UNDO_NO:
				if(undoRequest>0){
					msglng(878, "Sorry, the other player does not allow to UNDO your move.");
					undoRequest=0;
				}
				break;
			case C_NEW_YES:
				if(undoRequest>=0) goto le;
				postNewGame();
				break;
			case C_NEW_NO:
				if(undoRequest<0){
					msglng(879, "Sorry, the other player does not allow to start a NEW game.");
					undoRequest=0;
				}
				break;
			default: //move or error
				if(x<0 || x>=width){
					show(logDlg);
					goto le;
				}
				while(finished && (getTickCount()-lastTick<5000 || saveLock)){
					Sleep(200);
				}
				if(finished) SendMessage(hWin, WM_COMMAND, 101, 0);
				y=rd1();
				if(y<0 || y>=height) goto le;
				p=Square(x, y);
				p->time=rd4();
				PostMessage(hWin, WM_COMMAND, 991, (LPARAM)p);
		}
	}
le:
	EnterCriticalSection(&netLock);
	netGameDone();
	LeaveCriticalSection(&netLock);
	return 0;
}
void wrBmp(TCHAR *fn, int type)
{
	BITMAPINFOHEADER bmi;
	BITMAPFILEHEADER hdr;
	HBITMAP hBmp;
	BYTE *bits;
	FILE *f;
	int w, h, oldtool, oldstatus, oldW, oldH;
#ifdef USE_PNG
	bool isPng= (type==1);
#else
	const bool isPng=false; type;
#endif

	//create bitmap
	HDC winDC= GetDC(hWin);
	HDC dcb= CreateCompatibleDC(winDC);
	hBmp= CreateCompatibleBitmap(winDC, w=gridx*extentx, h=gridy*extenty);
	HGDIOBJ oldB= SelectObject(dcb, hBmp);
	ReleaseDC(hWin, winDC);
	//paint
	oldtool=toolBarVisible; oldstatus=statusBarVisible;
	oldW=width; oldH=height;
	toolBarVisible=statusBarVisible=0;
	width=w; height=h;
	paint(dcb, 0);
	toolBarVisible=oldtool; statusBarVisible=oldstatus;
	width=oldW; height=oldH;
	SelectObject(dcb, oldB);
	//initialize bitmap structure
	bmi.biSize = sizeof(BITMAPINFOHEADER);
	bmi.biWidth = w;
	bmi.biHeight = h;
	bmi.biPlanes = 1;
	bmi.biBitCount = (WORD)(isPng ? 24 : 16);
	bmi.biCompression = BI_RGB;
	bmi.biXPelsPerMeter=bmi.biYPelsPerMeter=0;
	bmi.biClrUsed = bmi.biClrImportant = 0; //needed for Linux wine
	//get pixels
	bits = new BYTE[h*(w*3+4)];
	if(!GetDIBits(dcb, hBmp, 0, h, bits, (BITMAPINFO*)&bmi, DIB_RGB_COLORS)){
		msg("GetDIBits failed");
	}
	else{
		//save file
		f=_tfopen(fn, _T("wb"));
		if(!f){
			msglng(733, "Cannot create file %s", fn);
		}
		else{
#ifdef USE_PNG
			if(isPng) wrPng(bits, w, h, bmi.biSizeImage/h, f);
			else
#endif
			{
				hdr.bfType = 0x4d42;  //'BM'
				hdr.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmi.biSizeImage;
				hdr.bfReserved1 = hdr.bfReserved2 = 0;
				hdr.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
				fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, f);
				fwrite(&bmi, sizeof(BITMAPINFOHEADER), 1, f);
				fwrite(bits, bmi.biSizeImage, 1, f);
			}
			fclose(f);
		}
	}
	delete[] bits;
	DeleteObject(hBmp);
	DeleteDC(dcb);
}