• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
DIB_Available(void)129 static int DIB_Available(void)
130 {
131 	return(1);
132 }
133 
DIB_DeleteDevice(SDL_VideoDevice * device)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 
DIB_CreateDevice(int devindex)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 
cmpmodes(const void * va,const void * vb)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 
DIB_AddMode(_THIS,int bpp,int w,int h)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 
DIB_CreatePalette(_THIS,int bpp)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 
DIB_VideoInit(_THIS,SDL_PixelFormat * vformat)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 */
DIB_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)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 */
DIB_SussScreenDepth()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 
DIB_ResizeWindow(_THIS,int width,int height,int prev_width,int prev_height,Uint32 flags)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