From 823e1e39388ef2c3b65e73ad538a3bd362d98954 Mon Sep 17 00:00:00 2001
From: stephanr <>
Date: Thu, 5 Jul 2001 23:48:28 +0000
Subject: [PATCH] Let sprite and rectangle cursor be handled independently from
 other sources

---
 Rules.make                 | 269 +++-------------
 src/include/cursor.h       |  21 +-
 src/include/video.h        |   2 +
 src/stratagus/mainloop.cpp |  73 ++---
 src/ui/menus.cpp           |  15 +-
 src/video/cursor.cpp       | 633 ++++++++++++++++++++-----------------
 src/video/graphic.cpp      |  52 +--
 src/video/intern_video.h   | 123 +++++++
 src/video/linedraw.cpp     |  43 +--
 src/video/video.cpp        |   3 +-
 10 files changed, 570 insertions(+), 664 deletions(-)
 create mode 100644 src/video/intern_video.h

diff --git a/Rules.make b/Rules.make
index 6110e261d..14f0e363c 100644
--- a/Rules.make
+++ b/Rules.make
@@ -1,6 +1,6 @@
 ##   ___________		     _________		      _____  __
 ##   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
-##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+##    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \   __\   __\ 
 ##    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
 ##    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
 ##	  \/		    \/	   \/	     \/		   \/
@@ -8,241 +8,70 @@
 ##			  T H E   W A R   B E G I N S
 ##	   FreeCraft - A free fantasy real time strategy game engine
 ##
-##	Rules.make	-	Make RULES (GNU MAKE) (included from Makefile).
-##
-##	(c) Copyright 1998-2001 by Lutz Sammer
-##
-##	FreeCraft is free software; you can redistribute it and/or modify
-##	it under the terms of the GNU General Public License as published
-##	by the Free Software Foundation; either version 2 of the License,
-##	or (at your option) any later version.
-##
-##	FreeCraft is distributed in the hope that it will be useful,
-##	but WITHOUT ANY WARRANTY; without even the implied warranty of
-##	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-##	GNU General Public License for more details.
-##
-##	$Id$
-##
 
-############################################################################
-#	Configurable:
-#			Choose what you want to include and the correct
-#			version.  Minimal is now the default.
-############################################################################
-
-#------------------------------------------------------------------------------
-# Uncomment next to add threaded sound support
-#	You should have a thread safe X11 (libc6 or glibc)
-#	Any modern linux distribution are thread safe.
-#	Don't enable, if you use SDL sound support.
-
-#THREAD		= -D_REENTRANT -DUSE_THREAD
-#THREADLIB	= -lpthread
-
-#------------------------------------------------------------------------------
-#	Video driver part
-#------------------------------------------------------------------------------
-
-#------------------------------------------------------------------------------
-# SDL - Simple DirectMedia Layer configuration (any >=1.0.0)
-
-SDL_CFLAGS	= $(shell sdl-config --cflags)
-SDLLIB		= $(shell sdl-config --static-libs)
-#SDLLIB		= $(shell sdl-config --libs)
-
-# Without SDL Sound (only not win32)
-#SDL		= -DUSE_SDL $(SDL_CFLAGS)
-# With SDL Sound
-SDL		= -DUSE_SDL -DUSE_SDLA $(SDL_CFLAGS)
-
-#------------------------------------------------------------------------------
-# Uncomment the next for the normal X11 support.
-
-VIDEO		= -DUSE_X11
-VIDEOLIB	= -lXext -lX11 -ldl
-
-#------------------------------------------------------------------------------
-# Uncomment th next to get svgalib support.
-
-#VIDEO		= -DUSE_SVGALIB
-#VIDEOLIB	= -lvga -lm -ldl
-
-#------------------------------------------------------------------------------
-# Uncomment one of the next for the SDL support.
-
-# Uncomment the next for the generic SDL support.
-
-#VIDEO		= $(SDL)
-#VIDEOLIB	= $(SDLLIB)
-
-# Uncomment the next for the SDL X11/SVGALIB support.
-#	(sdl-config --static-libs didn't work correct.)
-
-VIDEO		= $(SDL)
-VIDEOLIB	= $(SDLLIB) -lXext -lX11 -lXxf86dga -lXxf86vm -lvga -lvgagl -ldl -lesd -lm -lslang -lgpm
-
-# Uncomment the next for the win32/cygwin support. (not working?)
-
-#VIDEO		= -DUSE_WIN32 $(SDL)
-#VIDEOLIB	= $(SDLLIB)
-
-# Uncomment the next for the win32/mingw32 support.
-
-#VIDEO		= -DUSE_WIN32 $(SDL)
-#VIDEOLIB	= $(SDLLIB) -lwsock32 -Wl,--stack,33554432
-
-# Uncomment the next for the BeOS SDL support.
-
-#VIDEO		= -DUSE_BEOS $(SDL)
-#VIDEOLIB	= $(SDLLIB)
-
-#------------------------------------------------------------------------------
-#	Sound driver part
-#------------------------------------------------------------------------------
-
-# See above the USE_SDLA option.
-
-# Comment next if you want to remove sound support.
-
-DSOUND		= -DWITH_SOUND
-
-#------------------------------------------------------------------------------
-#	File I/O part
-#------------------------------------------------------------------------------
-
-# Choose which compress you like
-#	The win32 port didn't support BZ2LIB
-
-# None
-#ZDEFS		=
-#ZLIBS		=
-# GZ compression
-ZDEFS		= -DUSE_ZLIB
-ZLIBS		= -lz
-# BZ2 compression
-#ZDEFS		= -DUSE_BZ2LIB
-#ZLIBS		= -lbz2
-# GZ + BZ2 compression
-ZDEFS		= -DUSE_ZLIB -DUSE_BZ2LIB
-ZLIBS		= -lz -lbz2
-
-#------------------------------------------------------------------------------
-
-# May be required on some distributions for libpng and libz!
-# extra linker flags and include directory
-# -L/usr/lib
-
-XLDFLAGS	= -L/usr/X11R6/lib -L/usr/local/lib \
-		  -L$(TOPDIR)/libpng-1.0.5 -L$(TOPDIR)/zlib-1.1.3
-XIFLAGS		= -I/usr/X11R6/include -I/usr/local/include \
-		  -I$(TOPDIR)/libpng-1.0.5 -I$(TOPDIR)/zlib-1.1.3
-
-#------------------------------------------------------------------------------
-#	Support for SIOD (scheme interpreter)
-#	C C L	-	Craft Configuration Language
-
-CCL	= -DUSE_CCL
-CCLLIB	= -lm
-
-#------------------------------------------------------------------------------
-
-# Uncomment next to profile
-#PROFILE=	-pg
-
-# Compile Version
-VERSION=	'-DVERSION="1.17pre1-build14"'
-
-############################################################################
-# below this, nothing should be changed!
-
-# Libraries needed to build tools
-TOOLLIBS=$(XLDFLAGS) -lpng -lz -lm $(THREADLIB)
-
-# Libraries needed to build freecraft
-CLONELIBS=$(XLDFLAGS) -lpng -lz -lm \
-	$(THREADLIB) $(CCLLIB) $(VIDEOLIB) $(ZLIBS)
-
-DISTLIST=$(TOPDIR)/distlist
-TAGS=$(TOPDIR)/src/tags
-
-# LINUX
-OUTFILE=$(TOPDIR)/freecraft
-ARCH=linux
-OE=o
-EXE=
-
-# WIN32
-#OUTFILE=$(TOPDIR)/freecraft$(EXE)
-#ARCH=win32
-#OE=o
-#EXE=.exe
-
-## architecture-dependant objects
-#ARCHOBJS=stdmman.$(OE) svgalib.$(OE) unix_lib.$(OE) bitm_lnx.$(OE)
-
-## include flags
-IFLAGS=	-I$(TOPDIR)/src/include $(XIFLAGS)
-## define flags
-DEBUG=	-DDEBUG -DREFS_DEBUG # -DFLAG_DEBUG
-##
-## There are some still not well tested code parts or branches.
-## UNITS_ON_MAP:	Faster lookup of units
-## NEW_MAPDRAW:		Stephans new map draw code
-## NEW_AI:		New better improved AI code
-## This aren't working:
-## NEW_FOW:		New fog of war code, should work correct
-## NEW_SHIPS:		New correct ship movement.
-## NEW_NETMENUS:	Include new network menues.
-DFLAGS=	$(THREAD) $(CCL) $(VERSION) $(VIDEO) $(ZDEFS) $(DSOUND) $(DEBUG) \
-	-DHAVE_EXPANSION -DUNIT_ON_MAP -DNEW_AI -D_NEW_NETMENUS -DBPP8_IRGB # -DNEW_MAPDRAW=1 -DNEW_FOW -DNEW_SHIPS
-
-## choose optimise level
-#CFLAGS=-g -O0 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS)
-#CFLAGS=-g -O1 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS)
-CFLAGS=-g -O2 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS)
-#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS)
-#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -Wall $(IFLAGS)  $(DFLAGS)
-#CFLAGS=-g -O6 -pipe -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS)
-#-- Production
-#CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS)
-#CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS) -static
-
-# GCC 3.0
-#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -W -Wredundant-decls -Wno-sign-compare -Wall -Wno-comment $(IFLAGS) $(DFLAGS)
-#CC=gcc-3.0
-
-CC=cc
-#CC=gcc272
+# Compile commands
+CC=gcc
 RM=rm -f
 MAKE=make
 
