main.c 29.2 KB
Newer Older
Joshua Thielen's avatar
Joshua Thielen committed
1 2
/*
 * WineMine (main.c)
3
 *
4
 * Copyright 2000 Joshua Thielen
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Joshua Thielen's avatar
Joshua Thielen committed
19 20
 */

21 22
#define WIN32_LEAN_AND_MEAN

Joshua Thielen's avatar
Joshua Thielen committed
23 24 25
#include <string.h>
#include <time.h>
#include <windows.h>
26
#include <stdlib.h>
Joshua Thielen's avatar
Joshua Thielen committed
27 28 29
#include "main.h"
#include "resource.h"

30 31 32
#include <wine/debug.h>

WINE_DEFAULT_DEBUG_CHANNEL(winemine);
Joshua Thielen's avatar
Joshua Thielen committed
33

34
static const DWORD wnd_style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
35
static const char* registry_key = "Software\\Microsoft\\WinMine";
36 37


Joshua Thielen's avatar
Joshua Thielen committed
38
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow )
39
{
Joshua Thielen's avatar
Joshua Thielen committed
40 41 42
    MSG msg;
    WNDCLASS wc;
    HWND hWnd;
43
    HACCEL haccel;
44
    char appname[20];
Joshua Thielen's avatar
Joshua Thielen committed
45 46 47 48 49 50 51 52

    LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));

    wc.style = 0;
    wc.lpfnWndProc = MainProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
53 54
    wc.hIcon = LoadIcon( hInst, "WINEMINE" );
    wc.hCursor = LoadCursor( 0, IDI_APPLICATION );
Joshua Thielen's avatar
Joshua Thielen committed
55 56 57
    wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
    wc.lpszMenuName = "MENU_WINEMINE";
    wc.lpszClassName = appname;
58

59
    if (!RegisterClass(&wc)) ExitProcess(1);
60
    hWnd = CreateWindow( appname, appname,
61
	wnd_style,
62
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
63
        0, 0, hInst, NULL );
64

65
    if (!hWnd) ExitProcess(1);
66

Joshua Thielen's avatar
Joshua Thielen committed
67 68 69
    ShowWindow( hWnd, cmdshow );
    UpdateWindow( hWnd );

70
    haccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDA_WINEMINE) );
71
    SetTimer( hWnd, ID_TIMER, 1000, NULL );
Joshua Thielen's avatar
Joshua Thielen committed
72

73
    while( GetMessage(&msg, 0, 0, 0) ) {
Joshua Thielen's avatar
Joshua Thielen committed
74 75
        if (!TranslateAccelerator( hWnd, haccel, &msg ))
            TranslateMessage( &msg );
76

Joshua Thielen's avatar
Joshua Thielen committed
77 78 79 80 81 82 83 84 85
        DispatchMessage( &msg );
    }
    return msg.wParam;
}

LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
86 87
    HMENU hMenu;
    static BOARD board;
Joshua Thielen's avatar
Joshua Thielen committed
88 89

    switch( msg ) {
90
    case WM_CREATE:
Joshua Thielen's avatar
Joshua Thielen committed
91 92 93 94 95 96 97
        board.hInst = ((LPCREATESTRUCT) lParam)->hInstance;
        board.hWnd = hWnd;
        InitBoard( &board );
        CreateBoard( &board );
        return 0;

    case WM_PAINT:
98 99 100
      {
        HDC hMemDC;

101
        WINE_TRACE("WM_PAINT\n");
Joshua Thielen's avatar
Joshua Thielen committed
102
        hdc = BeginPaint( hWnd, &ps );
103 104 105 106 107
        hMemDC = CreateCompatibleDC( hdc );

        DrawBoard( hdc, hMemDC, &ps, &board );

        DeleteDC( hMemDC );
Joshua Thielen's avatar
Joshua Thielen committed
108
        EndPaint( hWnd, &ps );
109

Joshua Thielen's avatar
Joshua Thielen committed
110
        return 0;
111
      }
Joshua Thielen's avatar
Joshua Thielen committed
112 113

    case WM_MOVE:
114
        WINE_TRACE("WM_MOVE\n");
115 116
        board.pos.x = (short)LOWORD(lParam);
        board.pos.y = (short)HIWORD(lParam);
Joshua Thielen's avatar
Joshua Thielen committed
117 118 119 120
        return 0;

    case WM_DESTROY:
        SaveBoard( &board );
121
        DestroyBoard( &board );
Joshua Thielen's avatar
Joshua Thielen committed
122 123
        PostQuitMessage( 0 );
        return 0;
124

Joshua Thielen's avatar
Joshua Thielen committed
125 126 127
    case WM_TIMER:
        if( board.status == PLAYING ) {
            board.time++;
128 129
	    RedrawWindow( hWnd, &board.timer_rect, 0,
			  RDW_INVALIDATE | RDW_UPDATENOW );
Joshua Thielen's avatar
Joshua Thielen committed
130 131 132 133
        }
        return 0;

    case WM_LBUTTONDOWN:
134
        WINE_TRACE("WM_LBUTTONDOWN\n");
Joshua Thielen's avatar
Joshua Thielen committed
135
        if( wParam & MK_RBUTTON )
136
            msg = WM_MBUTTONDOWN;
137
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
Joshua Thielen's avatar
Joshua Thielen committed
138 139 140 141
        SetCapture( hWnd );
        return 0;

    case WM_LBUTTONUP:
142
        WINE_TRACE("WM_LBUTTONUP\n");
Joshua Thielen's avatar
Joshua Thielen committed
143
        if( wParam & MK_RBUTTON )
144
            msg = WM_MBUTTONUP;
145
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
Joshua Thielen's avatar
Joshua Thielen committed
146 147 148 149
        ReleaseCapture();
        return 0;

    case WM_RBUTTONDOWN:
150
        WINE_TRACE("WM_RBUTTONDOWN\n");
151
        if( wParam & MK_LBUTTON ) {
Joshua Thielen's avatar
Joshua Thielen committed
152
            board.press.x = 0;
153
            board.press.y = 0;
Joshua Thielen's avatar
Joshua Thielen committed
154
            msg = WM_MBUTTONDOWN;
155
        }
156
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
Joshua Thielen's avatar
Joshua Thielen committed
157 158 159
        return 0;

    case WM_RBUTTONUP:
160
        WINE_TRACE("WM_RBUTTONUP\n");
161 162
        if( wParam & MK_LBUTTON )
            msg = WM_MBUTTONUP;
163
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
Joshua Thielen's avatar
Joshua Thielen committed
164 165
        return 0;

166
    case WM_MBUTTONDOWN:
167
        WINE_TRACE("WM_MBUTTONDOWN\n");
168
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
169 170 171
        return 0;

    case WM_MBUTTONUP:
172
        WINE_TRACE("WM_MBUTTONUP\n");
173
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
174 175
        return 0;

Joshua Thielen's avatar
Joshua Thielen committed
176
    case WM_MOUSEMOVE:
177 178 179 180 181 182 183 184 185 186 187
    {
        if( (wParam & MK_LBUTTON) && (wParam & MK_RBUTTON) ) {
            msg = WM_MBUTTONDOWN;
        }
        else if( wParam & MK_LBUTTON ) {
            msg = WM_LBUTTONDOWN;
        }
        else {
            return 0;
        }

188
        TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam),  msg );
