diff -Naur windows_split/src/viewport.cpp windows_split2/src/viewport.cpp
--- windows_split/src/viewport.cpp	2008-04-04 21:18:03.000000000 +0200
+++ windows_split2/src/viewport.cpp	2008-04-05 12:38:01.000000000 +0200
@@ -1,6 +1,23 @@
 /* $Id: viewport.cpp 12547 2008-04-03 19:55:40Z smatz $ */
 
-/** @file viewport.cpp */
+/**
+ * @file viewport.cpp
+ *
+ * The in-game coordiante system looks like this
+ * \verbatim
+ *                                               *
+ *                    ^ Z                        *
+ *                    |                          *
+ *                    |                          *
+ *                    |                          *
+ *                    |                          *
+ *                 /     \                       *
+ *              /           \                    *
+ *           /                 \                 *
+ *        /                       \              *
+ *   X <                             > Y         *
+ * \endverbatim
+ */
 
 #include "stdafx.h"
 #include "openttd.h"
@@ -42,38 +59,6 @@
 Point _tile_fract_coords;
 ZoomLevel _saved_scrollpos_zoom;
 
-/**
- * The maximum number of viewports depends on the maximum number
- * of windows. Technically is could be the maximum number of
- * windows, but there is always at least one window that does
- * not need a viewport. Not having 'support' for that viewport
- * saves some time and memory.
- * For the introduction GUI and create game GUIs there is no
- * need for more than one viewport, however in the normal game
- * and scenario editor one can make a lot of viewports. For the
- * normal game one always has a main toolbar and a status bar,
- * however the statusbar does not exist on the scenario editor.
- *
- * This means that we can only safely assume that there is one
- * window without viewport.
- */
-static ViewPort _viewports[MAX_NUMBER_OF_WINDOWS - 1];
-static uint32 _active_viewports;    ///< bitmasked variable where each bit signifies if a viewport is in use or not
-assert_compile(lengthof(_viewports) < sizeof(_active_viewports) * 8);
-
-/* The in-game coordiante system looks like this *
- *                                               *
- *                    ^ Z                        *
- *                    |                          *
- *                    |                          *
- *                    |                          *
- *                    |                          *
- *                 /     \                       *
- *              /           \                    *
- *           /                 \                 *
- *        /                       \              *
- *   X <                             > Y         *
- */
 
 struct StringSpriteToDraw {
 	uint16 string;
@@ -179,31 +164,11 @@
 	return p;
 }
 
-void InitViewports()
-{
-	memset(_viewports, 0, sizeof(_viewports));
-	_active_viewports = 0;
-}
-
-void DeleteWindowViewport(Window *w)
-{
-	ClrBit(_active_viewports, w->viewport - _viewports);
-	w->viewport->width = 0;
-	w->viewport = NULL;
-}
-
 void AssignWindowViewport(Window *w, int x, int y,
 	int width, int height, uint32 follow_flags, ZoomLevel zoom)
 {
-	ViewPort *vp;
+	ViewPort *vp = &w->vp_data;
 	Point pt;
-	uint32 bit;
-
-	for (vp = _viewports, bit = 0; ; vp++, bit++) {
-		assert(vp != endof(_viewports));
-		if (vp->width == 0) break;
-	}
-	SetBit(_active_viewports, bit);
 
 	vp->left = x + w->left;
 	vp->top = y + w->top;
@@ -234,7 +199,7 @@
 	WP(w, vp_d).dest_scrollpos_x = pt.x;
 	WP(w, vp_d).dest_scrollpos_y = pt.y;
 
-	w->viewport = vp;
+	w->SetViewport(vp);
 	vp->virtual_left = 0;//pt.x;
 	vp->virtual_top = 0;//pt.y;
 }
