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

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

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ 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 ] ~

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

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

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.