189

190 191
        return 0;
    }
Joshua Thielen's avatar
Joshua Thielen committed
192 193 194 195 196 197 198 199

    case WM_COMMAND:
        switch(LOWORD(wParam)) {
        case IDM_NEW:
            CreateBoard( &board );
            return 0;

        case IDM_MARKQ:
200
            hMenu = GetMenu( hWnd );
Joshua Thielen's avatar
Joshua Thielen committed
201 202 203
            board.IsMarkQ = !board.IsMarkQ;
            if( board.IsMarkQ )
                CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
204
            else
Joshua Thielen's avatar
Joshua Thielen committed
205 206 207 208
                CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
            return 0;

        case IDM_BEGINNER:
209
            SetDifficulty( &board, BEGINNER );
Joshua Thielen's avatar
Joshua Thielen committed
210 211 212 213
            CreateBoard( &board );
            return 0;

        case IDM_ADVANCED:
214
            SetDifficulty( &board, ADVANCED );
Joshua Thielen's avatar
Joshua Thielen committed
215 216 217 218
            CreateBoard( &board );
            return 0;

        case IDM_EXPERT:
219
            SetDifficulty( &board, EXPERT );
Joshua Thielen's avatar
Joshua Thielen committed
220 221 222 223 224 225 226 227 228 229 230 231 232
            CreateBoard( &board );
            return 0;

        case IDM_CUSTOM:
            SetDifficulty( &board, CUSTOM );
            CreateBoard( &board );
            return 0;

        case IDM_EXIT:
            SendMessage( hWnd, WM_CLOSE, 0, 0);
            return 0;

        case IDM_TIMES:
233
            DialogBoxParam( board.hInst, "DLG_TIMES", hWnd,
Joshua Thielen's avatar
Joshua Thielen committed
234 235 236 237 238 239
                    TimesDlgProc, (LPARAM) &board);
            return 0;

        case IDM_ABOUT:
            DialogBox( board.hInst, "DLG_ABOUT", hWnd, AboutDlgProc );
            return 0;
240
        default:
241
            WINE_TRACE("Unknown WM_COMMAND command message received\n");
242
            break;
Joshua Thielen's avatar
Joshua Thielen committed
243
        }
244
    }
Joshua Thielen's avatar
Joshua Thielen committed
245 246 247 248 249 250 251 252 253
    return( DefWindowProc( hWnd, msg, wParam, lParam ));
}

void InitBoard( BOARD *p_board )
{
    HMENU hMenu;

    p_board->hMinesBMP = LoadBitmap( p_board->hInst, "mines");
    p_board->hFacesBMP = LoadBitmap( p_board->hInst, "faces");
254 255 256 257
    p_board->hLedsBMP = LoadBitmap( p_board->hInst, "leds");

    LoadBoard( p_board );

Joshua Thielen's avatar
Joshua Thielen committed
258
    hMenu = GetMenu( p_board->hWnd );
259
    CheckMenuItem( hMenu, IDM_BEGINNER + (unsigned) p_board->difficulty,
Joshua Thielen's avatar
Joshua Thielen committed
260 261 262
            MF_CHECKED );
    if( p_board->IsMarkQ )
        CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
263
    else
Joshua Thielen's avatar
Joshua Thielen committed
264 265 266 267
        CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
    CheckLevel( p_board );
}

