(svn r12742) [NewGRF_ports] -Sync: with trunk r12673:12705. NewGRF_ports
authorrichk
Wed, 16 Apr 2008 22:16:04 +0000
branchNewGRF_ports
changeset 10210 a2131f7a315d
parent 10200 aba3af04cdbd
child 10211 c1391c8ed5c6
(svn r12742) [NewGRF_ports] -Sync: with trunk r12673:12705.
source.list
src/core/alloc_func.hpp
src/core/alloc_type.hpp
src/debug.h
src/lang/english.txt
src/misc.cpp
src/misc_gui.cpp
src/network/network_gui.cpp
src/newgrf_station.cpp
src/news_gui.cpp
src/news_type.h
src/openttd.cpp
src/order_cmd.cpp
src/order_func.h
src/order_gui.cpp
src/pathfind.cpp
src/player_gui.cpp
src/road_cmd.cpp
src/roadveh_cmd.cpp
src/ship_cmd.cpp
src/signs_gui.cpp
src/station_cmd.cpp
src/tgp.cpp
src/timetable.h
src/timetable_gui.cpp
src/town_gui.cpp
src/train_cmd.cpp
src/vehicle.cpp
src/vehicle_gui.cpp
src/viewport.cpp
src/widgets/dropdown.cpp
src/widgets/dropdown_type.h
src/window.cpp
src/window_gui.h
src/window_type.h
--- a/source.list	Wed Apr 16 00:07:47 2008 +0000
+++ b/source.list	Wed Apr 16 22:16:04 2008 +0000
@@ -107,6 +107,7 @@
 aircraft.h
 airport.h
 core/alloc_func.hpp
+core/alloc_type.hpp
 articulated_vehicles.h
 autoreplace_base.h
 autoreplace_func.h
--- a/src/core/alloc_func.hpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/core/alloc_func.hpp	Wed Apr 16 22:16:04 2008 +0000
@@ -90,56 +90,4 @@
 	return t_ptr;
 }
 
-/**
- * A small 'wrapper' for allocations that can be done on most OSes on the
- * stack, but are just too large to fit in the stack on devices with a small
- * stack such as the NDS.
- * So when it is possible a stack allocation is made, otherwise a heap
- * allocation is made and this is freed once the struct goes out of scope.
- * @param T      the type to make the allocation for
- * @param length the amount of items to allocate
- */
-template <typename T, size_t length>
-struct SmallStackSafeStackAlloc {
-#if !defined(__NDS__)
-	/** Storing the data on the stack */
-	T data[length];
-#else
-	/** Storing it on the heap */
-	T *data;
-	/** The length (in elements) of data in this allocator. */
-	size_t len;
-
-	/** Allocating the memory */
-	SmallStackSafeStackAlloc() : data(MallocT<T>(length)), len(length) {}
-	/** And freeing when it goes out of scope */
-	~SmallStackSafeStackAlloc() { free(data); }
-#endif
-
-	/**
-	 * Gets a pointer to the data stored in this wrapper.
-	 * @return the pointer.
-	 */
-	inline operator T* () { return data; }
-
-	/**
-	 * Gets a pointer to the data stored in this wrapper.
-	 * @return the pointer.
-	 */
-	inline T* operator -> () { return data; }
-
-	/**
-	 * Gets a pointer to the last data element stored in this wrapper.
-	 * @note needed because endof does not work properly for pointers.
-	 * @return the 'endof' pointer.
-	 */
-	inline T* EndOf() {
-#if !defined(__NDS__)
-		return endof(data);
-#else
-		return &data[len];
-#endif
-	}
-};
-
 #endif /* ALLOC_FUNC_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/alloc_type.hpp	Wed Apr 16 22:16:04 2008 +0000
@@ -0,0 +1,102 @@
+
+/* $Id$ */
+
+/** @file alloc_type.hpp Helper types related to the allocation of memory */
+
+#ifndef ALLOC_TYPE_HPP
+#define ALLOC_TYPE_HPP
+
+#include "alloc_func.hpp"
+
+/**
+ * A small 'wrapper' for allocations that can be done on most OSes on the
+ * stack, but are just too large to fit in the stack on devices with a small
+ * stack such as the NDS.
+ * So when it is possible a stack allocation is made, otherwise a heap
+ * allocation is made and this is freed once the struct goes out of scope.
+ * @param T      the type to make the allocation for
+ * @param length the amount of items to allocate
+ */
+template <typename T, size_t length>
+struct SmallStackSafeStackAlloc {
+#if !defined(__NDS__)
+	/** Storing the data on the stack */
+	T data[length];
+#else
+	/** Storing it on the heap */
+	T *data;
+	/** The length (in elements) of data in this allocator. */
+	size_t len;
+
+	/** Allocating the memory */
+	SmallStackSafeStackAlloc() : data(MallocT<T>(length)), len(length) {}
+	/** And freeing when it goes out of scope */
+	~SmallStackSafeStackAlloc() { free(data); }
+#endif
+
+	/**
+	 * Gets a pointer to the data stored in this wrapper.
+	 * @return the pointer.
+	 */
+	inline operator T* () { return data; }
+
+	/**
+	 * Gets a pointer to the data stored in this wrapper.
+	 * @return the pointer.
+	 */
+	inline T* operator -> () { return data; }
+
+	/**
+	 * Gets a pointer to the last data element stored in this wrapper.
+	 * @note needed because endof does not work properly for pointers.
+	 * @return the 'endof' pointer.
+	 */
+	inline T* EndOf() {
+#if !defined(__NDS__)
+		return endof(data);
+#else
+		return &data[len];
+#endif
+	}
+};
+
+/**
+ * Base class that provides memory initialization on dynamically created objects.
+ * All allocated memory will be zeroed.
+ */
+class ZeroedMemoryAllocator
+{
+public:
+	ZeroedMemoryAllocator() {}
+	virtual ~ZeroedMemoryAllocator() {}
+
+	/**
+	 * Memory allocator for a single class instance.
+	 * @param size the amount of bytes to allocate.
+	 * @return the given amounts of bytes zeroed.
+	 */
+	void *operator new(size_t size) { return CallocT<byte>(size); }
+
+	/**
+	 * Memory allocator for an array of class instances.
+	 * @param size the amount of bytes to allocate.
+	 * @return the given amounts of bytes zeroed.
+	 */
+	void *operator new[](size_t size) { return CallocT<byte>(size); }
+
+	/**
+	 * Memory release for a single class instance.
+	 * @param ptr  the memory to free.
+	 * @param size the amount of allocated memory (unused).
+	 */
+	void operator delete(void *ptr, size_t size) { free(ptr); }
+
+	/**
+	 * Memory release for an array of class instances.
+	 * @param ptr  the memory to free.
+	 * @param size the amount of allocated memory (unused).
+	 */
+	void operator delete[](void *ptr, size_t size) { free(ptr); }
+};
+
+#endif /* ALLOC_TYPE_HPP */
--- a/src/debug.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/debug.h	Wed Apr 16 22:16:04 2008 +0000
@@ -103,7 +103,13 @@
 #ifdef DEBUG_DUMP_COMMANDS
 	void CDECL DebugDumpCommands(const char *s, ...);
 #else /* DEBUG_DUMP_COMMANDS */
-	static inline void DebugDumpCommands(const char *s, ...) {}
+	/* when defined as an empty function with variable argument list,
+	 * it can't be inlined - so define it as an empty macro */
+	#if defined(__GNUC__) && (__GNUC__ < 3)
+		#define DebugDumpCommands(s, args...)
+	#else
+		#define DebugDumpCommands(s, ...)
+	#endif
 #endif /* DEBUG_DUMP_COMMANDS */
 
 #endif /* DEBUG_H */
--- a/src/lang/english.txt	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/lang/english.txt	Wed Apr 16 22:16:04 2008 +0000
@@ -2723,7 +2723,6 @@
 STR_CONDITIONAL_NUM                                             :Jump to order {COMMA} when {STRING} {STRING} {COMMA}
 STR_CONDITIONAL_TRUE_FALSE                                      :Jump to order {COMMA} when {STRING} {STRING}
 
-STR_TIMETABLE_GO_TO                                             :{STRING4} {STRING2}
 STR_TIMETABLE_TRAVEL_NOT_TIMETABLED                             :Travel (not timetabled)
 STR_TIMETABLE_TRAVEL_FOR                                        :Travel for {STRING1}
 STR_TIMETABLE_STAY_FOR                                          :and stay for {STRING1}
@@ -2780,6 +2779,7 @@
 STR_882D_VALUE                                                  :{LTBLUE}{ENGINE}{BLACK}   Value: {LTBLUE}{CURRENCY}
 STR_882E                                                        :{WHITE}{VEHICLE}
 STR_882F_LOADING_UNLOADING                                      :{LTBLUE}Loading / Unloading
+STR_LEAVING                                                     :{LTBLUE}Leaving
 STR_TRAIN_MUST_BE_STOPPED                                       :{WHITE}Train must be stopped inside a depot
 STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT                              :{WHITE}Can't send train to depot...
 STR_8831_NO_MORE_SPACE_FOR_ORDERS                               :{WHITE}No more space for orders
--- a/src/misc.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/misc.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -24,7 +24,7 @@
 #include "texteff.hpp"
 #include "string_func.h"
 #include "gfx_func.h"
-#include "core/alloc_func.hpp"
+#include "core/alloc_type.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
--- a/src/misc_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/misc_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -778,7 +778,7 @@
 			case SCT_ALL: break;
 			default: NOT_REACHED();
 		}
