~ubuntu-branches/ubuntu/raring/simutrans/raring-proposed

« back to all changes in this revision

Viewing changes to simsys_w.cc

  • Committer: Package Import Robot
  • Author(s): Ansgar Burchardt
  • Date: 2011-11-03 19:59:02 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20111103195902-uopgwf488mfctb75
Tags: 111.0-1
* New upstream release.
* debian/rules: Update get-orig-source target for new upstream release.
* Use xz compression for source and binary packages.
* Use override_* targets to simplify debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997 - 2001 Hansj�rg Malthaner
 
3
 *
 
4
 * This file is part of the Simutrans project under the artistic licence.
 
5
 */
 
6
 
 
7
#ifndef _WIN32
 
8
#error "Only Windows has GDI!"
 
9
#endif
 
10
 
 
11
#ifndef _MSC_VER
 
12
#include <unistd.h>
 
13
#include <sys/time.h>
 
14
#endif
 
15
 
 
16
#include <stdio.h>
 
17
#include <stdlib.h>
 
18
 
 
19
// windows Bibliotheken DirectDraw 5.x
 
20
#define UNICODE 1
 
21
// windows.h defines min and max macros which we don't want
 
22
#define NOMINMAX 1
 
23
#include <windows.h>
 
24
#include <winreg.h>
 
25
#include <wingdi.h>
 
26
#include <mmsystem.h>
 
27
 
 
28
#include "simgraph.h"
 
29
 
 
30
 
 
31
// needed for wheel
 
32
#ifndef WM_MOUSEWHEEL
 
33
#       define WM_MOUSEWHEEL 0x020A
 
34
#endif
 
35
#ifndef GET_WHEEL_DELTA_WPARAM
 
36
#       define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam))
 
37
#endif
 
38
 
 
39
// 16 Bit may be much slower than 15 unfourtunately on some hardware
 
40
#define USE_16BIT_DIB
 
41
 
 
42
// for redraws in another thread
 
43
//#define MULTI_THREAD
 
44
 
 
45
#include "simmain.h"
 
46
#include "simmem.h"
 
47
#include "simsys_w32_png.h"
 
48
#include "simversion.h"
 
49
#include "simsys.h"
 
50
#include "simevent.h"
 
51
#include "simdebug.h"
 
52
#include "macros.h"
 
53
 
 
54
#if COLOUR_DEPTH == 8
 
55
typedef unsigned char PIXVAL;
 
56
#elif COLOUR_DEPTH == 16
 
57
typedef unsigned short PIXVAL;
 
58
#else
 
59
#       error unknown COLOUR_DEPTH
 
60
#endif
 
61
 
 
62
static HWND hwnd;
 
63
static bool is_fullscreen = false;
 
64
static bool is_not_top = false;
 
65
static MSG msg;
 
66
static RECT WindowSize = { 0, 0, 0, 0 };
 
67
static RECT MaxSize;
 
68
static HINSTANCE hInstance;
 
69
 
 
70
static BITMAPINFO* AllDib;
 
71
static PIXVAL*     AllDibData;
 
72
 
 
73
volatile HDC hdc = NULL;
 
74
 
 
75
const wchar_t* const title =
 
76
#ifdef _MSC_VER
 
77
#define TOW_(x) L#x
 
78
#define TOW(x) TOW_(x)
 
79
                        L"Simutrans " WIDE_VERSION_NUMBER
 
80
#ifdef REVISION
 
81
                        L" - r" TOW(REVISION)
 
82
#endif
 
83
#else
 
84
                        L"" SAVEGAME_PREFIX " " VERSION_NUMBER " - " VERSION_DATE
 
85
#ifdef REVISION
 
86
                        " - r" QUOTEME(REVISION)
 
87
#endif
 
88
#endif
 
89
;
 
90
 
 
91
#ifdef MULTI_THREAD
 
92
 
 
93
 
 
94
HANDLE  hFlushThread=0;
 
95
#define WAIT_FOR_SCREEN() {while(hdc) Sleep(5);}
 
96
 
 
97
#else
 
98
 
 
99
// nothing to de done
 
100
#define WAIT_FOR_SCREEN()
 
101
#endif
 
102
 
 
103
 
 
104
 
 
105
/*
 
106
 * Hier sind die Basisfunktionen zur Initialisierung der
 
107
 * Schnittstelle untergebracht
 
108
 * -> init,open,close
 
109
 */
 