@@ -1759,14 +1724,15 @@
 
 void MarkAllViewportsDirty(int left, int top, int right, int bottom)
 {
-	const ViewPort *vp = _viewports;
-	uint32 act = _active_viewports;
-	do {
-		if (act & 1) {
+	Window* const *wz;
+
+	FOR_ALL_WINDOWS(wz) {
+		const ViewPort *vp = (*wz)->viewport;
+		if (vp != NULL) {
 			assert(vp->width != 0);
 			MarkViewportDirty(vp, left, top, right, bottom);
 		}
-	} while (vp++,act>>=1);
+	}
 }
 
 void MarkTileDirtyByTile(TileIndex tile)
diff -Naur windows_split/src/viewport_func.h windows_split2/src/viewport_func.h
--- windows_split/src/viewport_func.h	2008-03-27 21:30:01.000000000 +0100
+++ windows_split2/src/viewport_func.h	2008-04-05 12:39:05.000000000 +0200
@@ -12,8 +12,6 @@
 
 void SetSelectionRed(bool);
 
-void InitViewports();
-void DeleteWindowViewport(Window *w);
 void AssignWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom);
 ViewPort *IsPtInWindowViewport(const Window *w, int x, int y);
 Point GetTileBelowCursor();
diff -Naur windows_split/src/viewport_type.h windows_split2/src/viewport_type.h
--- windows_split/src/viewport_type.h	2008-04-04 21:18:03.000000000 +0200
+++ windows_split2/src/viewport_type.h	2008-04-05 10:36:30.000000000 +0200
@@ -11,7 +11,7 @@
 #include "tile_type.h"
 
 /**
- * Data structure for viewport, a continuously moving part of the world
+ * Data structure for viewport, display of a part of the world
  */
 struct ViewPort {
 	int left,top;                       ///< screen coordinates for the viewport
@@ -61,7 +61,9 @@
 	VHM_RAIL    = 5, ///< rail pieces
 };
 
-/* highlighting draw styles */
+/**
+ * highlighting draw styles
+ */
 enum HighLightStyle {
 	HT_NONE   = 0x00,
 	HT_RECT   = 0x80,
diff -Naur windows_split/src/window.cpp windows_split2/src/window.cpp
--- windows_split/src/window.cpp	2008-04-03 20:40:09.000000000 +0200
+++ windows_split2/src/window.cpp	2008-04-05 12:36:39.000000000 +0200
@@ -25,6 +25,101 @@
 
 #include "table/sprites.h"
 
+/*
+ * BaseWindow class methods
+ */
+
+
+BaseWindow::BaseWindow(WindowClass p_cls, WindowNumber p_window_number,
+                       int p_left, int p_top, int p_min_width, int p_min_height)
+{
+	window_class = p_cls;
+	window_number = p_window_number;
+
+	left = p_left;
+	top = p_top;
+	width = p_min_width;
+	height = p_min_height;
+	resize.width = p_min_width; resize.height = p_min_height;
+	resize.step_width = 1; resize.step_height = 1;
+
+	desc_flags = 0;
+	viewport = NULL;
+	parent = NULL;
+}
+
+BaseWindow::~BaseWindow()
+{
+	SetViewport(NULL);	// Remove any viewport
+	parent = NULL;
+}
+
+/**
+ * Make the given viewport available for the viewport code. Caller should initialize the
+ * data structure before this call by using InitializeViewport().
+ * Disable the viewport by calling this function with \c NULL .
+ *
+ * @param vp New viewport to display by this window (\c NULL means display no viewport)
+ */
+void BaseWindow::SetViewport(ViewPort *vp)
+{
+	if (viewport != NULL) {
+		viewport->width = 0;	// Ensure old viewport is not used any more
+	}
+	viewport = vp;
+}
+
+/*
+ * Window class methods
+ */
+
+Window::Window(WindowClass p_cls, uint16 p_flags4, byte p_caption_color,
+		int p_left, int p_top, int p_min_width, int p_min_height,
+		WindowProc *p_proc, const Widget *p_widget, WindowNumber p_window_number)
+	: BaseWindow(p_cls, p_window_number, p_left, p_top, p_min_width, p_min_height)
+{
+	flags4 = p_flags4;
+	caption_color = p_caption_color;
+	wndproc = p_proc;
+
+	hscroll.count = 0; hscroll.cap = 0; hscroll.pos = 0;
+	vscroll.count = 0; vscroll.cap = 0; vscroll.pos = 0;
+	vscroll2.count = 0; vscroll2.cap = 0; vscroll2.pos = 0;
+
+	original_widget = p_widget;
+	if (p_widget != NULL) {
+		uint index = 1;
+		const Widget *wi;
+
+		for (wi = p_widget; wi->type != WWT_LAST; wi++) index++;
+
+		widget = NULL;
+		widget = ReallocT(widget, index);
+		memcpy(widget, p_widget, sizeof(widget[0]) * index);
+		widget_count = index - 1;
+	} else {
+		widget = NULL;
+		widget_count = 0;
+	}
+
+	message.msg = 0; message.wparam = 0; message.lparam = 0;
+	for (int i = 0; i < WINDOW_CUSTOM_SIZE; i++) {
+		custom[i] = 0;
+	}
+}
+
+
+Window::~Window()
+{
+	SetViewport(NULL);	// Remove viewport
+	
+	/* Release widgets */
+	if (widget != NULL) {
+		free(widget); widget = NULL;
+	}
+	widget_count = 0;
+}
+
 
 void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...)
 {
@@ -240,28 +335,6 @@
 	return (w->original_widget == widget);
 }
 