-		if (cargo[i] >= (supplies ? 1 : 8)) {
+		if (cargo[i] >= (supplies ? 1U : 8U)) {
 			if (first) {
 				first = false;
 			} else {
--- a/src/network/network_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/network/network_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -218,22 +218,27 @@
 
 /** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
 enum NetworkGameWindowWidgets {
-	NGWW_CLOSE    = 0,  ///< Close 'X' button
-	NGWW_CONN_BTN = 4,  ///< 'Connection' droplist button
-	NGWW_PLAYER   = 5,  ///< Panel with editbox to set player name
+	NGWW_CLOSE,         ///< Close 'X' button
+	NGWW_CAPTION,       ///< Caption of the window
+	NGWW_RESIZE,        ///< Resize button
 
-	NGWW_NAME     = 6,  ///< 'Name' button
+	NGWW_CONNECTION,    ///< Label in from of connection droplist
+	NGWW_CONN_BTN,      ///< 'Connection' droplist button
+	NGWW_PLAYER,        ///< Panel with editbox to set player name
+
+	NGWW_NAME,          ///< 'Name' button
 	NGWW_CLIENTS,       ///< 'Clients' button
 	NGWW_INFO,          ///< Third button in the game list panel
 
-	NGWW_MATRIX   = 9,  ///< Panel with list of games
+	NGWW_MATRIX,        ///< Panel with list of games
+	NGWW_SCROLLBAR,     ///< Scrollbar of matrix
 
-	NGWW_DETAILS  = 11, ///< Panel with game details
-	NGWW_JOIN     = 12, ///< 'Join game' button
-	NGWW_REFRESH  = 13, ///< 'Refresh server' button
-	NGWW_NEWGRF   = 14, ///< 'NewGRF Settings' button
+	NGWW_DETAILS,       ///< Panel with game details
+	NGWW_JOIN,          ///< 'Join game' button
+	NGWW_REFRESH,       ///< 'Refresh server' button
+	NGWW_NEWGRF,        ///< 'NewGRF Settings' button
 
-	NGWW_FIND     = 15, ///< 'Find server' button
+	NGWW_FIND,          ///< 'Find server' button
 	NGWW_ADD,           ///< 'Add server' button
 	NGWW_START,         ///< 'Start server' button
 	NGWW_CANCEL,        ///< 'Cancel' button
@@ -579,10 +584,10 @@
 static const Widget _network_game_window_widgets[] = {
 /* TOP */
 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},            // NGWW_CLOSE
-{    WWT_CAPTION,   RESIZE_RIGHT,  BGC,    11,   449,     0,    13, STR_NETWORK_MULTIPLAYER,          STR_NULL},
-{      WWT_PANEL,   RESIZE_RB,     BGC,     0,   449,    14,   263, 0x0,                              STR_NULL},
+{    WWT_CAPTION,   RESIZE_RIGHT,  BGC,    11,   449,     0,    13, STR_NETWORK_MULTIPLAYER,          STR_NULL},                         // NGWW_CAPTION
+{      WWT_PANEL,   RESIZE_RB,     BGC,     0,   449,    14,   263, 0x0,                              STR_NULL},                         // NGWW_RESIZE
 
-{       WWT_TEXT,   RESIZE_NONE,   BGC,     9,    85,    23,    35, STR_NETWORK_CONNECTION,           STR_NULL},
+{       WWT_TEXT,   RESIZE_NONE,   BGC,     9,    85,    23,    35, STR_NETWORK_CONNECTION,           STR_NULL},                         // NGWW_CONNECTION
 { WWT_DROPDOWNIN,   RESIZE_NONE,   BGC,    90,   181,    22,    33, STR_NETWORK_LAN_INTERNET_COMBO,   STR_NETWORK_CONNECTION_TIP},       // NGWW_CONN_BTN
 
 {    WWT_EDITBOX,   RESIZE_LR,     BGC,   290,   440,    22,    33, STR_NETWORK_PLAYER_NAME_OSKTITLE, STR_NETWORK_ENTER_NAME_TIP},       // NGWW_PLAYER
@@ -592,8 +597,8 @@
 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,    71,   150,    42,    53, STR_NETWORK_CLIENTS_CAPTION,      STR_NETWORK_CLIENTS_CAPTION_TIP},  // NGWW_CLIENTS
 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,   151,   190,    42,    53, STR_EMPTY,                        STR_NETWORK_INFO_ICONS_TIP},       // NGWW_INFO
 
-{     WWT_MATRIX,   RESIZE_RB,     BGC,    10,   190,    54,   236, (13 << 8) + 1,                    STR_NETWORK_CLICK_GAME_TO_SELECT}, // NGWW_MATRIX
-{  WWT_SCROLLBAR,   RESIZE_LRB,    BGC,   191,   202,    42,   236, 0x0,                              STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{     WWT_MATRIX,   RESIZE_RB,     BGC,    10,   190,    54,   236, (11 << 8) + 1,                    STR_NETWORK_CLICK_GAME_TO_SELECT}, // NGWW_MATRIX
+{  WWT_SCROLLBAR,   RESIZE_LRB,    BGC,   191,   202,    42,   236, 0x0,                              STR_0190_SCROLL_BAR_SCROLLS_LIST}, // NGWW_SCROLLBAR
 
 /* RIGHT SIDE */
 {      WWT_PANEL,   RESIZE_LRB,    BGC,   210,   440,    42,   236, 0x0,                              STR_NULL},                         // NGWW_DETAILS
--- a/src/newgrf_station.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/newgrf_station.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -755,7 +755,7 @@
 	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 	SpriteID relocation;
 	SpriteID image;
-	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
+	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
 	uint tile = 2;
 
 	statspec = GetCustomStationSpec(sclass, station);
@@ -793,6 +793,17 @@
 			image += relocation;
 		}
 
+		SpriteID pal;
+		if (HasBit(image, PALETTE_MODIFIER_TRANSPARENT) || HasBit(image, PALETTE_MODIFIER_COLOR)) {
+			if (seq->image.pal > 0) {
+				pal = seq->image.pal;
+			} else {
+				pal = palette;
+			}
+		} else {
+			pal = PAL_NONE;
+		}
+
 		if ((byte)seq->delta_z != 0x80) {
 			pt = RemapCoords(seq->delta_x, seq->delta_y, seq->delta_z);
 			DrawSprite(image, pal, x + pt.x, y + pt.y);
--- a/src/news_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/news_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -998,6 +998,7 @@
 			if (_total_news == 0) {
 				assert(_latest_news == _oldest_news);
 				_latest_news = INVALID_NEWS;
+				_current_news = INVALID_NEWS;
 			}
 
 			/* Since we only imitate a FIFO removing an arbitrary element does need
--- a/src/news_type.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/news_type.h	Wed Apr 16 22:16:04 2008 +0000
@@ -66,12 +66,13 @@
 
 /**
  * Kinds of bankrupcy
+ * @note These flags are or'd with player index
  */
 enum NewsBankrupcy {
-	NB_BTROUBLE,    ///< Company is in trouble (warning)
-	NB_BMERGER,     ///< Company has been bought by another company
-	NB_BBANKRUPT,   ///< Company has gone bankrupt
-	NB_BNEWCOMPANY, ///< A new company has been started
+	NB_BTROUBLE    = (1 << 4), ///< Company is in trouble (warning)
+	NB_BMERGER     = (2 << 4), ///< Company has been bought by another company
+	NB_BBANKRUPT   = (3 << 4), ///< Company has gone bankrupt
+	NB_BNEWCOMPANY = (4 << 4), ///< A new company has been started
 };
 
 struct NewsItem {
--- a/src/openttd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/openttd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -2350,6 +2350,40 @@
 		}
 	}
 
+
+	if (CheckSavegameVersion(93)) {
+		/* Rework of orders. */
+		Order *order;
+		FOR_ALL_ORDERS(order) order->ConvertFromOldSavegame();
+
+		Vehicle *v;
+		FOR_ALL_VEHICLES(v) {
+			if (v->orders != NULL && !v->orders->IsValid()) v->orders = NULL;
+
+			v->current_order.ConvertFromOldSavegame();
+			if (v->type == VEH_ROAD && v->IsPrimaryVehicle() && v->prev_shared == NULL) {
+				FOR_VEHICLE_ORDERS(v, order) order->SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+			}
+		}
+	} else if (CheckSavegameVersion(94)) {
+		/* Unload and transfer are now mutual exclusive. */
+		Order *order;
+		FOR_ALL_ORDERS(order) {
+			if ((order->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
+				order->SetUnloadType(OUFB_TRANSFER);
+				order->SetLoadType(OLFB_NO_LOAD);
+			}
+		}
+
+		Vehicle *v;
+		FOR_ALL_VEHICLES(v) {
+			if ((v->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
+				v->current_order.SetUnloadType(OUFB_TRANSFER);
+				v->current_order.SetLoadType(OLFB_NO_LOAD);
+			}
+		}
+	}
+
 	if (CheckSavegameVersion(84)) {
 		/* Update go to buoy orders because they are just waypoints */
 		Order *order;
@@ -2494,32 +2528,6 @@
 		}
 	}
 
-	if (CheckSavegameVersion(93)) {
-		/* Rework of orders. */
-		Order *order;
-		FOR_ALL_ORDERS(order) order->ConvertFromOldSavegame();
-
-		Vehicle *v;
-		FOR_ALL_VEHICLES(v) v->current_order.ConvertFromOldSavegame();
-	} else if (CheckSavegameVersion(94)) {
-		/* Unload and transfer are now mutual exclusive. */
-		Order *order;
-		FOR_ALL_ORDERS(order) {
-			if ((order->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
-				order->SetUnloadType(OUFB_TRANSFER);
-				order->SetLoadType(OLFB_NO_LOAD);
-			}
-		}
-
-		Vehicle *v;
-		FOR_ALL_VEHICLES(v) {
-			if ((v->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
-				v->current_order.SetUnloadType(OUFB_TRANSFER);
-				v->current_order.SetLoadType(OLFB_NO_LOAD);
-			}
-		}
-	}
-
 	return InitializeWindowsAndCaches();
 }
 
--- a/src/order_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/order_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -216,9 +216,7 @@
 	 * Sanity check
 	 * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
 	 */
-	if (!order.IsValid() && (order.GetLoadType() != 0 || order.GetUnloadType() != 0 || order.GetDestination() != 0)) {
-		order.MakeDummy();
-	}
+	if (!order.IsValid() && packed != 0) order.MakeDummy();
 
 	return order;
 }
@@ -358,7 +356,7 @@
 			}
 
 			/* Non stop not allowed for non-trains. */