-# TAGS 5.0
-CTAGSFLAGS=--c-types=defmpstuvx -a -f
-#CTAGSFLAGS=-i defmpstuvFS -a -f
-#CTAGSFLAGS=-i defptvS -a -f
+# Use SIOD support
+CCL		= -DUSE_CCL
+CCLLIB		= -lm
 
-#
-#	Locks versions with symbolic name
-#
+# Video support
+VIDEO		= -DUSE_X11
+VIDEOLIB	= -lXext -lX11 -ldl
+
+# Sound support
+DSOUND		= -DWITH_SOUND
+
+# Compression support
+ZDEFS		= -DUSE_ZLIB -DUSE_BZ2LIB
+ZLIBS		= -lz -lbz2
+
+XLDFLAGS	= -L/usr/X11R6/lib -L/usr/local/lib  
+XIFLAGS		= -I/usr/X11R6/include -I/usr/local/include  
+
+#####################################################################
+# Don't change anything below here unless you know what you're doing!
+
+VERSION=	'-DVERSION="1.17pre1-build14"'
+PROFILE=
+
+TOOLLIBS=$(XLDFLAGS) -lpng -lz -lm $(THREADLIB)
+CLONELIBS=$(XLDFLAGS) -lpng -lz -lm \
+	$(THREADLIB) $(CCLLIB) $(VIDEOLIB) $(ZLIBS)
+DISTLIST=$(TOPDIR)/distlist
+TAGS=$(TOPDIR)/src/tags
+
+# Linux
+EXE=
+OUTFILE=$(TOPDIR)/freecraft
+ARCH=linux
+OE=o
+
+#ARCHOBJS=stdmman.$(OE) svgalib.$(OE) unix_lib.$(OE) bitm_lnx.$(OE)
+IFLAGS=	-I$(TOPDIR)/src/include $(XIFLAGS)
+DFLAGS=	$(THREAD) $(CCL) $(VERSION) \
+	$(VIDEO) $(ZDEFS) $(DSOUND) \
+	$(DEBUG)
+CFLAGS=-O2 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math  $(IFLAGS) $(DFLAGS)  -DUNIT_ON_MAP -DNEW_AI
+CFLAGS=-g -pipe -fconserve-space $(IFLAGS) $(DFLAGS)  -DUNIT_ON_MAP -DNEW_AI
+CTAGSFLAGS=-i defptvS -a -f 
+
+# Locks versions with a symbolic name
 LOCKVER=	rcs -q -n$(NAME)
 
 %.o: %.c
 	$(CC) -c $(CFLAGS) $< -o $@
 	@ar cru $(TOPDIR)/src/libclone.a $@
 
-#------------
-#	Source code documentation
-#
+# Source code documentation
 DOXYGEN=	doxygen
 DOCIFY=		docify
 DOCPP=		doc++
-# Still didn't work
-#DOCIFY=		/root/doc++-3.4.2/src/docify
-#DOCPP=		/root/doc++-3.4.2/src/doc++
 
 %.doc: %.c
 	@$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-c.doc 2>/dev/null
-
 %.doc: %.h
 	@$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-h.doc 2>/dev/null
diff --git a/src/include/cursor.h b/src/include/cursor.h
index eacb49b9e..d05fbd978 100644
--- a/src/include/cursor.h
+++ b/src/include/cursor.h
@@ -168,11 +168,6 @@ extern int CursorY;			/// cursor position on screen Y
 extern int CursorStartX;		/// rectangle started on screen X
 extern int CursorStartY;		/// rectangle started on screen Y
 
-extern int OldCursorX;			/// saved cursor position on screen X
-extern int OldCursorY;			/// saved cursor position on screen Y
-extern int OldCursorW;			/// saved cursor width in pixel
-extern int OldCursorH;			/// saved cursor height in pixel
-
 /*----------------------------------------------------------------------------
 --	Functions
 ----------------------------------------------------------------------------*/
@@ -183,20 +178,14 @@ extern void LoadCursors(const char* racename);
     /// Cursor-type by identifier
 extern CursorType* CursorTypeByIdent(const char* ident);
 
-    /// Draw cursor on screen in position x,y
-extern void DrawCursor(const CursorType* type,int x,int y,int frame);
-
-    /// Destroy the cursor background (for menu use!)
-extern void DestroyCursorBackground(void);
-
-    /// Hide the cursor
-extern void HideCursor(void);
-
     /// Draw any cursor
 extern void DrawAnyCursor(void);
-
     /// Hide any cursor
-extern int HideAnyCursor(void);
+extern void HideAnyCursor(void);
+    /// Invalidate given area and check if cursor won't need any
+extern void InvalidateAreaAndCheckCursor( int x, int y, int w, int h );
+    /// Invalidate (remaining) cursor areas 
+extern void InvalidateCursorAreas(void);
 
     /// Initialize the cursor module
 extern void InitCursors(void);