268
void LoadBoard( BOARD *p_board )
Joshua Thielen's avatar
Joshua Thielen committed
269 270 271 272 273 274 275 276
{
    DWORD size;
    DWORD type;
    HKEY hkey;
    char data[16];
    char key_name[8];
    unsigned i;

277
    RegOpenKeyEx( HKEY_CURRENT_USER, registry_key,
Joshua Thielen's avatar
Joshua Thielen committed
278
            0, KEY_QUERY_VALUE, &hkey );
279

280 281 282
    size = sizeof( p_board->pos.x );
    if( !RegQueryValueEx( hkey, "Xpos", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->pos.x, (LPDWORD) &size ) == ERROR_SUCCESS )
283
	p_board->pos.x = 0;
Joshua Thielen's avatar
Joshua Thielen committed
284

285 286 287
    size = sizeof( p_board->pos.y );
    if( !RegQueryValueEx( hkey, "Ypos", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->pos.y, (LPDWORD) &size ) == ERROR_SUCCESS )
288
        p_board->pos.y = 0;
Joshua Thielen's avatar
Joshua Thielen committed
289

290 291 292
    size = sizeof( p_board->rows );
    if( !RegQueryValueEx( hkey, "Height", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->rows, (LPDWORD) &size ) == ERROR_SUCCESS )
Joshua Thielen's avatar
Joshua Thielen committed
293 294
        p_board->rows = BEGINNER_ROWS;

295 296 297
    size = sizeof( p_board->cols );
    if( !RegQueryValueEx( hkey, "Width", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->cols, (LPDWORD) &size ) == ERROR_SUCCESS )
298 299
        p_board->cols = BEGINNER_COLS;

300 301 302 303
    size = sizeof( p_board->mines );
    if( !RegQueryValueEx( hkey, "Mines", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->mines, (LPDWORD) &size ) == ERROR_SUCCESS )
        p_board->mines = BEGINNER_MINES;
Joshua Thielen's avatar
Joshua Thielen committed
304

305 306 307
    size = sizeof( p_board->difficulty );
    if( !RegQueryValueEx( hkey, "Difficulty", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->difficulty, (LPDWORD) &size ) == ERROR_SUCCESS )
Joshua Thielen's avatar
Joshua Thielen committed
308 309
        p_board->difficulty = BEGINNER;

310 311 312
    size = sizeof( p_board->IsMarkQ );
    if( !RegQueryValueEx( hkey, "Mark", NULL, (LPDWORD) &type,
            (LPBYTE) &p_board->IsMarkQ, (LPDWORD) &size ) == ERROR_SUCCESS )
Joshua Thielen's avatar
Joshua Thielen committed
313
        p_board->IsMarkQ = TRUE;
314

Joshua Thielen's avatar
Joshua Thielen committed
315
    for( i = 0; i < 3; i++ ) {
316
        wsprintf( key_name, "Name%d", i+1 );
Joshua Thielen's avatar
Joshua Thielen committed
317
        size = sizeof( data );
318 319
        if( RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
                (LPBYTE) data,
Joshua Thielen's avatar
Joshua Thielen committed
320
                (LPDWORD) &size ) == ERROR_SUCCESS )
321
                    lstrcpynA( p_board->best_name[i], data, sizeof(p_board->best_name[i]) );
322
        else
323
            LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], 16 );
Joshua Thielen's avatar
Joshua Thielen committed
324
    }
325

Joshua Thielen's avatar
Joshua Thielen committed
326
    for( i = 0; i < 3; i++ ) {
327 328 329 330
        wsprintf( key_name, "Time%d", i+1 );
        size = sizeof( p_board->best_time[i] );
        if( !RegQueryValueEx( hkey, key_name, NULL, (LPDWORD) &type,
                (LPBYTE) &p_board->best_time[i],
Joshua Thielen's avatar
Joshua Thielen committed
331 332 333 334 335 336 337 338 339 340 341 342
                (LPDWORD) &size ) == ERROR_SUCCESS )
            p_board->best_time[i] = 999;
    }
    RegCloseKey( hkey );
}

void SaveBoard( BOARD *p_board )
{
    HKEY hkey;
    unsigned i;
    char data[16];
    char key_name[8];
343

344 345
    if( RegCreateKeyEx( HKEY_CURRENT_USER, registry_key,
	        0, NULL,
346 347
                REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
                &hkey, NULL ) != ERROR_SUCCESS)
348
        return;
349

350 351 352 353 354 355 356
    RegSetValueEx( hkey, "Xpos", 0, REG_DWORD, (LPBYTE) &p_board->pos.x, sizeof(p_board->pos.x) );
    RegSetValueEx( hkey, "Ypos", 0, REG_DWORD, (LPBYTE) &p_board->pos.y, sizeof(p_board->pos.y) );
    RegSetValueEx( hkey, "Difficulty", 0, REG_DWORD, (LPBYTE) &p_board->difficulty, sizeof(p_board->difficulty) );
    RegSetValueEx( hkey, "Height", 0, REG_DWORD, (LPBYTE) &p_board->rows, sizeof(p_board->rows) );
    RegSetValueEx( hkey, "Width", 0, REG_DWORD, (LPBYTE) &p_board->cols, sizeof(p_board->cols) );
    RegSetValueEx( hkey, "Mines", 0, REG_DWORD, (LPBYTE) &p_board->mines, sizeof(p_board->mines) );
    RegSetValueEx( hkey, "Mark", 0, REG_DWORD, (LPBYTE) &p_board->IsMarkQ, sizeof(p_board->IsMarkQ) );
Joshua Thielen's avatar
Joshua Thielen committed
357 358

    for( i = 0; i < 3; i++ ) {
359
        wsprintf( key_name, "Name%u", i+1 );
360
        lstrcpyn( data, p_board->best_name[i], sizeof( data ) );
361
        RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
Joshua Thielen's avatar
Joshua Thielen committed
362 363 364
    }

    for( i = 0; i < 3; i++ ) {
365 366
        wsprintf( key_name, "Time%u", i+1 );
        RegSetValueEx( hkey, key_name, 0, REG_DWORD, (LPBYTE) &p_board->best_time[i], sizeof(p_board->best_time[i]) );
Joshua Thielen's avatar
Joshua Thielen committed
367 368 369 370
    }
    RegCloseKey( hkey );
}

371 372 373 374 375 376 377
void DestroyBoard( BOARD *p_board )
{
    DeleteObject( p_board->hFacesBMP );
    DeleteObject( p_board->hLedsBMP );
    DeleteObject( p_board->hMinesBMP );
}