110
int dr_os_init(const int* /*parameter*/)
 
111
{
 
112
        // prepare for next event
 
113
        sys_event.type = SIM_NOEVENT;
 
114
        sys_event.code = 0;
 
115
 
 
116
        return TRUE;
 
117
}
 
118
 
 
119
 
 
120
resolution dr_query_screen_resolution()
 
121
{
 
122
        resolution res;
 
123
        res.w = GetSystemMetrics(SM_CXSCREEN);
 
124
        res.h = GetSystemMetrics(SM_CYSCREEN);
 
125
        return res;
 
126
}
 
127
 
 
128
 
 
129
// open the window
 
130
int dr_os_open(int const w, int const h, int fullscreen)
 
131
{
 
132
        MaxSize.right = (w+15)&0x7FF0;
 
133
        MaxSize.bottom = h+1;
 
134
 
 
135
        // fake fullscreen
 
136
        if (fullscreen) {
 
137
                // try to force display mode and size
 
138
                DEVMODE settings;
 
139
 
 
140
                MEMZERO(settings);
 
141
                settings.dmSize = sizeof(settings);
 
142
                settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
143
#if COLOUR_DEPTH != 16 || defined USE_16BIT_DIB
 
144
                settings.dmBitsPerPel = COLOUR_DEPTH;
 
145
#else
 
146
                settings.dmBitsPerPel = 16;
 
147
#endif
 
148
                settings.dmPelsWidth  = w;
 
149
                settings.dmPelsHeight = h;
 
150
                settings.dmDisplayFrequency = 0;
 
151
 
 
152
                if(  ChangeDisplaySettings(&settings, CDS_TEST)!=DISP_CHANGE_SUCCESSFUL  ) {
 
153
                        ChangeDisplaySettings( NULL, 0 );
 
154
                        printf( "dr_os_open()::Could not reduce color depth to 16 Bit in fullscreen." );
 
155
                        fullscreen = false;
 
156
                }
 
157
                else {
 
158
                        ChangeDisplaySettings(&settings, CDS_FULLSCREEN);
 
159
                }
 
160
                is_fullscreen = fullscreen;
 
161
        }
 
162
        if(  fullscreen  ) {
 
163
                hwnd = CreateWindowEx(
 
164
                        WS_EX_TOPMOST,
 
165
                        L"Simu", title,
 
166
                        WS_POPUP,
 
167
                        0, 0,
 
168
                        w, h,
 
169
                        NULL, NULL, hInstance, NULL
 
170
                );
 
171
        } else {
 
172
                hwnd = CreateWindow(
 
173
                        L"Simu", title,
 
174
                        WS_OVERLAPPEDWINDOW,
 
175
                        CW_USEDEFAULT, CW_USEDEFAULT,
 
176
                        w + GetSystemMetrics(SM_CXFRAME),
 
177
                        h - 1 + 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION),
 
178
                        NULL, NULL, hInstance, NULL
 
179
                );
 
180
        }
 
181
        ShowWindow(hwnd, SW_SHOW);
 
182
 
 
183
        WindowSize.right  = w;
 
184
        WindowSize.bottom = h;
 
185
 
 
186
#if COLOUR_DEPTH == 8
 
187
        DWORD const clr = 224 + 15;
 
188
        AllDib = MALLOCF(BITMAPINFO, bmiColors, 256);
 
189
#else
 
190
        DWORD const clr = 0;
 
191
        AllDib = MALLOCF(BITMAPINFO, bmiColors, 3);
 
192
#endif
 
193
        BITMAPINFOHEADER& header = AllDib->bmiHeader;
 
194
        header.biSize          = sizeof(BITMAPINFOHEADER);
 
195
        header.biWidth         = w;
 
196
        header.biHeight        = h;
 
197
        header.biPlanes        = 1;
 
198
        header.biBitCount      = COLOUR_DEPTH;
 
199
        header.biCompression   = BI_RGB;
 
200
        header.biSizeImage     = 0;
 
201
        header.biXPelsPerMeter = 0;
 
202
        header.biYPelsPerMeter = 0;
 
203
        header.biClrUsed       = clr;
 
204
        header.biClrImportant  = clr;
 
205
#if COLOUR_DEPTH == 16
 
206
        DWORD* const masks = (DWORD*)AllDib->bmiColors;
 
207
#       ifdef USE_16BIT_DIB
 