-			if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
+			if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR;
 
 			/* Full load and unload are mutual exclusive. */
 			if ((new_order.GetLoadType() & OLFB_FULL_LOAD) && (new_order.GetUnloadType() & OUFB_UNLOAD)) return CMD_ERROR;
@@ -412,7 +410,7 @@
 				if (!IsPlayerBuildableVehicleType(v)) return CMD_ERROR;
 			}
 
-			if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
+			if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR;
 			if (new_order.GetDepotOrderType() & ~ODTFB_PART_OF_ORDERS) return CMD_ERROR;
 			if (new_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT) return CMD_ERROR;
 			break;
@@ -869,6 +867,7 @@
 		default: NOT_REACHED();
 
 		case MOF_NON_STOP:
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR;
 			if (data >= ONSF_END) return CMD_ERROR;
 			if (data == order->GetNonStopType()) return CMD_ERROR;
 			break;
@@ -1644,7 +1643,7 @@
 	}
 
 	/* If it is unchanged, keep it. */
-	if (order->Equals(v->current_order) &&
+	if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
 			(v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || GetStation(order->GetDestination())->dock_tile != 0)) {
 		return false;
 	}
--- a/src/order_func.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/order_func.h	Wed Apr 16 22:16:04 2008 +0000
@@ -37,6 +37,8 @@
 void DeleteVehicleOrders(Vehicle *v);
 bool ProcessOrders(Vehicle *v);
 
+void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable);
+
 #define MIN_SERVINT_PERCENT  5
 #define MAX_SERVINT_PERCENT 90
 #define MIN_SERVINT_DAYS    30
--- a/src/order_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/order_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -211,6 +211,105 @@
 extern uint ConvertDisplaySpeedToSpeed(uint speed);
 
 
+void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable)
+{
+	StringID str = (v->cur_order_index == order_index) ? STR_8805 : STR_8804;
+	SetDParam(6, STR_EMPTY);
+
+	switch (order->GetType()) {
+		case OT_DUMMY:
+			SetDParam(1, STR_INVALID_ORDER);
+			SetDParam(2, order->GetDestination());
+			break;
+
+		case OT_GOTO_STATION: {
+			OrderLoadFlags load = order->GetLoadType();
+			OrderUnloadFlags unload = order->GetUnloadType();
+
+			SetDParam(1, STR_GO_TO_STATION);
+			SetDParam(2, STR_ORDER_GO_TO + ((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? order->GetNonStopType() : 0));
+			SetDParam(3, order->GetDestination());
+
+			if (timetable) {
+				SetDParam(4, STR_EMPTY);
+
+				if (order->wait_time > 0) {
+					SetDParam(6, STR_TIMETABLE_STAY_FOR);
+					SetTimetableParams(7, 8, order->wait_time);
+				}
+			} else {
+				SetDParam(4, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[unload][load]);
+			}
+		} break;
+
+		case OT_GOTO_DEPOT:
+			if (v->type == VEH_AIRCRAFT) {
+				if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
+					SetDParam(1, STR_GO_TO_NEAREST_DEPOT);
+					SetDParam(3, STR_ORDER_NEAREST_HANGAR);
+				} else {
+					SetDParam(1, STR_GO_TO_HANGAR);
+					SetDParam(3, order->GetDestination());
+				}
+				SetDParam(4, STR_EMPTY);
+			} else {
+				if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
+					SetDParam(1, STR_GO_TO_NEAREST_DEPOT);
+					SetDParam(3, STR_ORDER_NEAREST_DEPOT);
+				} else {
+					SetDParam(1, STR_GO_TO_DEPOT);
+					SetDParam(3, GetDepot(order->GetDestination())->town_index);
+				}
+
+				switch (v->type) {
+					case VEH_TRAIN: SetDParam(4, STR_ORDER_TRAIN_DEPOT); break;
+					case VEH_ROAD:  SetDParam(4, STR_ORDER_ROAD_DEPOT); break;
+					case VEH_SHIP:  SetDParam(4, STR_ORDER_SHIP_DEPOT); break;
+					default: NOT_REACHED();
+				}
+			}
+
+			if (order->GetDepotOrderType() & ODTFB_SERVICE) {
+				SetDParam(2, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT);
+			} else {
+				SetDParam(2, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO);
+			}
+
+			if (!timetable && order->IsRefit()) {
+				SetDParam(6, STR_REFIT_ORDER);
+				SetDParam(7, GetCargo(order->GetRefitCargo())->name);
+			}
+			break;
+
+		case OT_GOTO_WAYPOINT:
+			SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
+			SetDParam(2, order->GetDestination());
+			break;
+
+		case OT_CONDITIONAL:
+			SetDParam(2, order->GetConditionSkipToOrder() + 1);
+			if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) {
+				SetDParam(1, STR_CONDITIONAL_UNCONDITIONAL);
+			} else {
+				OrderConditionComparator occ = order->GetConditionComparator();
+				SetDParam(1, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_CONDITIONAL_TRUE_FALSE : STR_CONDITIONAL_NUM);
+				SetDParam(3, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
+				SetDParam(4, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
+
+				uint value = order->GetConditionValue();
+				if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
+				SetDParam(5, value);
+			}
+			break;
+
+		default: NOT_REACHED();
+	}
+
+	SetDParam(0, order_index + 1);
+	DrawString(2, y, str, selected ? TC_WHITE : TC_BLACK);
+}
+
+
 static void DrawOrdersWindow(Window *w)
 {
 	const Vehicle *v = GetVehicle(w->window_number);
@@ -237,7 +336,7 @@
 				(uint)v->num_orders + ((shared_orders || v->num_orders != 0) ? 1 : 0) <= (uint)WP(w, order_d).sel);
 
 		/* non-stop only for trains */
-		w->SetWidgetDisabledState(ORDER_WIDGET_NON_STOP,  v->type != VEH_TRAIN || order == NULL);
+		w->SetWidgetDisabledState(ORDER_WIDGET_NON_STOP,  (v->type != VEH_TRAIN && v->type != VEH_ROAD) || order == NULL);
 		w->SetWidgetDisabledState(ORDER_WIDGET_FULL_LOAD, order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // full load
 		w->SetWidgetDisabledState(ORDER_WIDGET_UNLOAD,    order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // unload
 		/* Disable list of vehicles with the same shared orders if there is no list */
@@ -310,94 +409,11 @@
 	order = GetVehicleOrder(v, i);
 	StringID str;
 	while (order != NULL) {
-		str = (v->cur_order_index == i) ? STR_8805 : STR_8804;
-		SetDParam(6, STR_EMPTY);
-
-		if (i - w->vscroll.pos < w->vscroll.cap) {
-			switch (order->GetType()) {
-				case OT_DUMMY:
-					SetDParam(1, STR_INVALID_ORDER);
-					SetDParam(2, order->GetDestination());
-					break;
-
-				case OT_GOTO_STATION: {
-					OrderLoadFlags load = order->GetLoadType();
-					OrderUnloadFlags unload = order->GetUnloadType();
-
-					SetDParam(1, STR_GO_TO_STATION);
-					SetDParam(2, STR_ORDER_GO_TO + (v->type == VEH_TRAIN ? order->GetNonStopType() : 0));
-					SetDParam(3, order->GetDestination());
-					SetDParam(4, (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) ? STR_EMPTY : _station_load_types[unload][load]);
-				} break;
-
-				case OT_GOTO_DEPOT:
-					if (v->type == VEH_AIRCRAFT) {
-						if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
-							SetDParam(1, STR_GO_TO_NEAREST_DEPOT);
-							SetDParam(3, STR_ORDER_NEAREST_HANGAR);
-						} else {
-							SetDParam(1, STR_GO_TO_HANGAR);
-							SetDParam(3, order->GetDestination());
-						}
-						SetDParam(4, STR_EMPTY);
-					} else {
-						if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
-							SetDParam(1, STR_GO_TO_NEAREST_DEPOT);
-							SetDParam(3, STR_ORDER_NEAREST_DEPOT);
-						} else {
-							SetDParam(1, STR_GO_TO_DEPOT);
-							SetDParam(3, GetDepot(order->GetDestination())->town_index);
-						}
+		/* Don't draw anything if it extends past the end of the window. */
+		if (i - w->vscroll.pos >= w->vscroll.cap) break;
 
-						switch (v->type) {
-							case VEH_TRAIN: SetDParam(4, STR_ORDER_TRAIN_DEPOT); break;
-							case VEH_ROAD:  SetDParam(4, STR_ORDER_ROAD_DEPOT); break;
-							case VEH_SHIP:  SetDParam(4, STR_ORDER_SHIP_DEPOT); break;
-							default: NOT_REACHED();
-						}
-					}
-
-					if (order->GetDepotOrderType() & ODTFB_SERVICE) {
-						SetDParam(2, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT);
-					} else {
-						SetDParam(2, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO);
-					}
-
-					if (order->IsRefit()) {
-						SetDParam(6, STR_REFIT_ORDER);
-						SetDParam(7, GetCargo(order->GetRefitCargo())->name);
-					}
-					break;
-
-				case OT_GOTO_WAYPOINT:
-					SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
-					SetDParam(2, order->GetDestination());
-					break;
-
-				case OT_CONDITIONAL:
-					SetDParam(2, order->GetConditionSkipToOrder() + 1);
-					if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) {
-						SetDParam(1, STR_CONDITIONAL_UNCONDITIONAL);
-					} else {
-						OrderConditionComparator occ = order->GetConditionComparator();
-						SetDParam(1, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_CONDITIONAL_TRUE_FALSE : STR_CONDITIONAL_NUM);
-						SetDParam(3, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
-						SetDParam(4, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
-
-						uint value = order->GetConditionValue();
-						if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
-						SetDParam(5, value);
-					}
-					break;
-
-				default: NOT_REACHED();
-			}
-
-			SetDParam(0, i + 1);
-			DrawString(2, y, str, (i == WP(w, order_d).sel) ? TC_WHITE : TC_BLACK);
-
-			y += 10;
-		}
+		DrawOrderString(v, order, i, y, i == WP(w, order_d).sel, false);
+		y += 10;
 
 		i++;
 		order = order->next;
@@ -422,6 +438,7 @@
 				if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_player)) {
 					if (IsRailDepot(tile)) {
 						order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS);
+						if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 						return order;
 					}
 				}