diff --git a/src/include/video.h b/src/include/video.h
index 58d01e26d..016266b8d 100644
--- a/src/include/video.h
+++ b/src/include/video.h
@@ -985,6 +985,7 @@ extern void VideoDrawTransRectangleClip(SysColors color,int x,int y
     /// Does ColorCycling..
 extern void (*ColorCycle)(void);
 
+
 /*----------------------------------------------------------------------------
 --	Macros
 ----------------------------------------------------------------------------*/
@@ -1054,6 +1055,7 @@ extern void (*ColorCycle)(void);
 #define VideoSaveFree(o) \
 	do { if( (o) ) ((o)->Type->Free)((o)); } while( 0 )
 
+
 /*----------------------------------------------------------------------------
 --	Functions
 ----------------------------------------------------------------------------*/
diff --git a/src/stratagus/mainloop.cpp b/src/stratagus/mainloop.cpp
index eff6bb337..25884c4cf 100644
--- a/src/stratagus/mainloop.cpp
+++ b/src/stratagus/mainloop.cpp
@@ -203,14 +203,13 @@ global void DebugTestDisplay(void)
 */
 global void UpdateDisplay(void)
 {
-    int update_old_cursor;
+    if (!MustRedraw) {
+      return;
+    }
 
     VideoLockScreen();			// prepare video write
-    if (MustRedraw) {
-	update_old_cursor=HideAnyCursor();	// remove cursor
-    } else {
-	update_old_cursor = 0;
-    }
+
+    HideAnyCursor();	// remove cursor (when available)
 
     if( MustRedraw&RedrawMap ) {
 	if (InterfaceState == IfaceStateNormal) {
@@ -311,84 +310,72 @@ global void UpdateDisplay(void)
 	DrawMenu(CurrentMenu);
     }
 
-    // FIXME: this could be written better, less drawing
-    if( update_old_cursor && MustRedraw!=-1  ) {
-	// Draw restored area only if not same.
-	if( OldCursorX!=(CursorX-GameCursor->HotX)
-		|| OldCursorY!=(CursorY-GameCursor->HotY)
-		|| OldCursorW!=VideoGraphicWidth(GameCursor->Sprite)
-		|| OldCursorH!=VideoGraphicHeight(GameCursor->Sprite) ) {
-	    InvalidateArea(OldCursorX,OldCursorY,OldCursorW,OldCursorH);
-	}
-    }
-
-    if (!MustRedraw) {
-	VideoUnlockScreen();		// End write access
-	return;
-    }
-
     DrawAnyCursor();
+
     VideoUnlockScreen();		// End write access
 
     //
     //	Update changes to X11.
     //
     if( MustRedraw==-1 ) {
-	Invalidate();
+	// refresh entire screen, so no further invalidate needed
+	InvalidateAreaAndCheckCursor(0,0,VideoWidth,VideoHeight);
     } else {
 	if( MustRedraw&RedrawMap ) {
 	    // FIXME: split into small parts see RedrawTile and RedrawRow
-	    InvalidateArea(TheUI.MapX,TheUI.MapY
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.MapX,TheUI.MapY
 		    ,TheUI.MapEndX-TheUI.MapX+1,TheUI.MapEndY-TheUI.MapY+1);
 	}
 	if( (MustRedraw&RedrawFiller1) && TheUI.Filler1.Graphic ) {
-	    InvalidateArea(TheUI.Filler1X,TheUI.Filler1Y
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.Filler1X,TheUI.Filler1Y
 		    ,TheUI.Filler1.Graphic->Width
 		    ,TheUI.Filler1.Graphic->Height);
 	}
-	if( MustRedraw&RedrawMenuButton ) {
-	    InvalidateArea(TheUI.MenuButtonX,TheUI.MenuButtonY
+	if(MustRedraw&RedrawMenuButton ) {
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.MenuButtonX,TheUI.MenuButtonY
 		    ,TheUI.MenuButton.Graphic->Width
 		    ,TheUI.MenuButton.Graphic->Height);
 	}
 	if( MustRedraw&RedrawMinimapBorder ) {
-	    InvalidateArea(TheUI.MinimapX,TheUI.MinimapY
+	    InvalidateAreaAndCheckCursor(
+		 TheUI.MinimapX,TheUI.MinimapY
 		,TheUI.Minimap.Graphic->Width,TheUI.Minimap.Graphic->Height);
 	} else if( (MustRedraw&RedrawMinimap)
 		|| (MustRedraw&RedrawMinimapCursor) ) {
 	    // FIXME: Redraws too much of the minimap
-	    InvalidateArea(TheUI.MinimapX+24,TheUI.MinimapY+2
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.MinimapX+24,TheUI.MinimapY+2
 		    ,MINIMAP_W,MINIMAP_H);
 	}
 	if( MustRedraw&RedrawInfoPanel ) {
-	    InvalidateArea(TheUI.InfoPanelX,TheUI.InfoPanelY
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.InfoPanelX,TheUI.InfoPanelY
 		    ,TheUI.InfoPanelW,TheUI.InfoPanelH);
 	}
 	if( MustRedraw&RedrawButtonPanel ) {
-	    InvalidateArea(TheUI.ButtonPanelX,TheUI.ButtonPanelY
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.ButtonPanelX,TheUI.ButtonPanelY
 		    ,TheUI.ButtonPanel.Graphic->Width
 		    ,TheUI.ButtonPanel.Graphic->Height);
 	}
 	if( MustRedraw&RedrawResources ) {
-	    InvalidateArea(TheUI.ResourceX,TheUI.ResourceY
+	    InvalidateAreaAndCheckCursor(
+		     TheUI.ResourceX,TheUI.ResourceY
 		    ,TheUI.Resource.Graphic->Width
 		    ,TheUI.Resource.Graphic->Height);
 	}
 	if( MustRedraw&RedrawStatusLine || MustRedraw&RedrawCosts ) {
-	    InvalidateArea(TheUI.StatusLineX,TheUI.StatusLineY
+	    InvalidateAreaAndCheckCursor(
+                     TheUI.StatusLineX,TheUI.StatusLineY
 		    ,TheUI.StatusLine.Graphic->Width
 		    ,TheUI.StatusLine.Graphic->Height);
 	}
-	/* if (MustRedraw) */ {
-	// FIXME: JOHNS: That didn't work: if (MustRedraw&RedrawCursor)
-	    DebugLevel3Fn("%d,%d,%d,%d\n",CursorX-GameCursor->HotX
-		,CursorY-GameCursor->HotY
-		,VideoGraphicWidth(GameCursor->Sprite)
-		,VideoGraphicHeight(GameCursor->Sprite));
-	    InvalidateArea(CursorX-GameCursor->HotX,CursorY-GameCursor->HotY
-		,VideoGraphicWidth(GameCursor->Sprite)
-		,VideoGraphicHeight(GameCursor->Sprite));
-	}
+
+        // And now as very last.. checking if the cursor needs a refresh
+        InvalidateCursorAreas();
     }
 }
 
diff --git a/src/ui/menus.cpp b/src/ui/menus.cpp
index 7cc0eaba3..33de1aa8b 100644
--- a/src/ui/menus.cpp
+++ b/src/ui/menus.cpp
@@ -1160,8 +1160,9 @@ global void DrawMenu(int MenuId)
 */
 local void StartMenusSetBackground(Menuitem *mi __attribute__((unused)))
 {
-    HideCursor();
-    DestroyCursorBackground();
+    //Doesn't seem to be needed
+    //HideAnyCursor();
+
     // FIXME: make this configurable from CCL.
     DisplayPicture("graphics/ui/Menu background without title.png");
 }
@@ -1256,7 +1257,6 @@ local void MultiScenSelectMenu(void)
 
 local void SinglePlayerGameMenu(void)
 {
-    DestroyCursorBackground();
     GuiGameStarted = 0;
     ProcessMenu(MENU_CUSTOM_GAME_SETUP, 1);
     if (GuiGameStarted) {
@@ -1312,7 +1312,6 @@ local void JoinNetGameMenu(void)
     EnterServerIPMenuItems[1].d.input.maxch = 24;
     EnterServerIPMenuItems[2].flags |= MenuButtonDisabled;
     ProcessMenu(MENU_NET_ENTER_SERVER_IP, 1);
-    DestroyCursorBackground();
     StartMenusSetBackground(NULL);
     if (EnterServerIPMenuItems[1].d.input.nch == 0) {
 	return;
@@ -1330,7 +1329,6 @@ local void JoinNetGameMenu(void)
 
 local void NetConnectingCancel(void)
 {
-    DestroyCursorBackground();
     StartMenusSetBackground(NULL);
     NetworkExitClientConnect();
     NetLocalState = ccs_unreachable;	// Trigger TerminateNetConnect() to call us again and end the menu
@@ -1345,7 +1343,6 @@ local void TerminateNetConnect(void)
     }
     DebugLevel1Fn("NetLocalState %d\n", NetLocalState);
     NetConnectRunning = 2;
-    DestroyCursorBackground();
     GuiGameStarted = 0;
     ProcessMenu(MENU_NET_MULTI_CLIENT, 1);
     if (GuiGameStarted) {
@@ -1357,7 +1354,6 @@ local void TerminateNetConnect(void)
 
 local void CreateNetGameMenu(void)
 {
-    DestroyCursorBackground();
     GuiGameStarted = 0;
     ProcessMenu(MENU_NET_MULTI_SETUP, 1);
     if (GuiGameStarted) {
@@ -1377,7 +1373,6 @@ local void MultiPlayerGameMenu(void)
     EnterNameMenuItems[1].d.input.maxch = 15;
     EnterNameMenuItems[2].flags &= ~MenuButtonDisabled;
     ProcessMenu(MENU_ENTER_NAME, 1);
-    DestroyCursorBackground();
     StartMenusSetBackground(NULL);
     if (EnterNameMenuItems[1].d.input.nch == 0) {
 	return;
@@ -1735,7 +1730,6 @@ local void ScenSelectCancel(void)
 
 local void GameCancel(void)
 {
-    DestroyCursorBackground();
     StartMenusSetBackground(NULL);
     FreeMapInfo(ScenSelectPudInfo);
     ScenSelectPudInfo = NULL;
@@ -2750,8 +2744,7 @@ global void ProcessMenu(int MenuId, int Loop)
     }
 
     InterfaceState = IfaceStateMenu;
-    HideCursor();
-    DestroyCursorBackground();
+    HideAnyCursor();
     MustRedraw |= RedrawCursor;
     CursorState = CursorStatePoint;
     GameCursor = TheUI.Point.Cursor;
diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp
index 1ef266b0c..42ad282bb 100644
--- a/src/video/cursor.cpp
+++ b/src/video/cursor.cpp
@@ -45,10 +45,17 @@
 #include "interface.h"
 #include "ui.h"
 
+#include "intern_video.h"
+
 /*----------------------------------------------------------------------------
 --	Variables
 ----------------------------------------------------------------------------*/
 
+/**
+**	Number of bytes needed for current video-mode
+*/
+local int memsize;
+
 /**
 **	Cursor-type type definition
 */
@@ -64,31 +71,82 @@ global CursorType* Cursors;
 global CursorStates CursorState;/// current cursor state (point,...)
 global int CursorAction;	/// action for selection
 global int CursorValue;		/// value for CursorAction (spell type f.e.)
-global UnitType* CursorBuilding;/// building cursor
 
-global CursorType* GameCursor;	/// current shown cursor-type
+	//Event changed mouse position, can alter at any moment
 global int CursorX;		/// cursor position on screen X
 global int CursorY;		/// cursor position on screen Y
+
 global int CursorStartX;	/// rectangle started on screen X
 global int CursorStartY;	/// rectangle started on screen Y
 
-global int OldCursorX;		/// saved cursor position on screen X
-global int OldCursorY;		/// saved cursor position on screen Y
-global int OldCursorW;		/// saved cursor width in pixel
-global int OldCursorH;		/// saved cursor height in pixel
-local int OldCursorSize;	/// size of saved cursor image
-local void* OldCursorImage;	/// background saved behind cursor
 
-local int OldCursorRectangleX;	/// saved cursor position on screen X
-local int OldCursorRectangleY;	/// saved cursor position on screen Y
-local int OldCursorRectangleW;	/// saved cursor width in pixel
-local int OldCursorRectangleH;	/// saved cursor height in pixel
-local void* OldCursorRectangle;	/// background saved behind rectangle
+/*--- DRAW BUILDING  CURSOR ------------------------------------------------*/
+local int BuildingCursor=0;		/// Flag (0/1): last cursor was building
+
+// area of tiles covered by building cursor (SX,SY;EX,EY)
+local int BuildingCursorSX;		/// FIXME: docu
+local int BuildingCursorSY;		/// FIXME: docu
+local int BuildingCursorEX;		/// FIXME: docu
+local int BuildingCursorEY;		/// FIXME: docu
+
+global UnitType* CursorBuilding;/// building cursor
+
+
+/*--- DRAW SPRITE CURSOR ---------------------------------------------------*/
+	// Saved area after draw cursor, needed later to hide it again
+	// (OldCursorW!=0 denotes it's defined)
+local int OldCursorInvalidate=0;/// flag (0/1): if cursor need invalidate
+local int OldCursorX;		/// saved cursor position on screen X
+local int OldCursorY;		/// saved cursor position on screen Y
+local int OldCursorW=0;		/// saved cursor width in pixel
+local int OldCursorH;		/// saved cursor height in pixel
+global CursorType* GameCursor;	/// current shown cursor-type
+
+	// Area which is already hidden, but needed for invalidate
+	// (HiddenCursorW!=0 denotes it's defined)
+local int HiddenCursorX;	/// saved cursor position on screen X
+local int HiddenCursorY;	/// saved cursor position on screen Y
+local int HiddenCursorW=0;	/// saved cursor width in pixel
+local int HiddenCursorH;	/// saved cursor height in pixel
+
+        /// Memory re-use, so can be defined although no save present!
+local unsigned int OldCursorSize;	/// size of saved cursor image
+local void* OldCursorImage;		/// background saved behind cursor
 
 	/// Function pointer: Save background behind cursor
-local void (*SaveCursorBackground)(int,int,int,int);
+/**
+**	Function pointer: Save 2D image behind sprite cursor
+**
+**	@param x	Screen X pixels coordinate for left-top corner.
+**	@param y	Screen Y pixels coordinate for left-top corner.
+**	@param w	Width in pixels for image starting at left-top.
+**	@param h	Height in pixels for image starting at left-top.
+**
+**	@note the complete image should be in Screen (no clipping) and
+**	non-empty
+**     ( x>=0,y>=0,w>0,h>0,(x+w-1)<=VideoWidth,(y+h-1)<=VideoHeight )
+*/
+local void (*SaveCursorBackground)(int x,int y,int w,int h);
 	/// Function pointer: Load background behind cursor
-local void (*LoadCursorBackground)(int,int,int,int);
+local void (*LoadCursorBackground)(int x,int y,int w,int h);
+
+
+/*--- DRAW RECTANGLE CURSOR ------------------------------------------------*/
+	// Saved area after draw rectangle, needed later to hide it again
+	// (OldCursorRectangleW!=0 denotes it's defined)
+local int OldCursorRectangleInvalidate=0;/// flag (0/1): ..need invalidate
+local int OldCursorRectangleX;		/// saved cursor position on screen X
+local int OldCursorRectangleY;		/// saved cursor position on screen Y
+local int OldCursorRectangleW=0;	/// saved cursor width in pixel
+local int OldCursorRectangleH;		/// saved cursor height in pixel
+local void* OldCursorRectangle;		/// background saved behind rectangle
+
+	// Area which is already hidden, but needed for invalidate
+	// (HiddenCursorRectangleW!=0 denotes it's defined)
+local int HiddenCursorRectangleX;	/// saved cursor position on screen X
+local int HiddenCursorRectangleY;	/// saved cursor position on screen Y
+local int HiddenCursorRectangleW=0;	/// saved cursor width in pixel
+local int HiddenCursorRectangleH;	/// saved cursor height in pixel
 
 /**
 **	Function pointer: Save rectangle behind cursor
@@ -119,7 +177,6 @@ local void (*LoadCursorRectangle)(int x,int y,int w,int h);
 /*----------------------------------------------------------------------------
 --	Functions
 ----------------------------------------------------------------------------*/
-
 /**
 **	Load all cursor sprites.
 **
@@ -188,11 +245,11 @@ global CursorType* CursorTypeByIdent(const char* ident)
 }
 
 /*----------------------------------------------------------------------------
---	Internal Functions
+--	DRAW RECTANGLE CURSOR
 ----------------------------------------------------------------------------*/
-
 /**
-**	FIXME: docu missing, better use an inline function.
+**	Puts stored 'image' from SAVECURSORRECTANGLE back on the screen.
+**      Note w and h are both > 0
 **
 **	FIXME: this kind of macros are hard to single step with gdb.
 **	FIXME: inline functions should have the same speed and are debugable.
@@ -216,7 +273,9 @@ global CursorType* CursorTypeByIdent(const char* ident)
 }
 
 /**
-**	FIXME: docu missing, better use an inline function.
+**	Saves 'image' of screen overlapped by rectangle cursor, to be able to
+**      restore it later using LOADCURSORRECTANGLE.
+**      Note w and h > 0
 **
 **	FIXME: this kind of macros are hard to single step with gdb.
 **	FIXME: inline functions should have the same speed and are debugable.
@@ -244,9 +303,7 @@ global CursorType* CursorTypeByIdent(const char* ident)
 */
 local void LoadCursorRectangle8(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	LOADCURSORRECTANGLE(VideoMemory8,VMemType8,x,y,w,h);
-    }
 }
 
 /** Restore cursor rectangle for 16bpp frame buffer.
@@ -255,9 +312,7 @@ local void LoadCursorRectangle8(int x,int y,int w,int h)
 */
 local void LoadCursorRectangle16(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	LOADCURSORRECTANGLE(VideoMemory16,VMemType16,x,y,w,h);
-    }
 }
 
 /** Restore cursor rectangle for 24bpp frame buffer.
@@ -266,9 +321,7 @@ local void LoadCursorRectangle16(int x,int y,int w,int h)
 */
 local void LoadCursorRectangle24(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	LOADCURSORRECTANGLE(VideoMemory24,VMemType24,x,y,w,h);
-    }
 }
 
 /** Restore cursor rectangle for 32bpp frame buffer.
@@ -277,9 +330,7 @@ local void LoadCursorRectangle24(int x,int y,int w,int h)
 */
 local void LoadCursorRectangle32(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	LOADCURSORRECTANGLE(VideoMemory32,VMemType32,x,y,w,h);
-    }
 }
 
 /** Save cursor rectangle for 8bpp frame buffer.
@@ -288,9 +339,7 @@ local void LoadCursorRectangle32(int x,int y,int w,int h)
 */
 local void SaveCursorRectangle8(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	SAVECURSORRECTANGLE(VideoMemory8,VMemType8,x,y,w,h);
-    }
 }
 
 /** Save cursor rectangle for 16bpp frame buffer.
@@ -299,9 +348,7 @@ local void SaveCursorRectangle8(int x,int y,int w,int h)
 */
 local void SaveCursorRectangle16(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	SAVECURSORRECTANGLE(VideoMemory16,VMemType16,x,y,w,h);
-    }
 }
 
 /** Save cursor rectangle for 24bpp frame buffer.
@@ -310,9 +357,7 @@ local void SaveCursorRectangle16(int x,int y,int w,int h)
 */
 local void SaveCursorRectangle24(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	SAVECURSORRECTANGLE(VideoMemory24,VMemType24,x,y,w,h);
-    }
 }
 
 /** Save cursor rectangle for 32bpp frame buffer.
@@ -321,11 +366,60 @@ local void SaveCursorRectangle24(int x,int y,int w,int h)
 */
 local void SaveCursorRectangle32(int x,int y,int w,int h)
 {
-    if( w && h ) {
 	SAVECURSORRECTANGLE(VideoMemory32,VMemType32,x,y,w,h);
+}
+
+/**
+**	Draw rectangle cursor when visible, defined by
+**      OldCursorRectangleW (!=0),.. 
+**      Pre: for this to work OldCursorRectangleW should be 0 upfront
+*/
+local void DrawVisibleRectangleCursor(int x,int y,int x1,int y1)
+{
+    int w;
+    int h;
+
+    //
+    //	Clip to map window.
+    // FIXME: should re-use CLIP_RECTANGLE in some way from linedraw.c ?
+    //
+    if( x1<TheUI.MapX ) {
+	x1=TheUI.MapX;
+    } else if( x1>TheUI.MapEndX ) {
+	x1=TheUI.MapEndX;
+    }
+    if( y1<TheUI.MapY ) {
+	y1=TheUI.MapY;
+    } else if( y1>TheUI.MapEndY ) {
+	y1=TheUI.MapEndY;
+    }
+
+    if( x>x1 ) {
+	x=x1;
+	w=CursorStartX-x+1;
+    } else {
+	w=x1-x+1;
+    }
+    if( y>y1 ) {
+	y=y1;
+	h=CursorStartY-y+1;
+    } else {
+	h=y1-y+1;
+    }
+
+    if ( w && h )
+    {
+      SaveCursorRectangle(OldCursorRectangleX=x,OldCursorRectangleY=y,
+  			  OldCursorRectangleW=w,OldCursorRectangleH=h);
+      VideoDrawRectangleClip(ColorGreen,x,y,w,h);
+      OldCursorRectangleInvalidate=1;
     }
 }
 
+
+/*----------------------------------------------------------------------------
+--	DRAW SPRITE CURSOR
+----------------------------------------------------------------------------*/
 /**
 **	Restore cursor background for 8bpp frame buffer.
 **
@@ -424,19 +518,9 @@ local void LoadCursorBackground32(int x,int y,int w,int h)
 */
 local void SaveCursorBackground8(int x,int y,int w,int h)
 {
-    int i;
     VMemType8* dp;
     VMemType8* sp;
 
-    i=w*h*sizeof(VMemType8);
-    if( OldCursorSize<i ) {
-	if( OldCursorImage ) {
-	    OldCursorImage=realloc(OldCursorImage,i);
-	} else {
-	    OldCursorImage=malloc(i);
-	}
-	OldCursorSize=i;
-    }
     dp=OldCursorImage;
     sp=VideoMemory8+y*VideoWidth+x;
     while( h-- ) {
@@ -456,19 +540,9 @@ local void SaveCursorBackground8(int x,int y,int w,int h)
 */
 local void SaveCursorBackground16(int x,int y,int w,int h)
 {
-    int i;
     VMemType16* dp;
     const VMemType16* sp;
 
-    i=w*h*sizeof(VMemType16);
-    if( OldCursorSize<i ) {
-	if( OldCursorImage ) {
-	    OldCursorImage=realloc(OldCursorImage,i);
-	} else {
-	    OldCursorImage=malloc(i);
-	}
-	OldCursorSize=i;
-    }
     dp=OldCursorImage;
     sp=VideoMemory16+y*VideoWidth+x;
     while( h-- ) {
@@ -488,19 +562,9 @@ local void SaveCursorBackground16(int x,int y,int w,int h)
 */
 local void SaveCursorBackground24(int x,int y,int w,int h)
 {
-    int i;
     VMemType24* dp;
     const VMemType24* sp;
 
-    i=w*h*sizeof(VMemType24);
-    if( OldCursorSize<i ) {
-	if( OldCursorImage ) {
-	    OldCursorImage=realloc(OldCursorImage,i);
-	} else {
-	    OldCursorImage=malloc(i);
-	}
-	OldCursorSize=i;
-    }
     dp=OldCursorImage;
     sp=VideoMemory24+y*VideoWidth+x;
     while( h-- ) {
@@ -520,19 +584,9 @@ local void SaveCursorBackground24(int x,int y,int w,int h)
 */
 local void SaveCursorBackground32(int x,int y,int w,int h)
 {
-    int i;
     VMemType32* dp;
     const VMemType32* sp;
 
-    i=w*h*sizeof(VMemType32);
-    if( OldCursorSize<i ) {
-	if( OldCursorImage ) {
-	    OldCursorImage=realloc(OldCursorImage,i);
-	} else {
-	    OldCursorImage=malloc(i);
-	}
-	OldCursorSize=i;
-    }
     dp=OldCursorImage;
     sp=VideoMemory32+y*VideoWidth+x;
     while( h-- ) {
@@ -542,49 +596,10 @@ local void SaveCursorBackground32(int x,int y,int w,int h)
     }
 }
 
-/**
-**	Save image behind cursor.
-*/
-local void SaveCursor(void)
-{
-    int w;
-    int h;
-    int x;
-    int y;
-
-    x=OldCursorX;
-    w=OldCursorW;
-    if( x<0 ) {
-	w-=x;
-	x=0;
-    }
-    if( w>VideoWidth-x) {	// normalize width
-	w=VideoWidth-x;
-    }
-    if( !w ) {
-	return;
-    }
-
-    y=OldCursorY;
-    h=OldCursorH;
-    if( y<0 ) {
-	w-=y;
-	y=0;
-    }
-    if( h>VideoHeight-y ) {	// normalize height
-	h=VideoHeight-y;
-    }
-    if( !h ) {
-	return;
-    }
-
-    SaveCursorBackground(x,y,w,h);
-}
-
 /**
 **	Destroy image behind cursor.
 */
-global void DestroyCursorBackground(void)
+local void DestroyCursorBackground(void)
 {
     if (OldCursorImage) {
 	free(OldCursorImage);
@@ -594,94 +609,51 @@ global void DestroyCursorBackground(void)
 }
 
 /**
-**	Restore image behind cursor.
-*/
-local void RestoreCursor(void)
-{
-    int w;
-    int h;
-    int x;
-    int y;
-
-    if( !OldCursorImage ) {		// no cursor saved
-	return;
-    }
-
-    // FIXME: I should better store the correct values on save.
-    x=OldCursorX;
-    w=OldCursorW;
-    if( x<0 ) {
-	w-=x;
-	x=0;
-    }
-    if( w>VideoWidth-x) {	// normalize width
-	w=VideoWidth-x;
-    }
-    if( !w ) {
-	return;
-    }
-
-    y=OldCursorY;
-    h=OldCursorH;
-    if( y<0 ) {
-	w-=y;
-	y=0;
-    }
-    if( h>VideoHeight-y ) {	// normalize height
-	h=VideoHeight-y;
-    }
-    if( !h ) {
-	return;
-    }
-
-    LoadCursorBackground(x,y,w,h);
-}
-
-/**
-**	Draw cursor.
+**	Draw (sprite) cursor when visible, defined by
+**      OldCursorW (!=0),.. 
+**      Pre: for this to work OldCursorW should be 0 upfront
 **
 **	@param type	Cursor-type of the cursor to draw.
 **	@param x	Screen x pixel position.
 **	@param y	Screen y pixel position.
 **	@param frame	Animation frame # of the cursor.
 */
-global void DrawCursor(const CursorType* type,int x,int y,int frame)
+local void DrawCursor(const CursorType* type,int x,int y,int frame)
 {
+    unsigned int size,w,h;
+    int spritex,spritey;
+
     //
     //	Save cursor position and size, for faster cursor redraw.
     //
-    OldCursorX=x-=type->HotX;
-    OldCursorY=y-=type->HotY;
-    OldCursorW=VideoGraphicWidth(type->Sprite);
-    OldCursorH=VideoGraphicHeight(type->Sprite);
+    spritex=(x-=type->HotX);
+    spritey=(y-=type->HotY);
+    w=VideoGraphicWidth(type->Sprite);
+    h=VideoGraphicHeight(type->Sprite);
 
-/* FIXME: SaveCusor done before rectangle
-    SaveCursor();
-*/
-    VideoDrawClip(type->Sprite,frame,x,y);
-}
+    //Reserve enough memory for background of sprite (also for future calls)
+    size=(unsigned int)w*(unsigned int)h*memsize;
+    if( OldCursorSize<size ) {
+	if( OldCursorImage ) {
+	    OldCursorImage=realloc(OldCursorImage,size);
+	} else {
+	    OldCursorImage=malloc(size);
+	}
+	OldCursorSize=size;
+    }
 
-/**
-**	Hide cursor.
-*/
-global void HideCursor(void)
-{
-    RestoreCursor();
+    //Save (seen) area behind sprite
+    CLIP_RECTANGLE(x,y,w,h);
+    SaveCursorBackground(OldCursorX=x,OldCursorY=y,OldCursorW=w,OldCursorH=h);
+
+    //Draw sprite (using its own clipping)  FIXME: prevent clipping twice
+    VideoDrawClip(type->Sprite,frame,spritex,spritey);
+    OldCursorInvalidate=1;
 }
 
 /*----------------------------------------------------------------------------
---	DRAW CURSOR
+--	DRAW BUILDING CURSOR
 ----------------------------------------------------------------------------*/
-
-local int RectangleCursor;		/// Flag: last cursor was rectangle
-local int BuildingCursor;		/// Flag: last cursor was building
-
-// area of tiles covered by building cursor (SX,SY;EX,EY)
-local int BuildingCursorSX;		/// FIXME: docu
-local int BuildingCursorSY;		/// FIXME: docu
-local int BuildingCursorEX;		/// FIXME: docu
-local int BuildingCursorEY;		/// FIXME: docu
-
 /**
 **	Draw cursor for selecting building position.
 */
@@ -787,131 +759,224 @@ local void DrawBuildingCursor(void)
     }
 }
 
+
+/*----------------------------------------------------------------------------
+--	DRAW/HIDE CURSOR (interface for the outside world)
+----------------------------------------------------------------------------*/
 /**
-**	Draw rectangle cursor.
-*/
-global void DrawRectangleCursor(void)
-{
-    int x;
-    int y;
-    int w;
-    int h;
-    int x1;
-    int y1;
-
-    //
-    //	Clip to map window.
-    //
-    x1=CursorX;
-    if( x1<TheUI.MapX ) {
-	x1=TheUI.MapX;
-    } else if( x1>TheUI.MapEndX ) {
-	x1=TheUI.MapEndX;
-    }
-    y1=CursorY;
-    if( y1<TheUI.MapY ) {
-	y1=TheUI.MapY;
-    } else if( y1>TheUI.MapEndY ) {
-	y1=TheUI.MapEndY;
-    }
-
-    x=CursorStartX;
-    if( x>x1 ) {
-	x=x1;
-	w=CursorStartX-x+1;
-    } else {
-	w=x1-x+1;
-    }
-    y=CursorStartY;
-    if( y>y1 ) {
-	y=y1;
-	h=CursorStartY-y+1;
-    } else {
-	h=y1-y+1;
-    }
-
-#ifdef NEW_MAPDRAW
-    SaveCursorRectangle(OldCursorRectangleX=x,OldCursorRectangleY=y,
-			OldCursorRectangleW=w,OldCursorRectangleH=h);
-    VideoDrawHLine(ColorGreen,x,y,w);
-    VideoDrawVLine(ColorGreen,x,y+1,--h);
-    VideoDrawHLine(ColorGreen,x+1,y+h,--w);
-    VideoDrawVLine(ColorGreen,x+w,y,h);
-#else
-    //FIXME VideoDrawRectangleClip uses different definition for w and h
-    VideoDrawRectangleClip(ColorGreen,x,y,w-1,h-1);
-#endif
-}
-
-/**
-**	Draw the cursor
+**	Draw the cursor and prepare tobe restored by HideAnyCursor again.
+**      Note: This function can be called, without calling HideAnyCursor first,
+**            which means that this function should re-use/free memory of the
+**            last call.
+**            When calling multiple times, the old cursor is expected to be
+**            overdrawn by something else (else HideAnyCursor is needed!)
+**            Also the cursors are not invalidated (refresh on real screen)
+**            here, but this is done by InvalidateCursorAreas.
+**
+**  FIXME: event handler should be temporary stopped while copying
+**         CursorX,CursorY,.. because between two copy commands another
+**         event can occure, which let invalid mouse position be delivered.
 */
 global void DrawAnyCursor(void)
 {
-    RectangleCursor=BuildingCursor=0;
-
-/*FIXME: temporary, as SaveCursor must happen before rectangle
-*/
-    OldCursorX=CursorX-GameCursor->HotX;
-    OldCursorY=CursorY-GameCursor->HotY;
-    OldCursorW=VideoGraphicWidth(GameCursor->Sprite);
-    OldCursorH=VideoGraphicHeight(GameCursor->Sprite);
-    SaveCursor();
+    // Disable any previous drawn cursor
+    OldCursorInvalidate=OldCursorW=
+      OldCursorRectangleInvalidate=OldCursorRectangleW=
+      BuildingCursor=0;
 
     //
-    //	Selecting rectangle
+    //	First, Selecting rectangle
     //
     if( CursorState==CursorStateRectangle
 	     && (CursorStartX!=CursorX || CursorStartY!=CursorY) ) {
-	DrawRectangleCursor();
-	RectangleCursor=1;
-    } else
-
+	DrawVisibleRectangleCursor(CursorStartX,CursorStartY,CursorX,CursorY);
+    }
     //
-    //	Selecting position for building
+    //	Or Selecting position for building
     //
-    if( CursorBuilding && CursorOn==CursorOnMap ) {
+    else if( CursorBuilding && CursorOn==CursorOnMap ) {
 	DrawBuildingCursor();
 	BuildingCursor=1;
     }
 
     //
-    //	Normal cursor.
+    //	Last, Normal cursor.
+    //  This will also save (part of) drawn rectangle cursor, but that's ok.
     //
     DrawCursor(GameCursor,CursorX,CursorY,0);
 }
 
 /**
 **	Remove old cursor from display.
+**      (in the opposite direction of DrawAnyCursor)
+**      Note: this function can be called, without calling DrawAnyCursor first,
+**            which means that cursors shouldn't be restored twice.
+**            As cursors are, like DrawAnyCursor,  not invalidated here, it
+**            still needs to be done by InvalidateCursorAreas.
 */
-global int HideAnyCursor(void)
+global void HideAnyCursor(void)
 {
-    if( RectangleCursor ) {
-	LoadCursorRectangle(OldCursorRectangleX,OldCursorRectangleY,
-		OldCursorRectangleW,OldCursorRectangleH);
-    }
-    if( BuildingCursor ) {
-    //NOTE: this will restore tiles themselves later in next video update
-	MarkDrawAreaMap(BuildingCursorSX,BuildingCursorSY,
-		BuildingCursorEX,BuildingCursorEY);
+    //
+    //	First, Normal cursor (might restore part of rectangle cursor also).
+    //
+    if( OldCursorW ) {
+        // restore area of visible cursor
+        LoadCursorBackground(OldCursorX,OldCursorY,OldCursorW,OldCursorH);
+
+        // save hidden area to be invalidated
+        HiddenCursorX=OldCursorX;
+        HiddenCursorY=OldCursorY;
+        HiddenCursorW=OldCursorW;
+        HiddenCursorH=OldCursorH;
+
+        // Denote cursor no longer visible
+        OldCursorW=0;
     }
 
     //
-    //	Cursor complete on map and map must be redrawn, no restore.
-    //StephanR: but prevented when not entire map is redrawn ;)
+    //	Last, Selecting rectangle
     //
-#ifndef NEW_MAPDRAW
-    if( OldCursorX>=TheUI.MapX
-	    && OldCursorX+OldCursorW-1<=TheUI.MapEndX
-	    && OldCursorY>=TheUI.MapY
-	    && OldCursorY+OldCursorH-1<=TheUI.MapEndY
-	    && (MustRedraw&RedrawMap)
-	    && (InterfaceState != IfaceStateMenu) ) {
-	return 0;
+    if( OldCursorRectangleW ) {
+        //  restore area of visible cursor
+	LoadCursorRectangle(OldCursorRectangleX,OldCursorRectangleY,
+			    OldCursorRectangleW,OldCursorRectangleH);
+
+        // save hidden area to be invalidated
+        HiddenCursorRectangleX=OldCursorRectangleX;
+        HiddenCursorRectangleY=OldCursorRectangleY;
+        HiddenCursorRectangleW=OldCursorRectangleW;
+        HiddenCursorRectangleH=OldCursorRectangleH;
+
+        // Denote cursor no longer visible
+        OldCursorRectangleW=0;
     }
-#endif
-    HideCursor();
-    return 1;
+    //
+    //	Or Selecting position for building
+    //
+    else if( BuildingCursor ) {
+    //NOTE: this will restore tiles themselves later in next video update
+	MarkDrawAreaMap(BuildingCursorSX,BuildingCursorSY,
+		BuildingCursorEX,BuildingCursorEY);
+        BuildingCursor=0;
+    }
+}
+
+/**
+**      Let an area be invalidated, but remembering if cursor is automaticly 
+**      invalidated with this area.
+**      Note: building-cursor is already invalidated by redraw-map
+**
+**	@param x	left-top x-position of area on screen
+**	@param y	left-top y-position of area on screen
+**	@param w	width of area on screen
+**	@param h	height of area on screen
+*/
+global void InvalidateAreaAndCheckCursor( int x, int y, int w, int h )
+{
+  int dx,dy;
+
+  //Invalidate area
+  InvalidateArea(x,y,w,h);
+
+  //Now check if cursor sprite is inside it, then no need for invalidate
+  if ( OldCursorInvalidate )
+  {
+    dx = OldCursorX-x;
+    dy = OldCursorY-y;
+    if ( dx >= 0 && dy >= 0 && (w-dx) >= OldCursorW && (h-dy) >= OldCursorH )
+      OldCursorInvalidate = 0;
+  }
+
+  //Now check if previously hidden cursor sprite is inside it..
+  if ( HiddenCursorW )
+  {
+    dx = HiddenCursorX-x;
+    dy = HiddenCursorY-y;
+    if ( dx >= 0 && dy >= 0 &&
+         (w-dx) >= HiddenCursorW && (h-dy) >= HiddenCursorH )
+      HiddenCursorW = 0;
+  }
+
+  //Now check if cursor rectangle is inside it..
+  if ( OldCursorRectangleInvalidate )
+  {
+    dx = OldCursorRectangleX-x;
+    dy = OldCursorRectangleY-y;
+    if ( dx >= 0 && dy >= 0 &&
+         (w-dx) >= OldCursorRectangleW && (h-dy) >= OldCursorRectangleH )
+      OldCursorRectangleInvalidate = 0;
+  }
+
+  //Now check if previously hidden cursor rectangle is inside it..
+  if ( HiddenCursorRectangleW )
+  {
+    dx = HiddenCursorRectangleX-x;
+    dy = HiddenCursorRectangleY-y;
+    if ( dx >= 0 && dy >= 0 &&
+         (w-dx) >= HiddenCursorRectangleW && (h-dy) >= HiddenCursorRectangleH )
+      HiddenCursorRectangleW = 0;
+  }
+}
+
+/**
+**      Invalidate only the sides of a given rectangle (not its contents)
+**
+**	@param x	left-top x-position of rectangle on screen
+**	@param y	left-top y-position of rectangle on screen
+**	@param w	width of rectangle on screen
+**	@param h	height of rectangle on screen
+*/
+local void InvalidateRectangle(int x, int y, int w, int h)
+{
+    InvalidateArea(x,y,w,1); // top side
+    if ( --h > 0 )
+    {
+      InvalidateArea(x,y+h,w,1); // bottom side
+      if ( --h > 0 )
+      {
+        InvalidateArea(x,++y,1,h); // left side
+        if ( --w > 0 )
+          InvalidateArea(x+w,y,1,h); // right side
+      } 
+    }
+}
+
+/**
+**      Let the (remaining) areas taken by the cursors, as determined by
+**      DrawAnyCursor and InvalidateAreaAndCheckcursor,  be invalidated.
+**      Note: building-cursor is already invalidated by redraw-map
+*/
+global void InvalidateCursorAreas(void)
+{
+  //Invalidate cursor sprite
+  if ( OldCursorInvalidate )
+  {
+    InvalidateArea(OldCursorX,OldCursorY,OldCursorW,OldCursorH);
+    OldCursorInvalidate=0;
+  }
+
+  //Invalidate hidden cursor sprite
+  if ( HiddenCursorW )
+  {
+    InvalidateArea(HiddenCursorX,HiddenCursorY,HiddenCursorW,HiddenCursorH);
+    HiddenCursorW=0;
+  }
+
+  //Invalidate cursor rectangle
+  if ( OldCursorRectangleInvalidate )
+  {
+    InvalidateRectangle(OldCursorRectangleX,OldCursorRectangleY,
+                        OldCursorRectangleW,OldCursorRectangleH);
+    OldCursorRectangleInvalidate=0;
+  }
+
+  //Invalidate hidden cursor rectangle
+  if ( HiddenCursorRectangleW )
+  {
+    InvalidateRectangle(HiddenCursorRectangleX,HiddenCursorRectangleY,
+                        HiddenCursorRectangleW,HiddenCursorRectangleH);
+    HiddenCursorRectangleW=0;
+  }
 }
 
 /**
@@ -922,8 +987,6 @@ global int HideAnyCursor(void)
 */
 global void InitCursors(void)
 {
-    int memsize;
-
     if( OldCursorRectangle ) {	// memory of possible previous video-setting?
 	free( OldCursorRectangle );
     }
diff --git a/src/video/graphic.cpp b/src/video/graphic.cpp
index 829295257..f8c0ffd15 100644
--- a/src/video/graphic.cpp
+++ b/src/video/graphic.cpp
@@ -36,6 +36,7 @@
 #include "freecraft.h"
 #include "video.h"
 #include "iolib.h"
+#include "intern_video.h"
 
 /*----------------------------------------------------------------------------
 --	Declarations
@@ -241,49 +242,6 @@ local void VideoDrawSub8to32(
     }
 }
 
-/**
-**	Clip to clipping rectangle.
-**
-**	@param w	width to display
-**	@param h	height to display
-**	@param x	X screen position
-**	@param y	Y screen position
-*/
-#define DO_CLIPPING(w,h,x,y) \
-    do {						\
-	int f;						\
-							\
-	if( x<ClipX1 ) {				\
-	    f=ClipX1-x;					\
-	    x=ClipX1;					\
-	    if( w<f ) {			/* outside */	\
-		return;					\
-	    }						\
-	    w-=f;					\
-	}						\
-	if( (x+w)>ClipX2 ) {				\
-	    if( w<ClipX2-x ) {		/* outside */	\
-		return;					\
-	    }						\
-	    w=ClipX2-x;					\
-	}						\
-							\
-	if( y<ClipY1 ) {				\
-	    f=ClipY1-y;					\
-	    y=ClipY1;					\
-	    if( h<f ) {			/* outside */	\
-		return;					\
-	    }						\
-	    h-=f;					\
-	}						\
-	if( (y+h)>ClipY2 ) {				\
-	    if( h<ClipY2-y ) {		/* outside */	\
-		return;					\
-	    }						\
-	    h=ClipY2-y;					\
-	}						\
-    } while( 0 )
-
 /**
 **	Video draw part of 8bit graphic clipped into 8 bit framebuffer.
 **
@@ -299,7 +257,7 @@ local void VideoDrawSub8to8Clip(
 	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    DO_CLIPPING(w,h,x,y);
+    CLIP_RECTANGLE(x,y,w,h);
     VideoDrawSub8to8(graphic,gx,gy,w,h,x,y);
 }
 
@@ -318,7 +276,7 @@ local void VideoDrawSub8to16Clip(
 	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    DO_CLIPPING(w,h,x,y);
+    CLIP_RECTANGLE(x,y,w,h);
     VideoDrawSub8to16(graphic,gx,gy,w,h,x,y);
 }
 
@@ -337,7 +295,7 @@ local void VideoDrawSub8to24Clip(
 	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    DO_CLIPPING(w,h,x,y);
+    CLIP_RECTANGLE(x,y,w,h);
     VideoDrawSub8to24(graphic,gx,gy,w,h,x,y);
 }
 
@@ -356,7 +314,7 @@ local void VideoDrawSub8to32Clip(
 	const Graphic* graphic,int gx,int gy,unsigned w,unsigned h,
 	int x,int y)
 {
-    DO_CLIPPING(w,h,x,y);
+    CLIP_RECTANGLE(x,y,w,h);
     VideoDrawSub8to32(graphic,gx,gy,w,h,x,y);
 }
 
diff --git a/src/video/intern_video.h b/src/video/intern_video.h
new file mode 100644
index 000000000..ff29e1eb3
--- /dev/null
+++ b/src/video/intern_video.h
@@ -0,0 +1,123 @@
+//   ___________		     _________		      _____  __
+//   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
+//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
+//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
+//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
+//	  \/		    \/	   \/	     \/		   \/
+//  ______________________                           ______________________
+//			  T H E   W A R   B E G I N S
+//	   FreeCraft - A free fantasy real time strategy game engine
+//
+/**@name intern_video.h	- The video headerfile for video sources only. */
+//
+//	(c) Copyright 1999-2001 by Lutz Sammer
+//
+//	FreeCraft is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published
+//	by the Free Software Foundation; either version 2 of the License,
+//	or (at your option) any later version.
+//
+//	FreeCraft is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//	GNU General Public License for more details.
+//
+//	$Id$
+
+#ifndef __INTERN_VIDEO_H__
+#define __INTERN_VIDEO_H__
+
+//@{
+
+
+/*----------------------------------------------------------------------------
+--	Documentation
+----------------------------------------------------------------------------*/
+/**
+**  THIS HEADER FILE SHOULD ONLY BE INCLUDED BY SOURCE-FILES IN VIDEO !!!
+**
+**  This delivers an interface to basic video operations in video.c, while 
+**  keeping these detailed operations out of the main include-file video.h
+**
+**  FIXME: Currently some interfaces listed in video.h should be moved in
+**         here, this includes possible "extern" declarations in source-files
+**         themselves.
+**
+*/
+
+/*----------------------------------------------------------------------------
+--	Includes
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+--	Declarations
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+--	Variables
+----------------------------------------------------------------------------*/
+    /// Direct acces to clipping rectangle for macro CLIP_RECTANGLE
+extern int ClipX1;                      /// current clipping top left
+extern int ClipY1;                      /// current clipping top left
+extern int ClipX2;                      /// current clipping bottom right
+extern int ClipY2;                      /// current clipping bottom right
+
+
+/*----------------------------------------------------------------------------
+--	Macros
+----------------------------------------------------------------------------*/
+/**
+**      Clip to clipping rectangle.
+**      FIXME: not easy to debug, but making it a function needs:
+**             - pointers to be able to alter given arguments
+**             - special return value to denote 'outside' clipping region
+**               (which is now handled by a simple return in caller function)
+**
+**      @param w        unsigned int width to display
+**      @param h        unsigned int height to display
+**      @param x        int X screen position
+**      @param y        int Y screen position
+*/
+#define CLIP_RECTANGLE(x,y,width,height) { \
+  unsigned int f;                          \
+  if( x<ClipX1 ) {                         \
+    f=ClipX1-x;                            \
+    if( width<=f ) {                       \
+       return;                             \
+    }                                      \
+    width-=f;                              \
+    x=ClipX1;                              \
+  }                                        \
+  if( (x+width)>ClipX2+1 ) {               \
+    if( x>ClipX2 ) {                       \
+      return;                              \
+    }                                      \
+    width=ClipX2-x+1;                      \
+  }                                        \
+  if( y<ClipY1 ) {                         \
+    f=ClipY1-y;                            \
+    if( height<=f ) {                      \
+      return;                              \
+    }                                      \
+    height-=f;                             \
+    y=ClipY1;                              \
+  }                                        \
+  if( (y+height)>ClipY2+1 ) {              \
+    if( y>ClipY2 ) {                       \
+        return;                            \
+    }                                      \
+    height=ClipY2-y+1;                     \
+  }                                        \
+}
+
+
+/*----------------------------------------------------------------------------
+--	Functions
+----------------------------------------------------------------------------*/
+
+
+//@}
+
+#endif	// !__INTERN_VIDEO_H__
diff --git a/src/video/linedraw.cpp b/src/video/linedraw.cpp
index b8d451caa..ce3e72932 100644
--- a/src/video/linedraw.cpp
+++ b/src/video/linedraw.cpp
@@ -36,6 +36,8 @@
 #include "freecraft.h"
 #include "video.h"
 
+#include "intern_video.h"
+
 /*----------------------------------------------------------------------------
 --	Declarations
 ----------------------------------------------------------------------------*/
@@ -51,15 +53,6 @@ typedef enum {
    ClipCodeRight  = 8
 } ClipCode;
 
-/*----------------------------------------------------------------------------
---	Externals
-----------------------------------------------------------------------------*/
-
-extern int ClipX1;			/// current clipping top left
-extern int ClipY1;			/// current clipping top left
-extern int ClipX2;			/// current clipping bottom right
-extern int ClipY2;			/// current clipping bottom right
-
 /*----------------------------------------------------------------------------
 --	Variables
 ----------------------------------------------------------------------------*/
@@ -4513,38 +4506,6 @@ local void DrawTransRectangle32(SysColors color,int x,int y
   }
 }
 
-#define CLIP_RECTANGLE(x,y,width,height) { \
-  unsigned f; \
-  if( x<ClipX1 ) { \
-    f=ClipX1-x; \
-    if( width<=f ) { \
-       return; \
-    } \
-    width-=f; \
-    x=ClipX1; \
-  } \
-  if( (x+width)>ClipX2+1 ) { \
-    if( x>ClipX2 ) { \
-      return; \
-    } \
-    width=ClipX2-x+1; \
-  } \
-  if( y<ClipY1 ) { \
-    f=ClipY1-y; \
-    if( height<=f ) { \
-      return; \
-    } \
-    height-=f; \
-    y=ClipY1; \
-  } \
-  if( (y+height)>ClipY2+1 ) { \
-    if( y>ClipY2 ) { \
-        return; \
-    } \
-    height=ClipY2-y+1; \
-  } \
-}
-
 /**
 **	Draw rectangle clipped.
 **
diff --git a/src/video/video.cpp b/src/video/video.cpp
index caa7d3ca5..1b2cc21eb 100644
--- a/src/video/video.cpp
+++ b/src/video/video.cpp
@@ -35,12 +35,13 @@
 
 #include "freecraft.h"
 #include "video.h"
-
 #include "map.h"
 #include "ui.h"
 #include "cursor.h"
 #include "iolib.h"
 
+#include "intern_video.h"
+
 #ifdef USE_SDL
 #include <SDL/SDL.h>
 #endif