~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/winemine/main.c

Version: ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * WineMine (main.c)
  3  *
  4  * Copyright 2000 Joshua Thielen
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #define WIN32_LEAN_AND_MEAN
 22 
 23 #include <string.h>
 24 #include <time.h>
 25 #include <windows.h>
 26 #include <stdlib.h>
 27 #include <shellapi.h>
 28 #include "main.h"
 29 #include "resource.h"
 30 
 31 #include <wine/debug.h>
 32 
 33 WINE_DEFAULT_DEBUG_CHANNEL(winemine);
 34 
 35 static const DWORD wnd_style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
 36 static const char* registry_key = "Software\\Microsoft\\WinMine";
 37 
 38 
 39 int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow )
 40 {
 41     MSG msg;
 42     WNDCLASS wc;
 43     HWND hWnd;
 44     HACCEL haccel;
 45     char appname[20];
 46 
 47     LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
 48 
 49     wc.style = 0;
 50     wc.lpfnWndProc = MainProc;
 51     wc.cbClsExtra = 0;
 52     wc.cbWndExtra = 0;
 53     wc.hInstance = hInst;
 54     wc.hIcon = LoadIcon( hInst, "WINEMINE" );
 55     wc.hCursor = LoadCursor( 0, IDI_APPLICATION );
 56     wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
 57     wc.lpszMenuName = "MENU_WINEMINE";
 58     wc.lpszClassName = appname;
 59 
 60     if (!RegisterClass(&wc)) ExitProcess(1);
 61     hWnd = CreateWindow( appname, appname,
 62         wnd_style,
 63         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
 64         0, 0, hInst, NULL );
 65 
 66     if (!hWnd) ExitProcess(1);
 67 
 68     ShowWindow( hWnd, cmdshow );
 69     UpdateWindow( hWnd );
 70 
 71     haccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDA_WINEMINE) );
 72     SetTimer( hWnd, ID_TIMER, 1000, NULL );
 73 
 74     while( GetMessage(&msg, 0, 0, 0) ) {
 75         if (!TranslateAccelerator( hWnd, haccel, &msg ))
 76             TranslateMessage( &msg );
 77 
 78         DispatchMessage( &msg );
 79     }
 80     return msg.wParam;
 81 }
 82 
 83 LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 84 {
 85     HDC hdc;
 86     PAINTSTRUCT ps;
 87     HMENU hMenu;
 88     static BOARD board;
 89 
 90     switch( msg ) {
 91     case WM_CREATE:
 92         board.hInst = ((LPCREATESTRUCT) lParam)->hInstance;
 93         board.hWnd = hWnd;
 94         InitBoard( &board );
 95         CreateBoard( &board );
 96         return 0;
 97 
 98     case WM_PAINT:
 99       {
100         HDC hMemDC;
101 
102         WINE_TRACE("WM_PAINT\n");
103         hdc = BeginPaint( hWnd, &ps );
104         hMemDC = CreateCompatibleDC( hdc );
105 
106         DrawBoard( hdc, hMemDC, &ps, &board );
107 
108         DeleteDC( hMemDC );
109         EndPaint( hWnd, &ps );
110 
111         return 0;
112       }
113 
114     case WM_MOVE:
115         WINE_TRACE("WM_MOVE\n");
116         board.pos.x = (short)LOWORD(lParam);
117         board.pos.y = (short)HIWORD(lParam);
118         return 0;
119 
120     case WM_DESTROY:
121         SaveBoard( &board );
122         DestroyBoard( &board );
123         PostQuitMessage( 0 );
124         return 0;
125 
126     case WM_TIMER:
127         if( board.status == PLAYING ) {
128             board.time++;
129             RedrawWindow( hWnd, &board.timer_rect, 0,
130                           RDW_INVALIDATE | RDW_UPDATENOW );
131         }
132         return 0;
133 
134     case WM_LBUTTONDOWN:
135         WINE_TRACE("WM_LBUTTONDOWN\n");
136         if( wParam & MK_RBUTTON )
137             msg = WM_MBUTTONDOWN;
138         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
139         SetCapture( hWnd );
140         return 0;
141 
142     case WM_LBUTTONUP:
143         WINE_TRACE("WM_LBUTTONUP\n");
144         if( wParam & MK_RBUTTON )
145             msg = WM_MBUTTONUP;
146         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
147         ReleaseCapture();
148         return 0;
149 
150     case WM_RBUTTONDOWN:
151         WINE_TRACE("WM_RBUTTONDOWN\n");
152         if( wParam & MK_LBUTTON ) {
153             board.press.x = 0;
154             board.press.y = 0;
155             msg = WM_MBUTTONDOWN;
156         }
157         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
158         return 0;
159 
160     case WM_RBUTTONUP:
161         WINE_TRACE("WM_RBUTTONUP\n");
162         if( wParam & MK_LBUTTON )
163             msg = WM_MBUTTONUP;
164         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
165         return 0;
166 
167     case WM_MBUTTONDOWN:
168         WINE_TRACE("WM_MBUTTONDOWN\n");
169         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
170         return 0;
171 
172     case WM_MBUTTONUP:
173         WINE_TRACE("WM_MBUTTONUP\n");
174         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
175         return 0;
176 
177     case WM_MOUSEMOVE:
178     {
179         if( wParam & MK_MBUTTON ) {
180             msg = WM_MBUTTONDOWN;
181         }
182         else if( wParam & MK_LBUTTON ) {
183             msg = WM_LBUTTONDOWN;
184         }
185         else {
186             return 0;
187         }
188 
189         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam),  msg );
190 
191         return 0;
192     }
193 
194     case WM_COMMAND:
195         switch(LOWORD(wParam)) {
196         case IDM_NEW:
197             CreateBoard( &board );
198             return 0;
199 
200         case IDM_MARKQ:
201             hMenu = GetMenu( hWnd );
202             board.IsMarkQ = !board.IsMarkQ;
203             if( board.IsMarkQ )
204                 CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
205             else
206                 CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
207             return 0;
208 
209         case IDM_BEGINNER:
210             SetDifficulty( &board, BEGINNER );
211             CreateBoard( &board );
212             return 0;
213 
214         case IDM_ADVANCED:
215             SetDifficulty( &board, ADVANCED );
216             CreateBoard( &board );
217             return 0;
218 
219         case IDM_EXPERT:
220             SetDifficulty( &board, EXPERT );
221             CreateBoard( &board );
222             return 0;
223 
224         case IDM_CUSTOM:
225             SetDifficulty( &board, CUSTOM );
226             CreateBoard( &board );
227             return 0;
228 
229         case IDM_EXIT:
230             SendMessage( hWnd, WM_CLOSE, 0, 0);
231             return 0;
232 
233         case IDM_TIMES:
234             DialogBoxParam( board.hInst, "DLG_TIMES", hWnd,
235                     TimesDlgProc, (LPARAM) &board);
236             return 0;
237 
238         case IDM_ABOUT:
239         {
240             WCHAR appname[256], other[256];
241             LoadStringW( board.hInst, IDS_APPNAME, appname, sizeof(appname)/sizeof(WCHAR) );
242             LoadStringW( board.hInst, IDS_ABOUT, other, sizeof(other)/sizeof(WCHAR) );
243             ShellAboutW( hWnd, appname, other,
244                          LoadImageA( board.hInst, "WINEMINE", IMAGE_ICON, 48, 48, LR_SHARED ));
245             return 0;
246         }
247         default:
248             WINE_TRACE("Unknown WM_COMMAND command message received\n");
249             break;
250         }
251     }
252     return( DefWindowProc( hWnd, msg, wParam, lParam ));
253 }
254 
255 void InitBoard( BOARD *p_board )
256 {
257     HMENU hMenu;
258 
259     p_board->hMinesBMP = LoadBitmap( p_board->hInst, "mines");
260     p_board->hFacesBMP = LoadBitmap( p_board->hInst, "faces");
261     p_board->hLedsBMP = LoadBitmap( p_board->hInst, "leds");
262 
263     LoadBoard( p_board );
264 
265     hMenu = GetMenu( p_board->hWnd );
266     CheckMenuItem( hMenu, IDM_BEGINNER + (unsigned) p_board->difficulty,
267             MF_CHECKED );
268     if( p_board->IsMarkQ )
269         CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
270     else
271         CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
272     CheckLevel( p_board );
273 }
274 
275 void LoadBoard( BOARD *p_board )
276 {
277     DWORD size;
278     DWORD type;
279     HKEY hkey;
280     char data[MAX_PLAYER_NAME_SIZE+1];
281     char key_name[8];
282     unsigned i;
283 
284     RegOpenKeyEx( HKEY_CURRENT_USER, registry_key,
285             0, KEY_QUERY_VALUE, &hkey );
286 
287     size = sizeof( p_board->pos.x );
288     if( !RegQueryValueEx( hkey, "Xpos", NULL, (LPDWORD) &type,
289             (LPBYTE) &p_board->pos.x, (LPDWORD) &size ) == ERROR_SUCCESS )
290         p_board->pos.x = 0;
291 
292     size = sizeof( p_board->pos.y );
293     if( !RegQueryValueEx( hkey, "Ypos", NULL, (LPDWORD) &type,
294             (LPBYTE) &p_board->pos.y, (LPDWORD) &size ) == ERROR_SUCCESS )
295         p_board->pos.y = 0;
296 
297     size = sizeof( p_board->rows );
298     if( !RegQueryValueEx( hkey, "Height", NULL, (LPDWORD) &type,
299             (LPBYTE) &p_board->rows, (LPDWORD) &size ) == ERROR_SUCCESS )
300         p_board->rows = BEGINNER_ROWS;
301 
302     size = sizeof( p_board->cols );
303     if( !RegQueryValueEx( hkey, "Width", NULL, (LPDWORD) &type,
304             (LPBYTE) &p_board->cols, (LPDWORD) &size ) == ERROR_SUCCESS )
305         p_board->cols = BEGINNER_COLS;
306 
307     size = sizeof( p_board->mines );
308     if( !RegQueryValueEx( hkey, "Mines", NULL, (LPDWORD) &type,
309             (LPBYTE) &p_board->mines, (LPDWORD) &size ) == ERROR_SUCCESS )
310         p_board->mines = BEGINNER_MINES;
311 
312     size = sizeof( p_board->difficulty );
313     if( !RegQueryValueEx( hkey, "Difficulty", NULL, (LPDWORD) &type,
314             (LPBYTE) &p_board->difficulty, (LPDWORD) &size ) == ERROR_SUCCESS )
315         p_board->difficulty = BEGINNER;
316 
317     size = sizeof( p_board->IsMarkQ );
318     if( !RegQueryValueEx( hkey, "Mark", NULL, (LPDWORD) &type,
319             (LPBYTE) &p_board->IsMarkQ, (LPDWORD) &size ) == ERROR_SUCCESS )
320         p_board->IsMarkQ = TRUE;
321 
322     for( i = 0; i < 3; i++ ) {
323         wsprintf( key_name, "Name%d", i+1 );
324         size = sizeof( data );
325         if( RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
326                 (LPBYTE) data,
327                 (LPDWORD) &size ) == ERROR_SUCCESS )
328                     lstrcpynA( p_board->best_name[i], data, sizeof(p_board->best_name[i]) );
329         else
330             LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], MAX_PLAYER_NAME_SIZE+1 );
331     }
332 
333     for( i = 0; i < 3; i++ ) {
334         wsprintf( key_name, "Time%d", i+1 );
335         size = sizeof( p_board->best_time[i] );
336         if( !RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
337                 (LPBYTE) &p_board->best_time[i],
338                 (LPDWORD) &size ) == ERROR_SUCCESS )
339             p_board->best_time[i] = 999;
340     }
341     RegCloseKey( hkey );
342 }
343 
344 void SaveBoard( BOARD *p_board )
345 {
346     HKEY hkey;
347     unsigned i;
348     char data[MAX_PLAYER_NAME_SIZE+1];
349     char key_name[8];
350 
351     if( RegCreateKeyEx( HKEY_CURRENT_USER, registry_key,
352                 0, NULL,
353                 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
354                 &hkey, NULL ) != ERROR_SUCCESS)
355         return;
356 
357     RegSetValueEx( hkey, "Xpos", 0, REG_DWORD, (LPBYTE) &p_board->pos.x, sizeof(p_board->pos.x) );
358     RegSetValueEx( hkey, "Ypos", 0, REG_DWORD, (LPBYTE) &p_board->pos.y, sizeof(p_board->pos.y) );
359     RegSetValueEx( hkey, "Difficulty", 0, REG_DWORD, (LPBYTE) &p_board->difficulty, sizeof(p_board->difficulty) );
360     RegSetValueEx( hkey, "Height", 0, REG_DWORD, (LPBYTE) &p_board->rows, sizeof(p_board->rows) );
361     RegSetValueEx( hkey, "Width", 0, REG_DWORD, (LPBYTE) &p_board->cols, sizeof(p_board->cols) );
362     RegSetValueEx( hkey, "Mines", 0, REG_DWORD, (LPBYTE) &p_board->mines, sizeof(p_board->mines) );
363     RegSetValueEx( hkey, "Mark", 0, REG_DWORD, (LPBYTE) &p_board->IsMarkQ, sizeof(p_board->IsMarkQ) );
364 
365     for( i = 0; i < 3; i++ ) {
366         wsprintf( key_name, "Name%u", i+1 );
367         lstrcpyn( data, p_board->best_name[i], sizeof( data ) );
368         RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
369     }
370 
371     for( i = 0; i < 3; i++ ) {
372         wsprintf( key_name, "Time%u", i+1 );
373         RegSetValueEx( hkey, key_name, 0, REG_DWORD, (LPBYTE) &p_board->best_time[i], sizeof(p_board->best_time[i]) );
374     }
375     RegCloseKey( hkey );
376 }
377 
378 void DestroyBoard( BOARD *p_board )
379 {
380     DeleteObject( p_board->hFacesBMP );
381     DeleteObject( p_board->hLedsBMP );
382     DeleteObject( p_board->hMinesBMP );
383 }
384 
385 void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty )
386 {
387     HMENU hMenu;
388 
389     if ( difficulty == CUSTOM )
390         if (DialogBoxParam( p_board->hInst, "DLG_CUSTOM", p_board->hWnd,
391                     CustomDlgProc, (LPARAM) p_board) != 0)
392            return;
393 
394     hMenu = GetMenu( p_board->hWnd );
395     CheckMenuItem( hMenu, IDM_BEGINNER + p_board->difficulty, MF_UNCHECKED );
396     p_board->difficulty = difficulty;
397     CheckMenuItem( hMenu, IDM_BEGINNER + difficulty, MF_CHECKED );
398 
399     switch( difficulty ) {
400     case BEGINNER:
401         p_board->cols = BEGINNER_COLS;
402         p_board->rows = BEGINNER_ROWS;
403         p_board->mines = BEGINNER_MINES;
404         break;
405 
406     case ADVANCED:
407         p_board->cols = ADVANCED_COLS;
408         p_board->rows = ADVANCED_ROWS;
409         p_board->mines = ADVANCED_MINES;
410         break;
411 
412     case EXPERT:
413         p_board->cols = EXPERT_COLS;
414         p_board->rows = EXPERT_ROWS;
415 
416         p_board->mines = EXPERT_MINES;
417         break;
418 
419     case CUSTOM:
420         break;
421     }
422 }
423 
424 static void ShiftBetween(LONG* x, LONG* y, LONG a, LONG b)
425 {
426     if (*x < a) {
427         *y += a - *x;
428         *x = a;
429     }
430     else if (*y > b) {
431         *x -= *y - b;
432         *y = b;
433     }
434 }
435 
436 static void MoveOnScreen(RECT* rect)
437 {
438     HMONITOR hMonitor;
439     MONITORINFO mi;
440 
441     /* find the nearest monitor ... */
442     hMonitor = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);
443 
444     /* ... and move it into the work area (ie excluding task bar)*/
445     mi.cbSize = sizeof(mi);
446     GetMonitorInfo(hMonitor, &mi);
447 
448     ShiftBetween(&rect->left, &rect->right, mi.rcWork.left, mi.rcWork.right);
449     ShiftBetween(&rect->top, &rect->bottom, mi.rcWork.top, mi.rcWork.bottom);
450 }
451 
452 void CreateBoard( BOARD *p_board )
453 {
454     int left, top, bottom, right;
455     unsigned col, row;
456     RECT wnd_rect;
457 
458     p_board->mb = MB_NONE;
459     p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines;
460     p_board->num_flags = 0;
461 
462     /* Create the boxes...
463      * We actually create them with an empty border,
464      * so special care doesn't have to be taken on the edges
465      */
466     for( col = 0; col <= p_board->cols + 1; col++ )
467       for( row = 0; row <= p_board->rows + 1; row++ ) {
468         p_board->box[col][row].IsPressed = FALSE;
469         p_board->box[col][row].IsMine = FALSE;
470         p_board->box[col][row].FlagType = NORMAL;
471         p_board->box[col][row].NumMines = 0;
472       }
473 
474     p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2;
475 
476     p_board->height = p_board->rows * MINE_HEIGHT + LED_HEIGHT
477         + BOARD_HMARGIN * 3;
478 
479     /* setting the mines rectangle boundary */
480     left = BOARD_WMARGIN;
481     top = BOARD_HMARGIN * 2 + LED_HEIGHT;
482     right = left + p_board->cols * MINE_WIDTH;
483     bottom = top + p_board->rows * MINE_HEIGHT;
484     SetRect( &p_board->mines_rect, left, top, right, bottom );
485 
486     /* setting the face rectangle boundary */
487     left = p_board->width / 2 - FACE_WIDTH / 2;
488     top = BOARD_HMARGIN;
489     right = left + FACE_WIDTH;
490     bottom = top + FACE_HEIGHT;
491     SetRect( &p_board->face_rect, left, top, right, bottom );
492 
493     /* setting the timer rectangle boundary */
494     left = BOARD_WMARGIN;
495     top = BOARD_HMARGIN;
496     right = left + LED_WIDTH * 3;
497     bottom = top + LED_HEIGHT;
498     SetRect( &p_board->timer_rect, left, top, right, bottom );
499 
500     /* setting the counter rectangle boundary */
501     left =  p_board->width - BOARD_WMARGIN - LED_WIDTH * 3;
502     top = BOARD_HMARGIN;
503     right = p_board->width - BOARD_WMARGIN;
504     bottom = top + LED_HEIGHT;
505     SetRect( &p_board->counter_rect, left, top, right, bottom );
506 
507     p_board->status = WAITING;
508     p_board->face_bmp = SMILE_BMP;
509     p_board->time = 0;
510 
511     wnd_rect.left   = p_board->pos.x;
512     wnd_rect.right  = p_board->pos.x + p_board->width;
513     wnd_rect.top    = p_board->pos.y;
514     wnd_rect.bottom = p_board->pos.y + p_board->height;
515     AdjustWindowRect(&wnd_rect, wnd_style, TRUE);
516 
517     /* Make sure the window is completely on the screen */
518     MoveOnScreen(&wnd_rect);
519     MoveWindow( p_board->hWnd, wnd_rect.left, wnd_rect.top,
520                 wnd_rect.right - wnd_rect.left,
521                 wnd_rect.bottom - wnd_rect.top,
522                 TRUE );
523     RedrawWindow( p_board->hWnd, NULL, 0,
524                   RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
525 }
526 
527 
528 void CheckLevel( BOARD *p_board )
529 {
530     if( p_board->rows < BEGINNER_ROWS )
531         p_board->rows = BEGINNER_ROWS;
532 
533     if( p_board->rows > MAX_ROWS )
534         p_board->rows = MAX_ROWS;
535 
536     if( p_board->cols < BEGINNER_COLS )
537         p_board->cols = BEGINNER_COLS;
538 
539     if( p_board->cols > MAX_COLS )
540         p_board->cols = MAX_COLS;
541 
542     if( p_board->mines < BEGINNER_MINES )
543         p_board->mines = BEGINNER_MINES;
544 
545     if( p_board->mines > p_board->cols * p_board->rows - 2 )
546         p_board->mines = p_board->cols * p_board->rows - 2;
547 }
548 
549 /* Randomly places mines everywhere except the selected box. */
550 void PlaceMines ( BOARD *p_board, int selected_col, int selected_row )
551 {
552     int i, j;
553     unsigned col, row;
554 
555     srand( (unsigned) time( NULL ) );
556 
557     /* Temporarily place a mine at the selected box until all the other
558      * mines are placed, this avoids checking in the mine creation loop. */
559     p_board->box[selected_col][selected_row].IsMine = TRUE;
560 
561     /* create mines */
562     i = 0;
563     while( (unsigned) i < p_board->mines ) {
564         col = (int) (p_board->cols * (float) rand() / RAND_MAX + 1);
565         row = (int) (p_board->rows * (float) rand() / RAND_MAX + 1);
566 
567         if( !p_board->box[col][row].IsMine ) {
568             i++;
569             p_board->box[col][row].IsMine = TRUE;
570         }
571     }
572 
573     /* Remove temporarily placed mine for selected box */
574     p_board->box[selected_col][selected_row].IsMine = FALSE;
575 
576     /*
577      * Now we label the remaining boxes with the
578      * number of mines surrounding them.
579      */
580     for( col = 1; col < p_board->cols + 1; col++ )
581     for( row = 1; row < p_board->rows + 1; row++ ) {
582         for( i = -1; i <= 1; i++ )
583         for( j = -1; j <= 1; j++ ) {
584             if( p_board->box[col + i][row + j].IsMine ) {
585                 p_board->box[col][row].NumMines++ ;
586             }
587         }
588     }
589 }
590 
591 void DrawMines ( HDC hdc, HDC hMemDC, BOARD *p_board )
592 {
593     HGDIOBJ hOldObj;
594     unsigned col, row;
595     hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
596 
597     for( row = 1; row <= p_board->rows; row++ ) {
598       for( col = 1; col <= p_board->cols; col++ ) {
599         DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
600       }
601     }
602     SelectObject( hMemDC, hOldObj );
603 }
604 
605 void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed )
606 {
607     MINEBMP_OFFSET offset = BOX_BMP;
608 
609     if( col == 0 || col > p_board->cols || row == 0 || row > p_board->rows )
610            return;
611 
612     if( p_board->status == GAMEOVER ) {
613         if( p_board->box[col][row].IsMine ) {
614             switch( p_board->box[col][row].FlagType ) {
615             case FLAG:
616                 offset = FLAG_BMP;
617                 break;
618             case COMPLETE:
619                 offset = EXPLODE_BMP;
620                 break;
621             case QUESTION:
622                 /* fall through */
623             case NORMAL:
624                 offset = MINE_BMP;
625             }
626         } else {
627             switch( p_board->box[col][row].FlagType ) {
628             case QUESTION:
629                 offset = QUESTION_BMP;
630                 break;
631             case FLAG:
632                 offset = WRONG_BMP;
633                 break;
634             case NORMAL:
635                 offset = BOX_BMP;
636                 break;
637             case COMPLETE:
638                 /* Do nothing */
639                 break;
640             default:
641                 WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
642                 break;
643             }
644         }
645     } else {    /* WAITING or PLAYING */
646         switch( p_board->box[col][row].FlagType ) {
647         case QUESTION:
648             if( !IsPressed )
649                 offset = QUESTION_BMP;
650             else
651                 offset = QPRESS_BMP;
652             break;
653         case FLAG:
654             offset = FLAG_BMP;
655             break;
656         case NORMAL:
657             if( !IsPressed )
658                 offset = BOX_BMP;
659             else
660                 offset = MPRESS_BMP;
661             break;
662         case COMPLETE:
663             /* Do nothing */
664             break;
665         default:
666             WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
667             break;
668         }
669     }
670 
671     if( p_board->box[col][row].FlagType == COMPLETE
672         && !p_board->box[col][row].IsMine )
673           offset = (MINEBMP_OFFSET) p_board->box[col][row].NumMines;
674 
675     BitBlt( hdc,
676             (col - 1) * MINE_WIDTH + p_board->mines_rect.left,
677             (row - 1) * MINE_HEIGHT + p_board->mines_rect.top,
678             MINE_WIDTH, MINE_HEIGHT,
679             hMemDC, 0, offset * MINE_HEIGHT, SRCCOPY );
680 }
681 
682 void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y )
683 {
684     HGDIOBJ hOldObj;
685     unsigned led[3], i;
686     int count;
687 
688     count = number;
689     if( count < 1000 ) {
690         if( count >= 0 ) {
691             led[0] = count / 100 ;
692             count -= led[0] * 100;
693         }
694         else {
695             led[0] = 10; /* negative sign */
696             count = -count;
697         }
698         led[1] = count / 10;
699         count -= led[1] * 10;
700         led[2] = count;
701     }
702     else {
703         for( i = 0; i < 3; i++ )
704             led[i] = 10;
705     }
706 
707     hOldObj = SelectObject (hMemDC, p_board->hLedsBMP);
708 
709     for( i = 0; i < 3; i++ ) {
710         BitBlt( hdc,
711             i * LED_WIDTH + x,
712             y,
713             LED_WIDTH,
714             LED_HEIGHT,
715             hMemDC,
716             0,
717             led[i] * LED_HEIGHT,
718             SRCCOPY);
719     }
720 
721     SelectObject( hMemDC, hOldObj );
722 }
723 
724 
725 void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board )
726 {
727     HGDIOBJ hOldObj;
728 
729     hOldObj = SelectObject (hMemDC, p_board->hFacesBMP);
730 
731     BitBlt( hdc,
732         p_board->face_rect.left,
733         p_board->face_rect.top,
734         FACE_WIDTH,
735         FACE_HEIGHT,
736         hMemDC, 0, p_board->face_bmp * FACE_HEIGHT, SRCCOPY);
737 
738     SelectObject( hMemDC, hOldObj );
739 }
740 
741 
742 void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board )
743 {
744     RECT tmp_rect;
745 
746     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->counter_rect ) )
747         DrawLeds( hdc, hMemDC, p_board, p_board->mines - p_board->num_flags,
748                   p_board->counter_rect.left,
749                   p_board->counter_rect.top );
750 
751     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->timer_rect ) )
752         DrawLeds( hdc, hMemDC, p_board, p_board->time,
753                   p_board->timer_rect.left,
754                   p_board->timer_rect.top );
755 
756     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->face_rect ) )
757         DrawFace( hdc, hMemDC, p_board );
758 
759     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->mines_rect ) )
760         DrawMines( hdc, hMemDC, p_board );
761 }
762 
763 
764 void TestBoard( HWND hWnd, BOARD *p_board, int x, int y, int msg )
765 {
766     POINT pt;
767     unsigned col,row;
768 
769     pt.x = x;
770     pt.y = y;
771 
772     if( PtInRect( &p_board->mines_rect, pt ) && p_board->status != GAMEOVER
773     && p_board->status != WON )
774         TestMines( p_board, pt, msg );
775     else {
776         UnpressBoxes( p_board,
777             p_board->press.x,
778             p_board->press.y );
779         p_board->press.x = 0;
780         p_board->press.y = 0;
781     }
782 
783     if( p_board->boxes_left == 0 ) {
784         p_board->status = WON;
785 
786         if (p_board->num_flags < p_board->mines) {
787             for( row = 1; row <= p_board->rows; row++ ) {
788                 for( col = 1; col <= p_board->cols; col++ ) {
789                     if (p_board->box[col][row].IsMine && p_board->box[col][row].FlagType != FLAG)
790                         p_board->box[col][row].FlagType = FLAG;
791                 }
792             }
793 
794             p_board->num_flags = p_board->mines;
795 
796             RedrawWindow( p_board->hWnd, NULL, 0,
797                 RDW_INVALIDATE | RDW_UPDATENOW );
798         }
799 
800         if( p_board->difficulty != CUSTOM &&
801                     p_board->time < p_board->best_time[p_board->difficulty] ) {
802             p_board->best_time[p_board->difficulty] = p_board->time;
803 
804             DialogBoxParam( p_board->hInst, "DLG_CONGRATS", hWnd,
805                     CongratsDlgProc, (LPARAM) p_board);
806 
807             DialogBoxParam( p_board->hInst, "DLG_TIMES", hWnd,
808                     TimesDlgProc, (LPARAM) p_board);
809         }
810     }
811     TestFace( p_board, pt, msg );
812 }
813 
814 void TestMines( BOARD *p_board, POINT pt, int msg )
815 {
816     BOOL draw = TRUE;
817     int col, row;
818 
819     col = (pt.x - p_board->mines_rect.left) / MINE_WIDTH + 1;
820     row = (pt.y - p_board->mines_rect.top ) / MINE_HEIGHT + 1;
821 
822     switch ( msg ) {
823     case WM_LBUTTONDOWN:
824         if( p_board->press.x != col || p_board->press.y != row ) {
825             UnpressBox( p_board,
826                     p_board->press.x, p_board->press.y );
827             p_board->press.x = col;
828             p_board->press.y = row;
829             PressBox( p_board, col, row );
830         }
831         draw = FALSE;
832         break;
833 
834     case WM_LBUTTONUP:
835         if( p_board->press.x != col || p_board->press.y != row )
836             UnpressBox( p_board,
837                     p_board->press.x, p_board->press.y );
838         p_board->press.x = 0;
839         p_board->press.y = 0;
840         if( p_board->box[col][row].FlagType != FLAG
841             && p_board->status != PLAYING )
842         {
843             p_board->status = PLAYING;
844             PlaceMines( p_board, col, row );
845         }
846         CompleteBox( p_board, col, row );
847         break;
848 
849     case WM_MBUTTONDOWN:
850         PressBoxes( p_board, col, row );
851         draw = FALSE;
852         break;
853 
854     case WM_MBUTTONUP:
855         if( p_board->press.x != col || p_board->press.y != row )
856             UnpressBoxes( p_board,
857                     p_board->press.x, p_board->press.y );
858         p_board->press.x = 0;
859         p_board->press.y = 0;
860         CompleteBoxes( p_board, col, row );
861         break;
862 
863     case WM_RBUTTONDOWN:
864         AddFlag( p_board, col, row );
865         break;
866     default:
867         WINE_TRACE("Unknown message type received in TestMines\n");
868         break;
869     }
870 
871     if( draw )
872     {
873         RedrawWindow( p_board->hWnd, NULL, 0,
874             RDW_INVALIDATE | RDW_UPDATENOW );
875     }
876 }
877 
878 
879 void TestFace( BOARD *p_board, POINT pt, int msg )
880 {
881     if( p_board->status == PLAYING || p_board->status == WAITING ) {
882         if( msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN )
883             p_board->face_bmp = OOH_BMP;
884         else p_board->face_bmp = SMILE_BMP;
885     }
886     else if( p_board->status == GAMEOVER )
887         p_board->face_bmp = DEAD_BMP;
888     else if( p_board->status == WON )
889             p_board->face_bmp = COOL_BMP;
890 
891     if( PtInRect( &p_board->face_rect, pt ) ) {
892         if( msg == WM_LBUTTONDOWN )
893             p_board->face_bmp = SPRESS_BMP;
894 
895         if( msg == WM_LBUTTONUP )
896             CreateBoard( p_board );
897     }
898 
899     RedrawWindow( p_board->hWnd, &p_board->face_rect, 0,
900         RDW_INVALIDATE | RDW_UPDATENOW );
901 }
902 
903