@@ -430,6 +447,7 @@
 			case MP_ROAD:
 				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_player)) {
 					order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS);
+					if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 					return order;
 				}
 				break;
@@ -463,6 +481,7 @@
 			IsTileOwner(tile, _local_player) &&
 			IsRailWaypoint(tile)) {
 		order.MakeGoToWaypoint(GetWaypointByTile(tile)->index);
+		if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 		return order;
 	}
 
@@ -479,7 +498,7 @@
 			(facil = FACIL_TRUCK_STOP, 1);
 			if (st->facilities & facil) {
 				order.MakeGoToStation(st_index);
-				if (_patches.new_nonstop && v->type == VEH_TRAIN) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+				if (_patches.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 				return order;
 			}
 		}
@@ -1167,7 +1186,7 @@
 	if (v->owner != _local_player) {
 		w = AllocateWindowDescFront(&_other_orders_desc, veh);
 	} else {
-		w = AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_orders_train_desc : &_orders_desc, veh);
+		w = AllocateWindowDescFront((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? &_orders_train_desc : &_orders_desc, veh);
 	}
 
 	if (w != NULL) {
--- a/src/pathfind.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/pathfind.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -17,7 +17,7 @@
 #include "depot.h"
 #include "tunnelbridge_map.h"
 #include "core/random_func.hpp"
-#include "core/alloc_func.hpp"
+#include "core/alloc_type.hpp"
 #include "tunnelbridge.h"
 
 /* remember which tiles we have already visited so we don't visit them again. */
--- a/src/player_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/player_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -29,6 +29,7 @@
 #include "string_func.h"
 #include "settings_type.h"
 #include "widgets/dropdown_func.h"
+#include "widgets/dropdown_type.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -283,7 +284,6 @@
 	STR_00DE_BROWN,
 	STR_00DF_GREY,
 	STR_00E0_WHITE,
-	INVALID_STRING_ID
 };
 
 /* Association of liveries to livery classes */
@@ -324,6 +324,29 @@
 	PLW_WIDGET_MATRIX,
 };
 
+class DropDownListColourItem : public DropDownListItem {
+public:
+	DropDownListColourItem(int result, bool masked) : DropDownListItem(result, masked) {}
+
+	virtual ~DropDownListColourItem() {}
+
+	virtual StringID String() const
+	{
+		return _colour_dropdown[this->result];
+	}
+
+	virtual uint Height(uint width) const
+	{
+		return 14;
+	}
+
+	virtual void Draw(int x, int y, uint width, uint height, bool sel) const
+	{
+		DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOR_START + this->result, x + 16, y + 7);
+		DrawStringTruncated(x + 32, y + 3, this->String(), sel ? TC_WHITE : TC_BLACK, x + width - 30);
+	}
+};
+
 static void ShowColourDropDownMenu(Window *w, uint32 widget)
 {
 	uint32 used_colours = 0;
@@ -345,7 +368,12 @@
 	if (scheme == LS_END) scheme = LS_DEFAULT;
 	livery = &GetPlayer((PlayerID)w->window_number)->livery[scheme];
 
-	ShowDropDownMenu(w, _colour_dropdown, widget == PLW_WIDGET_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget, used_colours, 0);
+	DropDownList *list = new DropDownList();
+	for (uint i = 0; i < lengthof(_colour_dropdown); i++) {
+		list->push_back(new DropDownListColourItem(i, HasBit(used_colours, i)));
+	}
+
+	ShowDropDownList(w, list, widget == PLW_WIDGET_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget);
 }
 
 static void SelectPlayerLiveryWndProc(Window *w, WindowEvent *e)
--- a/src/road_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/road_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -150,7 +150,7 @@
  * @param rt roadtype to remove
  * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
  */
