From d0a9890df6fbf548995966cb517ca50d7d89bbd7 Mon Sep 17 00:00:00 2001
From: johns <>
Date: Sun, 31 Mar 2002 13:25:26 +0000
Subject: [PATCH] Fixed locking and fullscreen switch for windows.

---
 src/stratagus/mainloop.cpp |  3 +-
 src/ui/menus.cpp           | 52 +++++++++++++++------
 src/video/sdl.cpp          | 94 ++++++++++++++++++++++++++++++++++++++
 src/video/video.cpp        | 24 ++++------
 4 files changed, 144 insertions(+), 29 deletions(-)

diff --git a/src/stratagus/mainloop.cpp b/src/stratagus/mainloop.cpp
index fcce313f6..c95642dae 100644
--- a/src/stratagus/mainloop.cpp
+++ b/src/stratagus/mainloop.cpp
@@ -230,7 +230,7 @@ global void UpdateDisplay(void)
 
     VideoLockScreen();			// prepare video write
 
-    HideAnyCursor();	// remove cursor (when available)
+    HideAnyCursor();			// remove cursor (when available)
 
 #ifdef NEW_DECODRAW
 // Experimental new drawing mechanism, which can keep track of what is
@@ -278,7 +278,6 @@ global void UpdateDisplay(void)
     }
 #endif
 
-
     if( MustRedraw&(RedrawMessage|RedrawMap) ) {
 	DrawMessage();
     }
diff --git a/src/ui/menus.cpp b/src/ui/menus.cpp
index 3d8d004a7..f253c7190 100644
--- a/src/ui/menus.cpp
+++ b/src/ui/menus.cpp
@@ -1194,6 +1194,7 @@ global void DrawMenu(int menu_id)
     if (menu_id == -1) {
 	return;
     }
+
     menu = Menus + menu_id;
     switch( menu->image ) {
 	case ImagePanel1:
@@ -1283,6 +1284,7 @@ global void DrawMenu(int menu_id)
     if (mip) {
 	DrawPulldown(mip,menu->x,menu->y);
     }
+
     InvalidateArea(menu->x,menu->y,menu->xsize,menu->ysize);
 }
 
@@ -1301,14 +1303,14 @@ local void StartMenusSetBackground(Menuitem *mi __attribute__((unused)))
 	VideoSetPalette(Menusbgnd->Pixels);
     }
 
-    VideoLockScreen();
+    // VideoLockScreen();
 
     // FIXME: bigger window ?
     VideoDrawSubClip(Menusbgnd,0,0,
 	Menusbgnd->Width,Menusbgnd->Height,
 	(VideoWidth-Menusbgnd->Width)/2,(VideoHeight-Menusbgnd->Height)/2);
 