208
        header.biCompression   = BI_BITFIELDS;
 
209
        masks[0]               = 0x0000F800;
 
210
        masks[1]               = 0x000007E0;
 
211
        masks[2]               = 0x0000001F;
 
212
#       else
 
213
        masks[0]               = 0x01;
 
214
        masks[1]               = 0x02;
 
215
        masks[2]               = 0x03;
 
216
#       endif
 
217
#endif
 
218
 
 
219
        return MaxSize.right;
 
220
}
 
221
 
 
222
 
 
223
int dr_os_close(void)
 
224
{
 
225
        if (hwnd != NULL) {
 
226
                DestroyWindow(hwnd);
 
227
        }
 
228
        free(AllDibData);
 
229
        AllDibData = NULL;
 
230
        free(AllDib);
 
231
        AllDib = NULL;
 
232
        ChangeDisplaySettings(NULL, 0);
 
233
        return TRUE;
 
234
}
 
235
 
 
236
 
 
237
// reiszes screen
 
238
int dr_textur_resize(unsigned short** const textur, int w, int const h)
 
239
{
 
240
        WAIT_FOR_SCREEN();
 
241
 
 
242
        // some cards need those alignments
 
243
        w = (w + 15) & 0x7FF0;
 
244
        if(  w<=0  ) {
 
245
                w = 16;
 
246
        }
 
247
 
 
248
        if(w>MaxSize.right  ||  h>=MaxSize.bottom) {
 
249
                // since the query routines that return the desktop data do not take into account a change of resolution
 
250
                free(AllDibData);
 
251
                AllDibData = NULL;
 
252
                MaxSize.right = w;
 
253
                MaxSize.bottom = h+1;
 
254
                AllDibData = MALLOCN(PIXVAL, MaxSize.right * MaxSize.bottom);
 
255
                *textur = (unsigned short*)AllDibData;
 
256
        }
 
257
 
 
258
        AllDib->bmiHeader.biWidth  = w;
 
259
        AllDib->bmiHeader.biHeight = h;
 
260
        WindowSize.right           = w;
 
261
        WindowSize.bottom          = h;
 
262
        return w;
 
263
}
 
264
 
 
265
 
 
266
unsigned short *dr_textur_init()
 
267
{
 
268
        size_t const n = MaxSize.right * MaxSize.bottom;
 
269
        AllDibData = MALLOCN(PIXVAL, n);
 
270
        // start with black
 
271
        MEMZERON(AllDibData, n);
 
272
        return (unsigned short*)AllDibData;
 
273
}
 
274
 
 
275
 
 
276
/**
 
277
 * Transform a 24 bit RGB color into the system format.
 
278
 * @return converted color value
 
279
 * @author Hj. Malthaner
 
280
 */
 
281
unsigned int get_system_color(unsigned int r, unsigned int g, unsigned int b)
 
282
{
 
283
#ifdef USE_16BIT_DIB
 
284
        return ((r & 0x00F8) << 8) | ((g & 0x00FC) << 3) | (b >> 3);
 
285
#else
 
286
        return ((r & 0x00F8) << 7) | ((g & 0x00F8) << 2) | (b >> 3); // 15 Bit
 
287
#endif
 
288
}
 
289
 
 
290
 
 
291
void dr_setRGB8multi(int first, int count, unsigned char* data)
 
292
{
 
293
        // set color in DibHeader ...
 
294
        RGBQUAD *pRGB = (RGBQUAD *)((char *)AllDib + sizeof(BITMAPINFOHEADER));
 
295
        for(  int i=first;  i<first+count;  i++  ) {
 
296
                pRGB[i].rgbRed = data[i*3];
 
297
                pRGB[i].rgbGreen = data[i*3+1];
 
298
                pRGB[i].rgbBlue = data[i*3+2];
 
299
        }
 
300
}
 
301
 
 
302
 
 
303
#ifdef MULTI_THREAD
 
304
// multhreaded screen copy ...
 
305
DWORD WINAPI dr_flush_screen(LPVOID lpParam)
 
306
{
 
307
        while(1) {
 
308
                // wait for finish of thread
 
309
                hdc = GetDC(hwnd);
 
310
                display_flush_buffer();
 
311
                ReleaseDC(hwnd, hdc);
 
312
                hdc = NULL;
 
313
                // suspend myself after one update
 
314
                SuspendThread( hFlushThread );
 
315
        }
 
316
        return 0;
 
317
}
 