-static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check)
+static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
 {
 	/* cost for removing inner/edge -roads */
 	static const uint16 road_remove_cost[2] = {50, 18};
@@ -188,7 +188,7 @@
 
 	/* check if you're allowed to remove the street owned by a town
 	 * removal allowance depends on difficulty setting */
-	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
+	if (town_check && !CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
 
 	if (!IsTileType(tile, MP_ROAD)) {
 		/* If it's the last roadtype, just clear the whole tile */
@@ -254,7 +254,7 @@
 				return CMD_ERROR;
 			}
 
-			ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+			if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
 			if (flags & DC_EXEC) {
 				if (present == ROAD_NONE) {
 					RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
@@ -291,7 +291,7 @@
 			if (rt == ROADTYPE_ROAD && HasTileRoadType(tile, ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR;
 
 			if (rt == ROADTYPE_ROAD) {
-				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+				if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
 			}
 
 			if (flags & DC_EXEC) {
@@ -768,7 +768,7 @@
 						_additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
 						return cost;
 					}
-					RemoveRoad(tile, flags, bits, rt, true);
+					RemoveRoad(tile, flags, bits, rt, true, false);
 				}
 				cost.AddCost(ret);
 			}
--- a/src/roadveh_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/roadveh_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -1708,7 +1708,7 @@
 	if (IsRoadVehFront(v) && ((IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
 			_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) ||
 			(IsInsideMM(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
-			v->current_order.GetDestination() == GetStationIndex(v->tile) &&
+			v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
 			GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
 			v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
@@ -1718,8 +1718,7 @@
 		/* Vehicle is at the stop position (at a bay) in a road stop.
 		 * Note, if vehicle is loading/unloading it has already been handled,
 		 * so if we get here the vehicle has just arrived or is just ready to leave. */
-		if (!v->current_order.IsType(OT_LEAVESTATION) &&
-				!v->current_order.IsType(OT_GOTO_DEPOT)) {
+		if (!v->current_order.IsType(OT_LEAVESTATION)) {
 			/* Vehicle has arrived at a bay in a road stop */
 
 			if (IsDriveThroughStopTile(v->tile)) {
@@ -1747,10 +1746,15 @@
 
 			rs->SetEntranceBusy(false);
 
-			v->last_station_visited = GetStationIndex(v->tile);
+			v->last_station_visited = st->index;
 
-			RoadVehArrivesAt(v, st);
-			v->BeginLoading();
+			if (IsDriveThroughStopTile(v->tile) || v->current_order.GetDestination() == st->index) {
+				RoadVehArrivesAt(v, st);
+				v->BeginLoading();
+			} else {
+				v->current_order.MakeLeaveStation();
+				InvalidateVehicleOrder(v);
+			}
 
 			return false;
 		}
@@ -1806,6 +1810,8 @@
 		return false;
 	}
 
+	if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) v->current_order.Free();
+
 	/* Move to next frame unless vehicle arrived at a stop position
 	 * in a depot or entered a tunnel/bridge */
 	if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++;
--- a/src/ship_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/ship_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -243,7 +243,7 @@
 {
 	if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
 
-	Station *st = GetStation(station);
+	const Station *st = GetStation(station);
 	if (st->dock_tile != 0) {
 		return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
 	} else {
--- a/src/signs_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/signs_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -68,63 +68,49 @@
 static void SignListWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
-	case WE_PAINT: {
-		int y = 16; // offset from top of widget
-
-		if (_sign_sort_dirty)
-			GlobalSortSignList();
-
-		SetVScrollCount(w, _num_sign_sort);
+		case WE_PAINT: {
+			if (_sign_sort_dirty) GlobalSortSignList();
 
-		SetDParam(0, w->vscroll.count);
-		DrawWindowWidgets(w);
+			SetVScrollCount(w, _num_sign_sort);
 
-		/* No signs? */
-		if (w->vscroll.count == 0) {
-			DrawString(2, y, STR_304A_NONE, TC_FROMSTRING);
-			return;
-		}
+			SetDParam(0, w->vscroll.count);
+			DrawWindowWidgets(w);
 
-		{
-			uint16 i;
+			/* No signs? */
+			int y = 16; // offset from top of widget
+			if (w->vscroll.count == 0) {
+				DrawString(2, y, STR_304A_NONE, TC_FROMSTRING);
+				return;
+			}
 
 			/* Start drawing the signs */
-			for (i = w->vscroll.pos; i < w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) {
+			for (uint16 i = w->vscroll.pos; i < w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) {
 				const Sign *si = _sign_sort[i];
 
-				if (si->owner != OWNER_NONE)
-					DrawPlayerIcon(si->owner, 4, y + 1);
+				if (si->owner != OWNER_NONE) DrawPlayerIcon(si->owner, 4, y + 1);
 
 				SetDParam(0, si->index);
 				DrawString(22, y, STR_SIGN_NAME, TC_YELLOW);
 				y += 10;
 			}
-		}
-	} break;
-
-	case WE_CLICK: {
-		switch (e->we.click.widget) {
-		case 3: {
-			uint32 id_v = (e->we.click.pt.y - 15) / 10;
-			const Sign *si;
-
-			if (id_v >= w->vscroll.cap)
-				return;
+		} break;
 
-			id_v += w->vscroll.pos;
-
-			if (id_v >= w->vscroll.count)
-				return;
+		case WE_CLICK:
+			if (e->we.click.widget == 3) {
+				uint32 id_v = (e->we.click.pt.y - 15) / 10;
 
-			si = _sign_sort[id_v];
-			ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
-		} break;
-		}
-	} break;
+				if (id_v >= w->vscroll.cap) return;
+				id_v += w->vscroll.pos;
+				if (id_v >= w->vscroll.count) return;
 
-	case WE_RESIZE:
-		w->vscroll.cap += e->we.sizing.diff.y / 10;
-		break;
+				const Sign *si = _sign_sort[id_v];
+				ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+			}
+			break;
+
+		case WE_RESIZE:
+			w->vscroll.cap += e->we.sizing.diff.y / 10;
+			break;
 	}
 }
 
@@ -149,9 +135,7 @@
 
 void ShowSignList()
 {
-	Window *w;
-
-	w = AllocateWindowDescFront(&_sign_list_desc, 0);
+	Window *w = AllocateWindowDescFront(&_sign_list_desc, 0);
 	if (w != NULL) {
 		w->vscroll.cap = 12;
 		w->resize.step_height = 10;
@@ -159,8 +143,7 @@
 	}
 }
 
-/* Edit sign window stuff */
-
+/** Edit sign window stuff */
 struct editsign_d : querystr_d {
 	SignID cur_sign;
 };
@@ -314,13 +297,11 @@
 
 void ShowRenameSignWindow(const Sign *si)
 {
-	Window *w;
-
 	/* Delete all other edit windows and the save window */
 	DeleteWindowById(WC_QUERY_STRING, 0);
 	DeleteWindowById(WC_SAVELOAD, 0);
 
-	w = AllocateWindowDesc(&_query_sign_edit_desc);
+	Window *w = AllocateWindowDesc(&_query_sign_edit_desc);
 
 	WP(w, editsign_d).caption = STR_280B_EDIT_SIGN_TEXT;
 	WP(w, editsign_d).afilter = CS_ALPHANUMERAL;
@@ -328,6 +309,3 @@
 
 	UpdateSignEditWindow(w, si);
 }
-
-
-
--- a/src/station_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/station_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -2312,10 +2312,14 @@
 		}
 
 		SpriteID pal;
-		if (!(!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
-			pal = palette;
+		if (HasBit(image, PALETTE_MODIFIER_TRANSPARENT) || HasBit(image, PALETTE_MODIFIER_COLOR)) {
+			if (dtss->image.pal > 0) {
+				pal = dtss->image.pal;
+			} else {
+				pal = palette;
+			}
 		} else {
-			pal = dtss->image.pal;
+			pal = PAL_NONE;
 		}
 
 		if ((byte)dtss->delta_z != 0x80) {
@@ -2517,9 +2521,9 @@
 static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
 {
 	StationID station_id = GetStationIndex(tile);
-	if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
 
 	if (v->type == VEH_TRAIN) {
+		if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
 			DiagDirection dir = DirToDiagDir(v->direction);
@@ -2547,6 +2551,8 @@
 				RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
 
 				if (IsDriveThroughStopTile(tile)) {
+					if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
+
 					/* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */
 					byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
 
--- a/src/tgp.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/tgp.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -683,14 +683,6 @@
 }
 
 
-/* The following decimals are the octave power modifiers for the Perlin noise */
-static const double _perlin_p_values[][7] = {    // perlin frequency per power
-	{ 0.35, 0.35, 0.35, 0.35, 0.35, 0.25, 0.539 }, ///< Very smooth
-	{ 0.45, 0.55, 0.45, 0.45, 0.35, 0.25, 0.89  }, ///< Smooth
-	{ 0.85, 0.80, 0.70, 0.45, 0.45, 0.35, 1.825 }, ///< Rough 1.825
-	{ 0.95, 0.85, 0.80, 0.55, 0.55, 0.45, 2.245 }  //< Very Rough 2.25
-};
-
 /**
  * The Perlin Noise calculation using large primes
  * The initial number is adjusted by two values; the generation_seed, and the
--- a/src/timetable.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/timetable.h	Wed Apr 16 22:16:04 2008 +0000
@@ -7,5 +7,6 @@
 
 void ShowTimetableWindow(const Vehicle *v);
 void UpdateVehicleTimetable(Vehicle *v, bool travelling);
+void SetTimetableParams(int param1, int param2, uint32 time);
 
 #endif /* TIMETABLE_H */
--- a/src/timetable_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/timetable_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -16,6 +16,7 @@
 #include "string_func.h"
 #include "gfx_func.h"
 #include "player_func.h"
+#include "order_func.h"
 #include "settings_type.h"
 
 #include "table/strings.h"
@@ -57,7 +58,7 @@
 	return (sel <= v->num_orders * 2 && sel >= 0) ? sel : INVALID_ORDER;
 }
 
-static inline void SetTimetableParams(int param1, int param2, uint32 time)
+void SetTimetableParams(int param1, int param2, uint32 time)
 {
 	if (_patches.timetable_in_ticks) {
 		SetDParam(param1, STR_TIMETABLE_TICKS);
@@ -116,90 +117,7 @@
 		if (i - w->vscroll.pos >= w->vscroll.cap) break;
 
 		if (i % 2 == 0) {
-			SetDParam(5, STR_EMPTY);
-
-			switch (order->GetType()) {
-				case OT_DUMMY:
-					SetDParam(0, STR_INVALID_ORDER);
-					break;
-
-				case OT_GOTO_STATION:
-					SetDParam(0, STR_GO_TO_STATION);
-					SetDParam(1, STR_ORDER_GO_TO + order->GetNonStopType());
-					SetDParam(2, order->GetDestination());
-					SetDParam(3, STR_EMPTY);
-
-					if (order->wait_time > 0) {
-						SetDParam(5, STR_TIMETABLE_STAY_FOR);
-						SetTimetableParams(6, 7, order->wait_time);
-					} else {
-						SetDParam(4, STR_EMPTY);
-					}
-
-					break;
-
-				case OT_GOTO_DEPOT:
-					SetDParam(4, STR_EMPTY);
-					if (v->type == VEH_AIRCRAFT) {
-						if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
-							SetDParam(0, STR_GO_TO_NEAREST_DEPOT);
-							SetDParam(2, STR_ORDER_NEAREST_HANGAR);
-						} else {
-							SetDParam(0, STR_GO_TO_HANGAR);
-							SetDParam(2, order->GetDestination());
-						}
-						SetDParam(3, STR_EMPTY);
-					} else {
-						if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
-							SetDParam(0, STR_GO_TO_NEAREST_DEPOT);
-							SetDParam(2, STR_ORDER_NEAREST_DEPOT);
-						} else {
-							SetDParam(0, STR_GO_TO_DEPOT);
-							SetDParam(2, GetDepot(order->GetDestination())->town_index);
-						}
-
-						switch (v->type) {
-							case VEH_TRAIN: SetDParam(3, STR_ORDER_TRAIN_DEPOT); break;
-							case VEH_ROAD:  SetDParam(3, STR_ORDER_ROAD_DEPOT); break;
-							case VEH_SHIP:  SetDParam(3, STR_ORDER_SHIP_DEPOT); break;
-							default: NOT_REACHED();
-						}
-					}
-
-					if (order->GetDepotOrderType() & ODTFB_SERVICE) {
-						SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT);
-					} else {
-						SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO);
-					}
-					break;
-
-				case OT_GOTO_WAYPOINT:
-					SetDParam(0, (order->GetNonStopType() != ONSF_STOP_EVERYWHERE) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
-					SetDParam(1, order->GetDestination());
-					break;
-
-
-				case OT_CONDITIONAL:
-					SetDParam(1, order->GetConditionSkipToOrder() + 1);
-					if (order->GetConditionVariable() == OCV_UNCONDITIONALLY) {
-						SetDParam(0, STR_CONDITIONAL_UNCONDITIONAL);
-					} else {
-						extern uint ConvertSpeedToDisplaySpeed(uint speed);
-						OrderConditionComparator occ = order->GetConditionComparator();
-						SetDParam(0, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_CONDITIONAL_TRUE_FALSE : STR_CONDITIONAL_NUM);
-						SetDParam(2, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
-						SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
-
-						uint value = order->GetConditionValue();
-						if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
-						SetDParam(4, value);
-					}
-					break;
-
-				default: break;
-			}
-
-			DrawString(2, y, STR_TIMETABLE_GO_TO, (i == selected) ? TC_WHITE : TC_BLACK);
+			DrawOrderString(v, order, order_id, y, i == selected, true);
 
 			order_id++;
 
@@ -219,7 +137,7 @@
 				string = STR_TIMETABLE_TRAVEL_FOR;
 			}
 
-			DrawString(12, y, string, (i == selected) ? TC_WHITE : TC_BLACK);
+			DrawString(22, y, string, (i == selected) ? TC_WHITE : TC_BLACK);
 
 			if (final_order) break;
 		}
--- a/src/town_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/town_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -142,117 +142,118 @@
 static void TownAuthorityWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
-	case WE_PAINT: {
-		const Town *t = GetTown(w->window_number);
-		int numact;
-		uint buttons = GetMaskOfTownActions(&numact, _local_player, t);
-
-		SetVScrollCount(w, numact + 1);
-
-		if (WP(w, def_d).data_1 != -1 && !HasBit(buttons, WP(w,def_d).data_1))
-			WP(w, def_d).data_1 = -1;
-
-		w->SetWidgetDisabledState(6, WP(w, def_d).data_1 == -1);
-
-		{
-			int y;
-			const Player *p;
-			int r;
-			StringID str;
-
-			SetDParam(0, w->window_number);
-			DrawWindowWidgets(w);
-
-			DrawString(2, 15, STR_2023_TRANSPORT_COMPANY_RATINGS, TC_FROMSTRING);
+		case WE_PAINT: {
+			const Town *t = GetTown(w->window_number);
+			int numact;
+			uint buttons = GetMaskOfTownActions(&numact, _local_player, t);
 
-			/* Draw list of players */
-			y = 25;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active && (HasBit(t->have_ratings, p->index) || t->exclusivity == p->index)) {
-					DrawPlayerIcon(p->index, 2, y);
-
-					SetDParam(0, p->index);
-					SetDParam(1, p->index);
+			SetVScrollCount(w, numact + 1);
 
-					r = t->ratings[p->index];
-					(str = STR_3035_APPALLING, r <= RATING_APPALLING) || // Apalling
-					(str++,                    r <= RATING_VERYPOOR)  || // Very Poor
-					(str++,                    r <= RATING_POOR)      || // Poor
-					(str++,                    r <= RATING_MEDIOCRE)  || // Mediocore
-					(str++,                    r <= RATING_GOOD)      || // Good
-					(str++,                    r <= RATING_VERYGOOD)  || // Very Good
-					(str++,                    r <= RATING_EXCELLENT) || // Excellent
-					(str++,                    true);                    // Outstanding
+			if (WP(w, def_d).data_1 != -1 && !HasBit(buttons, WP(w,def_d).data_1))
+				WP(w, def_d).data_1 = -1;
 
-					SetDParam(2, str);
-					if (t->exclusivity == p->index) { // red icon for player with exclusive rights
-						DrawSprite(SPR_BLOT, PALETTE_TO_RED, 18, y);
+			w->SetWidgetDisabledState(6, WP(w, def_d).data_1 == -1);
+
+			{
+				int y;
+				const Player *p;
+				int r;
+				StringID str;
+
+				SetDParam(0, w->window_number);
+				DrawWindowWidgets(w);
+
+				DrawString(2, 15, STR_2023_TRANSPORT_COMPANY_RATINGS, TC_FROMSTRING);
+
+				/* Draw list of players */
+				y = 25;
+				FOR_ALL_PLAYERS(p) {
+					if (p->is_active && (HasBit(t->have_ratings, p->index) || t->exclusivity == p->index)) {
+						DrawPlayerIcon(p->index, 2, y);
+
+						SetDParam(0, p->index);
+						SetDParam(1, p->index);
+
+						r = t->ratings[p->index];
+						(str = STR_3035_APPALLING, r <= RATING_APPALLING) || // Apalling
+						(str++,                    r <= RATING_VERYPOOR)  || // Very Poor
+						(str++,                    r <= RATING_POOR)      || // Poor
+						(str++,                    r <= RATING_MEDIOCRE)  || // Mediocore
+						(str++,                    r <= RATING_GOOD)      || // Good
+						(str++,                    r <= RATING_VERYGOOD)  || // Very Good
+						(str++,                    r <= RATING_EXCELLENT) || // Excellent
+						(str++,                    true);                    // Outstanding
+
+						SetDParam(2, str);
+						if (t->exclusivity == p->index) { // red icon for player with exclusive rights
+							DrawSprite(SPR_BLOT, PALETTE_TO_RED, 18, y);
+						}
+
+						DrawString(28, y, STR_2024, TC_FROMSTRING);
+						y += 10;
 					}
-
-					DrawString(28, y, STR_2024, TC_FROMSTRING);
-					y += 10;
 				}
 			}
-		}
-
-		/* Draw actions list */
-		{
-			int y = 107, i;
-			int pos = w->vscroll.pos;
 
-			if (--pos < 0) {
-				DrawString(2, y, STR_2045_ACTIONS_AVAILABLE, TC_FROMSTRING);
-				y += 10;
-			}
-			for (i = 0; buttons; i++, buttons >>= 1) {
-				if (pos <= -5) break; ///< Draw only the 5 fitting lines
+			/* Draw actions list */
+			{
+				int y = 107, i;
+				int pos = w->vscroll.pos;
 
-				if ((buttons & 1) && --pos < 0) {
-					DrawString(3, y, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i, TC_ORANGE);
+				if (--pos < 0) {
+					DrawString(2, y, STR_2045_ACTIONS_AVAILABLE, TC_FROMSTRING);
 					y += 10;
 				}
+
+				for (i = 0; buttons; i++, buttons >>= 1) {
+					if (pos <= -5) break; ///< Draw only the 5 fitting lines
+
+					if ((buttons & 1) && --pos < 0) {
+						DrawString(3, y, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i, TC_ORANGE);
+						y += 10;
+					}
+				}
 			}
-		}
-
-		{
-			int i = WP(w, def_d).data_1;
-
-			if (i != -1) {
-				SetDParam(1, (_price.build_industry >> 8) * _town_action_costs[i]);
-				SetDParam(0, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i);
-				DrawStringMultiLine(2, 159, STR_204D_INITIATE_A_SMALL_LOCAL + i, 313);
-			}
-		}
-
-	} break;
 
-	case WE_DOUBLE_CLICK:
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-			case TWA_COMMAND_LIST: {
-				const Town *t = GetTown(w->window_number);
-				int y = (e->we.click.pt.y - 0x6B) / 10;
+			{
+				int i = WP(w, def_d).data_1;
 
-				if (!IsInsideMM(y, 0, 5)) return;
-
-				y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, t), y + w->vscroll.pos - 1);
-				if (y >= 0) {
-					WP(w, def_d).data_1 = y;
-					SetWindowDirty(w);
+				if (i != -1) {
+					SetDParam(1, (_price.build_industry >> 8) * _town_action_costs[i]);
+					SetDParam(0, STR_2046_SMALL_ADVERTISING_CAMPAIGN + i);
+					DrawStringMultiLine(2, 159, STR_204D_INITIATE_A_SMALL_LOCAL + i, 313);
 				}
-				/* Fall through to clicking in case we are double-clicked */
-				if (e->event != WE_DOUBLE_CLICK || y < 0) break;
 			}
 
-			case TWA_EXECUTE:
-				DoCommandP(GetTown(w->window_number)->xy, w->window_number, WP(w, def_d).data_1, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
-				break;
-		}
-		break;
+		} break;
 
-	case WE_4:
-		SetWindowDirty(w);
-		break;
+		case WE_DOUBLE_CLICK:
+		case WE_CLICK:
+			switch (e->we.click.widget) {
+				case TWA_COMMAND_LIST: {
+					const Town *t = GetTown(w->window_number);
+					int y = (e->we.click.pt.y - 0x6B) / 10;
+
+					if (!IsInsideMM(y, 0, 5)) return;
+
+					y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, t), y + w->vscroll.pos - 1);
+					if (y >= 0) {
+						WP(w, def_d).data_1 = y;
+						SetWindowDirty(w);
+					}
+					/* Fall through to clicking in case we are double-clicked */
+					if (e->event != WE_DOUBLE_CLICK || y < 0) break;
+				}
+
+				case TWA_EXECUTE:
+					DoCommandP(GetTown(w->window_number)->xy, w->window_number, WP(w, def_d).data_1, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
+					break;
+			}
+			break;
+
+		case WE_4:
+			SetWindowDirty(w);
+			break;
 	}
 }
 
@@ -274,68 +275,78 @@
 	}
 }
 
+
+enum TownViewWidget {
+	TVW_CAPTION = 1,
+	TVW_CENTERVIEW = 6,
+	TVW_SHOWAUTORITY,
+	TVW_CHANGENAME,
+	TVW_EXPAND,
+	TVW_DELETE,
+};
+
 static void TownViewWndProc(Window *w, WindowEvent *e)
 {
 	Town *t = GetTown(w->window_number);
 
 	switch (e->event) {
-	case WE_CREATE:
-		if (t->larger_town) w->widget[1].data = STR_CITY;
-		break;
-
-	case WE_PAINT:
-		/* disable renaming town in network games if you are not the server */
-		w->SetWidgetDisabledState(8, _networking && !_network_server);
-
-		SetDParam(0, t->index);
-		DrawWindowWidgets(w);
-
-		SetDParam(0, t->population);
-		SetDParam(1, t->num_houses);
-		DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING);
-
-		SetDParam(0, t->act_pass);
-		SetDParam(1, t->max_pass);
-		DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING);
-
-		SetDParam(0, t->act_mail);
-		SetDParam(1, t->max_mail);
-		DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING);
-
-		DrawWindowViewport(w);
-		break;
+		case WE_CREATE:
+			if (t->larger_town) w->widget[TVW_CAPTION].data = STR_CITY;
+			break;
 
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-			case 6: /* scroll to location */
-				ScrollMainWindowToTile(t->xy);
-				break;
-
-			case 7: /* town authority */
-				ShowTownAuthorityWindow(w->window_number);
-				break;
-
-			case 8: /* rename */
-				SetDParam(0, w->window_number);
-				ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, w, CS_ALPHANUMERAL);
-				break;
+		case WE_PAINT:
+			/* disable renaming town in network games if you are not the server */
+			w->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server);
 
-			case 9: /* expand town */
-				ExpandTown(t);
-				break;
+			SetDParam(0, t->index);
+			DrawWindowWidgets(w);
 
-			case 10: /* delete town */
-				delete t;
-				break;
-		} break;
+			SetDParam(0, t->population);
+			SetDParam(1, t->num_houses);
+			DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING);
 
-	case WE_ON_EDIT_TEXT:
-		if (e->we.edittext.str[0] != '\0') {
-			_cmd_text = e->we.edittext.str;
-			DoCommandP(0, w->window_number, 0, NULL,
-				CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
-		}
-		break;
+			SetDParam(0, t->act_pass);
+			SetDParam(1, t->max_pass);
+			DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING);
+
+			SetDParam(0, t->act_mail);
+			SetDParam(1, t->max_mail);
+			DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING);
+
+			DrawWindowViewport(w);
+			break;
+
+		case WE_CLICK:
+			switch (e->we.click.widget) {
+				case TVW_CENTERVIEW: /* scroll to location */
+					ScrollMainWindowToTile(t->xy);
+					break;
+
+				case TVW_SHOWAUTORITY: /* town authority */
+					ShowTownAuthorityWindow(w->window_number);
+					break;
+
+				case TVW_CHANGENAME: /* rename */
+					SetDParam(0, w->window_number);
+					ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, w, CS_ALPHANUMERAL);
+					break;
+
+				case TVW_EXPAND: /* expand town - only available on Scenario editor */
+					ExpandTown(t);
+					break;
+
+				case TVW_DELETE: /* delete town - only available on Scenario editor */
+					delete t;
+					break;
+			} break;
+
+		case WE_ON_EDIT_TEXT:
+			if (e->we.edittext.str[0] != '\0') {
+				_cmd_text = e->we.edittext.str;
+				DoCommandP(0, w->window_number, 0, NULL,
+					CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
+			}
+			break;
 	}
 }
 
@@ -480,79 +491,79 @@
 static void TownDirectoryWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
-	case WE_PAINT: {
-		if (_town_sort_dirty) {
-			_town_sort_dirty = false;
-			MakeSortedTownList();
-		}
-
-		SetVScrollCount(w, _num_town_sort);
-
-		DrawWindowWidgets(w);
-		DrawSortButtonState(w, (_town_sort_order <= 1) ? TDW_SORTNAME : TDW_SORTPOPULATION, _town_sort_order & 1 ? SBS_DOWN : SBS_UP);
-
-		{
-			int n = 0;
-			uint16 i = w->vscroll.pos;
-			int y = 28;
-
-			while (i < _num_town_sort) {
-				const Town* t = _town_sort[i];
-
-				assert(t->xy);
-
-				SetDParam(0, t->index);
-				SetDParam(1, t->population);
-				DrawString(2, y, STR_2057, TC_FROMSTRING);
-
-				y += 10;
-				i++;
-				if (++n == w->vscroll.cap) break; // max number of towns in 1 window
+		case WE_PAINT: {
+			if (_town_sort_dirty) {
+				_town_sort_dirty = false;
+				MakeSortedTownList();
 			}
-			SetDParam(0, GetWorldPopulation());
-			DrawString(3, w->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING);
-		}
-	} break;
 
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-			case TDW_SORTNAME: { /* Sort by Name ascending/descending */
-				_town_sort_order = (_town_sort_order == 0) ? 1 : 0;
-				_town_sort_dirty = true;
-				SetWindowDirty(w);
-			} break;
-
-			case TDW_SORTPOPULATION: { /* Sort by Population ascending/descending */
-				_town_sort_order = (_town_sort_order == 2) ? 3 : 2;
-				_town_sort_dirty = true;
-				SetWindowDirty(w);
-			} break;
-
-			case TDW_CENTERTOWN: { /* Click on Town Matrix */
-				const Town* t;
-
-				uint16 id_v = (e->we.click.pt.y - 28) / 10;
+			SetVScrollCount(w, _num_town_sort);
 
-				if (id_v >= w->vscroll.cap) return; // click out of bounds
-
-				id_v += w->vscroll.pos;
-
-				if (id_v >= _num_town_sort) return; // click out of town bounds
+			DrawWindowWidgets(w);
+			DrawSortButtonState(w, (_town_sort_order <= 1) ? TDW_SORTNAME : TDW_SORTPOPULATION, _town_sort_order & 1 ? SBS_DOWN : SBS_UP);
 
-				t = _town_sort[id_v];
-				assert(t->xy);
-				ScrollMainWindowToTile(t->xy);
-			} break;
-		}
-		break;
+			{
+				int n = 0;
+				uint16 i = w->vscroll.pos;
+				int y = 28;
 
-	case WE_4:
-		SetWindowDirty(w);
-		break;
+				while (i < _num_town_sort) {
+					const Town* t = _town_sort[i];
 
-	case WE_RESIZE:
-		w->vscroll.cap += e->we.sizing.diff.y / 10;
-		break;
+					assert(t->xy);
+
+					SetDParam(0, t->index);
+					SetDParam(1, t->population);
+					DrawString(2, y, STR_2057, TC_FROMSTRING);
+
+					y += 10;
+					i++;
+					if (++n == w->vscroll.cap) break; // max number of towns in 1 window
+				}
+				SetDParam(0, GetWorldPopulation());
+				DrawString(3, w->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING);
+			}
+		} break;
+
+		case WE_CLICK:
+			switch (e->we.click.widget) {
+				case TDW_SORTNAME: /* Sort by Name ascending/descending */
+					_town_sort_order = (_town_sort_order == 0) ? 1 : 0;
+					_town_sort_dirty = true;
+					SetWindowDirty(w);
+					break;
+
+				case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */
+					_town_sort_order = (_town_sort_order == 2) ? 3 : 2;
+					_town_sort_dirty = true;
+					SetWindowDirty(w);
+					break;
+
+				case TDW_CENTERTOWN: { /* Click on Town Matrix */
+					const Town* t;
+
+					uint16 id_v = (e->we.click.pt.y - 28) / 10;
+
+					if (id_v >= w->vscroll.cap) return; // click out of bounds
+
+					id_v += w->vscroll.pos;
+
+					if (id_v >= _num_town_sort) return; // click out of town bounds
+
+					t = _town_sort[id_v];
+					assert(t->xy);
+					ScrollMainWindowToTile(t->xy);
+				} break;
+			}
+			break;
+
+		case WE_4:
+			SetWindowDirty(w);
+			break;
+
+		case WE_RESIZE:
+			w->vscroll.cap += e->we.sizing.diff.y / 10;
+			break;
 	}
 }
 