-/** Copies 'widget' to 'w->widget' to allow for resizable windows
- * @param w Window on which to attach the widget array
- * @param widget pointer of widget array to fill the window with */
-void AssignWidgetToWindow(Window *w, const Widget *widget)
-{
-	w->original_widget = widget;
-
-	if (widget != NULL) {
-		uint index = 1;
-		const Widget *wi;
-
-		for (wi = widget; wi->type != WWT_LAST; wi++) index++;
-
-		w->widget = ReallocT(w->widget, index);
-		memcpy(w->widget, widget, sizeof(*w->widget) * index);
-		w->widget_count = index - 1;
-	} else {
-		w->widget = NULL;
-		w->widget_count = 0;
-	}
-}
-
 
 /**
  * Resize the window.
diff -Naur windows_split/src/window_gui.h windows_split2/src/window_gui.h
--- windows_split/src/window_gui.h	2008-04-01 22:36:34.000000000 +0200
+++ windows_split2/src/window_gui.h	2008-04-05 18:12:32.000000000 +0200
@@ -287,10 +287,17 @@
 };
 
 /**
- * Data structure for an opened window
+ * Base class for an opened window
  */
-struct Window {
-	uint16 flags4;			///< Window flags, @see WindowFlags
+class BaseWindow
+{
+public:
+	BaseWindow(WindowClass p_cls, WindowNumber p_window_number,
+                   int p_left, int p_top, int p_min_width, int p_min_height);
+	virtual ~BaseWindow();
+
+	void SetViewport(ViewPort *vp);
+
 	WindowClass window_class;	///< Window class
 	WindowNumber window_number;
 
@@ -298,24 +305,43 @@
 	    top,	///< y position of top edge of the window
 	    width,	///< width of the window (number of pixels to the right in x direction)
 	    height;	///< Height of the window (number of pixels down in y direction)
-
-	Scrollbar hscroll,	///< Horizontal scroll bar
-	          vscroll,	///< First vertical scroll bar
-	          vscroll2;	///< Second vertical scroll bar
 	ResizeInfo resize;	///< Resize information
 
-	byte caption_color;	///< Background color of the window caption, contains PlayerID
+	uint32 desc_flags;	///< Window/widgets default flags setting, @see WindowDefaultFlag
+	ViewPort *viewport;	///< Pointer to viewport, if present (structure is part of derived class)
+	Window *parent;		///< Parent window
+};
 
-	WindowProc *wndproc;	///< Event handler function for the window
-	ViewPort *viewport;	///< Pointer to viewport, if present
+/**
+ * Data structure for an opened window
+ */
+class Window: public BaseWindow
+{
+public:
+	Window(WindowClass p_cls, uint16 p_flags4, byte p_caption_color,
+	       int p_left, int p_top, int p_min_width, int p_min_height,
+	       WindowProc *p_proc, const Widget *p_widget, WindowNumber p_window_number);
+	/* virtual */ ~Window();
+	
+	uint16 flags4;			///< Window flags, @see WindowFlags
+
+	Scrollbar hscroll,		///< Horizontal scroll bar
+	          vscroll,		///< First vertical scroll bar
+	          vscroll2;		///< Second vertical scroll bar
+
+	byte caption_color;		///< Background color of the window caption, contains PlayerID
+
+	WindowProc *wndproc;		///< Event handler function for the window
 	const Widget *original_widget;	///< Original widget layout, copied from WindowDesc
-	Widget *widget;		///< Widgets of the window
-	uint widget_count;	///< Number of widgets of the window
-	uint32 desc_flags;	///< Window/widgets default flags setting, @see WindowDefaultFlag
+	Widget *widget;			///< Widgets of the window
+	uint widget_count;		///< Number of widgets of the window
+
+	WindowMessage message;		///< Buffer for storing received messages (for communication between different window events)
+	byte custom[WINDOW_CUSTOM_SIZE]; ///< Additional data depending on window type
+
+	ViewPort vp_data;		///< Viewport data of the window. Do not access directly, instead use BaseWindow::viewport.
+					///< @see BaseWindow::SetViewport()
 
-	WindowMessage message;	///< Buffer for storing received messages (for communication between different window events)
-	Window *parent;		///< Parent window
-	byte custom[WINDOW_CUSTOM_SIZE];	///< Additional data depending on window type
 
 	void HandleButtonClick(byte widget);
 
@@ -542,7 +568,6 @@
 
 bool IsVitalWindow(const Window *w);
 bool IsWindowOfPrototype(const Window *w, const Widget *widget);
-void AssignWidgetToWindow(Window *w, const Widget *widget);
 void ResizeWindow(Window *w, int x, int y);
 int GetWidgetFromPos(const Window *w, int x, int y);
 void DrawWindowWidgets(const Window *w);
diff -Naur windows_split/src/window_list.cpp windows_split2/src/window_list.cpp
--- windows_split/src/window_list.cpp	2008-04-03 21:36:11.000000000 +0200
+++ windows_split2/src/window_list.cpp	2008-04-05 11:13:21.000000000 +0200
@@ -29,9 +29,9 @@
 
 static Point _drag_delta; //< delta between mouse cursor and upper left corner of dragged window
 
-static Window _windows[MAX_NUMBER_OF_WINDOWS];	// @todo: Move this to window.cpp
-Window *_z_windows[lengthof(_windows)];	///< Window stack, lowest window (behind all others) is at index 0
+Window *_z_windows[MAX_NUMBER_OF_WINDOWS];	///< Window stack, lowest window (behind all others) is at index 0
 Window **_last_z_window; ///< always points to the next free space in the z-array
+static Window *_mouseover_last_w = NULL;	///< Pointer to window last called with MOUSEOVER event
 
 Point _cursorpos_drag_start;
 
@@ -214,13 +214,7 @@
 	}
 
 	CallWindowEventNP(w, WE_DESTROY);
-	if (w->viewport != NULL) DeleteWindowViewport(w);
-
-	SetWindowDirty(w);
-	free(w->widget);
-	w->widget = NULL;
-	w->widget_count = 0;
-	w->parent = NULL;
+	SetWindowDirty(w);	// Ensure that the area covered by the deleted window will be redrawn
 
 	/* Find the window in the z-array, and effectively remove it
 	 * by moving all windows after it one to the left */
@@ -228,6 +222,11 @@
 	if (wz == NULL) return;
 	memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
 	_last_z_window--;
+
+	if (w == _mouseover_last_w) {
+		_mouseover_last_w = NULL; // Don't let HandleMouseOver() call this window
+	}
+	delete w;
 }
 
 /**
@@ -425,32 +424,6 @@
 }
 
 /**
- * Find a free window in the global _window Window data structures.
- * @return A window data structure not currently in use, or \c NULL if all windows are being used
- */
-static Window *FindFreeWindow()
-{
-	Window *w;
-
-	for (w = _windows; w < endof(_windows); w++) {
-		Window* const *wz;
-		bool window_in_use = false;
-
-		FOR_ALL_WINDOWS(wz) {
-			if (*wz == w) {
-				window_in_use = true;
-				break;
-			}
-		}
-
-		if (!window_in_use) return w;
-	}
-
-	assert(_last_z_window == endof(_z_windows));
-	return NULL;
-}
-
-/**
  * Open a new window.
  * This function is called from AllocateWindow() or AllocateWindowDesc()
  * See descriptions for those functions for usage
@@ -471,31 +444,17 @@
 static Window *LocalAllocateWindow(int x, int y, int min_width, int min_height, int def_width, int def_height,
 				WindowProc *proc, WindowClass cls, const Widget *widget, int window_number, void *data)
 {
-	Window *w = FindFreeWindow();
+	assert(_last_z_window >= _z_windows && _last_z_window <= endof(_z_windows)); // _last_z_window sanity check
 
-	/* We have run out of windows, close one and use that as the place for our new one */
-	if (w == NULL) {
-		w = FindDeletableWindow();
+	/* We have too many open windows, close one first */
+	if (_last_z_window == endof(_z_windows)) {
+		Window *w = FindDeletableWindow();
 		if (w == NULL) w = ForceFindDeletableWindow();
 		DeleteWindow(w);
 	}
-
-	/* Set up window properties */
-	memset(w, 0, sizeof(*w));
-	w->window_class = cls;
-	w->flags4 = WF_WHITE_BORDER_MASK; // just opened windows have a white border
-	w->caption_color = 0xFF;
-	w->left = x;
-	w->top = y;
-	w->width = min_width;
-	w->height = min_height;
-	w->wndproc = proc;
-	AssignWidgetToWindow(w, widget);
-	w->resize.width = min_width;
-	w->resize.height = min_height;
-	w->resize.step_width = 1;
-	w->resize.step_height = 1;
-	w->window_number = window_number;
+	
+	Window *w = new Window(cls, WF_WHITE_BORDER_MASK, 0xff,
+	                       x, y, min_width, min_height, proc, widget, window_number);
 
 	{
 		Window **wz = _last_z_window;
@@ -833,9 +792,8 @@
 {
 	IConsoleClose();
 
-	memset(&_windows, 0, sizeof(_windows));
 	_last_z_window = _z_windows;
-	InitViewports();
+	_mouseover_last_w = NULL;
 	_no_scroll = 0;
 }
 
@@ -977,18 +935,21 @@
 {
 	Window *w;
 	WindowEvent e;
-	static Window *last_w = NULL;
 
 	w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
 
-	/* We changed window, put a MOUSEOVER event to the last window */
-	if (last_w != NULL && last_w != w) {
+	/* We changed window, put a MOUSEOVER event to the last window.
+	 * There is one minor snag, the Window data structure may have disappeared due to a call to delete
+	 * To prevent this from crashing the application, _mouseover_last_w is reset with each delete
+	 * if the window deleted is equal to _mouseover_last_w
+	 */
+	if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
 		e.event = WE_MOUSEOVER;
 		e.we.mouseover.pt.x = -1;
 		e.we.mouseover.pt.y = -1;
-		if (last_w->wndproc) last_w->wndproc(last_w, &e);
+		if (_mouseover_last_w->wndproc) _mouseover_last_w->wndproc(_mouseover_last_w, &e);
 	}
-	last_w = w;
+	_mouseover_last_w = w;
 
 	if (w != NULL) {
 		/* send an event in client coordinates. */