318
#endif
 
319
 
 
320
void dr_prepare_flush()
 
321
{
 
322
#ifdef MULTI_THREAD
 
323
        // thread there?
 
324
        if(hFlushThread==0) {
 
325
                DWORD id=22;
 
326
                hFlushThread = CreateThread( NULL, 0, dr_flush_screen, 0, CREATE_SUSPENDED, &id );
 
327
        }
 
328
        WAIT_FOR_SCREEN();
 
329
#endif
 
330
}
 
331
 
 
332
void dr_flush()
 
333
{
 
334
#ifdef MULTI_THREAD
 
335
        // just let the thread do its work
 
336
        ResumeThread( hFlushThread );
 
337
#else
 
338
        assert(hdc==NULL);
 
339
        hdc = GetDC(hwnd);
 
340
        display_flush_buffer();
 
341
        ReleaseDC(hwnd, hdc);
 
342
        hdc = NULL;
 
343
#endif
 
344
}
 
345
 
 
346
 
 
347
 
 
348
void dr_textur(int xp, int yp, int w, int h)
 
349
{
 
350
        // make really sure we are not beyond screen coordinates
 
351
        h = min( yp+h, WindowSize.bottom ) - yp;
 
352
#ifdef DEBUG
 
353
        w = min( xp+w, WindowSize.right ) - xp;
 
354
        if(  h>1  &&  w>0  )
 
355
#endif
 
356
        {
 
357
                AllDib->bmiHeader.biHeight = h + 1;
 
358
                StretchDIBits(hdc, xp, yp, w, h, xp, h + 1, w, -h, AllDibData + yp * WindowSize.right, AllDib, DIB_RGB_COLORS, SRCCOPY);
 
359
        }
 
360
}
 
361
 
 
362
 
 
363
// move cursor to the specified location
 
364
void move_pointer(int x, int y)
 
365
{
 
366
        POINT pt = { x, y };
 
367
 
 
368
        ClientToScreen(hwnd, &pt);
 
369
        SetCursorPos(pt.x, pt.y);
 
370
}
 
371
 
 
372
 
 
373
// set the mouse cursor (pointer/load)
 
374
void set_pointer(int loading)
 
375
{
 
376
        SetCursor(LoadCursor(NULL, loading != 0 ? IDC_WAIT : IDC_ARROW));
 
377
}
 
378
 
 
379
 
 
380
/**
 
381
 * Some wrappers can save screenshots.
 
382
 * @return 1 on success, 0 if not implemented for a particular wrapper and -1
 
383
 *         in case of error.
 
384
 * @author Hj. Malthaner
 
385
 */
 
386
int dr_screenshot(const char *filename)
 
387
{
 
388
#if COLOUR_DEPTH != 16 || defined USE_16BIT_DIB
 
389
        int const bpp = COLOUR_DEPTH;
 
390
#else
 
391
        int const bpp = 15;
 
392
#endif
 
393
        if (!dr_screenshot_png(filename, display_get_width() - 1, WindowSize.bottom + 1, AllDib->bmiHeader.biWidth, (unsigned short*)AllDibData, bpp)) {
 
394
#if COLOUR_DEPTH != 8
 
395
                // not successful => save as BMP
 
396
                FILE *fBmp = fopen(filename, "wb");
 
397
                if (fBmp) {
 
398
                        BITMAPFILEHEADER bf;
 
399
 
 
400
                        // since the number of drawn pixel can be smaller than the actual width => only use the drawn pixel for bitmap
 
401
                        LONG const old_width = AllDib->bmiHeader.biWidth;
 
402
                        AllDib->bmiHeader.biWidth  = display_get_width() - 1;
 
403
                        AllDib->bmiHeader.biHeight = WindowSize.bottom   + 1;
 
404
 
 
405
                        bf.bfType = 0x4d42; //"BM"
 
406
                        bf.bfReserved1 = 0;
 
407
                        bf.bfReserved2 = 0;
 
408
                        bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(DWORD)*3;
 
409
                        bf.bfSize      = (bf.bfOffBits + AllDib->bmiHeader.biHeight * AllDib->bmiHeader.biWidth * 2L + 3L) / 4L;
 
410
                        fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, fBmp);
 
411
                        fwrite(AllDib, sizeof(AllDib->bmiHeader) + sizeof(*AllDib->bmiColors) * 3, 1, fBmp);
 
412
 
 
413
                        for (LONG i = 0; i < AllDib->bmiHeader.biHeight; ++i) {
 
414
                                // row must be alsway even number of pixel
 
415
                                fwrite(AllDibData + (AllDib->bmiHeader.biHeight - 1 - i) * old_width, (AllDib->bmiHeader.biWidth + 1) & 0xFFFE, 2, fBmp);
 
416
                        }
 
417
                        AllDib->bmiHeader.biWidth = old_width;
 
418
 
 
419
                        fclose(fBmp);
 
420
                }
 
421
                else {
 
422
                        return -1;
 
423
                }
 
424
#endif
 
425
        }
 