-    VideoUnlockScreen();
+    // VideoUnlockScreen();
 }
 
 /**
@@ -1438,9 +1440,11 @@ local void SinglePlayerGameMenu(void)
 
 local void CampaignGameMenu(void)
 {
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
+
     GuiGameStarted = 0;
     ProcessMenu(MENU_CAMPAIN_SELECT, 1);
     if (GuiGameStarted) {
@@ -1450,9 +1454,11 @@ local void CampaignGameMenu(void)
 
 local void AllianceCampaignMenu(void)
 {
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
+
     // Any Campaign info should be displayed through a DrawFunc() Item
     // int the CAMPAIN_CONT menu processed below...
     ProcessMenu(MENU_CAMPAIN_CONT, 1);
@@ -1463,8 +1469,9 @@ local void AllianceCampaignMenu(void)
     PlayCampaign("human");
     GuiGameStarted = 1;
 
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
 
     // FIXME: johns othewise crash in UpdateDisplay -> DrawMinimapCursor
@@ -1473,9 +1480,11 @@ local void AllianceCampaignMenu(void)
 
 local void MysticalCampaignMenu(void)
 {
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
+
     // Any Campaign info should be displayed through a DrawFunc() Item
     // int the CAMPAIN_CONT menu processed below...
     ProcessMenu(MENU_CAMPAIN_CONT, 1);
@@ -1486,8 +1495,9 @@ local void MysticalCampaignMenu(void)
     PlayCampaign("orc");
     GuiGameStarted = 1;
 
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
 
     // FIXME: johns othewise crash in UpdateDisplay -> DrawMinimapCursor
@@ -1496,9 +1506,11 @@ local void MysticalCampaignMenu(void)
 
 local void Alliance2CampaignMenu(void)
 {
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
+
     // Any Campaign info should be displayed through a DrawFunc() Item
     // int the CAMPAIN_CONT menu processed below...
     ProcessMenu(MENU_CAMPAIN_CONT, 1);
@@ -1509,8 +1521,9 @@ local void Alliance2CampaignMenu(void)
     PlayCampaign("human-exp");
     GuiGameStarted = 1;
 
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
 
     // FIXME: johns othewise crash in UpdateDisplay -> DrawMinimapCursor
@@ -1519,9 +1532,11 @@ local void Alliance2CampaignMenu(void)
 
 local void Mystical2CampaignMenu(void)
 {
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
+
     // Any Campaign info should be displayed through a DrawFunc() Item
     // int the CAMPAIN_CONT menu processed below...
     ProcessMenu(MENU_CAMPAIN_CONT, 1);
@@ -1532,11 +1547,12 @@ local void Mystical2CampaignMenu(void)
     PlayCampaign("orc-exp");
     GuiGameStarted = 1;
 
-    DestroyCursorBackground();
+    VideoLockScreen();
     StartMenusSetBackground(NULL);
+    VideoUnlockScreen();
     Invalidate();
 
-    // FIXME: johns othewise crash in UpdateDisplay -> DrawMinimapCursor
+    // FIXME: johns otherwise crash in UpdateDisplay -> DrawMinimapCursor
     EndMenu();
 }
 
@@ -3102,13 +3118,17 @@ local void EndMenu(void)
 **
 **	@param menu_id	The menu number to process
 **	@param loop	Indicates to setup handlers and really 'Process'
+**
+**	@todo FIXME: This function is called from the event handler!!
 */
 global void ProcessMenu(int menu_id, int loop)
 {
     int i, oldncr;
     Menu *menu;
     Menuitem *mi;
-    int CurrentMenuSave = -1, MenuButtonUnderCursorSave = -1, MenuButtonCurSelSave = -1;
+    int CurrentMenuSave = -1;
+    int MenuButtonUnderCursorSave = -1;
+    int MenuButtonCurSelSave = -1;
 
     // Recursion protection:
     if (loop) {
@@ -3118,7 +3138,9 @@ global void ProcessMenu(int menu_id, int loop)
     }
 
     InterfaceState = IfaceStateMenu;
+    VideoLockScreen();
     HideAnyCursor();
+    VideoUnlockScreen();
     DestroyCursorBackground();
     MustRedraw |= RedrawCursor;
     CursorState = CursorStatePoint;
@@ -3173,7 +3195,11 @@ global void ProcessMenu(int menu_id, int loop)
 	MenuHandleMouseMove(CursorX,CursorY);	// This activates buttons as appropriate!
 	MustRedraw |= RedrawCursor;
     }
+
+
+    VideoLockScreen();
     DrawMenu(CurrentMenu);