Joshua Thielen's avatar
Joshua Thielen committed
378 379
void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty )
{
380 381 382 383 384 385
    HMENU hMenu;

    if ( difficulty == CUSTOM )
        if (DialogBoxParam( p_board->hInst, "DLG_CUSTOM", p_board->hWnd,
                    CustomDlgProc, (LPARAM) p_board) != 0)
           return;
Joshua Thielen's avatar
Joshua Thielen committed
386

387
    hMenu = GetMenu( p_board->hWnd );
Joshua Thielen's avatar
Joshua Thielen committed
388
    CheckMenuItem( hMenu, IDM_BEGINNER + p_board->difficulty, MF_UNCHECKED );
389
    p_board->difficulty = difficulty;
Joshua Thielen's avatar
Joshua Thielen committed
390
    CheckMenuItem( hMenu, IDM_BEGINNER + difficulty, MF_CHECKED );
391

Joshua Thielen's avatar
Joshua Thielen committed
392
    switch( difficulty ) {
393
    case BEGINNER:
Joshua Thielen's avatar
Joshua Thielen committed
394 395 396 397 398
        p_board->cols = BEGINNER_COLS;
        p_board->rows = BEGINNER_ROWS;
        p_board->mines = BEGINNER_MINES;
        break;

399
    case ADVANCED:
Joshua Thielen's avatar
Joshua Thielen committed
400 401 402 403 404 405 406 407
        p_board->cols = ADVANCED_COLS;
        p_board->rows = ADVANCED_ROWS;
        p_board->mines = ADVANCED_MINES;
        break;

    case EXPERT:
        p_board->cols = EXPERT_COLS;
        p_board->rows = EXPERT_ROWS;
408

409 410
        p_board->mines = EXPERT_MINES;
        break;
Joshua Thielen's avatar
Joshua Thielen committed
411 412

    case CUSTOM:
413
        break;
Joshua Thielen's avatar
Joshua Thielen committed
414 415 416
    }
}

417
static void ShiftBetween(LONG* x, LONG* y, LONG a, LONG b)
418 419 420 421 422 423 424 425 426 427
{
    if (*x < a) {
	*y += a - *x;
	*x = a;
    }
    else if (*y > b) {
	*x -= *y - b;
	*y = b;
    }
}
428 429

static void MoveOnScreen(RECT* rect)
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
{
    HMONITOR hMonitor;
    MONITORINFO mi;

    /* find the nearest monitor ... */
    hMonitor = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);

    /* ... and move it into the work area (ie excluding task bar)*/
    mi.cbSize = sizeof(mi);
    GetMonitorInfo(hMonitor, &mi);

    ShiftBetween(&rect->left, &rect->right, mi.rcWork.left, mi.rcWork.right);
    ShiftBetween(&rect->top, &rect->bottom, mi.rcWork.top, mi.rcWork.bottom);
}