426
        return 0;
 
427
}
 
428
 
 
429
 
 
430
/*
 
431
 * Hier sind die Funktionen zur Messageverarbeitung
 
432
 */
 
433
 
 
434
static inline unsigned int ModifierKeys()
 
435
{
 
436
        return
 
437
                (GetKeyState(VK_SHIFT)   < 0  ? 1 : 0) |
 
438
                (GetKeyState(VK_CONTROL) < 0  ? 2 : 0); // highest bit set or return value<0 -> key is pressed
 
439
}
 
440
 
 
441
struct sys_event sys_event;
 
442
 
 
443
/* Windows eventhandler: does most of the work */
 
444
LRESULT WINAPI WindowProc(HWND this_hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
445
{
 
446
        static int last_mb = 0; // last mouse button state
 
447
        switch (msg) {
 
448
 
 
449
                case WM_ACTIVATE: // may check, if we have to restore color depth
 
450
                        if(is_fullscreen) {
 
451
                                // avoid double calls
 
452
                                static bool while_handling = false;
 
453
                                if(while_handling) {
 
454
                                        break;
 
455
                                }
 
456
                                while_handling = true;
 
457
 
 
458
                                if(LOWORD(wParam)!=WA_INACTIVE  &&  is_not_top) {
 
459
                                        // try to force display mode and size
 
460
                                        DEVMODE settings;
 
461
 
 
462
                                        MEMZERO(settings);
 
463
                                        settings.dmSize = sizeof(settings);
 
464
                                        settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
465
#if COLOUR_DEPTH != 16 || defined USE_16BIT_DIB
 
466
                                        settings.dmBitsPerPel = COLOUR_DEPTH;
 
467
#else
 
468
                                        settings.dmBitsPerPel = 15;
 
469
#endif
 
470
                                        settings.dmPelsWidth  = MaxSize.right;
 
471
                                        settings.dmPelsHeight = MaxSize.bottom;
 
472
                                        settings.dmDisplayFrequency = 0;
 
473
 
 
474
                                        // should be alsway sucessful, since it worked as least once ...
 
475
                                        ChangeDisplaySettings(&settings, CDS_FULLSCREEN);
 
476
                                        is_not_top = false;
 
477
 
 
478
                                        Beep( 110, 250 );
 
479
                                        // must reshow window, otherwise startbar will be topmost ...
 
480
                                        hwnd = CreateWindowEx(
 
481
                                                WS_EX_TOPMOST,
 
482
                                                L"Simu", title,
 
483
                                                WS_POPUP,
 
484
                                                0, 0,
 
485
                                                MaxSize.right, MaxSize.bottom,
 
486
                                                NULL, NULL, hInstance, NULL
 
487
                                        );
 
488
                                        ShowWindow( hwnd, SW_SHOW );
 
489
                                        DestroyWindow( this_hwnd );
 
490
                                        while_handling = false;
 
491
                                        return true;
 
492
                                }
 
493
                                else if(LOWORD(wParam)==WA_INACTIVE  &&  !is_not_top) {
 
494
                                        // restore default
 
495
                                        CloseWindow( hwnd );
 
496
                                        ChangeDisplaySettings( NULL, 0 );
 
497
                                        is_not_top = true;
 
498
                                        Beep( 440, 250 );
 
499
                                }
 
500
 
 
501
                                while_handling = false;
 
502
                        }
 
503
                        break;
 
504
 
 
505
                case WM_GETMINMAXINFO:
 
506
                        if(is_fullscreen) {
 
507
                                LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
 
508
                                lpmmi->ptMaxPosition.x = 0;
 
509
                                lpmmi->ptMaxPosition.y = 0;
 
510
                        }
 
511
                        break;
 
512
 
 
513
                case WM_LBUTTONDOWN: /* originally ButtonPress */
 
514
                        sys_event.type    = SIM_MOUSE_BUTTONS;
 
515
                        sys_event.code    = SIM_MOUSE_LEFTBUTTON;
 
516
                        sys_event.key_mod = ModifierKeys();
 
517
                        sys_event.mb = last_mb = (wParam&3);
 
518
                        sys_event.mx      = LOWORD(lParam);
 
519
                        sys_event.my      = HIWORD(lParam);
 
520
                        break;
 
521
 
 
522
                case WM_LBUTTONUP: /* originally ButtonRelease */
 
523
                        sys_event.type    = SIM_MOUSE_BUTTONS;
 
524
                        sys_event.code    = SIM_MOUSE_LEFTUP;
 
525
                        sys_event.key_mod = ModifierKeys();
 
526
                        sys_event.mb = last_mb = (wParam&3);
 
527
                        sys_event.mx      = LOWORD(lParam);
 
528
                        sys_event.my      = HIWORD(lParam);
 
529
                        break;
 
530
 
 
531
                case WM_RBUTTONDOWN: /* originally ButtonPress */
 
532
                        sys_event.type    = SIM_MOUSE_BUTTONS;
 
533
                        sys_event.code    = SIM_MOUSE_RIGHTBUTTON;
 
534
                        sys_event.key_mod = ModifierKeys();
 
535
                        sys_event.mb = last_mb = (wParam&3);
 
536
                        sys_event.mx      = LOWORD(lParam);
 
537
                        sys_event.my      = HIWORD(lParam);
 
538
                        break;
 
539
 
 
540
                case WM_RBUTTONUP: /* originally ButtonRelease */
 
541
                        sys_event.type    = SIM_MOUSE_BUTTONS;
 
542
                        sys_event.code    = SIM_MOUSE_RIGHTUP;
 
543
                        sys_event.key_mod = ModifierKeys();
 
544
                        sys_event.mb = last_mb = (wParam&3);
 
545
                        sys_event.mx      = LOWORD(lParam);
 
546
                        sys_event.my      = HIWORD(lParam);
 
547
                        break;
 
548
 
 
549
                case WM_MOUSEMOVE:
 
550
                        sys_event.type    = SIM_MOUSE_MOVE;
 
551
                        sys_event.code    = SIM_MOUSE_MOVED;
 
552
                        sys_event.key_mod = ModifierKeys();
 
553
                        sys_event.mb = last_mb = (wParam&3);
 
554
                        sys_event.mx      = LOWORD(lParam);
 
555
                        sys_event.my      = HIWORD(lParam);
 
556
                        break;
 
557
 
 
558
                case WM_MOUSEWHEEL:
 
559
                        sys_event.type = SIM_MOUSE_BUTTONS;
 
560
                        sys_event.code = GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? SIM_MOUSE_WHEELUP : SIM_MOUSE_WHEELDOWN;
 
561
                        sys_event.key_mod = ModifierKeys();
 
562
                        /* the returned coordinate in LPARAM are absolute coordinates, which will deeply confuse simutrans
 
563
                         * we just reuse the coordinates we used the last time but not chaning mx/my ...
 
564
                         */
 
565
                        return 0;
 
566
 
 
567
                case WM_SIZE: // resize client area
 
568
                        if(lParam!=0) {
 
569
                                sys_event.type = SIM_SYSTEM;
 
570
                                sys_event.code = SIM_SYSTEM_RESIZE;
 
571
 
 
572
                                sys_event.mx = LOWORD(lParam) + 1;
 
573
                                if (sys_event.mx <= 0) {
 
574
                                        sys_event.mx = 4;
 
575
                                }
 
576
 
 
577
                                sys_event.my = HIWORD(lParam);
 
578
                                if (sys_event.my <= 1) {
 
579
                                        sys_event.my = 64;
 
580
                                }
 
581
                        }
 
582
                        break;
 
583
 
 
584
                case WM_PAINT: {
 
585
                        PAINTSTRUCT ps;
 
586
                        HDC hdcp;
 
587
 
 
588
                        WAIT_FOR_SCREEN();
 
589
 
 
590
                        hdcp = BeginPaint(hwnd, &ps);
 
591
                        AllDib->bmiHeader.biHeight = WindowSize.bottom;
 
592
                        StretchDIBits(hdcp, 0, 0, WindowSize.right, WindowSize.bottom, 0, WindowSize.bottom + 1, WindowSize.right, -WindowSize.bottom, AllDibData, AllDib, DIB_RGB_COLORS, SRCCOPY);
 
593
                        EndPaint(this_hwnd, &ps);
 
594
                        break;
 
595
                }
 
596
 
 
597
                case WM_KEYDOWN: { /* originally KeyPress */
 
598
                        // check for not numlock!
 
599
                        int numlock = (GetKeyState(VK_NUMLOCK) & 1) == 0;
 
600
 
 
601
                        sys_event.type = SIM_KEYBOARD;
 
602
                        sys_event.code = 0;
 
603
                        sys_event.key_mod = ModifierKeys();
 
604
 
 
605
                        if (numlock) {
 
606
                                // do low level special stuff here
 
607
                                switch (wParam) {
 
608
                                        case VK_NUMPAD0:   sys_event.code = '0';           break;
 
609
                                        case VK_NUMPAD1:   sys_event.code = '1';           break;
 
610
                                        case VK_NUMPAD3:   sys_event.code = '3';           break;
 
611
                                        case VK_NUMPAD7:   sys_event.code = '7';           break;
 
612
                                        case VK_NUMPAD9:   sys_event.code = '9';           break;
 
613
                                        case VK_NUMPAD2:   sys_event.code = SIM_KEY_DOWN;  break;
 
614
                                        case VK_NUMPAD4:   sys_event.code = SIM_KEY_LEFT;  break;
 
615
                                        case VK_NUMPAD6:   sys_event.code = SIM_KEY_RIGHT; break;
 
616
                                        case VK_NUMPAD8:   sys_event.code = SIM_KEY_UP;    break;
 
617
                                        case VK_PAUSE:     sys_event.code = 16;            break;       // Pause -> ^P
 
618
                                        case VK_SEPARATOR: sys_event.code = 127;           break;       // delete
 
619
                                }
 
620
                                // check for numlock!
 
621
                                if (sys_event.code != 0) break;
 
622
                        }
 
623
 
 
624
                        // do low level special stuff here
 
625
                        switch (wParam) {
 
626
                                case VK_LEFT:   sys_event.code = SIM_KEY_LEFT;  break;
 
627
                                case VK_RIGHT:  sys_event.code = SIM_KEY_RIGHT; break;
 
628
                                case VK_UP:     sys_event.code = SIM_KEY_UP;    break;
 
629
                                case VK_DOWN:   sys_event.code = SIM_KEY_DOWN;  break;
 
630
                                case VK_PRIOR:  sys_event.code = '>';           break;
 
631
                                case VK_NEXT:   sys_event.code = '<';           break;
 
632
                                case VK_DELETE: sys_event.code = 127;           break;
 
633
                                case VK_HOME:   sys_event.code = SIM_KEY_HOME;  break;
 
634
                                case VK_END:    sys_event.code = SIM_KEY_END;   break;
 
635
                        }
 
636
                        // check for F-Keys!
 
637
                        if (sys_event.code == 0 && wParam >= VK_F1 && wParam <= VK_F15) {
 
638
                                sys_event.code = wParam - VK_F1 + SIM_KEY_F1;
 
639
                                //printf("WindowsEvent: Key %i, (state %i)\n", sys_event.code, sys_event.key_mod);
 
640
                        }
 
641
                        // some result?
 
642
                        if (sys_event.code != 0) return 0;
 
643
                        sys_event.type = SIM_NOEVENT;
 
644
                        sys_event.code = 0;
 
645
                        break;
 
646
                }
 
647
 
 
648
                case WM_CHAR: /* originally KeyPress */
 
649
                        sys_event.type = SIM_KEYBOARD;
 
650
                        sys_event.code = wParam;
 
651
                        sys_event.key_mod = ModifierKeys();
 
652
                        break;
 
653
 
 
654
                case WM_CLOSE:
 
655
                        if (AllDibData != NULL) {
 
656
                                sys_event.type = SIM_SYSTEM;
 
657
                                sys_event.code = SIM_SYSTEM_QUIT;
 
658
                                return FALSE;
 
659
                        }
 
660
                        break;
 
661
 
 
662
                case WM_DESTROY:
 
663
                        sys_event.type = SIM_SYSTEM;
 
664
                        sys_event.code = SIM_SYSTEM_QUIT;
 
665
                        if (AllDibData == NULL) {
 
666
                                PostQuitMessage(0);
 
667
                                hwnd = NULL;
 
668
                                return TRUE;
 
669
                        }
 
670
                        return FALSE;
 
671
 
 
672
                default:
 
673
                        return DefWindowProc(this_hwnd, msg, wParam, lParam);
 
674
        }
 
675
        return FALSE;
 
676
}
 
677
 
 
678
 
 
679
static void internal_GetEvents(int wait)
 
680
{
 
681
        do {
 
682
                // wait for keybord/mouse event
 
683
                GetMessage(&msg, NULL, 0, 0);
 
684
                TranslateMessage(&msg);
 
685
                DispatchMessage(&msg);
 
686
        } while (wait && sys_event.type == SIM_NOEVENT);
 
687
}
 
688
 
 
689
 
 
690
void GetEvents()
 
691
{
 
692
        // already even processed?
 
693
        if(sys_event.type==SIM_NOEVENT) {
 
694
                internal_GetEvents(TRUE);
 
695
        }
 
696
}
 
697
 
 
698
 
 
699
void GetEventsNoWait()
 
700
{
 
701
        if (sys_event.type==SIM_NOEVENT  &&  PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
 
702
                internal_GetEvents(FALSE);
 
703
        }
 
704
}
 
705
 
 
706
 
 
707
void show_pointer(int yesno)
 
708
{
 
709
        static int state=true;
 
710
        if(state^yesno) {
 
711
                ShowCursor(yesno);
 
712
                state = yesno;
 
713
        }
 
714
}
 
715
 
 
716
 
 
717
 
 
718
void ex_ord_update_mx_my()
 
719
{
 
720
        // evt. called before update
 
721
}
 
722
 
 
723
 
 
724
 
 
725
unsigned long dr_time(void)
 
726
{
 
727
        return timeGetTime();
 
728
}
 
729
 
 
730
 
 
731
 
 
732
 
 
733
void dr_sleep(uint32 millisec)
 
734
{
 
735
        Sleep(millisec);
 
736
}
 
737
 
 
738
 
 
739
 
 
740
bool dr_fatal_notify(const char* msg, int choices)
 
741
{
 
742
        if(choices==0) {
 
743
                MessageBoxA( hwnd, msg, "Fatal Error", MB_ICONEXCLAMATION|MB_OK );
 
744
                return 0;
 
745
        }
 
746
        else {
 
747
                return MessageBoxA( hwnd, msg, "Fatal Error", MB_ICONEXCLAMATION|MB_RETRYCANCEL )==IDRETRY;
 
748
        }
 
749
}
 
750
 
 
751
 
 
752
int CALLBACK WinMain(HINSTANCE const hInstance, HINSTANCE, LPSTR, int)
 
753
{
 
754
        WNDCLASSW wc;
 
755
 
 
756
        wc.lpszClassName = L"Simu";
 
757
        wc.style = CS_HREDRAW | CS_VREDRAW;
 
758
        wc.lpfnWndProc = WindowProc;
 
759
        wc.cbClsExtra = 0;
 
760
        wc.cbWndExtra = 0;
 
761
        wc.hInstance = hInstance;
 
762
        wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
 
763
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
 
764
        wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
 
765
        wc.lpszMenuName = NULL;
 
766
 
 
767
        RegisterClass(&wc);
 
768
 
 
769
        int    const argc = __argc;
 
770
        char** const argv = __argv;
 
771
        char         pathname[1024];
 
772
        GetModuleFileNameA(hInstance, pathname, lengthof(pathname));
 
773
        argv[0] = pathname;
 
774
 
 
775
        GetWindowRect(GetDesktopWindow(), &MaxSize);
 
776
 
 
777
        // maybe set timer to 1ms intervall on Win2k upwards ...
 
778
        {
 
779
                OSVERSIONINFO osinfo;
 
780
                osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
781
                if (GetVersionEx(&osinfo)  &&  osinfo.dwPlatformId==VER_PLATFORM_WIN32_NT) {
 
782
                        timeBeginPeriod(1);
 
783
                }
 
784
        }
 
785
 
 
786
        simu_main(argc, argv);
 
787
        timeEndPeriod(1);
 
788
 
 
789
#ifdef MULTI_THREAD
 
790
        if(     hFlushThread ) {
 
791
                TerminateThread( hFlushThread, 0 );
 
792
        }
 
793
#endif
 
794
        return 0;
 
795
}