@@ -591,6 +602,16 @@
 	DoCommandP(tile, size, mode, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
 }
 
+enum TownScenarioEditorWidget {
+	TSEW_NEWTOWN = 4,
+	TSEW_RANDOMTOWN,
+	TSEW_MANYRANDOMTOWNS,
+	TSEW_SMALLTOWN,
+	TSEW_MEDIUMTOWN,
+	TSEW_LARGETOWN,
+	TSEW_CITY,
+};
+
 static const Widget _scen_edit_town_gen_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   147,     0,    13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -610,68 +631,68 @@
 static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
-	case WE_PAINT:
-		DrawWindowWidgets(w);
-		break;
-
-	case WE_CREATE:
-		w->LowerWidget(_scengen_town_size + 7);
-		break;
-
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-		case 4: // new town
-			HandlePlacePushButton(w, 4, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town);
+		case WE_PAINT:
+			DrawWindowWidgets(w);
 			break;
-		case 5: {// random town
-			Town *t;
-			uint size = min(_scengen_town_size, (int)TSM_CITY);
-			TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
 
-			w->HandleButtonClick(5);
-			_generating_world = true;
-			t = CreateRandomTown(20, mode, size);
-			_generating_world = false;
-
-			if (t == NULL) {
-				ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
-			} else {
-				ScrollMainWindowToTile(t->xy);
-			}
-
+		case WE_CREATE:
+			w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
 			break;
-		}
-		case 6: {// many random towns
-			w->HandleButtonClick(6);
 
-			_generating_world = true;
-			if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
-			_generating_world = false;
-			break;
-		}
+		case WE_CLICK:
+			switch (e->we.click.widget) {
+				case TSEW_NEWTOWN:
+					HandlePlacePushButton(w, TSEW_NEWTOWN, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town);
+					break;
 
-		case 7: case 8: case 9: case 10:
-			w->RaiseWidget(_scengen_town_size + 7);
-			_scengen_town_size = e->we.click.widget - 7;
-			w->LowerWidget(_scengen_town_size + 7);
+				case TSEW_RANDOMTOWN: {
+					Town *t;
+					uint size = min(_scengen_town_size, (int)TSM_CITY);
+					TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
+
+					w->HandleButtonClick(TSEW_RANDOMTOWN);
+					_generating_world = true;
+					t = CreateRandomTown(20, mode, size);
+					_generating_world = false;
+
+					if (t == NULL) {
+						ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
+					} else {
+						ScrollMainWindowToTile(t->xy);
+					}
+				} break;
+
+				case TSEW_MANYRANDOMTOWNS:
+					w->HandleButtonClick(TSEW_MANYRANDOMTOWNS);
+
+					_generating_world = true;
+					if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
+					_generating_world = false;
+					break;
+
+				case TSEW_SMALLTOWN: case TSEW_MEDIUMTOWN: case TSEW_LARGETOWN: case TSEW_CITY:
+					w->RaiseWidget(_scengen_town_size + TSEW_SMALLTOWN);
+					_scengen_town_size = e->we.click.widget - TSEW_SMALLTOWN;
+					w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
+					SetWindowDirty(w);
+					break;
+			} break;
+
+		case WE_TIMEOUT:
+			w->RaiseWidget(TSEW_RANDOMTOWN);
+			w->RaiseWidget(TSEW_MANYRANDOMTOWNS);
 			SetWindowDirty(w);
 			break;