Joshua Thielen's avatar
Joshua Thielen committed
445 446
void CreateBoard( BOARD *p_board )
{
447 448
    int left, top, bottom, right;
    RECT wnd_rect;
Joshua Thielen's avatar
Joshua Thielen committed
449 450 451 452

    p_board->mb = MB_NONE;
    p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines;
    p_board->num_flags = 0;
453

Joshua Thielen's avatar
Joshua Thielen committed
454 455 456
    CreateBoxes( p_board );

    p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2;
457 458

    p_board->height = p_board->rows * MINE_HEIGHT + LED_HEIGHT
Joshua Thielen's avatar
Joshua Thielen committed
459 460
        + BOARD_HMARGIN * 3;

461 462 463
    /* setting the mines rectangle boundary */
    left = BOARD_WMARGIN;
    top = BOARD_HMARGIN * 2 + LED_HEIGHT;
Joshua Thielen's avatar
Joshua Thielen committed
464 465 466 467
    right = left + p_board->cols * MINE_WIDTH;
    bottom = top + p_board->rows * MINE_HEIGHT;
    SetRect( &p_board->mines_rect, left, top, right, bottom );

468
    /* setting the face rectangle boundary */
Joshua Thielen's avatar
Joshua Thielen committed
469 470 471
    left = p_board->width / 2 - FACE_WIDTH / 2;
    top = BOARD_HMARGIN;
    right = left + FACE_WIDTH;
472
    bottom = top + FACE_HEIGHT;
Joshua Thielen's avatar
Joshua Thielen committed
473
    SetRect( &p_board->face_rect, left, top, right, bottom );
474 475

    /* setting the timer rectangle boundary */
Joshua Thielen's avatar
Joshua Thielen committed
476 477 478
    left = BOARD_WMARGIN;
    top = BOARD_HMARGIN;
    right = left + LED_WIDTH * 3;
479
    bottom = top + LED_HEIGHT;
Joshua Thielen's avatar
Joshua Thielen committed
480
    SetRect( &p_board->timer_rect, left, top, right, bottom );
481 482

    /* setting the counter rectangle boundary */
Joshua Thielen's avatar
Joshua Thielen committed
483 484 485
    left =  p_board->width - BOARD_WMARGIN - LED_WIDTH * 3;
    top = BOARD_HMARGIN;
    right = p_board->width - BOARD_WMARGIN;
486
    bottom = top + LED_HEIGHT;
Joshua Thielen's avatar
Joshua Thielen committed
487
    SetRect( &p_board->counter_rect, left, top, right, bottom );
488

Joshua Thielen's avatar
Joshua Thielen committed
489
    p_board->status = WAITING;
490
    p_board->face_bmp = SMILE_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
491 492
    p_board->time = 0;

493 494 495 496 497 498 499 500 501 502 503 504 505 506
    wnd_rect.left   = p_board->pos.x;
    wnd_rect.right  = p_board->pos.x + p_board->width;
    wnd_rect.top    = p_board->pos.y;
    wnd_rect.bottom = p_board->pos.y + p_board->height;
    AdjustWindowRect(&wnd_rect, wnd_style, TRUE);

    /* Make sure the window is completely on the screen */
    MoveOnScreen(&wnd_rect);
    MoveWindow( p_board->hWnd, wnd_rect.left, wnd_rect.top,
		wnd_rect.right - wnd_rect.left,
		wnd_rect.bottom - wnd_rect.top,
		TRUE );
    RedrawWindow( p_board->hWnd, NULL, 0,
		  RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
Joshua Thielen's avatar
Joshua Thielen committed
507 508 509 510 511 512 513 514 515 516
}


void CheckLevel( BOARD *p_board )
{
    if( p_board->rows < BEGINNER_ROWS )
        p_board->rows = BEGINNER_ROWS;

    if( p_board->rows > MAX_ROWS )
        p_board->rows = MAX_ROWS;
517

Joshua Thielen's avatar
Joshua Thielen committed
518 519 520 521 522 523 524
    if( p_board->cols < BEGINNER_COLS )
        p_board->cols = BEGINNER_COLS;

    if( p_board->cols > MAX_COLS )
        p_board->cols = MAX_COLS;

    if( p_board->mines < BEGINNER_MINES )
525
        p_board->mines = BEGINNER_MINES;
Joshua Thielen's avatar
Joshua Thielen committed
526

527 528
    if( p_board->mines > p_board->cols * p_board->rows - 1 )
        p_board->mines = p_board->cols * p_board->rows - 1;
Joshua Thielen's avatar
Joshua Thielen committed
529 530 531 532 533 534 535 536 537 538
}


void CreateBoxes( BOARD *p_board )
{
    int i, j;
    unsigned col, row;

    srand( (unsigned) time( NULL ) );

539
    /* Create the boxes...
Joshua Thielen's avatar
Joshua Thielen committed
540 541 542
     * We actually create them with an empty border,
     * so special care doesn't have to be taken on the edges
     */
543

Joshua Thielen's avatar
Joshua Thielen committed
544
    for( col = 0; col <= p_board->cols + 1; col++ )
545
      for( row = 0; row <= p_board->rows + 1; row++ ) {
546
        p_board->box[col][row].IsPressed = FALSE;
Joshua Thielen's avatar
Joshua Thielen committed
547 548 549
        p_board->box[col][row].IsMine = FALSE;
        p_board->box[col][row].FlagType = NORMAL;
        p_board->box[col][row].NumMines = 0;
550
      }
Joshua Thielen's avatar
Joshua Thielen committed
551 552 553

    /* create mines */
    i = 0;
554 555 556
    while( (unsigned) i < p_board->mines ) {
        col = (int) (p_board->cols * (float) rand() / RAND_MAX + 1);
        row = (int) (p_board->rows * (float) rand() / RAND_MAX + 1);
Joshua Thielen's avatar
Joshua Thielen committed
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579

        if( !p_board->box[col][row].IsMine ) {
            i++;
            p_board->box[col][row].IsMine = TRUE;
        }
    }

    /*
     * Now we label the remaining boxes with the
     * number of mines surrounding them.
     */

    for( col = 1; col < p_board->cols + 1; col++ )
    for( row = 1; row < p_board->rows + 1; row++ ) {
        for( i = -1; i <= 1; i++ )
        for( j = -1; j <= 1; j++ ) {
            if( p_board->box[col + i][row + j].IsMine ) {
                p_board->box[col][row].NumMines++ ;
            }
        }
    }
}

580
void DrawMines ( HDC hdc, HDC hMemDC, BOARD *p_board )
Joshua Thielen's avatar
Joshua Thielen committed
581
{
582
    HGDIOBJ hOldObj;
Joshua Thielen's avatar
Joshua Thielen committed
583
    unsigned col, row;
584
    hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
Joshua Thielen's avatar
Joshua Thielen committed
585

586
    for( row = 1; row <= p_board->rows; row++ ) {
587
      for( col = 1; col <= p_board->cols; col++ ) {
588
        DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
589 590
      }
    }
591
    SelectObject( hMemDC, hOldObj );
Joshua Thielen's avatar
Joshua Thielen committed
592 593
}

594
void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed )
Joshua Thielen's avatar
Joshua Thielen committed
595 596 597 598
{
    MINEBMP_OFFSET offset = BOX_BMP;

    if( col == 0 || col > p_board->cols || row == 0 || row > p_board->rows )
599
           return;
Joshua Thielen's avatar
Joshua Thielen committed
600 601 602 603 604 605 606 607

    if( p_board->status == GAMEOVER ) {
        if( p_board->box[col][row].IsMine ) {
            switch( p_board->box[col][row].FlagType ) {
            case FLAG:
                offset = FLAG_BMP;
                break;
            case COMPLETE:
608
                offset = EXPLODE_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
609
                break;
610 611
            case QUESTION:
                /* fall through */
Joshua Thielen's avatar
Joshua Thielen committed
612 613 614
            case NORMAL:
                offset = MINE_BMP;
            }
615
        } else {
616
            switch( p_board->box[col][row].FlagType ) {
Joshua Thielen's avatar
Joshua Thielen committed
617
            case QUESTION:
618
                offset = QUESTION_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
619 620 621 622
                break;
            case FLAG:
                offset = WRONG_BMP;
                break;
623
            case NORMAL:
Joshua Thielen's avatar
Joshua Thielen committed
624
                offset = BOX_BMP;
625 626 627 628 629
                break;
            case COMPLETE:
                /* Do nothing */
                break;
            default:
630
                WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
631
                break;
Joshua Thielen's avatar
Joshua Thielen committed
632
            }
633
        }
634
    } else {    /* WAITING or PLAYING */
Joshua Thielen's avatar
Joshua Thielen committed
635 636
        switch( p_board->box[col][row].FlagType ) {
        case QUESTION:
637 638
            if( !IsPressed )
                offset = QUESTION_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
639
            else
640
                offset = QPRESS_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
641 642 643 644
            break;
        case FLAG:
            offset = FLAG_BMP;
            break;
645
        case NORMAL:
Joshua Thielen's avatar
Joshua Thielen committed
646 647
            if( !IsPressed )
                offset = BOX_BMP;
648
            else
Joshua Thielen's avatar
Joshua Thielen committed
649
                offset = MPRESS_BMP;
650 651 652 653 654
            break;
        case COMPLETE:
            /* Do nothing */
            break;
        default:
655
            WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
656
            break;
Joshua Thielen's avatar
Joshua Thielen committed
657
        }
658
    }
Joshua Thielen's avatar
Joshua Thielen committed
659

660
    if( p_board->box[col][row].FlagType == COMPLETE
661
        && !p_board->box[col][row].IsMine )
Joshua Thielen's avatar
Joshua Thielen committed
662
          offset = (MINEBMP_OFFSET) p_board->box[col][row].NumMines;
663

Joshua Thielen's avatar
Joshua Thielen committed
664
    BitBlt( hdc,
665 666 667 668
            (col - 1) * MINE_WIDTH + p_board->mines_rect.left,
            (row - 1) * MINE_HEIGHT + p_board->mines_rect.top,
            MINE_WIDTH, MINE_HEIGHT,
            hMemDC, 0, offset * MINE_HEIGHT, SRCCOPY );
Joshua Thielen's avatar
Joshua Thielen committed
669 670
}

