Home | History | Annotate | Download | only in windib
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #define WIN32_LEAN_AND_MEAN 1
     25 #include <windows.h>
     26 
     27 /* Not yet in the mingw32 cross-compile headers */
     28 #ifndef CDS_FULLSCREEN
     29 #define CDS_FULLSCREEN	4
     30 #endif
     31 
     32 #include "SDL_syswm.h"
     33 #include "../SDL_sysvideo.h"
     34 #include "../SDL_pixels_c.h"
     35 #include "../../events/SDL_sysevents.h"
     36 #include "../../events/SDL_events_c.h"
     37 #include "SDL_gapidibvideo.h"
     38 #include "SDL_dibvideo.h"
     39 #include "../wincommon/SDL_syswm_c.h"
     40 #include "../wincommon/SDL_sysmouse_c.h"
     41 #include "SDL_dibevents_c.h"
     42 #include "../wincommon/SDL_wingl_c.h"
     43 
     44 #ifdef _WIN32_WCE
     45 
     46 #ifndef DM_DISPLAYORIENTATION
     47 #define DM_DISPLAYORIENTATION 0x00800000L
     48 #endif
     49 #ifndef DM_DISPLAYQUERYORIENTATION
     50 #define DM_DISPLAYQUERYORIENTATION 0x01000000L
     51 #endif
     52 #ifndef DMDO_0
     53 #define DMDO_0      0
     54 #endif
     55 #ifndef DMDO_90
     56 #define DMDO_90     1
     57 #endif
     58 #ifndef DMDO_180
     59 #define DMDO_180    2
     60 #endif
     61 #ifndef DMDO_270
     62 #define DMDO_270    4
     63 #endif
     64 
     65 #define NO_GETDIBITS
     66 #define NO_GAMMA_SUPPORT
     67   #if _WIN32_WCE < 420
     68     #define NO_CHANGEDISPLAYSETTINGS
     69   #else
     70     #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0)
     71   #endif
     72 #endif
     73 #ifndef WS_MAXIMIZE
     74 #define WS_MAXIMIZE	0
     75 #endif
     76 #ifndef WS_THICKFRAME
     77 #define WS_THICKFRAME	0
     78 #endif
     79 #ifndef SWP_NOCOPYBITS
     80 #define SWP_NOCOPYBITS	0
     81 #endif
     82 #ifndef PC_NOCOLLAPSE
     83 #define PC_NOCOLLAPSE	0
     84 #endif
     85 
     86 #ifdef _WIN32_WCE
     87 // defined and used in SDL_sysevents.c
     88 extern HINSTANCE aygshell;
     89 #endif
     90 
     91 /* Initialization/Query functions */
     92 static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
     93 static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
     94 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     95 static int DIB_SetColors(_THIS, int firstcolor, int ncolors,
     96 			 SDL_Color *colors);
     97 static void DIB_CheckGamma(_THIS);
     98 void DIB_SwapGamma(_THIS);
     99 void DIB_QuitGamma(_THIS);
    100 int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
    101 int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
    102 static void DIB_VideoQuit(_THIS);
    103 
    104 /* Hardware surface functions */
    105 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);
    106 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);
    107 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);
    108 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
    109 
    110 /* Windows message handling functions */
    111 static void DIB_GrabStaticColors(HWND window);
    112 static void DIB_ReleaseStaticColors(HWND window);
    113 static void DIB_Activate(_THIS, BOOL active, BOOL minimized);
    114 static void DIB_RealizePalette(_THIS);
    115 static void DIB_PaletteChanged(_THIS, HWND window);
    116 static void DIB_WinPAINT(_THIS, HDC hdc);
    117 
    118 static void DIB_GetWinPos(_THIS, int* px, int *py);
    119 static void DIB_SetWinPos(_THIS, int  x, int  y);
    120 static int  DIB_IsWinVisible(_THIS, int recenter);
    121 static int  DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi);
    122 static int  DIB_GetMonitorRect(_THIS, SDL_Rect*  rect);
    123 
    124 /* helper fn */
    125 static int DIB_SussScreenDepth();
    126 
    127 /* DIB driver bootstrap functions */
    128 
    129 static int DIB_Available(void)
    130 {
    131 	return(1);
    132 }
    133 
    134 static void DIB_DeleteDevice(SDL_VideoDevice *device)
    135 {
    136 	if ( device ) {
    137 		if ( device->hidden ) {
    138 			if ( device->hidden->dibInfo ) {
    139 				SDL_free( device->hidden->dibInfo );
    140 			}
    141 			SDL_free(device->hidden);
    142 		}
    143 		if ( device->gl_data ) {
    144 			SDL_free(device->gl_data);
    145 		}
    146 		SDL_free(device);
    147 	}
    148 }
    149 
    150 static SDL_VideoDevice *DIB_CreateDevice(int devindex)
    151 {
    152 	SDL_VideoDevice *device;
    153 
    154 	/* Initialize all variables that we clean on shutdown */
    155 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
    156 	if ( device ) {
    157 		SDL_memset(device, 0, (sizeof *device));
    158 		device->hidden = (struct SDL_PrivateVideoData *)
    159 				SDL_malloc((sizeof *device->hidden));
    160 		if(device->hidden){
    161 			SDL_memset(device->hidden, 0, (sizeof *device->hidden));
    162 			device->hidden->dibInfo = (DibInfo *)SDL_malloc((sizeof(DibInfo)));
    163 			if(device->hidden->dibInfo == NULL)
    164 			{
    165 				SDL_free(device->hidden);
    166 				device->hidden = NULL;
    167 			}
    168 		}
    169 
    170 		device->gl_data = (struct SDL_PrivateGLData *)
    171 				SDL_malloc((sizeof *device->gl_data));
    172 	}
    173 	if ( (device == NULL) || (device->hidden == NULL) ||
    174 		                 (device->gl_data == NULL) ) {
    175 		SDL_OutOfMemory();
    176 		DIB_DeleteDevice(device);
    177 		return(NULL);
    178 	}
    179 	SDL_memset(device->hidden->dibInfo, 0, (sizeof *device->hidden->dibInfo));
    180 	SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
    181 
    182 	/* Set the function pointers */
    183 	device->VideoInit = DIB_VideoInit;
    184 	device->ListModes = DIB_ListModes;
    185 	device->SetVideoMode = DIB_SetVideoMode;
    186 	device->UpdateMouse = WIN_UpdateMouse;
    187 	device->SetColors = DIB_SetColors;
    188 	device->UpdateRects = NULL;
    189 	device->VideoQuit = DIB_VideoQuit;
    190 	device->AllocHWSurface = DIB_AllocHWSurface;
    191 	device->CheckHWBlit = NULL;
    192 	device->FillHWRect = NULL;
    193 	device->SetHWColorKey = NULL;
    194 	device->SetHWAlpha = NULL;
    195 	device->LockHWSurface = DIB_LockHWSurface;
    196 	device->UnlockHWSurface = DIB_UnlockHWSurface;
    197 	device->FlipHWSurface = NULL;
    198 	device->FreeHWSurface = DIB_FreeHWSurface;
    199 	device->SetGammaRamp = DIB_SetGammaRamp;
    200 	device->GetGammaRamp = DIB_GetGammaRamp;
    201 #if SDL_VIDEO_OPENGL
    202 	device->GL_LoadLibrary = WIN_GL_LoadLibrary;
    203 	device->GL_GetProcAddress = WIN_GL_GetProcAddress;
    204 	device->GL_GetAttribute = WIN_GL_GetAttribute;
    205 	device->GL_MakeCurrent = WIN_GL_MakeCurrent;
    206 	device->GL_SwapBuffers = WIN_GL_SwapBuffers;
    207 #endif
    208 	device->SetCaption = WIN_SetWMCaption;
    209 	device->SetIcon = WIN_SetWMIcon;
    210 	device->IconifyWindow = WIN_IconifyWindow;
    211 	device->GrabInput = WIN_GrabInput;
    212 	device->GetWMInfo = WIN_GetWMInfo;
    213 	device->FreeWMCursor = WIN_FreeWMCursor;
    214 	device->CreateWMCursor = WIN_CreateWMCursor;
    215 	device->ShowWMCursor = WIN_ShowWMCursor;
    216 	device->WarpWMCursor = WIN_WarpWMCursor;
    217 	device->CheckMouseMode = WIN_CheckMouseMode;
    218 	device->InitOSKeymap = DIB_InitOSKeymap;
    219 	device->PumpEvents = DIB_PumpEvents;
    220 
    221 	device->GetWindowPos = DIB_GetWinPos;
    222 	device->SetWindowPos = DIB_SetWinPos;
    223 	device->IsWindowVisible = DIB_IsWinVisible;
    224 	device->GetMonitorDPI = DIB_GetMonitorDPI;
    225 	device->GetMonitorRect = DIB_GetMonitorRect;
    226 
    227 	/* Set up the windows message handling functions */
    228 	WIN_Activate = DIB_Activate;
    229 	WIN_RealizePalette = DIB_RealizePalette;
    230 	WIN_PaletteChanged = DIB_PaletteChanged;
    231 	WIN_WinPAINT = DIB_WinPAINT;
    232 	HandleMessage = DIB_HandleMessage;
    233 
    234 	device->free = DIB_DeleteDevice;
    235 
    236 	/* We're finally ready */
    237 	return device;
    238 }
    239 
    240 VideoBootStrap WINDIB_bootstrap = {
    241 	"windib", "Win95/98/NT/2000/CE GDI",
    242 	DIB_Available, DIB_CreateDevice
    243 };
    244 
    245 static int cmpmodes(const void *va, const void *vb)
    246 {
    247     SDL_Rect *a = *(SDL_Rect **)va;
    248     SDL_Rect *b = *(SDL_Rect **)vb;
    249     if ( a->w == b->w )
    250         return b->h - a->h;
    251     else
    252         return b->w - a->w;
    253 }
    254 
    255 static int DIB_AddMode(_THIS, int bpp, int w, int h)
    256 {
    257 	SDL_Rect *mode;
    258 	int i, index;
    259 	int next_mode;
    260 
    261 	/* Check to see if we already have this mode */
    262 	if ( bpp < 8 || bpp > 32 ) {  /* Not supported */
    263 		return(0);
    264 	}
    265 	index = ((bpp+7)/8)-1;
    266 	for ( i=0; i<SDL_nummodes[index]; ++i ) {
    267 		mode = SDL_modelist[index][i];
    268 		if ( (mode->w == w) && (mode->h == h) ) {
    269 			return(0);
    270 		}
    271 	}
    272 
    273 	/* Set up the new video mode rectangle */
    274 	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
    275 	if ( mode == NULL ) {
    276 		SDL_OutOfMemory();
    277 		return(-1);
    278 	}
    279 	mode->x = 0;
    280 	mode->y = 0;
    281 	mode->w = w;
    282 	mode->h = h;
    283 
    284 	/* Allocate the new list of modes, and fill in the new mode */
    285 	next_mode = SDL_nummodes[index];
    286 	SDL_modelist[index] = (SDL_Rect **)
    287 	       SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
    288 	if ( SDL_modelist[index] == NULL ) {
    289 		SDL_OutOfMemory();
    290 		SDL_nummodes[index] = 0;
    291 		SDL_free(mode);
    292 		return(-1);
    293 	}
    294 	SDL_modelist[index][next_mode] = mode;
    295 	SDL_modelist[index][next_mode+1] = NULL;
    296 	SDL_nummodes[index]++;
    297 
    298 	return(0);
    299 }
    300 
    301 static void DIB_CreatePalette(_THIS, int bpp)
    302 {
    303 /*	RJR: March 28, 2000
    304 	moved palette creation here from "DIB_VideoInit" */
    305 
    306 	LOGPALETTE *palette;
    307 	HDC hdc;
    308 	int ncolors;
    309 
    310 	ncolors = (1 << bpp);
    311 	palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+
    312 				ncolors*sizeof(PALETTEENTRY));
    313 	palette->palVersion = 0x300;
    314 	palette->palNumEntries = ncolors;
    315 	hdc = GetDC(SDL_Window);
    316 	GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
    317 	ReleaseDC(SDL_Window, hdc);
    318 	screen_pal = CreatePalette(palette);
    319 	screen_logpal = palette;
    320 }
    321 
    322 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
    323 {
    324 	const char *env = NULL;
    325 #ifndef NO_CHANGEDISPLAYSETTINGS
    326 	int i;
    327 	DEVMODE settings;
    328 #endif
    329 
    330 	/* Create the window */
    331 	if ( DIB_CreateWindow(this) < 0 ) {
    332 		return(-1);
    333 	}
    334 
    335 #if !SDL_AUDIO_DISABLED
    336 	DX5_SoundFocus(SDL_Window);
    337 #endif
    338 
    339 	/* Determine the screen depth */
    340 	vformat->BitsPerPixel = DIB_SussScreenDepth();
    341 	switch (vformat->BitsPerPixel) {
    342 		case 15:
    343 			vformat->Rmask = 0x00007c00;
    344 			vformat->Gmask = 0x000003e0;
    345 			vformat->Bmask = 0x0000001f;
    346 			vformat->BitsPerPixel = 16;
    347 			break;
    348 		case 16:
    349 			vformat->Rmask = 0x0000f800;
    350 			vformat->Gmask = 0x000007e0;
    351 			vformat->Bmask = 0x0000001f;
    352 			break;
    353 		case 24:
    354 		case 32:
    355 			/* GDI defined as 8-8-8 */
    356 			vformat->Rmask = 0x00ff0000;
    357 			vformat->Gmask = 0x0000ff00;
    358 			vformat->Bmask = 0x000000ff;
    359 			break;
    360 		default:
    361 			break;
    362 	}
    363 
    364 	/* See if gamma is supported on this screen */
    365 	DIB_CheckGamma(this);
    366 
    367 #ifndef NO_CHANGEDISPLAYSETTINGS
    368 
    369 	settings.dmSize = sizeof(DEVMODE);
    370 	settings.dmDriverExtra = 0;
    371 #ifdef _WIN32_WCE
    372 	settings.dmFields = DM_DISPLAYQUERYORIENTATION;
    373 	this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL;
    374 #endif
    375 	/* Query for the desktop resolution */
    376 	SDL_desktop_mode.dmSize = sizeof(SDL_desktop_mode);
    377 	SDL_desktop_mode.dmDriverExtra = 0;
    378 	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
    379 	this->info.current_w = SDL_desktop_mode.dmPelsWidth;
    380 	this->info.current_h = SDL_desktop_mode.dmPelsHeight;
    381 
    382 	/* Query for the list of available video modes */
    383 	for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) {
    384 		DIB_AddMode(this, settings.dmBitsPerPel,
    385 			settings.dmPelsWidth, settings.dmPelsHeight);
    386 #ifdef _WIN32_WCE
    387 		if( this->hidden->supportRotation )
    388 			DIB_AddMode(this, settings.dmBitsPerPel,
    389 				settings.dmPelsHeight, settings.dmPelsWidth);
    390 #endif
    391 	}
    392 	/* Sort the mode lists */
    393 	for ( i=0; i<NUM_MODELISTS; ++i ) {
    394 		if ( SDL_nummodes[i] > 0 ) {
    395 			SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes);
    396 		}
    397 	}
    398 #else
    399 	// WinCE and fullscreen mode:
    400 	// We use only vformat->BitsPerPixel that allow SDL to
    401 	// emulate other bpp (8, 32) and use triple buffer,
    402 	// because SDL surface conversion is much faster than the WinCE one.
    403 	// Although it should be tested on devices with graphics accelerator.
    404 
    405 	DIB_AddMode(this, vformat->BitsPerPixel,
    406 			GetDeviceCaps(GetDC(NULL), HORZRES),
    407 			GetDeviceCaps(GetDC(NULL), VERTRES));
    408 
    409 #endif /* !NO_CHANGEDISPLAYSETTINGS */
    410 
    411 	/* Grab an identity palette if we are in a palettized mode */
    412 	if ( vformat->BitsPerPixel <= 8 ) {
    413 	/*	RJR: March 28, 2000
    414 		moved palette creation to "DIB_CreatePalette" */
    415 		DIB_CreatePalette(this, vformat->BitsPerPixel);
    416 	}
    417 
    418 	/* Fill in some window manager capabilities */
    419 	this->info.wm_available = 1;
    420 
    421 #ifdef _WIN32_WCE
    422 	this->hidden->origRotation = -1;
    423 #endif
    424 
    425 	/* Allow environment override of screensaver disable. */
    426 	env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
    427 	if ( env ) {
    428 		allow_screensaver = SDL_atoi(env);
    429 	} else {
    430 #ifdef SDL_VIDEO_DISABLE_SCREENSAVER
    431 		allow_screensaver = 0;
    432 #else
    433 		allow_screensaver = 1;
    434 #endif
    435 	}
    436 
    437 	/* We're done! */
    438 	return(0);
    439 }
    440 
    441 /* We support any format at any dimension */
    442 SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    443 {
    444 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    445 		return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
    446 	} else {
    447 		return((SDL_Rect **)-1);
    448 	}
    449 }
    450 
    451 
    452 /*
    453   Helper fn to work out which screen depth windows is currently using.
    454   15 bit mode is considered 555 format, 16 bit is 565.
    455   returns 0 for unknown mode.
    456   (Derived from code in sept 1999 Windows Developer Journal
    457   http://www.wdj.com/code/archive.html)
    458 */
    459 static int DIB_SussScreenDepth()
    460 {
    461 #ifdef NO_GETDIBITS
    462 	int depth;
    463 	HDC hdc;
    464 
    465 	hdc = GetDC(SDL_Window);
    466 	depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
    467 	ReleaseDC(SDL_Window, hdc);
    468 	return(depth);
    469 #else
    470     int depth;
    471     int dib_size;
    472     LPBITMAPINFOHEADER dib_hdr;
    473     HDC hdc;
    474     HBITMAP hbm;
    475 
    476     /* Allocate enough space for a DIB header plus palette (for
    477      * 8-bit modes) or bitfields (for 16- and 32-bit modes)
    478      */
    479     dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
    480     dib_hdr = (LPBITMAPINFOHEADER) SDL_malloc(dib_size);
    481     SDL_memset(dib_hdr, 0, dib_size);
    482     dib_hdr->biSize = sizeof(BITMAPINFOHEADER);
    483 
    484     /* Get a device-dependent bitmap that's compatible with the
    485        screen.
    486      */
    487     hdc = GetDC(NULL);
    488     hbm = CreateCompatibleBitmap( hdc, 1, 1 );
    489 
    490     /* Convert the DDB to a DIB.  We need to call GetDIBits twice:
    491      * the first call just fills in the BITMAPINFOHEADER; the
    492      * second fills in the bitfields or palette.
    493      */
    494     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
    495     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
    496     DeleteObject(hbm);
    497     ReleaseDC(NULL, hdc);
    498 
    499     depth = 0;
    500     switch( dib_hdr->biBitCount )
    501     {
    502     case 8:     depth = 8; break;
    503     case 24:    depth = 24; break;
    504     case 32:    depth = 32; break;
    505     case 16:
    506         if( dib_hdr->biCompression == BI_BITFIELDS ) {
    507             /* check the red mask */
    508             switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) {
    509                 case 0xf800: depth = 16; break;   /* 565 */
    510                 case 0x7c00: depth = 15; break;   /* 555 */
    511             }
    512         }
    513     }
    514     SDL_free(dib_hdr);
    515     return depth;
    516 #endif /* NO_GETDIBITS */
    517 }
    518 
    519 
    520 /* Various screen update functions available */
    521 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
    522 
    523 static void DIB_ResizeWindow(_THIS, int width, int height, int prev_width, int prev_height, Uint32 flags)
    524 {
    525 	RECT bounds;
    526 	int x, y;
    527 
    528 #ifndef _WIN32_WCE
    529 	/* Resize the window */
    530 	if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
    531 #else
    532 	if ( !SDL_windowid ) {
    533 #endif
    534 		HWND top;
    535 		UINT swp_flags;
    536 		const char *window = NULL;
    537 		const char *center = NULL;
    538 
    539 		if ( width != prev_width || height != prev_height ) {
    540 			window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
    541 			center = SDL_getenv("SDL_VIDEO_CENTERED");
    542 			if ( window ) {
    543 				if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
    544 					SDL_windowX = x;
    545 					SDL_windowY = y;
    546 				}
    547 				if ( SDL_strcmp(window, "center") == 0 ) {
    548 					center = window;
    549 				}
    550 			}
    551 		}
    552 		swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
    553 
    554 		bounds.left = SDL_windowX;
    555 		bounds.top = SDL_windowY;
    556 		bounds.right = SDL_windowX+width;
    557 		bounds.bottom = SDL_windowY+height;
    558 #ifndef _WIN32_WCE
    559 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0);
    560 #else
    561 		// The bMenu parameter must be FALSE; menu bars are not supported
    562 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0);
    563 #endif
    564 		width = bounds.right-bounds.left;
    565 		height = bounds.bottom-bounds.top;
    566 		if ( (flags & SDL_FULLSCREEN) ) {
    567 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
    568 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
    569 		} else if ( center ) {
    570 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
    571 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
    572 		} else if ( SDL_windowX || SDL_windowY || window ) {
    573 			x = bounds.left;
    574 			y = bounds.top;
    575 		} else {
    576 			x = y = -1;
    577 			swp_flags |= SWP_NOMOVE;
    578 		}
    579 		if ( flags & SDL_FULLSCREEN ) {
    580 			top = HWND_TOPMOST;
    581 		} else {
    582 			top = HWND_NOTOPMOST;
    583 		}
    584 		SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
    585 		if ( !(flags & SDL_FULLSCREEN) ) {
    586 			SDL_windowX = SDL_bounds.left;
    587 			SDL_windowY = SDL_bounds.top;
    588 		}
    589 		if ( GetParent(SDL_Window) == NULL ) {
    590 			SetForegroundWindow(SDL_Window);
    591 		}
    592 	}
    593 }
    594 
    595 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
    596 				int width, int height, int bpp, Uint32 flags)
    597 {
    598 	SDL_Surface *video;
    599 	int prev_w, prev_h;
    600 	Uint32 prev_flags;
    601 	DWORD style;
    602 	const DWORD directstyle =
    603 			(WS_POPUP);
    604 	const DWORD windowstyle =
    605 			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
    606 	const DWORD resizestyle =
    607 			(WS_THICKFRAME|WS_MAXIMIZEBOX);
    608 	int binfo_size;
    609 	BITMAPINFO *binfo;
    610 	HDC hdc;
    611 	Uint32 Rmask, Gmask, Bmask;
    612 
    613 	prev_w = current->w;
    614 	prev_h = current->h;
    615 	prev_flags = current->flags;
    616 
    617 	/*
    618 	 * Special case for OpenGL windows...since the app needs to call
    619 	 *  SDL_SetVideoMode() in response to resize events to continue to
    620 	 *  function, but WGL handles the GL context details behind the scenes,
    621 	 *  there's no sense in tearing the context down just to rebuild it
    622 	 *  to what it already was...tearing it down sacrifices your GL state
    623 	 *  and uploaded textures. So if we're requesting the same video mode
    624 	 *  attributes just resize the window and return immediately.
    625 	 */
    626 	if ( SDL_Window &&
    627 	     ((current->flags & ~SDL_ANYFORMAT) == (flags & ~SDL_ANYFORMAT)) &&
    628 	     (current->format->BitsPerPixel == bpp) &&
    629 	     (flags & SDL_OPENGL) &&
    630 	     !(flags & SDL_FULLSCREEN) ) {  /* probably not safe for fs */
    631 		current->w = width;
    632 		current->h = height;
    633 		SDL_resizing = 1;
    634 		DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
    635 		SDL_resizing = 0;
    636 		return current;
    637 	}
    638 
    639 	/* Clean up any GL context that may be hanging around */
    640 	if ( current->flags & SDL_OPENGL ) {
    641 		WIN_GL_ShutDown(this);
    642 	}
    643 	SDL_resizing = 1;
    644 
    645 	/* Recalculate the bitmasks if necessary */
    646 	if ( bpp == current->format->BitsPerPixel ) {
    647 		video = current;
    648 	} else {
    649 		switch (bpp) {
    650 			case 15:
    651 			case 16:
    652 				if ( DIB_SussScreenDepth() == 15 ) {
    653 					/* 5-5-5 */
    654 					Rmask = 0x00007c00;
    655 					Gmask = 0x000003e0;
    656 					Bmask = 0x0000001f;
    657 				} else {
    658 					/* 5-6-5 */
    659 					Rmask = 0x0000f800;
    660 					Gmask = 0x000007e0;
    661 					Bmask = 0x0000001f;
    662 				}
    663 				break;
    664 			case 24:
    665 			case 32:
    666 				/* GDI defined as 8-8-8 */
    667 				Rmask = 0x00ff0000;
    668 				Gmask = 0x0000ff00;
    669 				Bmask = 0x000000ff;
    670 				break;
    671 			default:
    672 				Rmask = 0x00000000;
    673 				Gmask = 0x00000000;
    674 				Bmask = 0x00000000;
    675 				break;
    676 		}
    677 		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
    678 					0, 0, bpp, Rmask, Gmask, Bmask, 0);
    679 		if ( video == NULL ) {
    680 			SDL_OutOfMemory();
    681 			return(NULL);
    682 		}
    683 	}
    684 
    685 	/* Fill in part of the video surface */
    686 	video->flags = 0;	/* Clear flags */
    687 	video->w = width;
    688 	video->h = height;
    689 	video->pitch = SDL_CalculatePitch(video);
    690 
    691 	/* Small fix for WinCE/Win32 - when activating window
    692 	   SDL_VideoSurface is equal to zero, so activating code
    693 	   is not called properly for fullscreen windows because
    694 	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
    695 	*/
    696 	SDL_VideoSurface = video;
    697 
    698 #if defined(_WIN32_WCE)
    699 	if ( flags & SDL_FULLSCREEN )
    700 		video->flags |= SDL_FULLSCREEN;
    701 #endif
    702 
    703 #ifndef NO_CHANGEDISPLAYSETTINGS
    704 	/* Set fullscreen mode if appropriate */
    705 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    706 		DEVMODE settings;
    707 		BOOL changed;
    708 
    709 		SDL_memset(&settings, 0, sizeof(DEVMODE));
    710 		settings.dmSize = sizeof(DEVMODE);
    711 
    712 #ifdef _WIN32_WCE
    713 		// try to rotate screen to fit requested resolution
    714 		if( this->hidden->supportRotation )
    715 		{
    716 			DWORD rotation;
    717 
    718 			// ask current mode
    719 			settings.dmFields = DM_DISPLAYORIENTATION;
    720 			ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
    721 			rotation = settings.dmDisplayOrientation;
    722 
    723 			if( (width > GetDeviceCaps(GetDC(NULL), HORZRES))
    724 				&& (height < GetDeviceCaps(GetDC(NULL), VERTRES)))
    725 			{
    726 				switch( rotation )
    727 				{
    728 				case DMDO_0:
    729 					settings.dmDisplayOrientation = DMDO_90;
    730 					break;
    731 				case DMDO_270:
    732 					settings.dmDisplayOrientation = DMDO_180;
    733 					break;
    734 				}
    735 				if( settings.dmDisplayOrientation != rotation )
    736 				{
    737 					// go to landscape
    738 					this->hidden->origRotation = rotation;
    739 					ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
    740 				}
    741 			}
    742 			if( (width < GetDeviceCaps(GetDC(NULL), HORZRES))
    743 				&& (height > GetDeviceCaps(GetDC(NULL), VERTRES)))
    744 			{
    745 				switch( rotation )
    746 				{
    747 				case DMDO_90:
    748 					settings.dmDisplayOrientation = DMDO_0;
    749 					break;
    750 				case DMDO_180:
    751 					settings.dmDisplayOrientation = DMDO_270;
    752 					break;
    753 				}
    754 				if( settings.dmDisplayOrientation != rotation )
    755 				{
    756 					// go to portrait
    757 					this->hidden->origRotation = rotation;
    758 					ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
    759 				}
    760 			}
    761 
    762 		}
    763 #endif
    764 
    765 #ifndef _WIN32_WCE
    766 		settings.dmBitsPerPel = video->format->BitsPerPixel;
    767 		settings.dmPelsWidth = width;
    768 		settings.dmPelsHeight = height;
    769 		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
    770 		if ( width <= (int)SDL_desktop_mode.dmPelsWidth &&
    771 		     height <= (int)SDL_desktop_mode.dmPelsHeight ) {
    772 			settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
    773 			settings.dmFields |= DM_DISPLAYFREQUENCY;
    774 		}
    775 		changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
    776 		if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) {
    777 			settings.dmFields &= ~DM_DISPLAYFREQUENCY;
    778 			changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
    779 		}
    780 #else
    781 		changed = 1;
    782 #endif
    783 		if ( changed ) {
    784 			video->flags |= SDL_FULLSCREEN;
    785 			SDL_fullscreen_mode = settings;
    786 		}
    787 
    788 	}
    789 #endif /* !NO_CHANGEDISPLAYSETTINGS */
    790 
    791 	/* Reset the palette and create a new one if necessary */
    792 	if ( grab_palette ) {
    793 		DIB_ReleaseStaticColors(SDL_Window);
    794 		grab_palette = FALSE;
    795 	}
    796 	if ( screen_pal != NULL ) {
    797 	/*	RJR: March 28, 2000
    798 		delete identity palette if switching from a palettized mode */
    799 		DeleteObject(screen_pal);
    800 		screen_pal = NULL;
    801 	}
    802 	if ( screen_logpal != NULL ) {
    803 		SDL_free(screen_logpal);
    804 		screen_logpal = NULL;
    805 	}
    806 
    807 	if ( bpp <= 8 )
    808 	{
    809 	/*	RJR: March 28, 2000
    810 		create identity palette switching to a palettized mode */
    811 		DIB_CreatePalette(this, bpp);
    812 	}
    813 
    814 	style = GetWindowLong(SDL_Window, GWL_STYLE);
    815 	style &= ~(resizestyle|WS_MAXIMIZE);
    816 	if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    817 		style &= ~windowstyle;
    818 		style |= directstyle;
    819 	} else {
    820 #ifndef NO_CHANGEDISPLAYSETTINGS
    821 		if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    822 			ChangeDisplaySettings(NULL, 0);
    823 		}
    824 #endif
    825 		if ( flags & SDL_NOFRAME ) {
    826 			style &= ~windowstyle;
    827 			style |= directstyle;
    828 			video->flags |= SDL_NOFRAME;
    829 		} else {
    830 			style &= ~directstyle;
    831 			style |= windowstyle;
    832 			if ( flags & SDL_RESIZABLE ) {
    833 				style |= resizestyle;
    834 				video->flags |= SDL_RESIZABLE;
    835 			}
    836 		}
    837 #if WS_MAXIMIZE && !defined(_WIN32_WCE)
    838 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
    839 #endif
    840 	}
    841 
    842 	/* DJM: Don't piss of anyone who has setup his own window */
    843 	if ( !SDL_windowid )
    844 		SetWindowLong(SDL_Window, GWL_STYLE, style);
    845 
    846 	/* Delete the old bitmap if necessary */
    847 	if ( screen_bmp != NULL ) {
    848 		DeleteObject(screen_bmp);
    849 	}
    850 	if ( ! (flags & SDL_OPENGL) ) {
    851 		BOOL is16bitmode = (video->format->BytesPerPixel == 2);
    852 
    853 		/* Suss out the bitmap info header */
    854 		binfo_size = sizeof(*binfo);
    855 		if( is16bitmode ) {
    856 			/* 16bit modes, palette area used for rgb bitmasks */
    857 			binfo_size += 3*sizeof(DWORD);
    858 		} else if ( video->format->palette ) {
    859 			binfo_size += video->format->palette->ncolors *
    860 							sizeof(RGBQUAD);
    861 		}
    862 		binfo = (BITMAPINFO *)SDL_malloc(binfo_size);
    863 		if ( ! binfo ) {
    864 			if ( video != current ) {
    865 				SDL_FreeSurface(video);
    866 			}
    867 			SDL_OutOfMemory();
    868 			return(NULL);
    869 		}
    870 
    871 		binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    872 		binfo->bmiHeader.biWidth = video->w;
    873 		binfo->bmiHeader.biHeight = -video->h;	/* -ve for topdown bitmap */
    874 		binfo->bmiHeader.biPlanes = 1;
    875 		binfo->bmiHeader.biSizeImage = video->h * video->pitch;
    876 		binfo->bmiHeader.biXPelsPerMeter = 0;
    877 		binfo->bmiHeader.biYPelsPerMeter = 0;
    878 		binfo->bmiHeader.biClrUsed = 0;
    879 		binfo->bmiHeader.biClrImportant = 0;
    880 		binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
    881 
    882 		if ( is16bitmode ) {
    883 			/* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */
    884 			binfo->bmiHeader.biCompression = BI_BITFIELDS;
    885 			((Uint32*)binfo->bmiColors)[0] = video->format->Rmask;
    886 			((Uint32*)binfo->bmiColors)[1] = video->format->Gmask;
    887 			((Uint32*)binfo->bmiColors)[2] = video->format->Bmask;
    888 		} else {
    889 			binfo->bmiHeader.biCompression = BI_RGB;	/* BI_BITFIELDS for 565 vs 555 */
    890 			if ( video->format->palette ) {
    891 				SDL_memset(binfo->bmiColors, 0,
    892 					video->format->palette->ncolors*sizeof(RGBQUAD));
    893 			}
    894 		}
    895 
    896 		/* Create the offscreen bitmap buffer */
    897 		hdc = GetDC(SDL_Window);
    898 		screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
    899 					(void **)(&video->pixels), NULL, 0);
    900 		ReleaseDC(SDL_Window, hdc);
    901 		SDL_free(binfo);
    902 		if ( screen_bmp == NULL ) {
    903 			if ( video != current ) {
    904 				SDL_FreeSurface(video);
    905 			}
    906 			SDL_SetError("Couldn't create DIB section");
    907 			return(NULL);
    908 		}
    909 		this->UpdateRects = DIB_NormalUpdate;
    910 
    911 		/* Set video surface flags */
    912 		if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) {
    913 			grab_palette = TRUE;
    914 		}
    915 		if ( screen_pal ) {
    916 			/* BitBlt() maps colors for us */
    917 			video->flags |= SDL_HWPALETTE;
    918 		}
    919 	}
    920 	DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags);
    921 	SDL_resizing = 0;
    922 
    923 	/* Set up for OpenGL */
    924 	if ( flags & SDL_OPENGL ) {
    925 		if ( WIN_GL_SetupWindow(this) < 0 ) {
    926 			return(NULL);
    927 		}
    928 		video->flags |= SDL_OPENGL;
    929 	}
    930 
    931 	/* JC 14 Mar 2006
    932 		Flush the message loop or this can cause big problems later
    933 		Especially if the user decides to use dialog boxes or assert()!
    934 	*/
    935 	WIN_FlushMessageQueue();
    936 
    937 	/* We're live! */
    938 	return(video);
    939 }
    940 
    941 /* We don't actually allow hardware surfaces in the DIB driver */
    942 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
    943 {
    944 	return(-1);
    945 }
    946 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
    947 {
    948 	return;
    949 }
    950 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
    951 {
    952 	return(0);
    953 }
    954 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
    955 {
    956 	return;
    957 }
    958 
    959 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
    960 {
    961 	HDC hdc, mdc;
    962 	int i;
    963 
    964 	hdc = GetDC(SDL_Window);
    965 	if ( screen_pal ) {
    966 		SelectPalette(hdc, screen_pal, FALSE);
    967 	}
    968 	mdc = CreateCompatibleDC(hdc);
    969 	SelectObject(mdc, screen_bmp);
    970 	for ( i=0; i<numrects; ++i ) {
    971 		BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h,
    972 					mdc, rects[i].x, rects[i].y, SRCCOPY);
    973 	}
    974 	DeleteDC(mdc);
    975 	ReleaseDC(SDL_Window, hdc);
    976 }
    977 
    978 static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b)
    979 {
    980 	PALETTEENTRY *entry;
    981 	int i;
    982 	int nentries = pal->palNumEntries;
    983 
    984 	for ( i = 0; i < nentries; ++i ) {
    985 		entry = &pal->palPalEntry[i];
    986 		if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) {
    987 			return i;
    988 		}
    989 	}
    990 	return -1;
    991 }
    992 
    993 static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b)
    994 {
    995 	PALETTEENTRY *entry;
    996 	BOOL moved = 0;
    997 
    998 	entry = &pal->palPalEntry[index];
    999 	if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) {
   1000 		int found = FindPaletteIndex(pal, r, g, b);
   1001 		if ( found >= 0 ) {
   1002 			pal->palPalEntry[found] = *entry;
   1003 		}
   1004 		entry->peRed = r;
   1005 		entry->peGreen = g;
   1006 		entry->peBlue = b;
   1007 		moved = 1;
   1008 	}
   1009 	entry->peFlags = 0;
   1010 
   1011 	return moved;
   1012 }
   1013 
   1014 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   1015 {
   1016 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
   1017 	HDC hdc, mdc;
   1018 	RGBQUAD *pal;
   1019 #else
   1020 	HDC hdc;
   1021 #endif
   1022 	int i;
   1023 	int moved_entries = 0;
   1024 
   1025 	/* Update the display palette */
   1026 	hdc = GetDC(SDL_Window);
   1027 	if ( screen_pal ) {
   1028 		PALETTEENTRY *entry;
   1029 
   1030 		for ( i=0; i<ncolors; ++i ) {
   1031 			entry = &screen_logpal->palPalEntry[firstcolor+i];
   1032 			entry->peRed   = colors[i].r;
   1033 			entry->peGreen = colors[i].g;
   1034 			entry->peBlue  = colors[i].b;
   1035 			entry->peFlags = PC_NOCOLLAPSE;
   1036 		}
   1037 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
   1038 		/* Check to make sure black and white are in position */
   1039 		if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
   1040 			moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00);
   1041 			moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff);
   1042 		}
   1043 		/* FIXME:
   1044 		   If we don't have full access to the palette, what we
   1045 		   really want to do is find the 236 most diverse colors
   1046 		   in the desired palette, set those entries (10-245) and
   1047 		   then map everything into the new system palette.
   1048 		 */
   1049 #endif
   1050 
   1051 #ifndef _WIN32_WCE
   1052 		/* Copy the entries into the system palette */
   1053 		UnrealizeObject(screen_pal);
   1054 #endif
   1055 		SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry);
   1056 		SelectPalette(hdc, screen_pal, FALSE);
   1057 		RealizePalette(hdc);
   1058 	}
   1059 
   1060 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
   1061 	/* Copy palette colors into DIB palette */
   1062 	pal = SDL_stack_alloc(RGBQUAD, ncolors);
   1063 	for ( i=0; i<ncolors; ++i ) {
   1064 		pal[i].rgbRed = colors[i].r;
   1065 		pal[i].rgbGreen = colors[i].g;
   1066 		pal[i].rgbBlue = colors[i].b;
   1067 		pal[i].rgbReserved = 0;
   1068 	}
   1069 
   1070 	/* Set the DIB palette and update the display */
   1071 	mdc = CreateCompatibleDC(hdc);
   1072 	SelectObject(mdc, screen_bmp);
   1073 	SetDIBColorTable(mdc, firstcolor, ncolors, pal);
   1074 	if ( moved_entries || !grab_palette ) {
   1075 		BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
   1076 		       mdc, 0, 0, SRCCOPY);
   1077 	}
   1078 	DeleteDC(mdc);
   1079 	SDL_stack_free(pal);
   1080 #endif
   1081 	ReleaseDC(SDL_Window, hdc);
   1082 	return(1);
   1083 }
   1084 
   1085 
   1086 static void DIB_CheckGamma(_THIS)
   1087 {
   1088 #ifndef NO_GAMMA_SUPPORT
   1089 	HDC hdc;
   1090 	WORD ramp[3*256];
   1091 
   1092 	/* If we fail to get gamma, disable gamma control */
   1093 	hdc = GetDC(SDL_Window);
   1094 	if ( ! GetDeviceGammaRamp(hdc, ramp) ) {
   1095 		this->GetGammaRamp = NULL;
   1096 		this->SetGammaRamp = NULL;
   1097 	}
   1098 	ReleaseDC(SDL_Window, hdc);
   1099 #endif /* !NO_GAMMA_SUPPORT */
   1100 }
   1101 void DIB_SwapGamma(_THIS)
   1102 {
   1103 #ifndef NO_GAMMA_SUPPORT
   1104 	HDC hdc;
   1105 
   1106 	if ( gamma_saved ) {
   1107 		hdc = GetDC(SDL_Window);
   1108 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1109 			/* About to leave active state, restore gamma */
   1110 			SetDeviceGammaRamp(hdc, gamma_saved);
   1111 		} else {
   1112 			/* About to enter active state, set game gamma */
   1113 			GetDeviceGammaRamp(hdc, gamma_saved);
   1114 			SetDeviceGammaRamp(hdc, this->gamma);
   1115 		}
   1116 		ReleaseDC(SDL_Window, hdc);
   1117 	}
   1118 #endif /* !NO_GAMMA_SUPPORT */
   1119 }
   1120 void DIB_QuitGamma(_THIS)
   1121 {
   1122 #ifndef NO_GAMMA_SUPPORT
   1123 	if ( gamma_saved ) {
   1124 		/* Restore the original gamma if necessary */
   1125 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1126 			HDC hdc;
   1127 
   1128 			hdc = GetDC(SDL_Window);
   1129 			SetDeviceGammaRamp(hdc, gamma_saved);
   1130 			ReleaseDC(SDL_Window, hdc);
   1131 		}
   1132 
   1133 		/* Free the saved gamma memory */
   1134 		SDL_free(gamma_saved);
   1135 		gamma_saved = 0;
   1136 	}
   1137 #endif /* !NO_GAMMA_SUPPORT */
   1138 }
   1139 
   1140 int DIB_SetGammaRamp(_THIS, Uint16 *ramp)
   1141 {
   1142 #ifdef NO_GAMMA_SUPPORT
   1143 	SDL_SetError("SDL compiled without gamma ramp support");
   1144 	return -1;
   1145 #else
   1146 	HDC hdc;
   1147 	BOOL succeeded;
   1148 
   1149 	/* Set the ramp for the display */
   1150 	if ( ! gamma_saved ) {
   1151 		gamma_saved = (WORD *)SDL_malloc(3*256*sizeof(*gamma_saved));
   1152 		if ( ! gamma_saved ) {
   1153 			SDL_OutOfMemory();
   1154 			return -1;
   1155 		}
   1156 		hdc = GetDC(SDL_Window);
   1157 		GetDeviceGammaRamp(hdc, gamma_saved);
   1158 		ReleaseDC(SDL_Window, hdc);
   1159 	}
   1160 	if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1161 		hdc = GetDC(SDL_Window);
   1162 		succeeded = SetDeviceGammaRamp(hdc, ramp);
   1163 		ReleaseDC(SDL_Window, hdc);
   1164 	} else {
   1165 		succeeded = TRUE;
   1166 	}
   1167 	return succeeded ? 0 : -1;
   1168 #endif /* !NO_GAMMA_SUPPORT */
   1169 }
   1170 
   1171 int DIB_GetGammaRamp(_THIS, Uint16 *ramp)
   1172 {
   1173 #ifdef NO_GAMMA_SUPPORT
   1174 	SDL_SetError("SDL compiled without gamma ramp support");
   1175 	return -1;
   1176 #else
   1177 	HDC hdc;
   1178 	BOOL succeeded;
   1179 
   1180 	/* Get the ramp from the display */
   1181 	hdc = GetDC(SDL_Window);
   1182 	succeeded = GetDeviceGammaRamp(hdc, ramp);
   1183 	ReleaseDC(SDL_Window, hdc);
   1184 	return succeeded ? 0 : -1;
   1185 #endif /* !NO_GAMMA_SUPPORT */
   1186 }
   1187 
   1188 void DIB_VideoQuit(_THIS)
   1189 {
   1190 	int i, j;
   1191 
   1192 	/* Destroy the window and everything associated with it */
   1193 	if ( SDL_Window ) {
   1194 		/* Delete the screen bitmap (also frees screen->pixels) */
   1195 		if ( this->screen ) {
   1196 			if ( grab_palette ) {
   1197 				DIB_ReleaseStaticColors(SDL_Window);
   1198 			}
   1199 #ifndef NO_CHANGEDISPLAYSETTINGS
   1200 			if ( this->screen->flags & SDL_FULLSCREEN ) {
   1201 				ChangeDisplaySettings(NULL, 0);
   1202 				ShowWindow(SDL_Window, SW_HIDE);
   1203 			}
   1204 #endif
   1205 			if ( this->screen->flags & SDL_OPENGL ) {
   1206 				WIN_GL_ShutDown(this);
   1207 			}
   1208 			this->screen->pixels = NULL;
   1209 		}
   1210 		if ( screen_pal != NULL ) {
   1211 			DeleteObject(screen_pal);
   1212 			screen_pal = NULL;
   1213 		}
   1214 		if ( screen_logpal != NULL ) {
   1215 			SDL_free(screen_logpal);
   1216 			screen_logpal = NULL;
   1217 		}
   1218 		if ( screen_bmp ) {
   1219 			DeleteObject(screen_bmp);
   1220 			screen_bmp = NULL;
   1221 		}
   1222 		if ( screen_icn ) {
   1223 			DestroyIcon(screen_icn);
   1224 			screen_icn = NULL;
   1225 		}
   1226 		DIB_QuitGamma(this);
   1227 		DIB_DestroyWindow(this);
   1228 
   1229 		SDL_Window = NULL;
   1230 
   1231 #if defined(_WIN32_WCE)
   1232 
   1233 // Unload wince aygshell library to prevent leak
   1234 		if( aygshell )
   1235 		{
   1236 			FreeLibrary(aygshell);
   1237 			aygshell = NULL;
   1238 		}
   1239 #endif
   1240 	}
   1241 
   1242 	for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) {
   1243 		if ( !SDL_modelist[i] ) {
   1244 			continue;
   1245 		}
   1246 		for ( j=0; SDL_modelist[i][j]; ++j ) {
   1247 			SDL_free(SDL_modelist[i][j]);
   1248 		}
   1249 		SDL_free(SDL_modelist[i]);
   1250 		SDL_modelist[i] = NULL;
   1251 		SDL_nummodes[i] = 0;
   1252 	}
   1253 }
   1254 
   1255 /* Exported for the windows message loop only */
   1256 static void DIB_GrabStaticColors(HWND window)
   1257 {
   1258 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
   1259 	HDC hdc;
   1260 
   1261 	hdc = GetDC(window);
   1262 	SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256);
   1263 	if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
   1264 		SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
   1265 	}
   1266 	ReleaseDC(window, hdc);
   1267 #endif
   1268 }
   1269 static void DIB_ReleaseStaticColors(HWND window)
   1270 {
   1271 #if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE)
   1272 	HDC hdc;
   1273 
   1274 	hdc = GetDC(window);
   1275 	SetSystemPaletteUse(hdc, SYSPAL_STATIC);
   1276 	ReleaseDC(window, hdc);
   1277 #endif
   1278 }
   1279 static void DIB_Activate(_THIS, BOOL active, BOOL minimized)
   1280 {
   1281 	if ( grab_palette ) {
   1282 		if ( !active ) {
   1283 			DIB_ReleaseStaticColors(SDL_Window);
   1284 			DIB_RealizePalette(this);
   1285 		} else if ( !minimized ) {
   1286 			DIB_GrabStaticColors(SDL_Window);
   1287 			DIB_RealizePalette(this);
   1288 		}
   1289 	}
   1290 }
   1291 static void DIB_RealizePalette(_THIS)
   1292 {
   1293 	if ( screen_pal != NULL ) {
   1294 		HDC hdc;
   1295 
   1296 		hdc = GetDC(SDL_Window);
   1297 #ifndef _WIN32_WCE
   1298 		UnrealizeObject(screen_pal);
   1299 #endif
   1300 		SelectPalette(hdc, screen_pal, FALSE);
   1301 		if ( RealizePalette(hdc) ) {
   1302 			InvalidateRect(SDL_Window, NULL, FALSE);
   1303 		}
   1304 		ReleaseDC(SDL_Window, hdc);
   1305 	}
   1306 }
   1307 static void DIB_PaletteChanged(_THIS, HWND window)
   1308 {
   1309 	if ( window != SDL_Window ) {
   1310 		DIB_RealizePalette(this);
   1311 	}
   1312 }
   1313 
   1314 /* Exported for the windows message loop only */
   1315 static void DIB_WinPAINT(_THIS, HDC hdc)
   1316 {
   1317 	HDC mdc;
   1318 
   1319 	if ( screen_pal ) {
   1320 		SelectPalette(hdc, screen_pal, FALSE);
   1321 	}
   1322 	mdc = CreateCompatibleDC(hdc);
   1323 	SelectObject(mdc, screen_bmp);
   1324 	BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h,
   1325 							mdc, 0, 0, SRCCOPY);
   1326 	DeleteDC(mdc);
   1327 }
   1328 
   1329 static void DIB_GetWinPos(_THIS, int* px, int *py)
   1330 {
   1331 	RECT  rect;
   1332 	GetWindowRect(SDL_Window, &rect);
   1333 	*px = rect.left;
   1334 	*py = rect.top;
   1335 }
   1336 
   1337 static void DIB_SetWinPos(_THIS, int  x, int  y)
   1338 {
   1339     SetWindowPos(SDL_Window, HWND_TOPMOST,
   1340                  x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
   1341 }
   1342 
   1343 typedef struct {
   1344     int   result;
   1345     int   first;
   1346     RECT  wrect;
   1347     RECT  primary;
   1348 } VisibilityData;
   1349 
   1350 
   1351 BOOL CALLBACK visibility_cb(HMONITOR  hMonitor,
   1352                             HDC       hdcMonitor,
   1353                             LPRECT    mrect,
   1354                             LPARAM    dwData)
   1355 {
   1356     VisibilityData*  data = (VisibilityData*)dwData;
   1357 
   1358     if ( data->first ) {
   1359         data->first   = 0;
   1360         data->primary = mrect[0];
   1361     }
   1362 
   1363     if ( data->wrect.left   >= mrect->left   &&
   1364          data->wrect.right  <= mrect->right  &&
   1365          data->wrect.top    >= mrect->top    &&
   1366          data->wrect.bottom <= mrect->bottom )
   1367     {
   1368         data->result = 1;
   1369         return FALSE;
   1370     }
   1371     return TRUE;
   1372 }
   1373 
   1374 static int  DIB_IsWinVisible(_THIS, int  recenter)
   1375 {
   1376     VisibilityData  data;
   1377     data.result = 0;
   1378     data.first  = 1;
   1379 
   1380     GetWindowRect(SDL_Window, &data.wrect);
   1381 
   1382     EnumDisplayMonitors(NULL, NULL, visibility_cb, (LPARAM)&data);
   1383 
   1384     if ( !data.result && recenter ) {
   1385         int  new_x = 10;
   1386         int  new_y = 10;
   1387 
   1388         if ( !data.first ) {
   1389             int  primary_w = data.primary.right  - data.primary.left;
   1390             int  primary_h = data.primary.bottom - data.primary.top;
   1391 
   1392             new_x = data.primary.left + (primary_w - this->screen->w)/2;
   1393             new_y = data.primary.top  + (primary_h - this->screen->h)/2;
   1394         }
   1395         DIB_SetWinPos(this, new_x, new_y);
   1396     }
   1397     return  data.result;
   1398 }
   1399 
   1400 static int  DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi)
   1401 {
   1402     HDC  displayDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
   1403     int  xdpi, ydpi;
   1404 
   1405     if (displayDC == NULL) {
   1406         return -1;
   1407     }
   1408     xdpi = GetDeviceCaps( displayDC, LOGPIXELSX );
   1409     ydpi = GetDeviceCaps( displayDC, LOGPIXELSY );
   1410 
   1411     DeleteDC(displayDC);
   1412 
   1413     /* sanity checks */
   1414     if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) {
   1415         return -1;
   1416     }
   1417 
   1418     *xDpi = xdpi;
   1419     *yDpi = ydpi;
   1420     return 0;
   1421 }
   1422 
   1423 
   1424 typedef struct {
   1425     int   first;
   1426     RECT  wrect;
   1427 	long  bestArea;
   1428 	RECT  bestRect;
   1429 	RECT  primary;
   1430 } ProximityData;
   1431 
   1432 BOOL CALLBACK proximity_cb(HMONITOR  hMonitor,
   1433                            HDC       hdcMonitor,
   1434                            LPRECT    mrect,
   1435                            LPARAM    dwData)
   1436 {
   1437     ProximityData*  data = (ProximityData*)dwData;
   1438     int   x1, y1, x2, y2, area;
   1439 
   1440 	x1 = mrect->left;
   1441 	x2 = mrect->right;
   1442 	y1 = mrect->top;
   1443 	y2 = mrect->bottom;
   1444 
   1445 	if (data->first) {
   1446 		data->primary = mrect[0];
   1447 	}
   1448 
   1449 	if (x1 < data->wrect.left)
   1450 		x1 = data->wrect.left;
   1451     if (x2 > data->wrect.right)
   1452 		x2 = data->wrect.right;
   1453 	if (y1 < data->wrect.top)
   1454 		y1 = data->wrect.top;
   1455 	if (y2 > data->wrect.bottom)
   1456 		y2 = data->wrect.bottom;
   1457 
   1458 	if (x1 >= x2 || y1 >= y2)
   1459 		return TRUE;
   1460 
   1461 	area = (x2-x1)*(y2-y1);
   1462 	if (data->first || area > data->bestArea) {
   1463 		data->first    = 0;
   1464 		data->bestRect = mrect[0];
   1465 		data->bestArea = area;
   1466 	}
   1467     return TRUE;
   1468 }
   1469 
   1470 static int  DIB_GetMonitorRect(_THIS, SDL_Rect*  rect)
   1471 {
   1472     ProximityData  data;
   1473 	RECT*          sr;
   1474 
   1475     data.first  = 1;
   1476     GetWindowRect(SDL_Window, &data.wrect);
   1477 
   1478     EnumDisplayMonitors(NULL, NULL, proximity_cb, (LPARAM)&data);
   1479 
   1480 	if (data.first)
   1481 		return -1;
   1482 
   1483 	sr = &data.bestRect;
   1484 
   1485 	rect->x = sr->left;
   1486 	rect->y = sr->top;
   1487 	rect->w = sr->right - sr->left;
   1488 	rect->h = sr->bottom - sr->top;
   1489 
   1490 	return 0;
   1491 }
   1492 
   1493 /* Stub in case DirectX isn't available */
   1494 #if !SDL_AUDIO_DRIVER_DSOUND
   1495 void DX5_SoundFocus(HWND hwnd)
   1496 {
   1497 	return;
   1498 }
   1499 #endif
   1500