-		}
-		break;
 
-	case WE_TIMEOUT:
-		w->RaiseWidget(5);
-		w->RaiseWidget(6);
-		SetWindowDirty(w);
-		break;
-	case WE_PLACE_OBJ:
-		_place_proc(e->we.place.tile);
-		break;
-	case WE_ABORT_PLACE_OBJ:
-		w->RaiseButtons();
-		w->LowerWidget(_scengen_town_size + 7);
-		SetWindowDirty(w);
-		break;
+		case WE_PLACE_OBJ:
+			_place_proc(e->we.place.tile);
+			break;
+
+		case WE_ABORT_PLACE_OBJ:
+			w->RaiseButtons();
+			w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
+			SetWindowDirty(w);
+			break;
 	}
 }
 
--- a/src/train_cmd.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/train_cmd.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -2563,7 +2563,14 @@
 {
 	if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
 
-	return GetStation(station)->xy;
+	const Station *st = GetStation(station);
+	if (!(st->facilities & FACIL_TRAIN)) {
+		/* The destination station has no trainstation tiles. */
+		this->cur_order_index++;
+		return 0;
+	}
+
+	return st->xy;
 }
 
 void Train::MarkDirty()
--- a/src/vehicle.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/vehicle.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -137,7 +137,7 @@
 {
 	if (_patches.gotodepot && VehicleHasDepotOrders(this)) return false;
 	if (this->current_order.IsType(OT_LOADING))            return false;
-	if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotActionType() & ODATFB_HALT) return false;
+	if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
 	return NeedsServicing();
 }
 
