12 #include "../stdafx.h" 
   13 #include "../openttd.h" 
   14 #include "../gfx_func.h" 
   15 #include "../os/windows/win32.h" 
   17 #include "../blitter/factory.hpp" 
   18 #include "../network/network.h" 
   19 #include "../core/math_func.hpp" 
   20 #include "../core/random_func.hpp" 
   21 #include "../texteff.hpp" 
   22 #include "../thread/thread.h" 
   23 #include "../progress.h" 
   24 #include "../window_gui.h" 
   25 #include "../window_func.h" 
   30 #include "../safeguards.h" 
   33 #ifndef MAPVK_VK_TO_CHAR 
   34 #define MAPVK_VK_TO_CHAR    (2) 
   52 bool _force_full_redraw;
 
   53 bool _window_maximize;
 
   56 #if !defined(WINCE) || _WIN32_WCE >= 0x400 
   73 static void MakePalette()
 
   75   LOGPALETTE *pal = (LOGPALETTE*)alloca(
sizeof(LOGPALETTE) + (256 - 1) * 
sizeof(PALETTEENTRY));
 
   77   pal->palVersion = 0x300;
 
   78   pal->palNumEntries = 256;
 
   80   for (uint i = 0; i != 256; i++) {
 
   84     pal->palPalEntry[i].peFlags = 0;
 
   87   _wnd.gdi_palette = CreatePalette(pal);
 
   88   if (_wnd.gdi_palette == NULL) 
usererror(
"CreatePalette failed!\n");
 
   95 static void UpdatePalette(HDC dc, uint start, uint count)
 
  100   for (i = 0; i != count; i++) {
 
  101     rgb[i].rgbRed   = _local_palette.
palette[start + i].r;
 
  102     rgb[i].rgbGreen = _local_palette.
palette[start + i].g;
 
  103     rgb[i].rgbBlue  = _local_palette.
palette[start + i].b;
 
  104     rgb[i].rgbReserved = 0;
 
  107   SetDIBColorTable(dc, start, count, rgb);
 
  110 bool VideoDriver_Win32::ClaimMousePointer()
 
  112   MyShowCursor(
false, 
true);
 
  122 #define AS(x, z) {x, 0, z} 
  123 #define AM(x, y, z, w) {x, y - x, z} 
  127   AM(VK_PRIOR, VK_DOWN, WKC_PAGEUP, WKC_DOWN),
 
  129   AM(
'A', 
'Z', 
'A', 
'Z'),
 
  130   AM(
'0', 
'9', 
'0', 
'9'),
 
  132   AS(VK_ESCAPE,   WKC_ESC),
 
  133   AS(VK_PAUSE,    WKC_PAUSE),
 
  134   AS(VK_BACK,     WKC_BACKSPACE),
 
  135   AM(VK_INSERT,   VK_DELETE, WKC_INSERT, WKC_DELETE),
 
  137   AS(VK_SPACE,    WKC_SPACE),
 
  138   AS(VK_RETURN,   WKC_RETURN),
 
  142   AM(VK_F1, VK_F12, WKC_F1, WKC_F12),
 
  145   AM(VK_NUMPAD0, VK_NUMPAD9, 
'0', 
'9'),
 
  146   AS(VK_DIVIDE,   WKC_NUM_DIV),
 
  147   AS(VK_MULTIPLY, WKC_NUM_MUL),
 
  148   AS(VK_SUBTRACT, WKC_NUM_MINUS),
 
  149   AS(VK_ADD,      WKC_NUM_PLUS),
 
  150   AS(VK_DECIMAL,  WKC_NUM_DECIMAL),
 
  166 static uint MapWindowsKey(uint sym)
 
  171   for (map = _vk_mapping; map != 
endof(_vk_mapping); ++map) {
 
  172     if ((uint)(sym - map->vk_from) <= map->vk_count) {
 
  173       key = sym - map->vk_from + map->map_to;
 
  178   if (GetAsyncKeyState(VK_SHIFT)   < 0) key |= WKC_SHIFT;
 
  179   if (GetAsyncKeyState(VK_CONTROL) < 0) key |= WKC_CTRL;
 
  180   if (GetAsyncKeyState(VK_MENU)    < 0) key |= WKC_ALT;
 
  184 static bool AllocateDibSection(
int w, 
int h, 
bool force = 
false);
 
  186 static void ClientSizeChanged(
int w, 
int h)
 
  189   if (AllocateDibSection(w, h)) {
 
  204 int RedrawScreenDebug()
 
  209   HPALETTE old_palette;
 
  213   dc = GetDC(_wnd.main_wnd);
 
  214   dc2 = CreateCompatibleDC(dc);
 
  216   old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
 
  217   old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
 
  218   BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
 
  219   SelectPalette(dc, old_palette, TRUE);
 
  220   SelectObject(dc2, old_bmp);
 
  222   ReleaseDC(_wnd.main_wnd, dc);
 
  229 #if !defined(WM_MOUSELEAVE) 
  230 #define WM_MOUSELEAVE 0x02A3 
  232 #define TID_POLLMOUSE 1 
  233 #define MOUSE_POLL_DELAY 75 
  235 static void CALLBACK TrackMouseTimerProc(HWND hwnd, UINT msg, UINT event, DWORD time)
 
  243   GetClientRect(hwnd, &rc);
 
  244   MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)(LPRECT)&rc, 2);
 
  247   if (!PtInRect(&rc, pt) || (WindowFromPoint(pt) != hwnd)) {
 
  248     KillTimer(hwnd, event);
 
  249     PostMessage(hwnd, WM_MOUSELEAVE, 0, 0L);
 
  260   _fullscreen = full_screen;
 
  263   if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
 
  264     DestroyWindow(_wnd.main_wnd);
 
  274     memset(&settings, 0, 
sizeof(settings));
 
  275     settings.dmSize = 
sizeof(settings);
 
  280       (_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0);
 
  282     settings.dmPelsWidth  = _wnd.width_org;
 
  283     settings.dmPelsHeight = _wnd.height_org;
 
  284     settings.dmDisplayFrequency = _display_hz;
 
  287     if (settings.dmBitsPerPel == 8 &&
 
  288         (_support8bpp != 
S8BPP_HARDWARE || ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL)) {
 
  289       settings.dmBitsPerPel = 32;
 
  293     if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) {
 
  295       GetWindowRect(GetDesktopWindow(), &r);
 
  298       if ((
int)settings.dmPelsWidth != r.right - r.left || (
int)settings.dmPelsHeight != r.bottom - r.top) {
 
  303     if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
 
  307   } 
else if (_wnd.fullscreen) {
 
  309     ChangeDisplaySettings(NULL, 0);
 
  311     _wnd.width = _bck_resolution.width;
 
  312     _wnd.height = _bck_resolution.height;
 
  318     DWORD style, showstyle;
 
  321     showstyle = SW_SHOWNORMAL;
 
  322     _wnd.fullscreen = full_screen;
 
  323     if (_wnd.fullscreen) {
 
  325       SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
 
  327       style = WS_OVERLAPPEDWINDOW;
 
  329       if (_window_maximize) showstyle = SW_SHOWMAXIMIZED;
 
  330       SetRect(&r, 0, 0, _wnd.width, _wnd.height);
 
  334     AdjustWindowRect(&r, style, FALSE);
 
  336     w = r.right - r.left;
 
  337     h = r.bottom - r.top;
 
  339     if (_wnd.main_wnd != NULL) {
 
  340       if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
 
  342       TCHAR Windowtitle[50];
 
  343       int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
 
  344       int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
 
  346       _sntprintf(Windowtitle, 
lengthof(Windowtitle), _T(
"OpenTTD %s"), MB_TO_WIDE(_openttd_revision));
 
  348       _wnd.main_wnd = CreateWindow(_T(
"OTTD"), Windowtitle, style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0);
 
  349       if (_wnd.main_wnd == NULL) 
usererror(
"CreateWindow failed");
 
  350       ShowWindow(_wnd.main_wnd, showstyle);
 
  363   HDC dc2 = CreateCompatibleDC(dc);
 
  364   HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
 
  365   HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
 
  388   BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
 
  389   SelectPalette(dc, old_palette, TRUE);
 
  390   SelectObject(dc2, old_bmp);
 
  394 static void PaintWindowThread(
void *)
 
  406     ClientToScreen(_wnd.main_wnd, &pt);
 
  407     OffsetRect(&_wnd.update_rect, pt.x, pt.y);
 
  411     HRGN rgn = CreateRectRgnIndirect(&_wnd.update_rect);
 
  412     HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN);
 
  417     SetRectEmpty(&_wnd.update_rect);
 
  418     ReleaseDC(_wnd.main_wnd, dc);
 
  427   _draw_thread->
Exit();
 
  433 #if !defined(UNICODE) 
  434   static char prev_char = 0;
 
  436   char input[2] = {(char)charcode, 0};
 
  439   if (prev_char != 0) {
 
  441     input[0] = prev_char;
 
  442     input[1] = (char)charcode;
 
  444   } 
else if (IsDBCSLeadByte(charcode)) {
 
  446     prev_char = charcode;
 
  452   int len = MultiByteToWideChar(CP_ACP, 0, input, input_len, w, 2);
 
  463       DEBUG(driver, 1, 
"Invalid DBCS character sequence encountered, dropping input");
 
  468   static WChar prev_char = 0;
 
  472     if (prev_char != 0) 
DEBUG(driver, 1, 
"Got two UTF-16 lead surrogates, dropping the first one");
 
  473     prev_char = charcode;
 
  478   if (prev_char != 0) {
 
  482       DEBUG(driver, 1, 
"Got an UTF-16 lead surrogate without a trail surrogate, dropping the lead surrogate");
 
  493 #if !defined(WINCE) || _WIN32_WCE >= 0x400 
  497   return (_imm_props & IME_PROP_AT_CARET) && !(_imm_props & IME_PROP_SPECIAL_UI);
 
  503   HIMC hIMC = ImmGetContext(hwnd);
 
  506     cf.dwStyle = CFS_POINT;
 
  511       cf.ptCurrentPos.x = _focused_window->
left + pt.x;
 
  512       cf.ptCurrentPos.y = _focused_window->
top  + pt.y;
 
  514       cf.ptCurrentPos.x = 0;
 
  515       cf.ptCurrentPos.y = 0;
 
  517     ImmSetCompositionWindow(hIMC, &cf);
 
  519   ImmReleaseContext(hwnd, hIMC);
 
  525   HIMC hIMC = ImmGetContext(hwnd);
 
  529     cf.dwStyle = CFS_EXCLUDE;
 
  533       cf.ptCurrentPos.x = _focused_window->
left + pt.x;
 
  534       cf.ptCurrentPos.y = _focused_window->
top  + pt.y;
 
  536         cf.rcArea.left   = _focused_window->
left;
 
  537         cf.rcArea.top    = _focused_window->
top;
 
  538         cf.rcArea.right  = _focused_window->
left + _focused_window->
width;
 
  539         cf.rcArea.bottom = _focused_window->
top  + _focused_window->
height;
 
  547       cf.ptCurrentPos.x = 0;
 
  548       cf.ptCurrentPos.y = 0;
 
  549       SetRectEmpty(&cf.rcArea);
 
  551     ImmSetCandidateWindow(hIMC, &cf);
 
  553   ImmReleaseContext(hwnd, hIMC);
 
  559   HIMC hIMC = ImmGetContext(hwnd);
 
  562     if (lParam & GCS_RESULTSTR) {
 
  564       LONG len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); 
 
  565       TCHAR *str = (TCHAR *)_alloca(len + 
sizeof(TCHAR));
 
  566       len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, str, len);
 
  567       str[len / 
sizeof(TCHAR)] = 
'\0';
 
  577       lParam &= ~(GCS_RESULTSTR | GCS_RESULTCLAUSE | GCS_RESULTREADCLAUSE | GCS_RESULTREADSTR);
 
  582       LONG len = ImmGetCompositionString(hIMC, GCS_COMPSTR, NULL, 0); 
 
  583       TCHAR *str = (TCHAR *)_alloca(len + 
sizeof(TCHAR));
 
  584       len = ImmGetCompositionString(hIMC, GCS_COMPSTR, str, len);
 
  585       str[len / 
sizeof(TCHAR)] = 
'\0';
 
  588         static char utf8_buf[1024];
 
  592         LONG caret_bytes = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
 
  593         const char *caret = utf8_buf;
 
  594         for (
const TCHAR *c = str; *c != 
'\0' && *caret != 
'\0' && caret_bytes > 0; c++, caret_bytes--) {
 
  599           if (IsDBCSLeadByte(*c)) {
 
  612       lParam &= ~(GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE | GCS_CURSORPOS | GCS_DELTASTART);
 
  615   ImmReleaseContext(hwnd, hIMC);
 
  617   return lParam != 0 ? DefWindowProc(hwnd, WM_IME_COMPOSITION, wParam, lParam) : 0;
 
  623   HIMC hIMC = ImmGetContext(hwnd);
 
  624   if (hIMC != NULL) ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
 
  625   ImmReleaseContext(hwnd, hIMC);
 
  639 static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
  641   static uint32 keycode = 0;
 
  642   static bool console = 
false;
 
  643   static bool in_sizemove = 
false;
 
  647       SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
 
  649 #if !defined(WINCE) || _WIN32_WCE >= 0x400 
  654     case WM_ENTERSIZEMOVE:
 
  658     case WM_EXITSIZEMOVE:
 
  666         GetUpdateRect(hwnd, &r, FALSE);
 
  667         UnionRect(&_wnd.update_rect, &_wnd.update_rect, &r);
 
  670         ValidateRect(hwnd, NULL);
 
  675         BeginPaint(hwnd, &ps);
 
  681     case WM_PALETTECHANGED:
 
  682       if ((HWND)wParam == hwnd) 
return 0;
 
  685     case WM_QUERYNEWPALETTE: {
 
  686       HDC hDC = GetWindowDC(hwnd);
 
  687       HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE);
 
  688       UINT nChanged = RealizePalette(hDC);
 
  690       SelectPalette(hDC, hOldPalette, TRUE);
 
  691       ReleaseDC(hwnd, hDC);
 
  692       if (nChanged != 0) InvalidateRect(hwnd, NULL, FALSE);
 
  697       HandleExitGameRequest();
 
  738       int x = (int16)LOWORD(lParam);
 
  739       int y = (int16)HIWORD(lParam);
 
  747         SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
 
  751         pt.x = _cursor.
pos.x;
 
  752         pt.y = _cursor.
pos.y;
 
  753         ClientToScreen(hwnd, &pt);
 
  754         SetCursorPos(pt.x, pt.y);
 
  761 #if !defined(WINCE) || _WIN32_WCE >= 0x400 
  762     case WM_INPUTLANGCHANGE:
 
  766     case WM_IME_SETCONTEXT:
 
  771     case WM_IME_STARTCOMPOSITION:
 
  776     case WM_IME_COMPOSITION:
 
  779     case WM_IME_ENDCOMPOSITION:
 
  789 #if !defined(UNICODE) 
  791       if (
GB(wParam, 8, 8) != 0) {
 
  801       console = 
GB(lParam, 16, 8) == 41;
 
  805       uint scancode = 
GB(lParam, 16, 8);
 
  806       uint charcode = wParam;
 
  810       if (console && scancode == 41) {
 
  817       uint cur_keycode = keycode;
 
  825       uint scancode = 
GB(lParam, 16, 8);
 
  826       keycode = scancode == 41 ? (uint)WKC_BACKQUOTE : MapWindowsKey(wParam);
 
  830       if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
 
  831         if ((msg.message == WM_CHAR || msg.message == WM_DEADCHAR) && 
GB(lParam, 16, 8) == 
GB(msg.lParam, 16, 8)) {
 
  836       uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
 
  845       if (
HasBit(charcode, 31) && !console) {
 
  846         if (scancode == 41) {
 
  855       uint cur_keycode = keycode;
 
  865           ToggleFullScreen(!_wnd.fullscreen);
 
  882       if (wParam != SIZE_MINIMIZED) {
 
  885         _window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen));
 
  886         if (_window_maximize || _fullscreen) _bck_resolution = 
_cur_resolution;
 
  887         ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
 
  893       RECT *r = (RECT*)lParam;
 
  897       SetRect(&r2, 0, 0, 0, 0);
 
  898       AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
 
  900       w = r->right - r->left - (r2.right - r2.left);
 
  901       h = r->bottom - r->top - (r2.bottom - r2.top);
 
  904       SetRect(&r2, 0, 0, w, h);
 
  906       AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
 
  907       w = r2.right - r2.left;
 
  908       h = r2.bottom - r2.top;
 
  912           r->bottom = r->top + h;
 
  915         case WMSZ_BOTTOMLEFT:
 
  916           r->bottom = r->top + h;
 
  917           r->left = r->right - w;
 
  920         case WMSZ_BOTTOMRIGHT:
 
  921           r->bottom = r->top + h;
 
  922           r->right = r->left + w;
 
  926           r->left = r->right - w;
 
  930           r->right = r->left + w;
 
  934           r->top = r->bottom - h;
 
  938           r->top = r->bottom - h;
 
  939           r->left = r->right - w;
 
  943           r->top = r->bottom - h;
 
  944           r->right = r->left + w;
 
  952 #if !defined(WM_MOUSEWHEEL) 
  953 # define WM_MOUSEWHEEL 0x020A 
  955 #if !defined(GET_WHEEL_DELTA_WPARAM) 
  956 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) 
  959     case WM_MOUSEWHEEL: {
 
  960       int delta = GET_WHEEL_DELTA_WPARAM(wParam);
 
  964       } 
else if (delta > 0) {
 
  972       _wnd.has_focus = 
true;
 
  977       _wnd.has_focus = 
false;
 
  983       if (_exit_game) 
break;
 
  985       bool active = (LOWORD(wParam) != WA_INACTIVE);
 
  986       bool minimized = (HIWORD(wParam) != 0);
 
  987       if (_wnd.fullscreen) {
 
  988         if (active && minimized) {
 
  990           ShowWindow(hwnd, SW_RESTORE);
 
  992         } 
else if (!active && !minimized) {
 
  994           ShowWindow(hwnd, SW_MINIMIZE);
 
  995           ChangeDisplaySettings(NULL, 0);
 
 1003   return DefWindowProc(hwnd, msg, wParam, lParam);
 
 1006 static void RegisterWndClass()
 
 1008   static bool registered = 
false;
 
 1011     HINSTANCE hinst = GetModuleHandle(NULL);
 
 1018       LoadIcon(hinst, MAKEINTRESOURCE(100)),
 
 1019       LoadCursor(NULL, IDC_ARROW),
 
 1026     if (!RegisterClass(&wnd)) 
usererror(
"RegisterClass failed");
 
 1030 static bool AllocateDibSection(
int w, 
int h, 
bool force)
 
 1039   if (bpp == 0) 
usererror(
"Can't use a blitter that blits 0 bpp for normal visuals");
 
 1041   if (!force && w == _screen.width && h == _screen.height) 
return false;
 
 1043   bi = (BITMAPINFO*)alloca(
sizeof(BITMAPINFOHEADER) + 
sizeof(RGBQUAD) * 256);
 
 1044   memset(bi, 0, 
sizeof(BITMAPINFOHEADER) + 
sizeof(RGBQUAD) * 256);
 
 1045   bi->bmiHeader.biSize = 
sizeof(BITMAPINFOHEADER);
 
 1047   bi->bmiHeader.biWidth = _wnd.width = w;
 
 1048   bi->bmiHeader.biHeight = -(_wnd.height = h);
 
 1050   bi->bmiHeader.biPlanes = 1;
 
 1052   bi->bmiHeader.biCompression = BI_RGB;
 
 1054   if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
 
 1057   _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
 
 1058   if (_wnd.dib_sect == NULL) 
usererror(
"CreateDIBSection failed");
 
 1062   _screen.pitch = (bpp == 8) ? 
Align(w, 4) : w;
 
 1064   _screen.dst_ptr = _wnd.buffer_bits;
 
 1069 static const Dimension default_resolutions[] = {
 
 1083 static void FindResolutions()
 
 1099   for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
 
 1100     if (dm.dmBitsPerPel == bpp &&
 
 1101         dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480) {
 
 1104       for (j = 0; j < n; j++) {
 
 1123     memcpy(
_resolutions, default_resolutions, 
sizeof(default_resolutions));
 
 1135   memset(&_wnd, 0, 
sizeof(_wnd));
 
 1161   DeleteObject(_wnd.gdi_palette);
 
 1162   DeleteObject(_wnd.dib_sect);
 
 1163   DestroyWindow(_wnd.main_wnd);
 
 1166   if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
 
 1173   RECT r = { left, top, left + width, top + height };
 
 1175   InvalidateRect(_wnd.main_wnd, &r, FALSE);
 
 1178 static void CheckPaletteAnim()
 
 1183   InvalidateRect(_wnd.main_wnd, NULL, FALSE);
 
 1189   uint32 cur_ticks = GetTickCount();
 
 1190   uint32 last_cur_ticks = cur_ticks;
 
 1211         DEBUG(driver, 1, 
"Threaded drawing enabled");
 
 1219   _wnd.running = 
true;
 
 1223     uint32 prev_cur_ticks = cur_ticks; 
 
 1225     while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) {
 
 1226       InteractiveRandom(); 
 
 1229       DispatchMessage(&mesg);
 
 1231     if (_exit_game) 
return;
 
 1234     if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0 &&
 
 1237     if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0 &&
 
 1241     } 
else if (_fast_forward & 2) {
 
 1245     cur_ticks = GetTickCount();
 
 1246     if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
 
 1248       last_cur_ticks = cur_ticks;
 
 1253       _ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
 
 1257       if (_wnd.has_focus) {
 
 1259           (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
 
 1260           (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
 
 1261           (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
 
 1262           (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
 
 1306     _draw_thread->
Join();
 
 1317   if (_window_maximize) ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL);
 
 1319   _wnd.width = _wnd.width_org = w;
 
 1320   _wnd.height = _wnd.height_org = h;
 
 1323   if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
 
 1331   if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
 
 1338   bool ret = AllocateDibSection(_screen.width, _screen.height, 
true) && this->
MakeWindow(_fullscreen);
 
 1339   if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
 
 1349   if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);