671
void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y )
Joshua Thielen's avatar
Joshua Thielen committed
672
{
673
    HGDIOBJ hOldObj;
Joshua Thielen's avatar
Joshua Thielen committed
674
    unsigned led[3], i;
675
    int count;
Joshua Thielen's avatar
Joshua Thielen committed
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698

    count = number;
    if( count < 1000 ) {
        if( count >= 0 ) {
            led[0] = count / 100 ;
            count -= led[0] * 100;
        }
        else {
            led[0] = 10; /* negative sign */
            count = -count;
        }
        led[1] = count / 10;
        count -= led[1] * 10;
        led[2] = count;
    }
    else {
        for( i = 0; i < 3; i++ )
            led[i] = 10;
    }

    /* use unlit led if not playing */
    if( p_board->status == WAITING )
        for( i = 0; i < 3; i++ )
699 700
            led[i] = 11;

701
    hOldObj = SelectObject (hMemDC, p_board->hLedsBMP);
702

Joshua Thielen's avatar
Joshua Thielen committed
703 704 705 706 707 708
    for( i = 0; i < 3; i++ ) {
        BitBlt( hdc,
            i * LED_WIDTH + x,
            y,
            LED_WIDTH,
            LED_HEIGHT,
709 710 711
            hMemDC,
            0,
            led[i] * LED_HEIGHT,
Joshua Thielen's avatar
Joshua Thielen committed
712 713
            SRCCOPY);
    }
714

715
    SelectObject( hMemDC, hOldObj );
Joshua Thielen's avatar
Joshua Thielen committed
716 717 718
}


719
void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board )
Joshua Thielen's avatar
Joshua Thielen committed
720
{
721
    HGDIOBJ hOldObj;
722 723

    hOldObj = SelectObject (hMemDC, p_board->hFacesBMP);
Joshua Thielen's avatar
Joshua Thielen committed
724 725 726 727 728 729 730

    BitBlt( hdc,
        p_board->face_rect.left,
        p_board->face_rect.top,
        FACE_WIDTH,
        FACE_HEIGHT,
        hMemDC, 0, p_board->face_bmp * FACE_HEIGHT, SRCCOPY);
731

732
    SelectObject( hMemDC, hOldObj );
Joshua Thielen's avatar
Joshua Thielen committed
733 734 735
}


736
void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board )
Joshua Thielen's avatar
Joshua Thielen committed
737
{
738 739 740
    RECT tmp_rect;

    if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->counter_rect ) )
741 742 743
        DrawLeds( hdc, hMemDC, p_board, p_board->mines - p_board->num_flags,
                  p_board->counter_rect.left,
                  p_board->counter_rect.top );
Joshua Thielen's avatar
Joshua Thielen committed
744

745
    if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->timer_rect ) )
746
        DrawLeds( hdc, hMemDC, p_board, p_board->time,
747
                  p_board->timer_rect.left,
748
                  p_board->timer_rect.top );
749 750

    if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->face_rect ) )
751
        DrawFace( hdc, hMemDC, p_board );
752 753

    if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->mines_rect ) )
754
        DrawMines( hdc, hMemDC, p_board );
755
}
Joshua Thielen's avatar
Joshua Thielen committed
756 757


758
void TestBoard( HWND hWnd, BOARD *p_board, int x, int y, int msg )
Joshua Thielen's avatar
Joshua Thielen committed
759 760
{
    POINT pt;
761
    unsigned col,row;
762

Joshua Thielen's avatar
Joshua Thielen committed
763 764 765 766
    pt.x = x;
    pt.y = y;

    if( PtInRect( &p_board->mines_rect, pt ) && p_board->status != GAMEOVER
767
    && p_board->status != WON )
Joshua Thielen's avatar
Joshua Thielen committed
768 769
        TestMines( p_board, pt, msg );
    else {
770 771 772
        UnpressBoxes( p_board,
            p_board->press.x,
            p_board->press.y );
Joshua Thielen's avatar
Joshua Thielen committed
773 774 775 776 777 778
        p_board->press.x = 0;
        p_board->press.y = 0;
    }

    if( p_board->boxes_left == 0 ) {
        p_board->status = WON;
779

780 781 782 783 784 785 786 787 788 789
        if (p_board->num_flags < p_board->mines) {
            for( row = 1; row <= p_board->rows; row++ ) {
                for( col = 1; col <= p_board->cols; col++ ) {
                    if (p_board->box[col][row].IsMine && p_board->box[col][row].FlagType != FLAG)
                        p_board->box[col][row].FlagType = FLAG;
                }
            }

            p_board->num_flags = p_board->mines;

790
            RedrawWindow( p_board->hWnd, NULL, 0,
791 792 793
                RDW_INVALIDATE | RDW_UPDATENOW );
        }

Joshua Thielen's avatar
Joshua Thielen committed
794 795 796
        if( p_board->difficulty != CUSTOM &&
                    p_board->time < p_board->best_time[p_board->difficulty] ) {
            p_board->best_time[p_board->difficulty] = p_board->time;
797 798

            DialogBoxParam( p_board->hInst, "DLG_CONGRATS", hWnd,
Joshua Thielen's avatar
Joshua Thielen committed
799
                    CongratsDlgProc, (LPARAM) p_board);
800 801

            DialogBoxParam( p_board->hInst, "DLG_TIMES", hWnd,
Joshua Thielen's avatar
Joshua Thielen committed
802 803 804
                    TimesDlgProc, (LPARAM) p_board);
        }
    }
805
    TestFace( p_board, pt, msg );
Joshua Thielen's avatar
Joshua Thielen committed
806 807 808 809 810
}