--- a/src/vehicle_gui.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/vehicle_gui.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -1990,7 +1990,7 @@
 
 			case OT_LEAVESTATION:
 				if (v->type != VEH_AIRCRAFT) {
-					str = STR_882F_LOADING_UNLOADING;
+					str = STR_LEAVING;
 					break;
 				}
 				/* fall-through if aircraft. Does this even happen? */
--- a/src/viewport.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/viewport.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -28,7 +28,7 @@
 #include "player_func.h"
 #include "settings_type.h"
 #include "station_func.h"
-#include "core/alloc_func.hpp"
+#include "core/alloc_type.hpp"
 
 #include "table/sprites.h"
 #include "table/strings.h"
--- a/src/widgets/dropdown.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/widgets/dropdown.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -36,6 +36,11 @@
 	return this->string;
 }
 
+void DropDownListItem::Draw(int x, int y, uint width, uint height, bool sel) const
+{
+	DrawStringTruncated(x + 2, y, this->String(), sel ? TC_WHITE : TC_BLACK, x + width);
+}
+
 /**
  * Delete all items of a drop down list and the list itself
  * @param list List to delete.
@@ -122,7 +127,7 @@
 					if (item->String() != STR_NULL) {
 						if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + item_height - 1, 0);
 
-						DrawStringTruncated(x + 2, y, item->String(), sel == item->result ? TC_WHITE : TC_BLACK, x + width);
+						item->Draw(x, y, width, 10, sel == item->result);
 
 						if (item->masked) {
 							GfxFillRect(x, y, x + width, y + item_height - 1,
--- a/src/widgets/dropdown_type.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/widgets/dropdown_type.h	Wed Apr 16 22:16:04 2008 +0000
@@ -19,6 +19,7 @@
 	virtual ~DropDownListItem() {}
 	virtual StringID String() const;
 	virtual uint Height(uint width) const;
+	virtual void Draw(int x, int y, uint width, uint height, bool sel) const;
 };
 
 /**
--- a/src/window.cpp	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/window.cpp	Wed Apr 16 22:16:04 2008 +0000
@@ -22,17 +22,15 @@
 
 #include "table/sprites.h"
 
-/** delta between mouse cursor and upper left corner of dragged window */
-static Point _drag_delta;
-
-static Window _windows[MAX_NUMBER_OF_WINDOWS];
+static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window
+static Window *_mouseover_last_w = NULL; ///< Window of the last MOUSEOVER event
 
 /**
  * List of windows opened at the screen.
  * Uppermost window is at  _z_windows[_last_z_window - 1],
  * bottom window is at _z_windows[0]
  */
-Window *_z_windows[lengthof(_windows)];
+Window *_z_windows[MAX_NUMBER_OF_WINDOWS];
 Window **_last_z_window; ///< always points to the next free space in the z-array
 
 Point _cursorpos_drag_start;
@@ -250,33 +248,6 @@
 	}
 }
 
-static void DrawOverlappedWindow(Window* const *wz, int left, int top, int right, int bottom);
-
-/**
- * From a rectangle that needs redrawing, find the windows that intersect with the rectangle.
- * These windows should be re-painted.
- * @param left Left edge of the rectangle that should be repainted
- * @param top Top edge of the rectangle that should be repainted
- * @param right Right edge of the rectangle that should be repainted
- * @param bottom Bottom edge of the rectangle that should be repainted
- */
-void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
-{
-	Window* const *wz;
-	DrawPixelInfo bk;
-	_cur_dpi = &bk;
-
-	FOR_ALL_WINDOWS(wz) {
-		const Window *w = *wz;
-		if (right > w->left &&
-				bottom > w->top &&
-				left < w->left + w->width &&
-				top < w->top + w->height) {
-			DrawOverlappedWindow(wz, left, top, right, bottom);
-		}
-	}
-}
-
 /**
  * Generate repaint events for the visible part of window *wz within the rectangle.
  *
@@ -288,8 +259,6 @@
  * @param top Top edge of the rectangle that should be repainted
  * @param right Right edge of the rectangle that should be repainted
  * @param bottom Bottom edge of the rectangle that should be repainted
- *
- * @todo Swap this function to above DrawOverlappedWindowForAll() to eliminate the forward declaration
  */
 static void DrawOverlappedWindow(Window* const *wz, int left, int top, int right, int bottom)
 {
@@ -333,16 +302,39 @@
 		}
 	}
 
-	{
-		DrawPixelInfo *dp = _cur_dpi;
-		dp->width = right - left;
-		dp->height = bottom - top;
-		dp->left = left - (*wz)->left;
-		dp->top = top - (*wz)->top;
-		dp->pitch = _screen.pitch;
-		dp->dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
-		dp->zoom = ZOOM_LVL_NORMAL;
-		CallWindowEventNP(*wz, WE_PAINT);
+	DrawPixelInfo *dp = _cur_dpi;
+	dp->width = right - left;
+	dp->height = bottom - top;
+	dp->left = left - (*wz)->left;
+	dp->top = top - (*wz)->top;
+	dp->pitch = _screen.pitch;
+	dp->dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
+	dp->zoom = ZOOM_LVL_NORMAL;
+	CallWindowEventNP(*wz, WE_PAINT);
+}
+
+/**
+ * From a rectangle that needs redrawing, find the windows that intersect with the rectangle.
+ * These windows should be re-painted.
+ * @param left Left edge of the rectangle that should be repainted
+ * @param top Top edge of the rectangle that should be repainted
+ * @param right Right edge of the rectangle that should be repainted
+ * @param bottom Bottom edge of the rectangle that should be repainted
+ */
+void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
+{
+	Window* const *wz;
+	DrawPixelInfo bk;
+	_cur_dpi = &bk;
+
+	FOR_ALL_WINDOWS(wz) {
+		const Window *w = *wz;
+		if (right > w->left &&
+				bottom > w->top &&
+				left < w->left + w->width &&
+				top < w->top + w->height) {
+			DrawOverlappedWindow(wz, left, top, right, bottom);
+		}
 	}
 }
 
@@ -430,12 +422,17 @@
 	w->widget_count = 0;
 	w->parent = NULL;
 
+	/* Prevent Mouseover() from resetting mouse-over coordinates on a non-existing window */
+	if (_mouseover_last_w == w) _mouseover_last_w = NULL;
+
 	/* Find the window in the z-array, and effectively remove it
 	 * by moving all windows after it one to the left */
 	Window **wz = FindWindowZPosition(w);
 	if (wz == NULL) return;
 	memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
 	_last_z_window--;
+
+	delete w;
 }
 
 /**
@@ -658,28 +655,6 @@
 	}
 }
 
-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
@@ -700,17 +675,18 @@
 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();
+	Window *w;
 
 	/* We have run out of windows, close one and use that as the place for our new one */
-	if (w == NULL) {
+	if (_last_z_window == endof(_z_windows)) {
 		w = FindDeletableWindow();
 		if (w == NULL) w = ForceFindDeletableWindow();
 		DeleteWindow(w);
 	}
 
+	w = new Window;
+
 	/* 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;
@@ -1053,16 +1029,21 @@
 	return NULL;
 }
 
+/**
+ * (re)initialize the windowing system
+ */
 void InitWindowSystem()
 {
 	IConsoleClose();
 
-	memset(&_windows, 0, sizeof(_windows));
 	_last_z_window = _z_windows;
 	InitViewports();
 	_no_scroll = 0;
 }
 
+/**
+ * Close down the windowing system
+ */
 void UnInitWindowSystem()
 {
 	Window **wz;
@@ -1081,6 +1062,9 @@
 	assert(_last_z_window == _z_windows);
 }
 
+/**
+ * Reset the windowing system, by means of shutting it down followed by re-initialization
+ */
 void ResetWindowSystem()
 {
 	UnInitWindowSystem();
@@ -1195,20 +1179,21 @@
 
 static bool HandleMouseOver()
 {
-	Window *w;
 	WindowEvent e;
-	static Window *last_w = NULL;
 
-	w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
+	Window *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) {
+	if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
+		/* Reset mouse-over coordinates of previous window */
 		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 != NULL) _mouseover_last_w->wndproc(_mouseover_last_w, &e);
 	}
-	last_w = w;
+
+	/* _mouseover_last_w will get reset when the window is deleted, see DeleteWindow() */
+	_mouseover_last_w = w;
 
 	if (w != NULL) {
 		/* send an event in client coordinates. */
--- a/src/window_gui.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/window_gui.h	Wed Apr 16 22:16:04 2008 +0000
@@ -10,6 +10,7 @@
 #include "viewport_type.h"
 #include "player_type.h"
 #include "strings_type.h"
+#include "core/alloc_type.hpp"
 
 /**
  * The maximum number of windows that can be opened.
@@ -289,7 +290,7 @@
 /**
  * Data structure for an opened window
  */
-struct Window {
+struct Window : ZeroedMemoryAllocator {
 	uint16 flags4;              ///< Window flags, @see WindowFlags
 	WindowClass window_class;   ///< Window class
 	WindowNumber window_number; ///< Window number within the window class
@@ -307,7 +308,7 @@
 	byte caption_color; ///< Background color of the window caption, contains PlayerID
 
 	WindowProc *wndproc;   ///< Event handler function for the window
-	ViewPort *viewport;    ///< Pointer to viewport, if present (structure is part of derived class)
+	ViewPort *viewport;    ///< Pointer to viewport, if present
 	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
--- a/src/window_type.h	Wed Apr 16 00:07:47 2008 +0000
+++ b/src/window_type.h	Wed Apr 16 22:16:04 2008 +0000
@@ -7,6 +7,9 @@
 
 #include "core/enum_type.hpp"
 
+/**
+ * Window classes
+ */
 enum WindowClass {
 	WC_NONE,
 	WC_MAIN_WINDOW = WC_NONE,