+    VideoUnlockScreen();
 
     if (loop) {
 	while (CurrentMenu != -1) {
diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp
index 6b6d9d65f..1872d7762 100644
--- a/src/video/sdl.cpp
+++ b/src/video/sdl.cpp
@@ -811,6 +811,28 @@ global void RealizeVideoMemory(void)
 {
 }
 
+/**
+**	Lock the screen for write access.
+*/
+global void SdlLockScreen(void)
+{
+    SDL_LockSurface(Screen);
+    VideoMemory=Screen->pixels;
+}
+
+/**
+**	Unlock the screen for write access.
+*/
+global void SdlUnlockScreen(void)
+{
+    SDL_UnlockSurface(Screen);
+#ifdef DEBUG
+    VideoMemory=NULL;			// Catch errors!
+#else
+    VideoMemory=Screen->pixels;		// Be kind
+#endif
+}
+
 /**
 **	Toggle grab mouse.
 */
@@ -836,7 +858,79 @@ global void ToggleGrabMouse(void)
 */
 global void ToggleFullScreen(void)
 {
+#ifndef USE_WIN32
+    long framesize;
+    void *pixels;
+    SDL_Color *palette;
+    SDL_Rect clip;
+    int ncolors;
+    Uint32 flags;
+    int w;
+    int h;
+    int bpp;
+
+    if ( !Screen ) {			// don't bother if there's no surface.
+	return;
+    }
+
+    flags = Screen->flags;
+    w = Screen->w;
+    h = Screen->h;
+    bpp = Screen->format->BitsPerPixel;
+
+    SDL_GetClipRect(Screen, &clip);
+
+    // save the contents of the screen.
+    framesize = w * h * Screen->format->BytesPerPixel;
+    
+    if ( !(pixels = malloc(framesize)) ) {	// out of memory
+	return;
+    }
+    SDL_LockSurface(Screen);
+    memcpy(pixels, Screen->pixels, framesize);
+
+    IfDebug( palette=NULL; ncolors=0; );	// shut up compiler
+    if ( Screen->format->palette ) {
+	ncolors = Screen->format->palette->ncolors;
+	if ( !(palette = malloc(ncolors * sizeof(SDL_Color))) ) {
+	    free(pixels);
+	    return;
+	}
+	memcpy(palette, Screen->format->palette->colors,
+	    ncolors * sizeof(SDL_Color));
+    }
+    SDL_UnlockSurface(Screen);
+
+    Screen = SDL_SetVideoMode(w, h, bpp, flags ^ SDL_FULLSCREEN);
+    if( !Screen ) {
+	Screen = SDL_SetVideoMode(w, h, bpp, flags);
+	if ( !Screen ) {		// completely screwed.
+	    free(pixels);
+	    if( Screen->format->palette ) {
+		free(palette);
+	    }
+	    fprintf(stderr,"Toggle to fullscreen, crashed all\n");
+	    Exit(-1);
+	}
+    }
+
+    SDL_LockSurface(Screen);
+    memcpy(Screen->pixels, pixels, framesize);
+    free(pixels);
+
+    if ( Screen->format->palette ) {
+	// !!! FIXME : No idea if that flags param is right.
+	SDL_SetPalette(Screen, SDL_LOGPAL, palette, 0, ncolors);
+	free(palette);
+    }
+    SDL_UnlockSurface(Screen);
+
+    SDL_SetClipRect(Screen, &clip);
+
+    return;
+#else
     SDL_WM_ToggleFullScreen(Screen);
+#endif
 }
 
 #endif // } USE_SDL
diff --git a/src/video/video.cpp b/src/video/video.cpp
index eeb995094..286c8b342 100644
--- a/src/video/video.cpp
+++ b/src/video/video.cpp
@@ -168,10 +168,14 @@ typedef struct _clip_ {
 --	Externals
 ----------------------------------------------------------------------------*/
 
-extern void InitVideoSdl(void);
-extern void InitVideoX11(void);
-extern void InitVideoSVGA(void);
-extern void InitVideoWin32(void);
+extern void InitVideoSdl(void);		/// Init SDL video hardware driver
+extern void InitVideoX11(void);		/// Init X11 video hardware driver
+extern void InitVideoSVGA(void);	/// Init SVGA video hardware driver
+extern void InitVideoWin32(void);	/// Init Win32 video hardware driver
+extern void InitVideoWinCE(void);	/// Init WinCE video hardware driver
+
+extern void SdlLockScreen(void);	/// Do SDL hardware lock
+extern void SdlUnlockScreen(void);	/// Do SDL hardware unlock
 
 /*----------------------------------------------------------------------------
 --	Variables
@@ -1174,11 +1178,7 @@ global void VideoCreatePalette(const Palette* palette)
 global void VideoLockScreen(void)
 {
 #ifdef USE_SDL
-    // FIXME: move to system api part!
-    extern SDL_Surface *Screen;			/// internal screen
-
-    SDL_LockSurface(Screen);
-    VideoMemory=Screen->pixels;
+    SdlLockScreen();
 #endif
 }
 
@@ -1188,11 +1188,7 @@ global void VideoLockScreen(void)
 global void VideoUnlockScreen(void)
 {
 #ifdef USE_SDL
-    // FIXME: move to system api part!
-    extern SDL_Surface *Screen;			/// internal screen
-
-    SDL_UnlockSurface(Screen);
-    VideoMemory=Screen->pixels;
+    SdlUnlockScreen();
 #endif
 }