void TestMines( BOARD *p_board, POINT pt, int msg )
{
    BOOL draw = TRUE;
811
    int col, row;
Joshua Thielen's avatar
Joshua Thielen committed
812 813 814

    col = (pt.x - p_board->mines_rect.left) / MINE_WIDTH + 1;
    row = (pt.y - p_board->mines_rect.top ) / MINE_HEIGHT + 1;
815

Joshua Thielen's avatar
Joshua Thielen committed
816 817 818
    switch ( msg ) {
    case WM_LBUTTONDOWN:
        if( p_board->press.x != col || p_board->press.y != row ) {
819
            UnpressBox( p_board,
Joshua Thielen's avatar
Joshua Thielen committed
820 821 822
                    p_board->press.x, p_board->press.y );
            p_board->press.x = col;
            p_board->press.y = row;
823 824 825
            PressBox( p_board, col, row );
        }
        draw = FALSE;
Joshua Thielen's avatar
Joshua Thielen committed
826 827 828 829
        break;

    case WM_LBUTTONUP:
        if( p_board->press.x != col || p_board->press.y != row )
830
            UnpressBox( p_board,
Joshua Thielen's avatar
Joshua Thielen committed
831 832 833 834
                    p_board->press.x, p_board->press.y );
        p_board->press.x = 0;
        p_board->press.y = 0;
        if( p_board->box[col][row].FlagType != FLAG )
835
            p_board->status = PLAYING;
Joshua Thielen's avatar
Joshua Thielen committed
836 837 838 839 840
        CompleteBox( p_board, col, row );
        break;

    case WM_MBUTTONDOWN:
        PressBoxes( p_board, col, row );
841
        draw = FALSE;
Joshua Thielen's avatar
Joshua Thielen committed
842 843 844 845
        break;

    case WM_MBUTTONUP:
        if( p_board->press.x != col || p_board->press.y != row )
846
            UnpressBoxes( p_board,
Joshua Thielen's avatar
Joshua Thielen committed
847 848 849 850 851 852 853 854
                    p_board->press.x, p_board->press.y );
        p_board->press.x = 0;
        p_board->press.y = 0;
        CompleteBoxes( p_board, col, row );
        break;

    case WM_RBUTTONDOWN:
        AddFlag( p_board, col, row );
855
        p_board->status = PLAYING;
856 857
        break;
    default:
858
        WINE_TRACE("Unknown message type received in TestMines\n");
Joshua Thielen's avatar
Joshua Thielen committed
859 860
        break;
    }
861

Joshua Thielen's avatar
Joshua Thielen committed
862 863
    if( draw )
    {
864
        RedrawWindow( p_board->hWnd, NULL, 0,
Joshua Thielen's avatar
Joshua Thielen committed
865 866
            RDW_INVALIDATE | RDW_UPDATENOW );
    }
867
}
Joshua Thielen's avatar
Joshua Thielen committed
868 869 870 871 872 873 874 875 876


void TestFace( BOARD *p_board, POINT pt, int msg )
{
    if( p_board->status == PLAYING || p_board->status == WAITING ) {
        if( msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN )
            p_board->face_bmp = OOH_BMP;
        else p_board->face_bmp = SMILE_BMP;
    }
877
    else if( p_board->status == GAMEOVER )
Joshua Thielen's avatar
Joshua Thielen committed
878
        p_board->face_bmp = DEAD_BMP;
879
    else if( p_board->status == WON )
Joshua Thielen's avatar
Joshua Thielen committed
880 881
            p_board->face_bmp = COOL_BMP;

882 883
    if( PtInRect( &p_board->face_rect, pt ) ) {
        if( msg == WM_LBUTTONDOWN )
Joshua Thielen's avatar
Joshua Thielen committed
884
            p_board->face_bmp = SPRESS_BMP;
885 886 887

        if( msg == WM_LBUTTONUP )
            CreateBoard( p_board );
Joshua Thielen's avatar
Joshua Thielen committed
888
    }
889

890
    RedrawWindow( p_board->hWnd, &p_board->face_rect, 0,
Joshua Thielen's avatar
Joshua Thielen committed
891 892 893 894 895 896 897 898
        RDW_INVALIDATE | RDW_UPDATENOW );
}


void CompleteBox( BOARD *p_board, unsigned col, unsigned row )
{
    int i, j;

899 900 901
    if( p_board->box[col][row].FlagType != COMPLETE &&
            p_board->box[col][row].FlagType != FLAG &&
            col > 0 && col < p_board->cols + 1 &&
Joshua Thielen's avatar
Joshua Thielen committed
902 903
            row > 0 && row < p_board->rows + 1 ) {
        p_board->box[col][row].FlagType = COMPLETE;
904

Joshua Thielen's avatar
Joshua Thielen committed
905
        if( p_board->box[col][row].IsMine ) {
906
            p_board->face_bmp = DEAD_BMP;
Joshua Thielen's avatar
Joshua Thielen committed
907 908
            p_board->status = GAMEOVER;
        }
909
        else if( p_board->status != GAMEOVER )
Joshua Thielen's avatar
Joshua Thielen committed
910 911
            p_board->boxes_left--;

912
        if( p_board->box[col][row].NumMines == 0 )
Joshua Thielen's avatar
Joshua Thielen committed
913 914 915 916 917
        {
            for( i = -1; i <= 1; i++ )
            for( j = -1; j <= 1; j++ )
                CompleteBox( p_board, col + i, row + j  );
        }
918
    }
Joshua Thielen's avatar
Joshua Thielen committed
919 920 921 922 923 924 925 926 927 928
}


void CompleteBoxes( BOARD *p_board, unsigned col, unsigned row )
{
    unsigned numFlags = 0;
    int i, j;

    if( p_board->box[col][row].FlagType == COMPLETE ) {
        for( i = -1; i <= 1; i++ )
929
          for( j = -1; j <= 1; j++ ) {
930
            if( p_board->box[col+i][row+j].FlagType == FLAG )
Joshua Thielen's avatar
Joshua Thielen committed
931
                numFlags++;
932
          }
933

Joshua Thielen's avatar
Joshua Thielen committed
934 935
        if( numFlags == p_board->box[col][row].NumMines ) {
            for( i = -1; i <= 1; i++ )
936
              for( j = -1; j <= 1; j++ ) {
937
                if( p_board->box[col+i][row+j].FlagType != FLAG )
Joshua Thielen's avatar
Joshua Thielen committed
938
                    CompleteBox( p_board, col+i, row+j );
939
              }
Joshua Thielen's avatar
Joshua Thielen committed
940 941 942 943 944 945 946 947 948 949 950 951
        }
    }
}


void AddFlag( BOARD *p_board, unsigned col, unsigned row )
{
    if( p_board->box[col][row].FlagType != COMPLETE ) {
        switch( p_board->box[col][row].FlagType ) {
        case FLAG:
            if( p_board->IsMarkQ )
                p_board->box[col][row].FlagType = QUESTION;
952
            else
Joshua Thielen's avatar
Joshua Thielen committed
953 954 955 956 957 958 959
                p_board->box[col][row].FlagType = NORMAL;
            p_board->num_flags--;
            break;

        case QUESTION:
            p_board->box[col][row].FlagType = NORMAL;
            break;
960

Joshua Thielen's avatar
Joshua Thielen committed
961 962 963
        default:
            p_board->box[col][row].FlagType = FLAG;
            p_board->num_flags++;
964 965
        }
    }
Joshua Thielen's avatar
Joshua Thielen committed
966 967 968 969 970
}


void PressBox( BOARD *p_board, unsigned col, unsigned row )
{
971 972
    HDC hdc;
    HGDIOBJ hOldObj;
973
    HDC hMemDC;
Joshua Thielen's avatar
Joshua Thielen committed
974 975

    hdc = GetDC( p_board->hWnd );
976
    hMemDC = CreateCompatibleDC( hdc );
977
    hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
978 979 980

    DrawMine( hdc, hMemDC, p_board, col, row, TRUE );

981
    SelectObject( hMemDC, hOldObj );
982
    DeleteDC( hMemDC );
Joshua Thielen's avatar
Joshua Thielen committed
983 984 985 986 987 988 989 990 991
    ReleaseDC( p_board->hWnd, hdc );
}


void PressBoxes( BOARD *p_board, unsigned col, unsigned row )
{
    int i, j;

    for( i = -1; i <= 1; i++ )
992
      for( j = -1; j <= 1; j++ ) {
993
        p_board->box[col + i][row + j].IsPressed = TRUE;
Joshua Thielen's avatar
Joshua Thielen committed
994 995 996 997
        PressBox( p_board, col + i, row + j );
    }

    for( i = -1; i <= 1; i++ )
998
      for( j = -1; j <= 1; j++ ) {
999
        if( !p_board->box[p_board->press.x + i][p_board->press.y + j].IsPressed )
Joshua Thielen's avatar
Joshua Thielen committed
1000 1001 1002 1003
            UnpressBox( p_board, p_board->press.x + i, p_board->press.y + j );
    }

    for( i = -1; i <= 1; i++ )
1004
      for( j = -1; j <= 1; j++ ) {
1005
        p_board->box[col + i][row + j].IsPressed = FALSE;
Joshua Thielen's avatar
Joshua Thielen committed
1006 1007 1008 1009
        PressBox( p_board, col + i, row + j );
    }

    p_board->press.x = col;
1010
    p_board->press.y = row;
Joshua Thielen's avatar
Joshua Thielen committed
1011 1012 1013 1014 1015
}


void UnpressBox( BOARD *p_board, unsigned col, unsigned row )
{
1016 1017
    HDC hdc;
    HGDIOBJ hOldObj;
1018
    HDC hMemDC;
Joshua Thielen's avatar
Joshua Thielen committed
1019 1020

    hdc = GetDC( p_board->hWnd );
1021
    hMemDC = CreateCompatibleDC( hdc );
1022
    hOldObj = SelectObject( hMemDC, p_board->hMinesBMP );
1023 1024 1025

    DrawMine( hdc, hMemDC, p_board, col, row, FALSE );

1026
    SelectObject( hMemDC, hOldObj );
1027
    DeleteDC( hMemDC );
Joshua Thielen's avatar
Joshua Thielen committed
1028 1029 1030 1031 1032 1033
    ReleaseDC( p_board->hWnd, hdc );
}


void UnpressBoxes( BOARD *p_board, unsigned col, unsigned row )
{
1034 1035
    int i, j;

Joshua Thielen's avatar
Joshua Thielen committed
1036
    for( i = -1; i <= 1; i++ )
1037
      for( j = -1; j <= 1; j++ ) {
Joshua Thielen's avatar
Joshua Thielen committed
1038
        UnpressBox( p_board, col + i, row + j );
1039
      }
Joshua Thielen's avatar
Joshua Thielen committed
1040
}