(svn r13281) [NewGRF_ports] -Sync: with trunk r13145:13280. Includes support for Noise Level on Prop 24 in .grf files. NewGRF_ports
authorrichk
Tue, 27 May 2008 00:50:55 +0000
branchNewGRF_ports
changeset 10731 67db0d431d5e
parent 10724 68a692eacf22
child 10991 d8811e327d12
(svn r13281) [NewGRF_ports] -Sync: with trunk r13145:13280. Includes support for Noise Level on Prop 24 in .grf files.
bin/data/airportsbasic.grf
bin/data/airportsextended.grf
bin/data/seaplaneport.grf
bin/data/sprites/airportsbasic.nfo
bin/data/sprites/airportsextended.nfo
bin/data/sprites/seaplaneport.nfo
docs/NewGRFAirports.doc
projects/openttd_vs80.vcproj
projects/openttd_vs90.vcproj
source.list
src/ai/ai.cpp
src/ai/ai.h
src/ai/default/default.cpp
src/ai/trolly/trolly.cpp
src/aircraft_cmd.cpp
src/airport.h
src/airport_gui.cpp
src/autoreplace_cmd.cpp
src/autoreplace_gui.cpp
src/autoslope.h
src/blitter/factory.hpp
src/bridge_gui.cpp
src/build_vehicle_gui.cpp
src/cheat_gui.cpp
src/clear_cmd.cpp
src/command.cpp
src/command_type.h
src/console.cpp
src/console.h
src/console_cmds.cpp
src/console_func.h
src/console_gui.cpp
src/console_gui.h
src/console_internal.h
src/console_type.h
src/core/bitmath_func.hpp
src/currency.cpp
src/currency.h
src/date.cpp
src/debug.cpp
src/depot_gui.cpp
src/disaster_cmd.cpp
src/dock_gui.cpp
src/dummy_land.cpp
src/economy.cpp
src/elrail_func.h
src/engine.cpp
src/engine_gui.cpp
src/genworld.cpp
src/genworld_gui.cpp
src/gfx.cpp
src/gfxinit.cpp
src/graph_gui.cpp
src/group_gui.cpp
src/heightmap.cpp
src/industry.h
src/industry_cmd.cpp
src/industry_gui.cpp
src/intro_gui.cpp
src/landscape.cpp
src/lang/english.txt
src/main_gui.cpp
src/misc.cpp
src/misc/smallvec.h
src/misc_cmd.cpp
src/misc_gui.cpp
src/music_gui.cpp
src/network/network.cpp
src/network/network_client.cpp
src/network/network_data.h
src/network/network_gui.cpp
src/network/network_server.cpp
src/network/network_udp.cpp
src/newgrf.cpp
src/newgrf_commons.cpp
src/newgrf_engine.cpp
src/newgrf_gui.cpp
src/newgrf_town.cpp
src/news_gui.cpp
src/news_type.h
src/npf.cpp
src/oldloader.cpp
src/openttd.cpp
src/order_cmd.cpp
src/order_gui.cpp
src/osk_gui.cpp
src/pathfind.cpp
src/player_gui.cpp
src/players.cpp
src/querystring_gui.h
src/rail.cpp
src/rail_cmd.cpp
src/rail_gui.cpp
src/road.cpp
src/road_cmd.cpp
src/road_gui.cpp
src/road_internal.h
src/road_map.h
src/roadveh_cmd.cpp
src/saveload.cpp
src/saveload.h
src/settings.cpp
src/settings_func.h
src/settings_gui.cpp
src/settings_internal.h
src/settings_type.h
src/ship_cmd.cpp
src/signal.cpp
src/signs_gui.cpp
src/smallmap_gui.cpp
src/sortlist_type.h
src/station.cpp
src/station_cmd.cpp
src/station_func.h
src/station_gui.cpp
src/station_gui.h
src/station_map.h
src/station_type.h
src/statusbar_gui.cpp
src/strings.cpp
src/subsidy_gui.cpp
src/terraform_cmd.cpp
src/terraform_gui.cpp
src/textbuf_gui.h
src/texteff.cpp
src/tgp.cpp
src/tile_cmd.h
src/tilehighlight_func.h
src/timetable_cmd.cpp
src/timetable_gui.cpp
src/toolbar_gui.cpp
src/town.h
src/town_cmd.cpp
src/town_gui.cpp
src/town_type.h
src/train_cmd.cpp
src/train_gui.cpp
src/transparency_gui.cpp
src/tree_cmd.cpp
src/tree_gui.cpp
src/tunnelbridge_cmd.cpp
src/unmovable_cmd.cpp
src/vehicle.cpp
src/vehicle_base.h
src/vehicle_func.h
src/vehicle_gui.cpp
src/vehicle_gui.h
src/vehicle_type.h
src/video/cocoa/event.mm
src/video/dedicated_v.cpp
src/viewport.cpp
src/water_cmd.cpp
src/waypoint.cpp
src/widgets/dropdown.cpp
src/window.cpp
src/window_gui.h
src/window_type.h
src/yapf/yapf_base.hpp
src/yapf/yapf_rail.cpp
src/yapf/yapf_road.cpp
src/yapf/yapf_settings.h
src/yapf/yapf_ship.cpp
Binary file bin/data/airportsbasic.grf has changed
Binary file bin/data/airportsextended.grf has changed
Binary file bin/data/seaplaneport.grf has changed
--- a/bin/data/sprites/airportsbasic.nfo	Mon May 26 20:45:25 2008 +0000
+++ b/bin/data/sprites/airportsbasic.nfo	Tue May 27 00:50:55 2008 +0000
@@ -40,7 +40,7 @@
 //        Small Airport
 //----------------------------
 // 11 properties to change, 1 station to change, station id = 0
-   15 * 656	 00 0D 0B 01 00
+   15 * 656	 00 0D 0C 01 00
 
 // Class ID
 	08 "SMLL"
@@ -263,12 +263,15 @@
 // Prop22 Catchment Area
 		22 04
 
+// Prop24 Noise Level
+		24 03
+
 
 //------------------------------
 // Large Airport
 //------------------------------
 // 11 properties to change, 1 airport to change, airport id = 1
-   16 * 1086	 00 0D 0B 01 01
+   16 * 1086	 00 0D 0C 01 01
 
 // Class ID
 	08 "LRGE"
@@ -649,6 +652,9 @@
 // Prop22 Catchment Area
 		22 05
 
+// Prop24 Noise Level
+		24 05
+
 //availability date varaction2
 //small airport available from 1927 (1920+7) to 1964 (1920+44)
    17 * 14	 02 0D
@@ -695,7 +701,7 @@
 // Heliport
 //------------------------------
 // 10 properties to change, 1 airport to change, airport id = 2
-   23 * 204	 00 0D 0A 01 02
+   23 * 204	 00 0D 0B 01 02
 
 // Class ID
 	08 "HELI"
@@ -787,6 +793,9 @@
 // Prop22 Catchment area
 		22 04
 
+// Prop24 Noise Level
+		24 01
+
 //availability date varaction2
 //large airport available from 1975 (1920+55) to 2175 (1920+255)
    24 * 14	 02 0D
@@ -814,7 +823,7 @@
 //-------------------------
 
 // 10 properties to change, 1 station to change, station id = 3
-   27 * 189	 00 0D 09 01 03
+   27 * 189	 00 0D 0A 01 03
 
 // Class ID
 	08 "SYST"
@@ -895,6 +904,9 @@
 // Prop22 Catchment Area
 		22 03
 
+// Prop24 Noise Level
+		24 00
+
 //availability date varaction2
 //Oilrig available from 1920 (1920+00) to 2175 (1920+255)
    28 * 14	 02 0D
@@ -923,7 +935,7 @@
 //-------------------------
 
 // 10 properties to change, 1 station to change, station id = 4
-   31 * 87	 00 0D 06 01 04
+   31 * 87	 00 0D 07 01 04
 
 // Class ID
 	08 "SYST"
@@ -965,6 +977,9 @@
 // Prop20 Port Subtype
 		20 0F
 
+// Prop24 Noise Level
+		24 00
+
 	// Use graphics ID (1 station, ID 0, 3 cargo specific graphics, default cargo = 0)
    32 * 7	 03 0D 01 04 00 00 00
 
--- a/bin/data/sprites/airportsextended.nfo	Mon May 26 20:45:25 2008 +0000
+++ b/bin/data/sprites/airportsextended.nfo	Tue May 27 00:50:55 2008 +0000
@@ -167,7 +167,7 @@
 //Commuter Airport
 
 // 10 properties to change, 1 station to change, station id = 0
-  140 * 1191	 00 0D 0C 01 00
+  140 * 1191	 00 0D 0D 01 00
 // Class ID
 	08 "SMLL"
 // Sprite layout, of 23 sprites
@@ -550,6 +550,9 @@
 // Prop22 Catchment Area
 		22 04
 
+// Prop24 Noise Level
+		24 04
+
 //availability date varaction2
 //commuter airport available from 1981 (1920+61) to 2175 (1920+255)
   141 * 14	 02 0D
@@ -578,7 +581,7 @@
 //-------------------------
 
 // 11 properties to change, 1 station to change, station id = 01
-  144 * 935	 00 0D 0B 01 01
+  144 * 935	 00 0D 0C 01 01
 
 // Class ID
 	08 "LRGE"
@@ -894,6 +897,9 @@
 // Prop22 Catchment Area
 		22 06
 
+// Prop24 Noise Level
+		24 08
+
 //availability date varaction2
 //Metropolitan Airport available from 1980 (1920+60) to 2175 (1920+255)
   145 * 14	 02 0D
@@ -923,7 +929,7 @@
 
 // 12 properties to change, 1 station to change, station id = 02
 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 1768.)
-  148 * 1768	 00 0D 0C 01 02
+  148 * 1768	 00 0D 0D 01 02
 
 // Class ID
 	08 "INTL"
@@ -1415,6 +1421,9 @@
 // Prop22 Catchment Area
 		22 08
 
+// Prop24 Noise Level
+		24 11
+
 //availability date varaction2
 //International Airport available from 1994 (1920+74) to 2175 (1920+255)
   149 * 14	 02 0D
@@ -1443,7 +1452,7 @@
 //-------------------------
 
 // 11 properties to change, 1 station to change, station id = nn
-  152 * 817	 00 0D 0B 01 03
+  152 * 817	 00 0D 0C 01 03
 
 // Class ID
 	08 "HELI"
@@ -1688,6 +1697,9 @@
 // Prop22 Catchment Area
 		22 04
 
+// Prop24 Noise Level
+		24 02
+
 //availability date varaction2
 //Helidepot available from 1981 (1920+61) to 2175 (1920+255)
   153 * 14	 02 0D
@@ -1718,7 +1730,7 @@
 
 // 12 properties to change, 1 station to change, station id = 04
 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 2395.)
-  156 * 2395	 00 0D 0C 01 04
+  156 * 2395	 00 0D 0D 01 04
 
 // Class ID
 	08 "INTL"
@@ -2424,6 +2436,9 @@
 // Prop22 Catchment Area
 		22 0A
 
+// Prop24 Noise Level
+		24 19
+
 //availability date varaction2
 //Intercontinental Airport available from 2003 (1920+83) to 2175 (1920+255)
   157 * 14	 02 0D
@@ -2453,7 +2468,7 @@
 
 // 11 properties to change, 1 station to change, station id = 05
 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 876.)
-  160 * 876	 00 0D 0B 01 05
+  160 * 876	 00 0D 0C 01 05
 
 // Class ID
 	08 "HELI"
@@ -2734,6 +2749,9 @@
 // Prop22 Catchment Area
 		22 04
 
+// Prop24 Noise Level
+		24 03
+
 //availability date varaction2
 //Helistation available from 1999 (1920+79) to 2175 (1920+255)
   161 * 14	 02 0D
--- a/bin/data/sprites/seaplaneport.nfo	Mon May 26 20:45:25 2008 +0000
+++ b/bin/data/sprites/seaplaneport.nfo	Tue May 27 00:50:55 2008 +0000
@@ -21,7 +21,7 @@
     7 * 53	 08 07 C0 DE D0 0D "Seaplane Airport" 00 "Adds a Small Seaplane Airport" 00
 
 // 13 properties to change, 1 station to change, station id = 0
-    8 * 734	 00 0D 0C 01 00
+    8 * 734	 00 0D 0D 01 00
 
 // Small Seaplane Airport
 // uses normal small airport state machine. Runway moved to lower position
@@ -257,6 +257,9 @@
 // Prop22 Catchment Area
 		22 04
 
+// Prop24 Noise Level
+		24 02
+
 // Define placement layout mask
 // similar format to custom layout, but gives tile info for placement checks
 // set order must match custom layout order and orientations.
Binary file docs/NewGRFAirports.doc has changed
--- a/projects/openttd_vs80.vcproj	Mon May 26 20:45:25 2008 +0000
+++ b/projects/openttd_vs80.vcproj	Tue May 27 00:50:55 2008 +0000
@@ -508,6 +508,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\console_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.cpp"
 				>
 			</File>
@@ -880,7 +884,19 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\console.h"
+				RelativePath=".\..\src\console_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_gui.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_internal.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_type.h"
 				>
 			</File>
 			<File
@@ -2496,10 +2512,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\yapf\yapf_settings.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\yapf\yapf_ship.cpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj	Mon May 26 20:45:25 2008 +0000
+++ b/projects/openttd_vs90.vcproj	Tue May 27 00:50:55 2008 +0000
@@ -505,6 +505,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\console_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.cpp"
 				>
 			</File>
@@ -873,7 +877,19 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\console.h"
+				RelativePath=".\..\src\console_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_gui.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_internal.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\console_type.h"
 				>
 			</File>
 			<File
@@ -2473,10 +2489,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\yapf\yapf_settings.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\yapf\yapf_ship.cpp"
 				>
 			</File>
--- a/source.list	Mon May 26 20:45:25 2008 +0000
+++ b/source.list	Tue May 27 00:50:55 2008 +0000
@@ -13,6 +13,7 @@
 command.cpp
 console.cpp
 console_cmds.cpp
+console_gui.cpp
 currency.cpp
 date.cpp
 debug.cpp
@@ -145,7 +146,10 @@
 cmd_helper.h
 command_func.h
 command_type.h
-console.h
+console_func.h
+console_gui.h
+console_internal.h
+console_type.h
 cheat_func.h
 cheat_type.h
 currency.h
@@ -577,7 +581,6 @@
 yapf/yapf_node_road.hpp
 yapf/yapf_rail.cpp
 yapf/yapf_road.cpp
-yapf/yapf_settings.h
 yapf/yapf_ship.cpp
 
 # Video
--- a/src/ai/ai.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/ai/ai.cpp	Tue May 27 00:50:55 2008 +0000
@@ -154,7 +154,7 @@
 	Player *p = GetPlayer(player);
 	_current_player = player;
 
-	if (_patches.ainew_active) {
+	if (_settings.ai.ainew_active) {
 		AiNewDoGameLoop(p);
 	} else {
 		/* Enable all kind of cheats the old AI needs in order to operate correctly... */
@@ -178,14 +178,14 @@
 	if (!_ai.enabled) return;
 
 	/* Don't do anything if we are a network-client, or the AI has been disabled */
-	if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
+	if (_networking && (!_network_server || !_settings.ai.ai_in_multiplayer)) return;
 
 	/* New tick */
 	_ai.tick++;
 
 	/* Make sure the AI follows the difficulty rule.. */
-	assert(_opt.diff.competitor_speed <= 4);
-	if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
+	assert(_settings.difficulty.competitor_speed <= 4);
+	if ((_ai.tick & ((1 << (4 - _settings.difficulty.competitor_speed)) - 1)) != 0) return;
 
 	/* Check for AI-client (so joining a network with an AI) */
 	if (!_networking || _network_server) {
--- a/src/ai/ai.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/ai/ai.h	Tue May 27 00:50:55 2008 +0000
@@ -67,14 +67,14 @@
 	/* If in network, and server, possible AI */
 	if (_networking && _network_server) {
 		/* Do we want AIs in multiplayer? */
-		if (!_patches.ai_in_multiplayer)
+		if (!_settings.ai.ai_in_multiplayer)
 			return false;
 
 		/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
 		 *  system, because all commands are delayed by at least 1 tick, which causes
 		 *  a big problem, because it uses variables that are only set AFTER the command
 		 *  is really executed... */
-		if (!_patches.ainew_active)
+		if (!_settings.ai.ainew_active)
 			return false;
 	}
 
--- a/src/ai/default/default.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/ai/default/default.cpp	Tue May 27 00:50:55 2008 +0000
@@ -1570,21 +1570,21 @@
 	for (;;) {
 		r = (uint16)Random();
 
-		if (_patches.ai_disable_veh_train &&
-				_patches.ai_disable_veh_roadveh &&
-				_patches.ai_disable_veh_aircraft &&
-				_patches.ai_disable_veh_ship) {
+		if (_settings.ai.ai_disable_veh_train &&
+				_settings.ai.ai_disable_veh_roadveh &&
+				_settings.ai.ai_disable_veh_aircraft &&
+				_settings.ai.ai_disable_veh_ship) {
 			return;
 		}
 
 		if (r < 0x7626) {
-			if (_patches.ai_disable_veh_train) continue;
+			if (_settings.ai.ai_disable_veh_train) continue;
 			AiWantTrainRoute(p);
 		} else if (r < 0xC4EA) {
-			if (_patches.ai_disable_veh_roadveh) continue;
+			if (_settings.ai.ai_disable_veh_roadveh) continue;
 			AiWantRoadRoute(p);
 		} else if (r < 0xD89B) {
-			if (_patches.ai_disable_veh_aircraft) continue;
+			if (_settings.ai.ai_disable_veh_aircraft) continue;
 			AiWantAircraftRoute(p);
 		} else {
 			/* Ships are not implemented in this (broken) AI */
@@ -1603,7 +1603,7 @@
 
 static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
 {
-	uint rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
+	uint rad = (_settings.station.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
 
 	for (; p->mode != 4; p++) {
 		AcceptedCargo values;
@@ -2550,7 +2550,7 @@
 		bool is_pass = (
 			_players_ai[p->index].cargo_type == CT_PASSENGERS ||
 			_players_ai[p->index].cargo_type == CT_MAIL ||
-			(_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
+			(_settings.game_creation.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
 		);
 		Order order;
 
@@ -2599,7 +2599,7 @@
 	uint values[NUM_CARGO];
 	int rad;
 
-	if (_patches.modified_catchment) {
+	if (_settings.station.modified_catchment) {
 		rad = CA_TRUCK; // Same as CA_BUS at the moment?
 	} else { // change that at some point?
 		rad = 4;
@@ -3285,7 +3285,7 @@
 		bool is_pass = (
 			_players_ai[p->index].cargo_type == CT_PASSENGERS ||
 			_players_ai[p->index].cargo_type == CT_MAIL ||
-			(_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
+			(_settings.game_creation.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
 		);
 		Order order;
 
@@ -3352,7 +3352,8 @@
 
 			AirportFTAClass::Flags flags = st->Airport()->flags;
 
-			if (!(flags & (_players_ai[p->index].build_kind == 1 && i == 0 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) {
+			/* if airport doesn't accept our kind of plane, dismiss it */
+			if (!(flags & (_players_ai[p->index].build_kind == 1 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) {
 				continue;
 			}
 
@@ -3415,7 +3416,7 @@
 
 	uint w = p->size_x[0];
 	uint h = p->size_y[0];
-	uint rad = _patches.modified_catchment ? p->portFSM->catchment : (uint)CA_UNMODIFIED;
+	uint rad = _settings.station.modified_catchment ? p->portFSM->catchment : (uint)CA_UNMODIFIED;
 
 	if (cargo & 0x80) {
 		GetProductionAroundTiles(values, tile, w, h, rad);
@@ -3431,14 +3432,33 @@
 {
 	std::list<uint16> airports = GetAvailableAirports();
 
+	bool no_small = false;
+	if (!heli) {
+		/* do not build small airport if we have large available and we are not building heli route */
+		for (std::list<uint16>::const_iterator it = airports.begin(); it != airports.end(); it++) {
+			const FSMportsSpec *spec = GetCustomFSMportsSpec((FSMportsClassID)GB(*it, 8, 8), GB(*it, 0, 8));
+			uint flags = spec->flags;
+			if ((flags & AirportFTAClass::AIRPLANES) && !(flags & AirportFTAClass::SHORT_STRIP)) {
+				no_small = true;
+				break;
+			}
+		}
+	}
+
 	for (std::list<uint16>::const_iterator it = airports.begin(); it != airports.end(); it++) {
 		const FSMportsSpec *spec = GetCustomFSMportsSpec((FSMportsClassID)GB(*it, 8, 8), GB(*it, 0, 8));
-		// If we are doing a helicopter service, avoid building
-		// airports where they can't land.
-		if (heli && !(spec->flags & AirportFTAClass::HELICOPTERS)) continue;
+		uint flags = spec->flags;
+
+		/* If we are doing a helicopter service, avoid building airports where they can't land */
+		if (heli && !(flags & AirportFTAClass::HELICOPTERS)) continue;
+		/* Similiar with aircraft ... */
+		if (!heli && !(flags & AirportFTAClass::AIRPLANES)) continue;
+		/* Do not build small airport if we prefer large */
+		if (no_small && (flags & AirportFTAClass::SHORT_STRIP)) continue;
 
 		*cost = AiDoBuildDefaultAirportBlock(tile, *it, 0);
-		if (CmdSucceeded(*cost) && AiCheckAirportResources(tile, spec, cargo)) return *it;
+		if (CmdSucceeded(*cost) && AiCheckAirportResources(tile, spec, cargo))
+			return *it;
 	}
 	return 0xFFFF;
 }
@@ -3721,11 +3741,11 @@
 			DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 		}
 	} else if (IsTileType(tile, MP_ROAD)) {
-		if (!IsTileOwner(tile, _current_player)) return;
-
 		if (IsLevelCrossing(tile)) goto is_rail_crossing;
 
 		if (IsRoadDepot(tile)) {
+			if (!IsTileOwner(tile, _current_player)) return;
+
 			DiagDirection dir;
 			TileIndex t;
 
@@ -3933,7 +3953,7 @@
 	//  to the patch-setting
 	// Also, it takes into account the setting if the service-interval is in days
 	//  or in %
-	_ai_service_interval = _patches.servint_ispercent ? 80 : 180;
+	_ai_service_interval = _settings.vehicle.servint_ispercent ? 80 : 180;
 
 	if (IsHumanPlayer(_current_player)) return;
 
--- a/src/ai/trolly/trolly.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/ai/trolly/trolly.cpp	Tue May 27 00:50:55 2008 +0000
@@ -130,9 +130,9 @@
 			// Check all vehicles once in a while
 			_players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES;
 			_players_ainew[p->index].last_vehiclecheck_date = _date;
-		} else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
+		} else if (c < 100 && !_settings.ai.ai_disable_veh_roadveh) {
 			// Do we have any spots for road-vehicles left open?
-			if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) {
+			if (GetFreeUnitNumber(VEH_ROAD) <= _settings.vehicle.max_roadveh) {
 				if (c < 85) {
 					_players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE;
 				} else {
@@ -140,8 +140,8 @@
 				}
 			}
 #if 0
-		} else if (c < 200 && !_patches.ai_disable_veh_train) {
-			if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) {
+		} else if (c < 200 && !_settings.ai.ai_disable_veh_train) {
+			if (GetFreeUnitNumber(VEH_TRAIN) <= _settings.vehicle.max_trains) {
 				_players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE;
 			}
 #endif
@@ -155,7 +155,7 @@
 		return;
 	}
 
-	if (_patches.ai_disable_veh_roadveh && (
+	if (_settings.ai.ai_disable_veh_roadveh && (
 				_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE ||
 				_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE
 			)) {
@@ -179,7 +179,7 @@
 	//  to build the route anyway..
 	if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE &&
 			money > AI_MINIMUM_BUS_ROUTE_MONEY) {
-		if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
+		if (GetFreeUnitNumber(VEH_ROAD) > _settings.vehicle.max_roadveh) {
 			_players_ainew[p->index].action = AI_ACTION_NONE;
 			return;
 		}
@@ -190,7 +190,7 @@
 	}
 	if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE &&
 			money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
-		if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
+		if (GetFreeUnitNumber(VEH_ROAD) > _settings.vehicle.max_roadveh) {
 			_players_ainew[p->index].action = AI_ACTION_NONE;
 			return;
 		}
@@ -1017,7 +1017,7 @@
 	if (_players_ainew[p->index].temp == -1) {
 		DEBUG(ai, 1, "Starting to build new path");
 		// Init the counter
-		_players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
+		_players_ainew[p->index].counter = (4 - _settings.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 		// Set the position to the startingplace (-1 because in a minute we do ++)
 		_players_ainew[p->index].path_info.position = -1;
 		// And don't do this again
@@ -1026,7 +1026,7 @@
 	// Building goes very fast on normal rate, so we are going to slow it down..
 	//  By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :)
 	if (--_players_ainew[p->index].counter != 0) return;
-	_players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
+	_players_ainew[p->index].counter = (4 - _settings.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 
 	// Increase the building position
 	_players_ainew[p->index].path_info.position++;
@@ -1035,7 +1035,7 @@
 	if (_players_ainew[p->index].path_info.position == -2) {
 		// This means we are done building!
 
-		if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) {
+		if (_players_ainew[p->index].tbt == AI_TRUCK && !_settings.pf.roadveh_queue) {
 			// If they not queue, they have to go up and down to try again at a station...
 			// We don't want that, so try building some road left or right of the station
 			DiagDirection dir1, dir2, dir3;
@@ -1186,7 +1186,7 @@
 	}
 
 	// Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
-	if (_patches.gotodepot) {
+	if (_settings.order.gotodepot) {
 		idx = 0;
 		order.MakeGoToDepot(GetDepotByTile(_players_ainew[p->index].depot_tile)->index, ODTFB_PART_OF_ORDERS);
 		AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER);
--- a/src/aircraft_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/aircraft_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -317,7 +317,7 @@
 	}
 
 	UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT);
-	if (unit_num > _patches.max_aircraft)
+	if (unit_num > _settings.vehicle.max_aircraft)
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 	if (flags & DC_EXEC) {
@@ -443,7 +443,7 @@
 		v->u.air.targetairport = GetStationIndex(tile);
 		v->SetNext(u);
 
-		v->service_interval = _patches.servint_aircraft;
+		v->service_interval = _settings.vehicle.servint_aircraft;
 
 		v->date_of_last_service = _date;
 		v->build_year = u->build_year = _cur_year;
@@ -485,7 +485,7 @@
 		}
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 		InvalidateWindow(WC_COMPANY, v->owner);
 		if (IsLocalPlayer())
 			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); //updates the replace Aircraft window
@@ -500,11 +500,10 @@
 static void DoDeleteAircraft(Vehicle *v)
 {
 	DeleteWindowById(WC_VEHICLE_VIEW, v->index);
-	RebuildVehicleLists();
 	InvalidateWindow(WC_COMPANY, v->owner);
 	DeleteDepotHighlightOfVehicle(v);
 	DeleteVehicleChain(v);
-	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
+	InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 }
 
 /** Sell an aircraft.
@@ -697,7 +696,7 @@
 		v->cargo_subtype = new_subtype;
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 	}
 
 	return cost;
@@ -706,7 +705,7 @@
 
 static void CheckIfAircraftNeedsService(Vehicle *v)
 {
-	if (_patches.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
+	if (_settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
 	if (v->IsInDepot()) {
 		VehicleServiceInDepot(v);
 		return;
@@ -944,7 +943,7 @@
 
 	/* Adjust speed limits by plane speed factor to prevent taxiing
 	 * and take-off speeds being too low. */
-	speed_limit *= _patches.plane_speed;
+	speed_limit *= _settings.vehicle.plane_speed;
 
 	if (v->u.air.cached_max_speed < speed_limit) {
 		if (v->cur_speed < speed_limit) hard_limit = false;
@@ -962,7 +961,7 @@
 	 * speeds to that aircraft do not get to taxi speed straight after
 	 * touchdown. */
 	if (!hard_limit && v->cur_speed > speed_limit) {
-		speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _patches.plane_speed);
+		speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings.vehicle.plane_speed);
 	}
 
 	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
@@ -973,12 +972,12 @@
 	/* updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
 		v->cur_speed = spd;
-		if (_patches.vehicle_speed)
+		if (_settings.gui.vehicle_speed)
 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 	}
 
 	/* Adjust distance moved by plane speed setting */
-	if (_patches.plane_speed > 1) spd /= _patches.plane_speed;
+	if (_settings.vehicle.plane_speed > 1) spd /= _settings.vehicle.plane_speed;
 
 	if (!(v->direction & 1)) spd = spd * 3 / 4;
 
@@ -1740,7 +1739,7 @@
 		AircraftEventHandler_EnterTerminal(v, apc);
 		/* on an airport with helipads, a helicopter will always land there
 		 * and get serviced at the same time - patch setting */
-		if (_patches.serviceathelipad) {
+		if (_settings.order.serviceathelipad) {
 			if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) {
 				/* an exerpt of ServiceAircraft, without the invisibility stuff */
 				v->date_of_last_service = _date;
--- a/src/airport.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/airport.h	Tue May 27 00:50:55 2008 +0000
@@ -7,6 +7,7 @@
 
 #include "fsmport.h"
 #include <list>
+#include "tile_type.h"
 
 typedef FSMCommand AirportFTA;
 typedef FSMPortMovingData AirportMovingData;
@@ -104,6 +105,7 @@
 	byte *helipads;
 	Flags flags;
 	byte *entry_points;             ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
+	uint8 noise_level;
 };
 
 DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags)
@@ -115,4 +117,8 @@
  */
 std::list<uint16> GetAvailableAirports();
 
+
+/* Calculate the noise this type airport will generate */
+uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
+
 #endif /* AIRPORT_H */
--- a/src/airport_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/airport_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -19,6 +19,8 @@
 #include "strings_func.h"
 #include "core/alloc_func.hpp"
 #include "window_func.h"
+#include "strings_func.h"
+#include "settings_type.h"
 #include "viewport_func.h"
 #include "gfx_func.h"
 #include "widgets/dropdown_func.h"
@@ -41,7 +43,7 @@
 	DirectionByte direction;
 } _airport;
 
-static void ShowBuildAirportPicker();
+static void ShowBuildAirportPicker(Window *parent);
 
 
 void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
@@ -69,7 +71,7 @@
 
 static void BuildAirClick_Airport(Window *w)
 {
-	if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, VHM_RECT, PlaceAirport)) ShowBuildAirportPicker();
+	if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, VHM_RECT, PlaceAirport)) ShowBuildAirportPicker(w);
 }
 
 static void BuildAirClick_Demolish(Window *w)
@@ -84,52 +86,65 @@
 	BuildAirClick_Demolish,
 };
 
-static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT:
-			w->DrawWidgets();
-			break;
-
-		case WE_CLICK:
-			if (e->we.click.widget - 3 >= 0)
-				_build_air_button_proc[e->we.click.widget - 3](w);
-			break;
-
-		case WE_KEYPRESS: {
-			switch (e->we.keypress.keycode) {
-				case '1': BuildAirClick_Airport(w); break;
-				case '2': BuildAirClick_Demolish(w); break;
-				default: return;
-			}
-			break;
-		}
+struct BuildAirToolbarWindow : Window {
+	BuildAirToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+		if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
+	}
 
-		case WE_PLACE_OBJ:
-			_place_proc(e->we.place.tile);
-			break;
-
-		case WE_PLACE_DRAG:
-			VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-			break;
+	~BuildAirToolbarWindow()
+	{
+		if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
+	}
 
-		case WE_PLACE_MOUSEUP:
-			if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
-				GUIPlaceProcDragXY(e);
-			}
-			break;
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
 
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseButtons();
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget - 3 >= 0) {
+			_build_air_button_proc[widget - 3](this);
+		}
+	}
 
-			delete FindWindowById(WC_BUILD_STATION, 0);
-			break;
 
-		case WE_DESTROY:
-			if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
-			break;
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		switch (keycode) {
+			case '1': BuildAirClick_Airport(this); break;
+			case '2': BuildAirClick_Demolish(this); break;
+			default: return ES_NOT_HANDLED;
+		}
+		return ES_HANDLED;
 	}
-}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) {
+			GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
+		}
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
+
+		delete FindWindowById(WC_BUILD_STATION, 0);
+	}
+};
 
 static const Widget _air_toolbar_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,            STR_018B_CLOSE_WINDOW },
@@ -146,7 +161,6 @@
 	WC_BUILD_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_air_toolbar_widgets,
-	BuildAirToolbWndProc
 };
 
 void ShowBuildAirToolbar()
@@ -154,8 +168,7 @@
 	if (!IsValidPlayer(_current_player)) return;
 
 	DeleteWindowByClass(WC_BUILD_TOOLBAR);
-	Window *w = AllocateWindowDescFront<Window>(&_air_toolbar_desc, TRANSPORT_AIR);
-	if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
+	AllocateWindowDescFront<BuildAirToolbarWindow>(&_air_toolbar_desc, TRANSPORT_AIR);
 }
 
 class AirportPickerWindow : public PickerWindowBase {
@@ -181,13 +194,17 @@
 	};
 
 public:
-	AirportPickerWindow(const WindowDesc *desc) : PickerWindowBase(desc)
+	AirportPickerWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
 	{
 		_airport.station_type = 0;
 		_airport.layout_set = 0;
 		_airport.direction = DIR_NE;
 		_airport.station_count = GetNumCustomFSMports(_airport.fsmports_class);
 
+		if (_settings.economy.station_noise_level) {
+			ResizeWindowForWidget(this, BAPW_BACKGROUND, 0, 10);
+		}
+
 		this->vscroll.count = _airport.station_count;
 		this->vscroll.cap   = 5;
 		this->vscroll.pos   = Clamp(_airport.station_type - 2, 0, this->vscroll.count - this->vscroll.cap);
@@ -200,6 +217,7 @@
 	virtual void OnPaint()
 	{
 		byte preview_sprite = 0xFF;
+		uint16 y_noise_offset = 0;
 
 		FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type);
 		/* if the port is no longer available, find one that is */
@@ -255,7 +273,7 @@
 			_thd.FSMportLayout = &fsmportspec->layouts[_airport.layout_set];  // irregular airport support
 			_thd.FSMportMask = NULL;
 			if (fsmportspec->layout_mask != NULL) _thd.FSMportMask = &fsmportspec->layout_mask[_airport.layout_set];  // irregular airport support
-			int rad = _patches.modified_catchment ? fsmportspec->portFSM->catchment : 4;
+			int rad = _settings.station.modified_catchment ? fsmportspec->portFSM->catchment : 4;
 			if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
 			int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad, false);
 			text_end = DrawStationCoverageAreaText(2, text_end + 4, SCT_ALL, rad, true) + 4;
@@ -411,12 +429,11 @@
 	WC_BUILD_STATION, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_airport_picker_widgets,
-	NULL
 };
 
-static void ShowBuildAirportPicker()
+static void ShowBuildAirportPicker(Window *parent)
 {
-	new AirportPickerWindow(&_build_airport_desc);
+	new AirportPickerWindow(&_build_airport_desc, parent);
 }
 
 void InitializeAirportGui()
--- a/src/autoreplace_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/autoreplace_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -216,7 +216,7 @@
 			// copy/clone the orders
 			DoCommand(0, (old_v->index << 16) | new_v->index, old_v->IsOrderListShared() ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER);
 			new_v->cur_order_index = old_v->cur_order_index;
-			ChangeVehicleViewWindow(old_v, new_v);
+			ChangeVehicleViewWindow(old_v->index, new_v->index);
 			new_v->profit_this_year = old_v->profit_this_year;
 			new_v->profit_last_year = old_v->profit_last_year;
 			new_v->service_interval = old_v->service_interval;
--- a/src/autoreplace_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/autoreplace_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -533,7 +533,6 @@
 	WC_REPLACE_VEHICLE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_replace_vehicle_widgets,
-	NULL
 };
 
 static const WindowDesc _replace_vehicle_desc = {
@@ -541,7 +540,6 @@
 	WC_REPLACE_VEHICLE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_replace_vehicle_widgets,
-	NULL
 };
 
 RailType ReplaceVehicleWindow::sel_railtype = RAILTYPE_RAIL;
--- a/src/autoslope.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/autoslope.h	Tue May 27 00:50:55 2008 +0000
@@ -38,7 +38,7 @@
  */
 static inline bool AutoslopeEnabled()
 {
-	return (_patches.autoslope &&
+	return (_settings.construction.autoslope &&
 	        ((IsValidPlayer(_current_player) && !_is_old_ai_player) ||
 	         (_current_player == OWNER_NONE && _game_mode == GM_EDITOR)));
 }
--- a/src/blitter/factory.hpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/blitter/factory.hpp	Tue May 27 00:50:55 2008 +0000
@@ -56,7 +56,13 @@
 		name(NULL)
 	{}
 
-	virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); }
+	virtual ~BlitterFactoryBase()
+	{
+		if (this->name == NULL) return;
+		GetBlitters().erase(this->name);
+		if (GetBlitters().empty()) delete &GetBlitters();
+		free(this->name);
+	}
 
 	/**
 	 * Find the requested blitter and return his class.
--- a/src/bridge_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/bridge_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -17,146 +17,282 @@
 #include "viewport_func.h"
 #include "gfx_func.h"
 #include "tunnelbridge.h"
+#include "sortlist_type.h"
+#include "widgets/dropdown_func.h"
 
 #include "table/strings.h"
 
-static struct BridgeData {
-	uint8 last_size;
-	uint count;
-	TileIndex start_tile;
-	TileIndex end_tile;
-	uint32 type; ///< Data type for the bridge. Bit 16,15 = transport type, 14..8 = road/rail pieces, 7..0 = type of bridge
-	BridgeType indexes[MAX_BRIDGES];
-	Money costs[MAX_BRIDGES];
+/**
+ * Carriage for the data we need if we want to build a bridge
+ */
+struct BuildBridgeData {
+	BridgeType index;
+	const BridgeSpec *spec;
+	Money cost;
+};
 
-	BridgeData()
-		: last_size(4)
-		, count(0)
-		{};
-} _bridgedata;
+typedef GUIList<BuildBridgeData> GUIBridgeList;
 
+/**
+ * Callback executed after a build Bridge CMD has been called
+ *
+ * @param scucess True if the build succeded
+ * @param tile The tile where the command has been executed
+ * @param p1 not used
+ * @param p2 not used
+ */
 void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
 	if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
 }
 
-static void BuildBridge(Window *w, int i)
-{
-	delete w;
-	DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
-		_bridgedata.type | _bridgedata.indexes[i], CcBuildBridge,
-		CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
-}
-
 /* Names of the build bridge selection window */
 enum BuildBridgeSelectionWidgets {
 	BBSW_CLOSEBOX = 0,
 	BBSW_CAPTION,
+	BBSW_DROPDOWN_ORDER,
+	BBSW_DROPDOWN_CRITERIA,
 	BBSW_BRIDGE_LIST,
 	BBSW_SCROLLBAR,
 	BBSW_RESIZEBOX
 };
 
-static void BuildBridgeWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_CREATE:
-			w->resize.step_height = 22;
-			w->vscroll.count = _bridgedata.count;
+class BuildBridgeWindow : public Window {
+private:
+	/* Runtime saved values */
+	static uint last_size;
+	static Listing last_sorting;
 
-			if (_bridgedata.last_size <= 4) {
-				w->vscroll.cap = 4;
-			} else {
-				/* Resize the bridge selection window if we used a bigger one the last time */
-				w->vscroll.cap = (w->vscroll.count > _bridgedata.last_size) ? _bridgedata.last_size : w->vscroll.count;
-				ResizeWindow(w, 0, (w->vscroll.cap - 4) * w->resize.step_height);
-				w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1;
-			}
-			break;
-
-		case WE_PAINT: {
-			w->DrawWidgets();
+	/* Constants for sorting the bridges */
+	static const StringID sorter_names[];
+	static GUIBridgeList::SortFunction *const sorter_funcs[];
 
-			uint y = 15;
-			for (uint i = 0; (i < w->vscroll.cap) && ((i + w->vscroll.pos) < _bridgedata.count); i++) {
-				const BridgeSpec *b = GetBridgeSpec(_bridgedata.indexes[i + w->vscroll.pos]);
+	/* Internal variables */
+	TileIndex start_tile;
+	TileIndex end_tile;
+	uint32 type;
+	GUIBridgeList *bridges;
 
-				SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
-				SetDParam(1, b->speed * 10 / 16);
-				SetDParam(0, b->material);
+	/** Sort the bridges by their index */
+	static int CDECL BridgeIndexSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->index - b->index;
+	}
 
-				DrawSprite(b->sprite, b->pal, 3, y);
-				DrawString(44, y, STR_500D, TC_FROMSTRING);
-				y += w->resize.step_height;
-			}
-			break;
+	/** Sort the bridges by their price */
+	static int CDECL BridgePriceSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->cost - b->cost;
+	}
+
+	/** Sort the bridges by their maximum speed */
+	static int CDECL BridgeSpeedSorter(const BuildBridgeData *a, const BuildBridgeData *b)
+	{
+		return a->spec->speed - b->spec->speed;
+	}
+
+	void BuildBridge(uint8 i)
+	{
+		DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index,
+				CcBuildBridge, CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
+	}
+
+	/** Sort the builable bridges */
+	void SortBridgeList()
+	{
+		this->bridges->Sort();
+
+		/* Display the current sort variant */
+		this->widget[BBSW_DROPDOWN_CRITERIA].data = this->sorter_names[this->bridges->SortType()];
+
+		/* Set the modified widgets dirty */
+		this->InvalidateWidget(BBSW_DROPDOWN_CRITERIA);
+		this->InvalidateWidget(BBSW_BRIDGE_LIST);
+	}
+
+public:
+	BuildBridgeWindow(const WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(desc),
+		start_tile(start),
+		end_tile(end),
+		type(br_type),
+		bridges(bl)
+	{
+		this->bridges->SetListing(this->last_sorting);
+		this->bridges->SetSortFuncs(this->sorter_funcs);
+		this->SortBridgeList();
+
+		/* Change the data, or the caption of the gui. Set it to road or rail, accordingly */
+		this->widget[BBSW_CAPTION].data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
+
+		this->resize.step_height = 22;
+		this->vscroll.count = bl->Length();
+
+		if (this->last_size <= 4) {
+			this->vscroll.cap = 4;
+		} else {
+			/* Resize the bridge selection window if we used a bigger one the last time */
+			this->vscroll.cap = (this->vscroll.count > this->last_size) ? this->last_size : this->vscroll.count;
+			ResizeWindow(this, 0, (this->vscroll.cap - 4) * this->resize.step_height);
+			this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1;
 		}
 
-		case WE_KEYPRESS: {
-			const uint8 i = e->we.keypress.keycode - '1';
-			if (i < 9 && i < _bridgedata.count) {
-				e->we.keypress.cont = false;
-				BuildBridge(w, i);
-			}
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			break;
-		}
+	~BuildBridgeWindow()
+	{
+		this->last_sorting = this->bridges->GetListing();
 
-		case WE_CLICK:
-			if (e->we.click.widget == BBSW_BRIDGE_LIST) {
-				uint ind = ((int)e->we.click.pt.y - 14) / w->resize.step_height;
-				if (ind < w->vscroll.cap) {
-					ind += w->vscroll.pos;
-					if (ind < _bridgedata.count) {
-						BuildBridge(w, ind);
+		delete bridges;
+	}
+
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+
+		this->DrawSortButtonState(BBSW_DROPDOWN_ORDER, (this->bridges->flags & VL_DESC) ? SBS_DOWN : SBS_UP);
+
+		uint y = this->widget[BBSW_BRIDGE_LIST].top + 2;
+
+		for (int i = this->vscroll.pos; (i < (this->vscroll.cap + this->vscroll.pos)) && (i < (int)this->bridges->Length()); i++) {
+			const BridgeSpec *b = this->bridges->Get(i)->spec;
+
+			SetDParam(2, this->bridges->Get(i)->cost);
+			SetDParam(1, b->speed * 10 / 16);
+			SetDParam(0, b->material);
+
+			DrawSprite(b->sprite, b->pal, 3, y);
+			DrawString(44, y, STR_500D, TC_FROMSTRING);
+			y += this->resize.step_height;
+
+		}
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		const uint8 i = keycode - '1';
+		if (i < 9 && i < this->bridges->Length()) {
+			/* Build the requested bridge */
+			this->BuildBridge(i);
+			delete this;
+			return ES_HANDLED;
+		}
+		return ES_NOT_HANDLED;
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			default: break;
+			case BBSW_BRIDGE_LIST: {
+				uint i = ((int)pt.y - this->widget[BBSW_BRIDGE_LIST].top) / this->resize.step_height;
+				if (i < this->vscroll.cap) {
+					i += this->vscroll.pos;
+					if (i < this->bridges->Length()) {
+						this->BuildBridge(i);
+						delete this;
 					}
 				}
-			}
-			break;
+			} break;
 
-		case WE_RESIZE:
-			w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
-			w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1;
-			SetVScrollCount(w, _bridgedata.count);
+			case BBSW_DROPDOWN_ORDER:
+				this->bridges->ToggleSortOrder();
+				this->SetDirty();
+				break;
 
-			_bridgedata.last_size = w->vscroll.cap;
-			break;
+			case BBSW_DROPDOWN_CRITERIA:
+				ShowDropDownMenu(this, this->sorter_names, this->bridges->SortType(), BBSW_DROPDOWN_CRITERIA, 0, 0);
+				break;
+		}
 	}
-}
+
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		if (widget == BBSW_DROPDOWN_CRITERIA && this->bridges->SortType() != index) {
+			this->bridges->SetSortType(index);
+
+			this->SortBridgeList();
+		}
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->vscroll.cap += delta.y / (int)this->resize.step_height;
+		this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1;
+		SetVScrollCount(this, this->bridges->Length());
+
+		this->last_size = this->vscroll.cap;
+	}
+};
+
+/* Set the default size of the Build Bridge Window */
+uint BuildBridgeWindow::last_size = 4;
+/* Set the default sorting for the bridges */
+Listing BuildBridgeWindow::last_sorting = {false, 0};
+
+/* Availible bridge sorting functions */
+GUIBridgeList::SortFunction* const BuildBridgeWindow::sorter_funcs[] = {
+	&BridgeIndexSorter,
+	&BridgePriceSorter,
+	&BridgeSpeedSorter
+};
+
+/* Names of the sorting functions */
+const StringID BuildBridgeWindow::sorter_names[] = {
+	STR_SORT_BY_NUMBER,
+	STR_ENGINE_SORT_COST,
+	STR_SORT_BY_MAX_SPEED,
+	INVALID_STRING_ID
+};
 
 /* Widget definition for the rail bridge selection window */
 static const Widget _build_bridge_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,  7,   0,  10,   0,  13, STR_00C5,                    STR_018B_CLOSE_WINDOW},            // BBSW_CLOSEBOX
 {    WWT_CAPTION,   RESIZE_NONE,  7,  11, 199,   0,  13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},  // BBSW_CAPTION
-{     WWT_MATRIX, RESIZE_BOTTOM,  7,   0, 187,  14, 101, 0x401,                       STR_101F_BRIDGE_SELECTION_CLICK},  // BBSW_BRIDGE_LIST
-{  WWT_SCROLLBAR, RESIZE_BOTTOM,  7, 188, 199,  14,  89, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR
-{  WWT_RESIZEBOX,     RESIZE_TB,  7, 188, 199,  90, 101, 0x0,                         STR_RESIZE_BUTTON},                // BBSW_RESIZEBOX
+
+{    WWT_TEXTBTN,   RESIZE_NONE,  7,   0,  80,  14,  25, STR_SORT_BY,                 STR_SORT_ORDER_TIP},               // BBSW_DROPDOWN_ORDER
+{   WWT_DROPDOWN,   RESIZE_NONE,  7,  81, 199,  14,  25, 0x0,                         STR_SORT_CRITERIA_TIP},            // BBSW_DROPDOWN_CRITERIA
+
+{     WWT_MATRIX, RESIZE_BOTTOM,  7,   0, 187,  26, 113, 0x401,                       STR_101F_BRIDGE_SELECTION_CLICK},  // BBSW_BRIDGE_LIST
+{  WWT_SCROLLBAR, RESIZE_BOTTOM,  7, 188, 199,  26, 101, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR
+{  WWT_RESIZEBOX,     RESIZE_TB,  7, 188, 199, 102, 113, 0x0,                         STR_RESIZE_BUTTON},                // BBSW_RESIZEBOX
 {   WIDGETS_END},
 };
 
 /* Window definition for the rail bridge selection window */
 static const WindowDesc _build_bridge_desc = {
-	WDP_AUTO, WDP_AUTO, 200, 102, 200, 102,
+	WDP_AUTO, WDP_AUTO, 200, 114, 200, 114,
 	WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 	_build_bridge_widgets,
-	BuildBridgeWndProc
 };
 
+/**
+ * Prepare the data for the build a bridge window.
+ *  If we can't build a bridge under the given conditions
+ *  show an error message.
+ *
+ * @parma start The start tile of the bridge
+ * @param end The end tile of the bridge
+ * @param transport_type The transport type
+ * @param bridge_type The bridge type
+ */
 void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type)
 {
 	DeleteWindowById(WC_BUILD_BRIDGE, 0);
 
-	_bridgedata.type = (transport_type << 15) | (bridge_type << 8); //prepare the parameter for use only once
-	_bridgedata.start_tile = start;
-	_bridgedata.end_tile = end;
+	/* Data type for the bridge.
+	 * Bit 16,15 = transport type,
+	 *     14..8 = road/rail pieces,
+	 *      7..0 = type of bridge */
+	uint32 type = (transport_type << 15) | (bridge_type << 8);
 
 	/* only query bridge building possibility once, result is the same for all bridges!
 	 * returns CMD_ERROR on failure, and price on success */
 	StringID errmsg = INVALID_STRING_ID;
-	CommandCost ret = DoCommand(end, start, _bridgedata.type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
+	CommandCost ret = DoCommand(end, start, type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
 
-	uint8 j = 0;
+	GUIBridgeList *bl = NULL;
 	if (CmdFailed(ret)) {
 		errmsg = _error_message;
 	} else {
@@ -167,27 +303,26 @@
 		/* total length of bridge */
 		const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2);
 
+		bl = new GUIBridgeList();
+
 		/* loop for all bridgetypes */
 		for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
 			if (CheckBridge_Stuff(brd_type, bridge_len)) {
 				/* bridge is accepted, add to list */
-				const BridgeSpec *b = GetBridgeSpec(brd_type);
+				BuildBridgeData *item = bl->Append();
+				item->index = brd_type;
+				item->spec = GetBridgeSpec(brd_type);
 				/* Add to terraforming & bulldozing costs the cost of the
 				 * bridge itself (not computed with DC_QUERY_COST) */
-				_bridgedata.costs[j] = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
-				_bridgedata.indexes[j] = brd_type;
-				j++;
+				item->cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * item->spec->price) >> 8);
 			}
 		}
-
-		_bridgedata.count = j;
 	}
 
-	if (j != 0) {
-		Window *w = new Window(&_build_bridge_desc);
-		/* Change the data, or the caption of the gui. Set it to road or rail, accordingly */
-		w->widget[BBSW_CAPTION].data = (transport_type == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
+	if (bl != NULL && bl->Length() != 0) {
+		new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl);
 	} else {
+		if (bl != NULL) delete bl;
 		ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
 	}
 }
--- a/src/build_vehicle_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/build_vehicle_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -506,7 +506,7 @@
 	y += 10;
 
 	/* Wagon speed limit, displayed if above zero */
-	if (_patches.wagon_speed_limits) {
+	if (_settings.vehicle.wagon_speed_limits) {
 		uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed);
 		if (max_speed > 0) {
 			SetDParam(0, max_speed * 10 / 16);
@@ -544,7 +544,7 @@
 	y += 10;
 
 	/* Max tractive effort - not applicable if old acceleration or maglev */
-	if (_patches.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
+	if (_settings.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
 		SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256);
 		DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING);
 		y += 10;
@@ -800,7 +800,6 @@
 		AirportFTAClass::Flags flags;
 		RoadTypes roadtypes;
 	} filter;
-	byte sel_index;  ///< deprecated value, used for 'unified' ship and road
 	bool descending_sort_order;
 	byte sort_criteria;
 	bool regenerate_list;
@@ -1182,7 +1181,6 @@
 	WC_BUILD_VEHICLE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_build_vehicle_widgets,
-	NULL
 };
 
 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
--- a/src/cheat_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/cheat_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -64,9 +64,9 @@
 {
 	if (p1 == -1) p1 = 3;
 	if (p1 ==  4) p1 = 0;
-	_opt.landscape = p1;
+	_settings.game_creation.landscape = p1;
 	ReloadNewGRFData();
-	return _opt.landscape;
+	return _settings.game_creation.landscape;
 }
 
 extern void EnginesMonthlyLoop();
@@ -100,15 +100,15 @@
 };
 
 static const CheatEntry _cheats_ui[] = {
-	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,            &_cheats.money.been_used,            &ClickMoneyCheat        },
-	{SLE_UINT8, STR_CHEAT_CHANGE_PLAYER,   &_local_player,                  &_cheats.switch_player.been_used,    &ClickChangePlayerCheat },
-	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,  &_cheats.magic_bulldozer.been_used,  NULL                    },
-	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, NULL                    },
-	{SLE_BOOL,  STR_CHEAT_BUILD_IN_PAUSE,  &_cheats.build_in_pause.value,   &_cheats.build_in_pause.been_used,   NULL                    },
-	{SLE_BOOL,  STR_CHEAT_NO_JETCRASH,     &_cheats.no_jetcrash.value,      &_cheats.no_jetcrash.been_used,      NULL                    },
-	{SLE_BOOL,  STR_CHEAT_SETUP_PROD,      &_cheats.setup_prod.value,       &_cheats.setup_prod.been_used,       NULL                    },
-	{SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE,  &_opt.landscape,                 &_cheats.switch_climate.been_used,   &ClickChangeClimateCheat},
-	{SLE_INT32, STR_CHEAT_CHANGE_DATE,     &_cur_year,                      &_cheats.change_date.been_used,      &ClickChangeDateCheat   },
+	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,               &_cheats.money.been_used,            &ClickMoneyCheat        },
+	{SLE_UINT8, STR_CHEAT_CHANGE_PLAYER,   &_local_player,                     &_cheats.switch_player.been_used,    &ClickChangePlayerCheat },
+	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,     &_cheats.magic_bulldozer.been_used,  NULL                    },
+	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,    &_cheats.crossing_tunnels.been_used, NULL                    },
+	{SLE_BOOL,  STR_CHEAT_BUILD_IN_PAUSE,  &_cheats.build_in_pause.value,      &_cheats.build_in_pause.been_used,   NULL                    },
+	{SLE_BOOL,  STR_CHEAT_NO_JETCRASH,     &_cheats.no_jetcrash.value,         &_cheats.no_jetcrash.been_used,      NULL                    },
+	{SLE_BOOL,  STR_CHEAT_SETUP_PROD,      &_cheats.setup_prod.value,          &_cheats.setup_prod.been_used,       NULL                    },
+	{SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE,  &_settings.game_creation.landscape, &_cheats.switch_climate.been_used,   &ClickChangeClimateCheat},
+	{SLE_INT32, STR_CHEAT_CHANGE_DATE,     &_cur_year,                         &_cheats.change_date.been_used,      &ClickChangeDateCheat   },
 };
 
 
@@ -125,6 +125,7 @@
 
 	CheatWindow(const WindowDesc *desc) : Window(desc)
 	{
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
@@ -226,7 +227,6 @@
 	WC_CHEATS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_cheat_widgets,
-	NULL
 };
 
 
--- a/src/clear_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/clear_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -218,7 +218,7 @@
 {
 	TileLoopClearHelper(tile);
 
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_TROPIC: TileLoopClearDesert(tile); break;
 		case LT_ARCTIC: TileLoopClearAlps(tile);   break;
 	}
@@ -336,7 +336,7 @@
 	} else {
 		td->str = _clear_land_str[GetClearGround(tile)];
 	}
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 }
 
 static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
@@ -346,7 +346,7 @@
 
 void InitializeClearLand()
 {
-	_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
+	_settings.game_creation.snow_line = _settings.game_creation.snow_line_height * TILE_HEIGHT;
 }
 
 static CommandCost TerraformTile_Clear(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
--- a/src/command.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/command.cpp	Tue May 27 00:50:55 2008 +0000
@@ -152,7 +152,6 @@
 
 DEF_COMMAND(CmdSetRoadDriveSide);
 
-DEF_COMMAND(CmdChangeDifficultyLevel);
 DEF_COMMAND(CmdChangePatchSetting);
 
 DEF_COMMAND(CmdStartStopShip);
@@ -304,7 +303,6 @@
 	{CmdDoTownAction,                        0}, /* CMD_DO_TOWN_ACTION */
 
 	{CmdSetRoadDriveSide,           CMD_SERVER}, /* CMD_SET_ROAD_DRIVE_SIDE */
-	{CmdChangeDifficultyLevel,      CMD_SERVER}, /* CMD_CHANGE_DIFFICULTY_LEVEL */
 
 	{CmdStartStopShip,                       0}, /* CMD_START_STOP_SHIP */
 	{CmdSellShip,                            0}, /* CMD_SELL_SHIP */
--- a/src/command_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/command_type.h	Tue May 27 00:50:55 2008 +0000
@@ -233,8 +233,6 @@
 
 	CMD_SET_ROAD_DRIVE_SIDE,          ///< set the side where the road vehicles drive
 
-	CMD_CHANGE_DIFFICULTY_LEVEL,      ///< change the difficult of a game (each setting for it own)
-
 	CMD_START_STOP_SHIP,              ///< start/stop a ship
 	CMD_SELL_SHIP,                    ///< sell a ship
 	CMD_BUILD_SHIP,                   ///< build a new ship
--- a/src/console.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/console.cpp	Tue May 27 00:50:55 2008 +0000
@@ -3,23 +3,15 @@
 /** @file console.cpp Handling of the in-game console. */
 
 #include "stdafx.h"
-#include "openttd.h"
-#include "gui.h"
-#include "textbuf_gui.h"
-#include "window_gui.h"
-#include "variables.h"
-#include <stdarg.h>
-#include <string.h>
-#include "console.h"
-#include "network/network.h"
+#include "console_internal.h"
 #include "network/network_data.h"
 #include "network/network_server.h"
 #include "core/alloc_func.hpp"
-#include "window_func.h"
 #include "string_func.h"
-#include "gfx_func.h"
 #include "rev.h"
 
+#include <stdarg.h>
+
 #include "table/strings.h"
 
 #define ICON_BUFFER 79
@@ -35,265 +27,21 @@
 IConsoleVar   *_iconsole_vars;    ///< list of registred vars
 IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
 
-/* console colors/modes */
-byte _icolour_def;
-byte _icolour_err;
-byte _icolour_warn;
-byte _icolour_dbg;
-byte _icolour_cmd;
-IConsoleModes _iconsole_mode;
-
-/* ** main console ** */
-static char *_iconsole_buffer[ICON_BUFFER + 1];
-static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
-static Textbuf _iconsole_cmdline;
-
 /* ** stdlib ** */
 byte _stdlib_developer = 1;
 bool _stdlib_con_developer = false;
 FILE *_iconsole_output_file;
 
-/* ** main console cmd buffer ** */
-static char *_iconsole_history[ICON_HISTORY_SIZE];
-static byte _iconsole_historypos;
-
-/* *************** *
- *  end of header  *
- * *************** */
-
-static void IConsoleClearCommand()
-{
-	memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
-	_iconsole_cmdline.length = 0;
-	_iconsole_cmdline.width = 0;
-	_iconsole_cmdline.caretpos = 0;
-	_iconsole_cmdline.caretxoffs = 0;
-	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
-}
-
-static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
-
-
-static void IConsoleHistoryAdd(const char *cmd);
-static void IConsoleHistoryNavigate(int direction);
-
-struct IConsoleWindow : Window
-{
-	static byte scroll;
-
-	IConsoleWindow(const WindowDesc *desc) : Window(desc)
-	{
-		_iconsole_mode = ICONSOLE_OPENED;
-		SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
-
-		this->height = _screen.height / 3;
-		this->width  = _screen.width;
-	}
-
-	~IConsoleWindow()
-	{
-		_iconsole_mode = ICONSOLE_CLOSED;
-		ClrBit(_no_scroll, SCROLL_CON);
-	}
-
-	virtual void OnPaint()
-	{
-		int i = IConsoleWindow::scroll;
-		int max = (this->height / ICON_LINE_HEIGHT) - 1;
-		int delta = 0;
-		GfxFillRect(this->left, this->top, this->width, this->height - 1, 0);
-		while ((i > 0) && (i > IConsoleWindow::scroll - max) && (_iconsole_buffer[i] != NULL)) {
-			DoDrawString(_iconsole_buffer[i], 5,
-				this->height - (IConsoleWindow::scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
-			i--;
-		}
-		/* If the text is longer than the window, don't show the starting ']' */
-		delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
-		if (delta > 0) {
-			DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, _icolour_cmd);
-			delta = 0;
-		}
-
-		DoDrawString(_iconsole_cmdline.buf, 10 + delta, this->height - ICON_LINE_HEIGHT, _icolour_cmd);
-
-		if (_iconsole_cmdline.caret) {
-			DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE);
-		}
-	}
-
-	virtual void OnMouseLoop()
-	{
-		if (HandleCaret(&_iconsole_cmdline)) this->SetDirty();
-	}
-
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
-	{
-		switch (keycode) {
-			case WKC_UP:
-				IConsoleHistoryNavigate(+1);
-				this->SetDirty();
-				break;
-
-			case WKC_DOWN:
-				IConsoleHistoryNavigate(-1);
-				this->SetDirty();
-				break;
-
-			case WKC_SHIFT | WKC_PAGEUP:
-				if (IConsoleWindow::scroll - (this->height / ICON_LINE_HEIGHT) - 1 < 0) {
-					IConsoleWindow::scroll = 0;
-				} else {
-					IConsoleWindow::scroll -= (this->height / ICON_LINE_HEIGHT) - 1;
-				}
-				this->SetDirty();
-				break;
-
-			case WKC_SHIFT | WKC_PAGEDOWN:
-				if (IConsoleWindow::scroll + (this->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
-					IConsoleWindow::scroll = ICON_BUFFER;
-				} else {
-					IConsoleWindow::scroll += (this->height / ICON_LINE_HEIGHT) - 1;
-				}
-				this->SetDirty();
-				break;
-
-			case WKC_SHIFT | WKC_UP:
-				if (IConsoleWindow::scroll <= 0) {
-					IConsoleWindow::scroll = 0;
-				} else {
-					--IConsoleWindow::scroll;
-				}
-				this->SetDirty();
-				break;
-
-			case WKC_SHIFT | WKC_DOWN:
-				if (IConsoleWindow::scroll >= ICON_BUFFER) {
-					IConsoleWindow::scroll = ICON_BUFFER;
-				} else {
-					++IConsoleWindow::scroll;
-				}
-				this->SetDirty();
-				break;
-
-			case WKC_BACKQUOTE:
-				IConsoleSwitch();
-				break;
-
-			case WKC_RETURN: case WKC_NUM_ENTER:
-				IConsolePrintF(_icolour_cmd, "] %s", _iconsole_cmdline.buf);
-				IConsoleHistoryAdd(_iconsole_cmdline.buf);
-
-				IConsoleCmdExec(_iconsole_cmdline.buf);
-				IConsoleClearCommand();
-				break;
-
-			case WKC_CTRL | WKC_RETURN:
-				_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
-				IConsoleResize(this);
-				MarkWholeScreenDirty();
-				break;
-
-			case (WKC_CTRL | 'V'):
-				if (InsertTextBufferClipboard(&_iconsole_cmdline)) {
-					IConsoleResetHistoryPos();
-					this->SetDirty();
-				}
-				break;
-
-			case (WKC_CTRL | 'L'):
-				IConsoleCmdExec("clear");
-				break;
-
-			case (WKC_CTRL | 'U'):
-				DeleteTextBufferAll(&_iconsole_cmdline);
-				this->SetDirty();
-				break;
-
-			case WKC_BACKSPACE: case WKC_DELETE:
-				if (DeleteTextBufferChar(&_iconsole_cmdline, keycode)) {
-					IConsoleResetHistoryPos();
-					this->SetDirty();
-				}
-				break;
-
-			case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
-				if (MoveTextBufferPos(&_iconsole_cmdline, keycode)) {
-					IConsoleResetHistoryPos();
-					this->SetDirty();
-				}
-				break;
-
-			default:
-				if (IsValidChar(key, CS_ALPHANUMERAL)) {
-					IConsoleWindow::scroll = ICON_BUFFER;
-					InsertTextBufferChar(&_iconsole_cmdline, key);
-					IConsoleResetHistoryPos();
-					this->SetDirty();
-				} else {
-					return true;
-				}
-		}
-		return false;
-	}
-};
-
-byte IConsoleWindow::scroll = ICON_BUFFER;
-
-static const Widget _iconsole_window_widgets[] = {
-	{WIDGETS_END}
-};
-
-static const WindowDesc _iconsole_window_desc = {
-	0, 0, 2, 2, 2, 2,
-	WC_CONSOLE, WC_NONE,
-	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
-	_iconsole_window_widgets,
-	NULL,
-};
-
 void IConsoleInit()
 {
 	_iconsole_output_file = NULL;
-	_icolour_def  =  1;
-	_icolour_err  =  3;
-	_icolour_warn = 13;
-	_icolour_dbg  =  5;
-	_icolour_cmd  = TC_GOLD;
-	_iconsole_historypos = ICON_HISTORY_SIZE - 1;
-	_iconsole_mode = ICONSOLE_CLOSED;
-
 #ifdef ENABLE_NETWORK /* Initialize network only variables */
 	_redirect_console_to_client = 0;
 #endif
 
-	memset(_iconsole_history, 0, sizeof(_iconsole_history));
-	memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
-	memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
-	_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
-	_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
+	IConsoleGUIInit();
 
-	IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
-	IConsolePrint(12,  "------------------------------------");
-	IConsolePrint(12,  "use \"help\" for more information");
-	IConsolePrint(12,  "");
 	IConsoleStdLibRegister();
-	IConsoleClearCommand();
-	IConsoleHistoryAdd("");
-}
-
-void IConsoleClearBuffer()
-{
-	uint i;
-	for (i = 0; i <= ICON_BUFFER; i++) {
-		free(_iconsole_buffer[i]);
-		_iconsole_buffer[i] = NULL;
-	}
-}
-
-static void IConsoleClear()
-{
-	free(_iconsole_cmdline.buf);
-	IConsoleClearBuffer();
 }
 
 static void IConsoleWriteToLogFile(const char *string)
@@ -304,7 +52,7 @@
 				fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
 			fclose(_iconsole_output_file);
 			_iconsole_output_file = NULL;
-			IConsolePrintF(_icolour_def, "cannot write to log file");
+			IConsolePrintF(CC_DEFAULT, "cannot write to log file");
 		}
 	}
 }
@@ -312,7 +60,7 @@
 bool CloseConsoleLogIfActive()
 {
 	if (_iconsole_output_file != NULL) {
-		IConsolePrintF(_icolour_def, "file output complete");
+		IConsolePrintF(CC_DEFAULT, "file output complete");
 		fclose(_iconsole_output_file);
 		_iconsole_output_file = NULL;
 		return true;
@@ -323,86 +71,10 @@
 
 void IConsoleFree()
 {
-	IConsoleClear();
+	IConsoleGUIFree();
 	CloseConsoleLogIfActive();
 }
 
-void IConsoleResize(Window *w)
-{
-	switch (_iconsole_mode) {
-		case ICONSOLE_OPENED:
-			w->height = _screen.height / 3;
-			w->width = _screen.width;
-			break;
-		case ICONSOLE_FULL:
-			w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
-			w->width = _screen.width;
-			break;
-		default: return;
-	}
-
-	MarkWholeScreenDirty();
-}
-
-void IConsoleSwitch()
-{
-	switch (_iconsole_mode) {
-		case ICONSOLE_CLOSED:
-			new IConsoleWindow(&_iconsole_window_desc);
-			break;
-
-		case ICONSOLE_OPENED: case ICONSOLE_FULL:
-			DeleteWindowById(WC_CONSOLE, 0);
-			break;
-	}
-
-	MarkWholeScreenDirty();
-}
-
-void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
-void IConsoleOpen()  {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
-
-/**
- * Add the entered line into the history so you can look it back
- * scroll, etc. Put it to the beginning as it is the latest text
- * @param cmd Text to be entered into the 'history'
- */
-static void IConsoleHistoryAdd(const char *cmd)
-{
-	free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
-
-	memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
-	_iconsole_history[0] = strdup(cmd);
-	IConsoleResetHistoryPos();
-}
-
-/**
- * Navigate Up/Down in the history of typed commands
- * @param direction Go further back in history (+1), go to recently typed commands (-1)
- */
-static void IConsoleHistoryNavigate(int direction)
-{
-	int i = _iconsole_historypos + direction;
-
-	/* watch out for overflows, just wrap around */
-	if (i < 0) i = ICON_HISTORY_SIZE - 1;
-	if (i >= ICON_HISTORY_SIZE) i = 0;
-
-	if (direction > 0)
-		if (_iconsole_history[i] == NULL) i = 0;
-
-	if (direction < 0) {
-		while (i > 0 && _iconsole_history[i] == NULL) i--;
-	}
-
-	_iconsole_historypos = i;
-	IConsoleClearCommand();
-	/* copy history to 'command prompt / bash' */
-	assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
-	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
-	UpdateTextBufferSize(&_iconsole_cmdline);
-}
-
 /**
  * Handle the printing of text entered into the console or redirected there
  * by any other means. Text can be redirected to other players in a network game
@@ -412,7 +84,7 @@
  * @param color_code the colour of the command. Red in case of errors, etc.
  * @param string the message entered or output on the console (notice, error, etc.)
  */
-void IConsolePrint(uint16 color_code, const char *string)
+void IConsolePrint(ConsoleColour color_code, const char *string)
 {
 	char *str;
 #ifdef ENABLE_NETWORK
@@ -437,18 +109,8 @@
 		return;
 	}
 
-	/* move up all the strings in the buffer one place and do the same for colour
-	 * to accomodate for the new command/message */
-	free(_iconsole_buffer[0]);
-	memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
-	_iconsole_buffer[ICON_BUFFER] = str;
-
-	memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
-	_iconsole_cbuffer[ICON_BUFFER] = color_code;
-
-	IConsoleWriteToLogFile(_iconsole_buffer[ICON_BUFFER]);
-
-	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
+	IConsoleWriteToLogFile(str);
+	IConsoleGUIPrint(color_code, str);
 }
 
 /**
@@ -456,7 +118,7 @@
  * by any other means. Uses printf() style format, for more information look
  * at IConsolePrint()
  */
-void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
+void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...)
 {
 	va_list va;
 	char buf[ICON_MAX_STREAMSIZE];
@@ -479,7 +141,7 @@
 void IConsoleDebug(const char *dbg, const char *string)
 {
 	if (_stdlib_developer > 1)
-		IConsolePrintF(_icolour_dbg, "dbg: [%s] %s", dbg, string);
+		IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string);
 }
 
 /**
@@ -490,7 +152,7 @@
 void IConsoleWarning(const char *string)
 {
 	if (_stdlib_developer > 0)
-		IConsolePrintF(_icolour_warn, "WARNING: %s", string);
+		IConsolePrintF(CC_WARNING, "WARNING: %s", string);
 }
 
 /**
@@ -499,7 +161,7 @@
  */
 void IConsoleError(const char *string)
 {
-	IConsolePrintF(_icolour_err, "ERROR: %s", string);
+	IConsolePrintF(CC_ERROR, "ERROR: %s", string);
 }
 
 /**
@@ -748,7 +410,7 @@
 	memset(&aliasstream, 0, sizeof(aliasstream));
 
 	if (_stdlib_con_developer)
-		IConsolePrintF(_icolour_dbg, "condbg: requested command is an alias; parsing...");
+		IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing...");
 
 	aliases[0] = aliasstream;
 	for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) {
@@ -788,7 +450,7 @@
 
 				if (param < 0 || param >= tokencount) {
 					IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
-					IConsolePrintF(_icolour_warn, "Usage of alias '%s': %s", alias->name, alias->cmdline);
+					IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline);
 					return;
 				}
 
@@ -1001,7 +663,7 @@
 	}
 
 	value = IConsoleVarGetStringValue(var);
-	IConsolePrintF(_icolour_warn, "Current value for '%s' is:  %s", var->name, value);
+	IConsolePrintF(CC_WARNING, "Current value for '%s' is:  %s", var->name, value);
 }
 
 /**
@@ -1011,7 +673,7 @@
 void IConsoleVarPrintSetValue(const IConsoleVar *var)
 {
 	char *value = IConsoleVarGetStringValue(var);
-	IConsolePrintF(_icolour_warn, "'%s' changed to:  %s", var->name, value);
+	IConsolePrintF(CC_WARNING, "'%s' changed to:  %s", var->name, value);
 }
 
 /**
@@ -1028,7 +690,7 @@
 	uint32 value;
 
 	if (_stdlib_con_developer)
-		IConsolePrintF(_icolour_dbg, "condbg: requested command is a variable");
+		IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable");
 
 	if (tokencount == 0) { /* Just print out value */
 		IConsoleVarPrintGetValue(var);
@@ -1105,13 +767,13 @@
 	for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
 		if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) {
 			IConsoleError("command contains malformed characters, aborting");
-			IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr);
+			IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr);
 			return;
 		}
 	}
 
 	if (_stdlib_con_developer)
-		IConsolePrintF(_icolour_dbg, "condbg: executing cmdline: '%s'", cmdstr);
+		IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr);
 
 	memset(&tokens, 0, sizeof(tokens));
 	memset(&tokenstream, 0, sizeof(tokenstream));
@@ -1159,7 +821,7 @@
 		uint i;
 
 		for (i = 0; tokens[i] != NULL; i++) {
-			IConsolePrintF(_icolour_dbg, "condbg: token %d is: '%s'", i, tokens[i]);
+			IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]);
 		}
 	}
 
--- a/src/console.h	Mon May 26 20:45:25 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* $Id$ */
-
-/** @file console.h In-game console. */
-
-#ifndef CONSOLE_H
-#define CONSOLE_H
-
-#include "window_type.h"
-
-/* maximum length of a typed in command */
-#define ICON_CMDLN_SIZE 255
-/* maximum length of a totally expanded command */
-#define ICON_MAX_STREAMSIZE 1024
-
-enum IConsoleVarTypes {
-	ICONSOLE_VAR_BOOLEAN,
-	ICONSOLE_VAR_BYTE,
-	ICONSOLE_VAR_UINT16,
-	ICONSOLE_VAR_UINT32,
-	ICONSOLE_VAR_INT16,
-	ICONSOLE_VAR_INT32,
-	ICONSOLE_VAR_STRING
-};
-
-enum IConsoleModes {
-	ICONSOLE_FULL,
-	ICONSOLE_OPENED,
-	ICONSOLE_CLOSED
-};
-
-enum IConsoleHookTypes {
-	ICONSOLE_HOOK_ACCESS,
-	ICONSOLE_HOOK_PRE_ACTION,
-	ICONSOLE_HOOK_POST_ACTION
-};
-
-/** --Hooks--
- * Hooks are certain triggers get get accessed/executed on either
- * access, before execution/change or after execution/change. This allows
- * for general flow of permissions or special action needed in some cases
- */
-typedef bool IConsoleHook();
-struct IConsoleHooks{
-	IConsoleHook *access; ///< trigger when accessing the variable/command
-	IConsoleHook *pre;    ///< trigger before the variable/command is changed/executed
-	IConsoleHook *post;   ///< trigger after the variable/command is changed/executed
-};
-
-/** --Commands--
- * Commands are commands, or functions. They get executed once and any
- * effect they produce are carried out. The arguments to the commands
- * are given to them, each input word seperated by a double-quote (") is an argument
- * If you want to handle multiple words as one, enclose them in double-quotes
- * eg. 'say "hello sexy boy"'
- */
-typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
-
-struct IConsoleCmd {
-	char *name;               ///< name of command
-	IConsoleCmd *next;        ///< next command in list
-
-	IConsoleCmdProc *proc;    ///< process executed when command is typed
-	IConsoleHooks hook;       ///< any special trigger action that needs executing
-};
-
-/** --Variables--
- * Variables are pointers to real ingame variables which allow for
- * changing while ingame. After changing they keep their new value
- * and can be used for debugging, gameplay, etc. It accepts:
- * - no arguments; just print out current value
- * - '= <new value>' to assign a new value to the variable
- * - '++' to increase value by one
- * - '--' to decrease value by one
- */
-struct IConsoleVar {
-	char *name;               ///< name of the variable
-	IConsoleVar *next;        ///< next variable in list
-
-	void *addr;               ///< the address where the variable is pointing at
-	uint32 size;              ///< size of the variable, used for strings
-	char *help;               ///< the optional help string shown when requesting information
-	IConsoleVarTypes type;    ///< type of variable (for correct assignment/output)
-	IConsoleCmdProc *proc;    ///< some variables need really special handling, use a callback function for that
-	IConsoleHooks hook;       ///< any special trigger action that needs executing
-};
-
-/** --Aliases--
- * Aliases are like shortcuts for complex functions, variable assignments,
- * etc. You can use a simple alias to rename a longer command (eg 'lv' for
- * 'list_vars' for example), or concatenate more commands into one
- * (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
- * given to them in the command line.
- * - "%A - %Z" substitute arguments 1 t/m 26
- * - "%+" lists all parameters keeping them seperated
- * - "%!" also lists all parameters but presenting them to the aliased command as one argument
- * - ";" allows for combining commands (see example 'ng')
- */
-struct IConsoleAlias {
-	char *name;                 ///< name of the alias
-	IConsoleAlias *next;        ///< next alias in list
-
-	char *cmdline;              ///< command(s) that is/are being aliased
-};
-
-/* console parser */
-extern IConsoleCmd   *_iconsole_cmds;    ///< list of registred commands
-extern IConsoleVar   *_iconsole_vars;    ///< list of registred vars
-extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
-
-/* console colors/modes */
-extern byte _icolour_def;
-extern byte _icolour_err;
-extern byte _icolour_warn;
-extern byte _icolour_dbg;
-extern byte _icolour_cmd;
-extern IConsoleModes _iconsole_mode;
-
-/* console functions */
-void IConsoleInit();
-void IConsoleFree();
-void IConsoleClearBuffer();
-void IConsoleResize(Window *w);
-void IConsoleSwitch();
-void IConsoleClose();
-void IConsoleOpen();
-
-/* console output */
-void IConsolePrint(uint16 color_code, const char *string);
-void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
-void IConsoleDebug(const char *dbg, const char *string);
-void IConsoleWarning(const char *string);
-void IConsoleError(const char *string);
-
-/* Commands */
-void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
-void IConsoleAliasRegister(const char *name, const char *cmd);
-IConsoleCmd *IConsoleCmdGet(const char *name);
-IConsoleAlias *IConsoleAliasGet(const char *name);
-
-/* Variables */
-void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
-void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
-IConsoleVar* IConsoleVarGet(const char *name);
-void IConsoleVarPrintGetValue(const IConsoleVar *var);
-void IConsoleVarPrintSetValue(const IConsoleVar *var);
-
-/* Parser */
-void IConsoleCmdExec(const char *cmdstr);
-void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
-
-/* console std lib (register ingame commands/aliases/variables) */
-void IConsoleStdLibRegister();
-
-/* Hooking code */
-void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
-void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
-void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
-
-/* Supporting functions */
-bool GetArgumentInteger(uint32 *value, const char *arg);
-#endif /* CONSOLE_H */
--- a/src/console_cmds.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/console_cmds.cpp	Tue May 27 00:50:55 2008 +0000
@@ -4,7 +4,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
-#include "console.h"
+#include "console_internal.h"
 #include "debug.h"
 #include "engine_func.h"
 #include "landscape.h"
@@ -107,7 +107,7 @@
 
 static void IConsoleHelp(const char *str)
 {
-	IConsolePrintF(_icolour_warn, "- %s", str);
+	IConsolePrintF(CC_WARNING, "- %s", str);
 }
 
 DEF_CONSOLE_CMD(ConResetEngines)
@@ -165,7 +165,7 @@
 		uint32 result;
 		if (GetArgumentInteger(&result, argv[1])) {
 			if (result >= MapSize()) {
-				IConsolePrint(_icolour_err, "Tile does not exist");
+				IConsolePrint(CC_ERROR, "Tile does not exist");
 				return true;
 			}
 			ScrollMainWindowToTile((TileIndex)result);
@@ -189,12 +189,12 @@
 
 	if (argc == 2) {
 		char *filename = str_fmt("%s.sav", argv[1]);
-		IConsolePrint(_icolour_def, "Saving map...");
+		IConsolePrint(CC_DEFAULT, "Saving map...");
 
 		if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
-			IConsolePrint(_icolour_err, "Saving map failed");
+			IConsolePrint(CC_ERROR, "Saving map failed");
 		} else {
-			IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", filename);
+			IConsolePrintF(CC_DEFAULT, "Map sucessfully saved to %s", filename);
 		}
 		free(filename);
 		return true;
@@ -212,7 +212,7 @@
 	}
 
 	SaveToConfig();
-	IConsolePrint(_icolour_def, "Saved config.");
+	IConsolePrint(CC_DEFAULT, "Saved config.");
 	return true;
 }
 
@@ -262,10 +262,10 @@
 				ttd_strlcpy(_file_to_saveload.name, FiosBrowseTo(item), sizeof(_file_to_saveload.name));
 				ttd_strlcpy(_file_to_saveload.title, item->title, sizeof(_file_to_saveload.title));
 			} break;
-			default: IConsolePrintF(_icolour_err, "%s: Not a savegame.", file);
+			default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
 		}
 	} else {
-		IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
+		IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
 	}
 
 	FiosFreeSavegameList();
@@ -289,9 +289,9 @@
 	item = GetFiosItem(file);
 	if (item != NULL) {
 		if (!FiosDelete(item->name))
-			IConsolePrintF(_icolour_err, "%s: Failed to delete file", file);
+			IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
 	} else {
-		IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
+		IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
 	}
 
 	FiosFreeSavegameList();
@@ -313,7 +313,7 @@
 
 	for (i = 0; i < _fios_num; i++) {
 		const FiosItem *item = &_fios_list[i];
-		IConsolePrintF(_icolour_def, "%d) %s", i, item->title);
+		IConsolePrintF(CC_DEFAULT, "%d) %s", i, item->title);
 	}
 
 	FiosFreeSavegameList();
@@ -340,10 +340,10 @@
 			case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
 				FiosBrowseTo(item);
 				break;
-			default: IConsolePrintF(_icolour_err, "%s: Not a directory.", file);
+			default: IConsolePrintF(CC_ERROR, "%s: Not a directory.", file);
 		}
 	} else {
-		IConsolePrintF(_icolour_err, "%s: No such file or directory.", file);
+		IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
 	}
 
 	FiosFreeSavegameList();
@@ -364,7 +364,7 @@
 	FiosFreeSavegameList();
 
 	FiosGetDescText(&path, NULL);
-	IConsolePrint(_icolour_def, path);
+	IConsolePrint(CC_DEFAULT, path);
 	return true;
 }
 
@@ -427,9 +427,9 @@
 	if (ci != NULL) {
 		banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
 		SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
-		IConsolePrint(_icolour_def, "Client banned");
+		IConsolePrint(CC_DEFAULT, "Client banned");
 	} else {
-		IConsolePrint(_icolour_def, "Client not online, banned IP");
+		IConsolePrint(CC_DEFAULT, "Client not online, banned IP");
 	}
 
 	/* Add user to ban-list */
@@ -464,12 +464,12 @@
 		if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) {
 			free(_network_ban_list[i]);
 			_network_ban_list[i] = NULL;
-			IConsolePrint(_icolour_def, "IP unbanned.");
+			IConsolePrint(CC_DEFAULT, "IP unbanned.");
 			return true;
 		}
 	}
 
-	IConsolePrint(_icolour_def, "IP not in ban-list.");
+	IConsolePrint(CC_DEFAULT, "IP not in ban-list.");
 	return true;
 }
 
@@ -482,11 +482,11 @@
 		return true;
 	}
 
-	IConsolePrint(_icolour_def, "Banlist: ");
+	IConsolePrint(CC_DEFAULT, "Banlist: ");
 
 	for (i = 0; i < lengthof(_network_ban_list); i++) {
 		if (_network_ban_list[i] != NULL)
-			IConsolePrintF(_icolour_def, "  %d) %s", i + 1, _network_ban_list[i]);
+			IConsolePrintF(CC_DEFAULT, "  %d) %s", i + 1, _network_ban_list[i]);
 	}
 
 	return true;
@@ -501,9 +501,9 @@
 
 	if (_pause_game == 0) {
 		DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
-		IConsolePrint(_icolour_def, "Game paused.");
+		IConsolePrint(CC_DEFAULT, "Game paused.");
 	} else {
-		IConsolePrint(_icolour_def, "Game is already paused.");
+		IConsolePrint(CC_DEFAULT, "Game is already paused.");
 	}
 
 	return true;
@@ -518,9 +518,9 @@
 
 	if (_pause_game != 0) {
 		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
-		IConsolePrint(_icolour_def, "Game unpaused.");
+		IConsolePrint(CC_DEFAULT, "Game unpaused.");
 	} else {
-		IConsolePrint(_icolour_def, "Game is already unpaused.");
+		IConsolePrint(CC_DEFAULT, "Game is already unpaused.");
 	}
 
 	return true;
@@ -570,7 +570,7 @@
 		const char* status;
 
 		status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
-		IConsolePrintF(8, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
+		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
 			cs->index, ci->client_name, status, lag,
 			ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
 			GetPlayerIP(ci), ci->unique_id);
@@ -590,9 +590,9 @@
 	}
 
 	gi = &_network_game_info;
-	IConsolePrintF(_icolour_def, "Current/maximum clients:    %2d/%2d", gi->clients_on, gi->clients_max);
-	IConsolePrintF(_icolour_def, "Current/maximum companies:  %2d/%2d", ActivePlayerCount(), gi->companies_max);
-	IConsolePrintF(_icolour_def, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max);
+	IConsolePrintF(CC_DEFAULT, "Current/maximum clients:    %2d/%2d", gi->clients_on, gi->clients_max);
+	IConsolePrintF(CC_DEFAULT, "Current/maximum companies:  %2d/%2d", ActivePlayerCount(), gi->companies_max);
+	IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max);
 
 	return true;
 }
@@ -693,7 +693,7 @@
 
 	/* Check valid range */
 	if (!IsValidPlayer(index)) {
-		IConsolePrintF(_icolour_err, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS);
+		IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS);
 		return true;
 	}
 
@@ -725,7 +725,7 @@
 
 	/* It is safe to remove this company */
 	DoCommandP(0, 2, index, NULL, CMD_PLAYER_CTRL);
-	IConsolePrint(_icolour_def, "Company deleted.");
+	IConsolePrint(CC_DEFAULT, "Company deleted.");
 
 	return true;
 }
@@ -740,7 +740,7 @@
 	}
 
 	FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
-		IConsolePrintF(8, "Client #%1d  name: '%s'  company: %1d  IP: %s",
+		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  company: %1d  IP: %s",
 		               ci->client_index, ci->client_name,
 		               ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
 		               GetPlayerIP(ci));
@@ -773,10 +773,10 @@
 
 	ParseConnectionString(&player, &port, ip);
 
-	IConsolePrintF(_icolour_def, "Connecting to %s...", ip);
+	IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
 	if (player != NULL) {
 		_network_playas = (PlayerID)atoi(player);
-		IConsolePrintF(_icolour_def, "    player-no: %d", _network_playas);
+		IConsolePrintF(CC_DEFAULT, "    player-no: %d", _network_playas);
 
 		/* From a user pov 0 is a new player, internally it's different and all
 		 * players are offset by one to ease up on users (eg players 1-8 not 0-7) */
@@ -787,7 +787,7 @@
 	}
 	if (port != NULL) {
 		rport = atoi(port);
-		IConsolePrintF(_icolour_def, "    port: %s", port);
+		IConsolePrintF(CC_DEFAULT, "    port: %s", port);
 	}
 
 	NetworkClientConnectGame(ip, rport);
@@ -870,7 +870,7 @@
 	if (!CloseConsoleLogIfActive()) {
 		if (argc < 2) return false;
 
-		IConsolePrintF(_icolour_def, "file output started to: %s", argv[1]);
+		IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
 		_iconsole_output_file = fopen(argv[1], "ab");
 		if (_iconsole_output_file == NULL) IConsoleError("could not open file");
 	}
@@ -887,7 +887,7 @@
 	}
 
 	if (argc < 2) return false;
-	IConsolePrint(_icolour_def, argv[1]);
+	IConsolePrint(CC_DEFAULT, argv[1]);
 	return true;
 }
 
@@ -899,7 +899,7 @@
 	}
 
 	if (argc < 3) return false;
-	IConsolePrint(atoi(argv[1]), argv[2]);
+	IConsolePrint((ConsoleColour)atoi(argv[1]), argv[2]);
 	return true;
 }
 
@@ -926,8 +926,8 @@
 	}
 
 	/* Don't copy the _newgame pointers to the real pointers, so call SwitchMode directly */
-	_patches.map_x = MapLogX();
-	_patches.map_y = FindFirstBit(MapSizeY());
+	_settings.game_creation.map_x = MapLogX();
+	_settings.game_creation.map_y = FindFirstBit(MapSizeY());
 	SwitchMode(SM_NEWGAME);
 	return true;
 }
@@ -940,7 +940,7 @@
 		return true;
 	}
 
-	IConsolePrintF(_icolour_def, "Generation Seed: %u", _patches.generation_seed);
+	IConsolePrintF(CC_DEFAULT, "Generation Seed: %u", _settings.game_creation.generation_seed);
 	return true;
 }
 
@@ -953,7 +953,7 @@
 
 	YearMonthDay ymd;
 	ConvertDateToYMD(_date, &ymd);
-	IConsolePrintF(_icolour_def, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
+	IConsolePrintF(CC_DEFAULT, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
 	return true;
 }
 
@@ -1019,9 +1019,9 @@
 		return true;
 	}
 
-	IConsolePrintF(_icolour_def, "variable name: %s", var->name);
-	IConsolePrintF(_icolour_def, "variable type: %s", _icon_vartypes[var->type]);
-	IConsolePrintF(_icolour_def, "variable addr: 0x%X", var->addr);
+	IConsolePrintF(CC_DEFAULT, "variable name: %s", var->name);
+	IConsolePrintF(CC_DEFAULT, "variable type: %s", _icon_vartypes[var->type]);
+	IConsolePrintF(CC_DEFAULT, "variable addr: 0x%X", var->addr);
 
 	if (var->hook.access) IConsoleWarning("variable is access hooked");
 	if (var->hook.pre) IConsoleWarning("variable is pre hooked");
@@ -1047,8 +1047,8 @@
 		return true;
 	}
 
-	IConsolePrintF(_icolour_def, "command name: %s", cmd->name);
-	IConsolePrintF(_icolour_def, "command proc: 0x%X", cmd->proc);
+	IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name);
+	IConsolePrintF(CC_DEFAULT, "command proc: 0x%X", cmd->proc);
 
 	if (cmd->hook.access) IConsoleWarning("command is access hooked");
 	if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
@@ -1068,7 +1068,7 @@
 	if (argc > 2) return false;
 
 	if (argc == 1) {
-		IConsolePrintF(_icolour_def, "Current debug-level: '%s'", GetDebugString());
+		IConsolePrintF(CC_DEFAULT, "Current debug-level: '%s'", GetDebugString());
 	} else {
 		SetDebugString(argv[1]);
 	}
@@ -1083,7 +1083,7 @@
 		return true;
 	}
 
-	if (_game_mode == GM_NORMAL && _patches.autosave_on_exit) DoExitSave();
+	if (_game_mode == GM_NORMAL && _settings.gui.autosave_on_exit) DoExitSave();
 
 	_exit_game = true;
 	return true;
@@ -1122,7 +1122,7 @@
 				cmd->proc(0, NULL);
 				return true;
 			}
-			IConsolePrintF(_icolour_err, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline);
+			IConsolePrintF(CC_ERROR, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline);
 			return true;
 		}
 
@@ -1136,18 +1136,18 @@
 		return true;
 	}
 
-	IConsolePrint(13, " ---- OpenTTD Console Help ---- ");
-	IConsolePrint( 1, " - variables: [command to list all variables: list_vars]");
-	IConsolePrint( 1, " set value with '<var> = <value>', use '++/--' to in-or decrement");
-	IConsolePrint( 1, " or omit '=' and just '<var> <value>'. get value with typing '<var>'");
-	IConsolePrint( 1, " - commands: [command to list all commands: list_cmds]");
-	IConsolePrint( 1, " call commands with '<command> <arg2> <arg3>...'");
-	IConsolePrint( 1, " - to assign strings, or use them as arguments, enclose it within quotes");
-	IConsolePrint( 1, " like this: '<command> \"string argument with spaces\"'");
-	IConsolePrint( 1, " - use 'help <command> | <variable>' to get specific information");
-	IConsolePrint( 1, " - scroll console output with shift + (up | down) | (pageup | pagedown))");
-	IConsolePrint( 1, " - scroll console input history with the up | down arrows");
-	IConsolePrint( 1, "");
+	IConsolePrint(CC_WARNING, " ---- OpenTTD Console Help ---- ");
+	IConsolePrint(CC_DEFAULT, " - variables: [command to list all variables: list_vars]");
+	IConsolePrint(CC_DEFAULT, " set value with '<var> = <value>', use '++/--' to in-or decrement");
+	IConsolePrint(CC_DEFAULT, " or omit '=' and just '<var> <value>'. get value with typing '<var>'");
+	IConsolePrint(CC_DEFAULT, " - commands: [command to list all commands: list_cmds]");
+	IConsolePrint(CC_DEFAULT, " call commands with '<command> <arg2> <arg3>...'");
+	IConsolePrint(CC_DEFAULT, " - to assign strings, or use them as arguments, enclose it within quotes");
+	IConsolePrint(CC_DEFAULT, " like this: '<command> \"string argument with spaces\"'");
+	IConsolePrint(CC_DEFAULT, " - use 'help <command> | <variable>' to get specific information");
+	IConsolePrint(CC_DEFAULT, " - scroll console output with shift + (up | down) | (pageup | pagedown))");
+	IConsolePrint(CC_DEFAULT, " - scroll console input history with the up | down arrows");
+	IConsolePrint(CC_DEFAULT, "");
 	return true;
 }
 
@@ -1165,7 +1165,7 @@
 
 	for (cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
 		if (argv[1] == NULL || strncmp(cmd->name, argv[1], l) == 0) {
-				IConsolePrintF(_icolour_def, "%s", cmd->name);
+				IConsolePrintF(CC_DEFAULT, "%s", cmd->name);
 		}
 	}
 
@@ -1186,7 +1186,7 @@
 
 	for (var = _iconsole_vars; var != NULL; var = var->next) {
 		if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
-			IConsolePrintF(_icolour_def, "%s", var->name);
+			IConsolePrintF(CC_DEFAULT, "%s", var->name);
 	}
 
 	return true;
@@ -1206,7 +1206,7 @@
 
 	for (alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
 		if (argv[1] == NULL || strncmp(alias->name, argv[1], l) == 0)
-			IConsolePrintF(_icolour_def, "%s => %s", alias->name, alias->cmdline);
+			IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name, alias->cmdline);
 	}
 
 	return true;
@@ -1250,7 +1250,7 @@
 		const NetworkPlayerInfo *npi = &_network_player_info[p->index];
 
 		GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer));
-		IConsolePrintF(8, "#:%d(%s) Company Name: '%s'  Year Founded: %d  Money: %" OTTD_PRINTF64 "d  Loan: %" OTTD_PRINTF64 "d  Value: %" OTTD_PRINTF64 "d  (T:%d, R:%d, P:%d, S:%d) %sprotected",
+		IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s'  Year Founded: %d  Money: %" OTTD_PRINTF64 "d  Loan: %" OTTD_PRINTF64 "d  Value: %" OTTD_PRINTF64 "d  (T:%d, R:%d, P:%d, S:%d) %sprotected",
 			p->index + 1, buffer, npi->company_name, p->inaugurated_year, (int64)p->player_money, (int64)p->current_loan, (int64)CalculateCompanyValue(p),
 			/* trains      */ npi->num_vehicle[0],
 			/* lorry + bus */ npi->num_vehicle[1] + npi->num_vehicle[2],
@@ -1273,7 +1273,7 @@
 	if (argc != 3) return false;
 
 	if (atoi(argv[1]) < 1 || atoi(argv[1]) > MAX_PLAYERS) {
-		IConsolePrintF(_icolour_def, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS);
+		IConsolePrintF(CC_DEFAULT, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS);
 		return true;
 	}
 
@@ -1335,7 +1335,7 @@
 {
 	if (argc == 0) {
 		if (!IsValidPlayer(_local_player)) return true; // dedicated server
-		IConsolePrintF(_icolour_warn, "Current value for 'company_pw': %s", _network_player_info[_local_player].password);
+		IConsolePrintF(CC_WARNING, "Current value for 'company_pw': %s", _network_player_info[_local_player].password);
 		return true;
 	}
 
@@ -1356,7 +1356,7 @@
 		HashCurrentCompanyPassword();
 	}
 
-	IConsolePrintF(_icolour_warn, "'company_pw' changed to:  %s", _network_player_info[_local_player].password);
+	IConsolePrintF(CC_WARNING, "'company_pw' changed to:  %s", _network_player_info[_local_player].password);
 
 	return true;
 }
@@ -1373,7 +1373,7 @@
 			SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
 		} else {
 			if (NetworkFindName(_network_player_name)) {
-				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", _network_player_name);
+				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _network_player_name);
 				ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
 				NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
 			}
@@ -1400,7 +1400,7 @@
 DEF_CONSOLE_CMD(ConProcServerIP)
 {
 	if (argc == 0) {
-		IConsolePrintF(_icolour_warn, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+		IConsolePrintF(CC_WARNING, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
 		return true;
 	}
 
@@ -1408,7 +1408,7 @@
 
 	_network_server_bind_ip = (strcmp(argv[0], "all") == 0) ? inet_addr("0.0.0.0") : inet_addr(argv[0]);
 	snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-	IConsolePrintF(_icolour_warn, "'server_ip' changed to:  %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+	IConsolePrintF(CC_WARNING, "'server_ip' changed to:  %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
 	return true;
 }
 #endif /* ENABLE_NETWORK */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console_func.h	Tue May 27 00:50:55 2008 +0000
@@ -0,0 +1,26 @@
+/* $Id$ */
+
+/** @file console_func.h Console functions used outside of the console code. */
+
+#ifndef CONSOLE_FUNC_H
+#define CONSOLE_FUNC_H
+
+#include "console_type.h"
+
+/* console modes */
+extern IConsoleModes _iconsole_mode;
+
+/* console functions */
+void IConsoleInit();
+void IConsoleFree();
+void IConsoleClose();
+
+/* console output */
+void IConsolePrint(ConsoleColour color_code, const char *string);
+void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...);
+void IConsoleDebug(const char *dbg, const char *string);
+
+/* Parser */
+void IConsoleCmdExec(const char *cmdstr);
+
+#endif /* CONSOLE_FUNC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -0,0 +1,366 @@
+/* $Id$ */
+
+/** @file console.cpp Handling of the in-game console. */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "textbuf_gui.h"
+#include "window_gui.h"
+#include "console_gui.h"
+#include <stdarg.h>
+#include <string.h>
+#include "console_internal.h"
+#include "window_func.h"
+#include "string_func.h"
+#include "gfx_func.h"
+#include "core/math_func.hpp"
+#include "rev.h"
+
+#include "table/strings.h"
+
+#define ICON_BUFFER 79
+#define ICON_HISTORY_SIZE 20
+#define ICON_LINE_HEIGHT 12
+#define ICON_RIGHT_BORDERWIDTH 10
+#define ICON_BOTTOM_BORDERWIDTH 12
+#define ICON_MAX_ALIAS_LINES 40
+#define ICON_TOKEN_COUNT 20
+
+/* console modes */
+IConsoleModes _iconsole_mode;
+
+/* ** main console ** */
+static char *_iconsole_buffer[ICON_BUFFER + 1];
+static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
+static Textbuf _iconsole_cmdline;
+
+/* ** main console cmd buffer ** */
+static char *_iconsole_history[ICON_HISTORY_SIZE];
+static byte _iconsole_historypos;
+
+/* *************** *
+ *  end of header  *
+ * *************** */
+
+static void IConsoleClearCommand()
+{
+	memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
+	_iconsole_cmdline.length = 0;
+	_iconsole_cmdline.width = 0;
+	_iconsole_cmdline.caretpos = 0;
+	_iconsole_cmdline.caretxoffs = 0;
+	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
+}
+
+static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
+
+
+static void IConsoleHistoryAdd(const char *cmd);
+static void IConsoleHistoryNavigate(int direction);
+
+struct IConsoleWindow : Window
+{
+	static byte scroll;
+
+	IConsoleWindow(const WindowDesc *desc) : Window(desc)
+	{
+		_iconsole_mode = ICONSOLE_OPENED;
+		SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
+
+		this->height = _screen.height / 3;
+		this->width  = _screen.width;
+	}
+
+	~IConsoleWindow()
+	{
+		_iconsole_mode = ICONSOLE_CLOSED;
+		ClrBit(_no_scroll, SCROLL_CON);
+	}
+
+	virtual void OnPaint()
+	{
+		int i = IConsoleWindow::scroll;
+		int max = (this->height / ICON_LINE_HEIGHT) - 1;
+		int delta = 0;
+		GfxFillRect(this->left, this->top, this->width, this->height - 1, 0);
+		while ((i > 0) && (i > IConsoleWindow::scroll - max) && (_iconsole_buffer[i] != NULL)) {
+			DoDrawString(_iconsole_buffer[i], 5,
+				this->height - (IConsoleWindow::scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
+			i--;
+		}
+		/* If the text is longer than the window, don't show the starting ']' */
+		delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
+		if (delta > 0) {
+			DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, CC_COMMAND);
+			delta = 0;
+		}
+
+		DoDrawString(_iconsole_cmdline.buf, 10 + delta, this->height - ICON_LINE_HEIGHT, CC_COMMAND);
+
+		if (_iconsole_cmdline.caret) {
+			DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE);
+		}
+	}
+
+	virtual void OnMouseLoop()
+	{
+		if (HandleCaret(&_iconsole_cmdline)) this->SetDirty();
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		switch (keycode) {
+			case WKC_UP:
+				IConsoleHistoryNavigate(+1);
+				this->SetDirty();
+				break;
+
+			case WKC_DOWN:
+				IConsoleHistoryNavigate(-1);
+				this->SetDirty();
+				break;
+
+			case WKC_SHIFT | WKC_PAGEUP:
+				if (IConsoleWindow::scroll - (this->height / ICON_LINE_HEIGHT) - 1 < 0) {
+					IConsoleWindow::scroll = 0;
+				} else {
+					IConsoleWindow::scroll -= (this->height / ICON_LINE_HEIGHT) - 1;
+				}
+				this->SetDirty();
+				break;
+
+			case WKC_SHIFT | WKC_PAGEDOWN:
+				if (IConsoleWindow::scroll + (this->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
+					IConsoleWindow::scroll = ICON_BUFFER;
+				} else {
+					IConsoleWindow::scroll += (this->height / ICON_LINE_HEIGHT) - 1;
+				}
+				this->SetDirty();
+				break;
+
+			case WKC_SHIFT | WKC_UP:
+				if (IConsoleWindow::scroll <= 0) {
+					IConsoleWindow::scroll = 0;
+				} else {
+					--IConsoleWindow::scroll;
+				}
+				this->SetDirty();
+				break;
+
+			case WKC_SHIFT | WKC_DOWN:
+				if (IConsoleWindow::scroll >= ICON_BUFFER) {
+					IConsoleWindow::scroll = ICON_BUFFER;
+				} else {
+					++IConsoleWindow::scroll;
+				}
+				this->SetDirty();
+				break;
+
+			case WKC_BACKQUOTE:
+				IConsoleSwitch();
+				break;
+
+			case WKC_RETURN: case WKC_NUM_ENTER:
+				IConsolePrintF(CC_COMMAND, "] %s", _iconsole_cmdline.buf);
+				IConsoleHistoryAdd(_iconsole_cmdline.buf);
+
+				IConsoleCmdExec(_iconsole_cmdline.buf);
+				IConsoleClearCommand();
+				break;
+
+			case WKC_CTRL | WKC_RETURN:
+				_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
+				IConsoleResize(this);
+				MarkWholeScreenDirty();
+				break;
+
+			case (WKC_CTRL | 'V'):
+				if (InsertTextBufferClipboard(&_iconsole_cmdline)) {
+					IConsoleResetHistoryPos();
+					this->SetDirty();
+				}
+				break;
+
+			case (WKC_CTRL | 'L'):
+				IConsoleCmdExec("clear");
+				break;
+
+			case (WKC_CTRL | 'U'):
+				DeleteTextBufferAll(&_iconsole_cmdline);
+				this->SetDirty();
+				break;
+
+			case WKC_BACKSPACE: case WKC_DELETE:
+				if (DeleteTextBufferChar(&_iconsole_cmdline, keycode)) {
+					IConsoleResetHistoryPos();
+					this->SetDirty();
+				}
+				break;
+
+			case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
+				if (MoveTextBufferPos(&_iconsole_cmdline, keycode)) {
+					IConsoleResetHistoryPos();
+					this->SetDirty();
+				}
+				break;
+
+			default:
+				if (IsValidChar(key, CS_ALPHANUMERAL)) {
+					IConsoleWindow::scroll = ICON_BUFFER;
+					InsertTextBufferChar(&_iconsole_cmdline, key);
+					IConsoleResetHistoryPos();
+					this->SetDirty();
+				} else {
+					return ES_NOT_HANDLED;
+				}
+		}
+		return ES_HANDLED;
+	}
+};
+
+byte IConsoleWindow::scroll = ICON_BUFFER;
+
+static const Widget _iconsole_window_widgets[] = {
+	{WIDGETS_END}
+};
+
+static const WindowDesc _iconsole_window_desc = {
+	0, 0, 2, 2, 2, 2,
+	WC_CONSOLE, WC_NONE,
+	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_iconsole_window_widgets,
+};
+
+void IConsoleGUIInit()
+{
+	_iconsole_historypos = ICON_HISTORY_SIZE - 1;
+	_iconsole_mode = ICONSOLE_CLOSED;
+
+	memset(_iconsole_history, 0, sizeof(_iconsole_history));
+	memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
+	memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
+	_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
+	_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
+
+	IConsolePrintF(CC_WARNING, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
+	IConsolePrint(CC_WHITE,  "------------------------------------");
+	IConsolePrint(CC_WHITE,  "use \"help\" for more information");
+	IConsolePrint(CC_WHITE,  "");
+	IConsoleClearCommand();
+	IConsoleHistoryAdd("");
+}
+
+void IConsoleClearBuffer()
+{
+	uint i;
+	for (i = 0; i <= ICON_BUFFER; i++) {
+		free(_iconsole_buffer[i]);
+		_iconsole_buffer[i] = NULL;
+	}
+}
+
+void IConsoleGUIFree()
+{
+	free(_iconsole_cmdline.buf);
+	IConsoleClearBuffer();
+}
+
+void IConsoleResize(Window *w)
+{
+	switch (_iconsole_mode) {
+		case ICONSOLE_OPENED:
+			w->height = _screen.height / 3;
+			w->width = _screen.width;
+			break;
+		case ICONSOLE_FULL:
+			w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH;
+			w->width = _screen.width;
+			break;
+		default: return;
+	}
+
+	MarkWholeScreenDirty();
+}
+
+void IConsoleSwitch()
+{
+	switch (_iconsole_mode) {
+		case ICONSOLE_CLOSED:
+			new IConsoleWindow(&_iconsole_window_desc);
+			break;
+
+		case ICONSOLE_OPENED: case ICONSOLE_FULL:
+			DeleteWindowById(WC_CONSOLE, 0);
+			break;
+	}
+
+	MarkWholeScreenDirty();
+}
+
+void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
+void IConsoleOpen()  {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
+
+/**
+ * Add the entered line into the history so you can look it back
+ * scroll, etc. Put it to the beginning as it is the latest text
+ * @param cmd Text to be entered into the 'history'
+ */
+static void IConsoleHistoryAdd(const char *cmd)
+{
+	free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
+
+	memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
+	_iconsole_history[0] = strdup(cmd);
+	IConsoleResetHistoryPos();
+}
+
+/**
+ * Navigate Up/Down in the history of typed commands
+ * @param direction Go further back in history (+1), go to recently typed commands (-1)
+ */
+static void IConsoleHistoryNavigate(int direction)
+{
+	int i = _iconsole_historypos + direction;
+
+	/* watch out for overflows, just wrap around */
+	if (i < 0) i = ICON_HISTORY_SIZE - 1;
+	if (i >= ICON_HISTORY_SIZE) i = 0;
+
+	if (direction > 0) {
+		if (_iconsole_history[i] == NULL) i = 0;
+	}
+
+	if (direction < 0) {
+		while (i > 0 && _iconsole_history[i] == NULL) i--;
+	}
+
+	_iconsole_historypos = i;
+	IConsoleClearCommand();
+	/* copy history to 'command prompt / bash' */
+	assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
+	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
+	UpdateTextBufferSize(&_iconsole_cmdline);
+}
+
+/**
+ * Handle the printing of text entered into the console or redirected there
+ * by any other means. Text can be redirected to other players in a network game
+ * as well as to a logfile. If the network server is a dedicated server, all activities
+ * are also logged. All lines to print are added to a temporary buffer which can be
+ * used as a history to print them onscreen
+ * @param color_code the colour of the command. Red in case of errors, etc.
+ * @param string the message entered or output on the console (notice, error, etc.)
+ */
+void IConsoleGUIPrint(ConsoleColour color_code, char *str)
+{
+	/* move up all the strings in the buffer one place and do the same for colour
+	 * to accomodate for the new command/message */
+	free(_iconsole_buffer[0]);
+	memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
+	_iconsole_buffer[ICON_BUFFER] = str;
+
+	memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
+	_iconsole_cbuffer[ICON_BUFFER] = color_code;
+
+	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -0,0 +1,13 @@
+/* $Id$ */
+
+/** @file console_gui.h GUI related functions in the console. */
+
+#ifndef CONSOLE_GUI_H
+#define CONSOLE_GUI_H
+
+#include "window_type.h"
+
+void IConsoleResize(Window *w);
+void IConsoleSwitch();
+
+#endif /* CONSOLE_GUI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console_internal.h	Tue May 27 00:50:55 2008 +0000
@@ -0,0 +1,143 @@
+/* $Id$ */
+
+/** @file console_internal.h Internally used functions for the console. */
+
+#ifndef CONSOLE_INTERNAL_H
+#define CONSOLE_INTERNAL_H
+
+#include "console_func.h"
+
+/* maximum length of a typed in command */
+#define ICON_CMDLN_SIZE 255
+/* maximum length of a totally expanded command */
+#define ICON_MAX_STREAMSIZE 1024
+
+enum IConsoleVarTypes {
+	ICONSOLE_VAR_BOOLEAN,
+	ICONSOLE_VAR_BYTE,
+	ICONSOLE_VAR_UINT16,
+	ICONSOLE_VAR_UINT32,
+	ICONSOLE_VAR_INT16,
+	ICONSOLE_VAR_INT32,
+	ICONSOLE_VAR_STRING
+};
+
+enum IConsoleHookTypes {
+	ICONSOLE_HOOK_ACCESS,
+	ICONSOLE_HOOK_PRE_ACTION,
+	ICONSOLE_HOOK_POST_ACTION
+};
+
+/** --Hooks--
+ * Hooks are certain triggers get get accessed/executed on either
+ * access, before execution/change or after execution/change. This allows
+ * for general flow of permissions or special action needed in some cases
+ */
+typedef bool IConsoleHook();
+struct IConsoleHooks{
+	IConsoleHook *access; ///< trigger when accessing the variable/command
+	IConsoleHook *pre;    ///< trigger before the variable/command is changed/executed
+	IConsoleHook *post;   ///< trigger after the variable/command is changed/executed
+};
+
+/** --Commands--
+ * Commands are commands, or functions. They get executed once and any
+ * effect they produce are carried out. The arguments to the commands
+ * are given to them, each input word seperated by a double-quote (") is an argument
+ * If you want to handle multiple words as one, enclose them in double-quotes
+ * eg. 'say "hello sexy boy"'
+ */
+typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
+
+struct IConsoleCmd {
+	char *name;               ///< name of command
+	IConsoleCmd *next;        ///< next command in list
+
+	IConsoleCmdProc *proc;    ///< process executed when command is typed
+	IConsoleHooks hook;       ///< any special trigger action that needs executing
+};
+
+/** --Variables--
+ * Variables are pointers to real ingame variables which allow for
+ * changing while ingame. After changing they keep their new value
+ * and can be used for debugging, gameplay, etc. It accepts:
+ * - no arguments; just print out current value
+ * - '= <new value>' to assign a new value to the variable
+ * - '++' to increase value by one
+ * - '--' to decrease value by one
+ */
+struct IConsoleVar {
+	char *name;               ///< name of the variable
+	IConsoleVar *next;        ///< next variable in list
+
+	void *addr;               ///< the address where the variable is pointing at
+	uint32 size;              ///< size of the variable, used for strings
+	char *help;               ///< the optional help string shown when requesting information
+	IConsoleVarTypes type;    ///< type of variable (for correct assignment/output)
+	IConsoleCmdProc *proc;    ///< some variables need really special handling, use a callback function for that
+	IConsoleHooks hook;       ///< any special trigger action that needs executing
+};
+
+/** --Aliases--
+ * Aliases are like shortcuts for complex functions, variable assignments,
+ * etc. You can use a simple alias to rename a longer command (eg 'lv' for
+ * 'list_vars' for example), or concatenate more commands into one
+ * (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
+ * given to them in the command line.
+ * - "%A - %Z" substitute arguments 1 t/m 26
+ * - "%+" lists all parameters keeping them seperated
+ * - "%!" also lists all parameters but presenting them to the aliased command as one argument
+ * - ";" allows for combining commands (see example 'ng')
+ */
+struct IConsoleAlias {
+	char *name;                 ///< name of the alias
+	IConsoleAlias *next;        ///< next alias in list
+
+	char *cmdline;              ///< command(s) that is/are being aliased
+};
+
+/* console parser */
+extern IConsoleCmd   *_iconsole_cmds;    ///< list of registred commands
+extern IConsoleVar   *_iconsole_vars;    ///< list of registred vars
+extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
+
+/* console functions */
+void IConsoleClearBuffer();
+void IConsoleOpen();
+
+/* console output */
+void IConsoleWarning(const char *string);
+void IConsoleError(const char *string);
+
+/* Commands */
+void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
+void IConsoleAliasRegister(const char *name, const char *cmd);
+IConsoleCmd *IConsoleCmdGet(const char *name);
+IConsoleAlias *IConsoleAliasGet(const char *name);
+
+/* Variables */
+void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
+void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
+IConsoleVar* IConsoleVarGet(const char *name);
+void IConsoleVarPrintGetValue(const IConsoleVar *var);
+void IConsoleVarPrintSetValue(const IConsoleVar *var);
+
+/* Parser */
+void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
+
+/* console std lib (register ingame commands/aliases/variables) */
+void IConsoleStdLibRegister();
+
+/* Hooking code */
+void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
+void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
+void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
+
+/* Supporting functions */
+bool GetArgumentInteger(uint32 *value, const char *arg);
+
+void IConsoleGUIInit();
+void IConsoleGUIFree();
+void IConsoleGUIPrint(ConsoleColour color_code, char *string);
+
+#endif /* CONSOLE_INTERNAL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console_type.h	Tue May 27 00:50:55 2008 +0000
@@ -0,0 +1,24 @@
+/* $Id$ */
+
+/** @file console_type.h Globally used console related types. */
+
+#ifndef CONSOLE_TYPE_H
+#define CONSOLE_TYPE_H
+
+enum IConsoleModes {
+	ICONSOLE_FULL,
+	ICONSOLE_OPENED,
+	ICONSOLE_CLOSED
+};
+
+enum ConsoleColour {
+	CC_DEFAULT =  1,
+	CC_ERROR   =  3,
+	CC_WARNING = 13,
+	CC_INFO    =  8,
+	CC_DEBUG   =  5,
+	CC_COMMAND =  2,
+	CC_WHITE   = 12,
+};
+
+#endif /* CONSOLE_TYPE_H */
--- a/src/core/bitmath_func.hpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/core/bitmath_func.hpp	Tue May 27 00:50:55 2008 +0000
@@ -97,7 +97,7 @@
  * @param y The second value
  * @return True if at least one bit is set in both values, false else.
  */
-#define HASBITS(x, y) ((x) & (y))
+#define HASBITS(x, y) (((x) & (y)) != 0)
 
 /**
  * Set a bit in a variable.
--- a/src/currency.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/currency.cpp	Tue May 27 00:50:55 2008 +0000
@@ -150,10 +150,10 @@
  **/
 void CheckSwitchToEuro()
 {
-	if (_currency_specs[_opt.currency].to_euro != CF_NOEURO &&
-			_currency_specs[_opt.currency].to_euro != CF_ISEURO &&
-			_cur_year >= _currency_specs[_opt.currency].to_euro) {
-		_opt.currency = 2; // this is the index of euro above.
+	if (_currency_specs[_settings.gui.currency].to_euro != CF_NOEURO &&
+			_currency_specs[_settings.gui.currency].to_euro != CF_ISEURO &&
+			_cur_year >= _currency_specs[_settings.gui.currency].to_euro) {
+		_settings.gui.currency = 2; // this is the index of euro above.
 		AddNewsItem(STR_EURO_INTRODUCE, NS_ECONOMY, 0, 0);
 	}
 }
--- a/src/currency.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/currency.h	Tue May 27 00:50:55 2008 +0000
@@ -39,7 +39,7 @@
 
 // XXX small hack, but makes the rest of the code a bit nicer to read
 #define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
-#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
+#define _currency ((const CurrencySpec*)&_currency_specs[(_game_mode == GM_MENU) ? _settings_newgame.gui.currency : _settings.gui.currency])
 
 uint GetMaskOfAllowedCurrencies();
 void CheckSwitchToEuro();
--- a/src/date.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/date.cpp	Tue May 27 00:50:55 2008 +0000
@@ -257,7 +257,7 @@
 		SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
 		DebugDumpCommands("ddc:save:%s\n", name);
 #endif /* DUMP_COMMANDS */
-		if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) {
+		if (_settings.gui.autosave != 0 && (_cur_month % _autosave_months[_settings.gui.autosave]) == 0) {
 			_do_autosave = true;
 			RedrawAutosave();
 		}
@@ -283,10 +283,10 @@
 	ShipsYearlyLoop();
 	if (_network_server) NetworkServerYearlyLoop();
 
-	if (_cur_year == _patches.semaphore_build_before) ResetSignalVariant();
+	if (_cur_year == _settings.gui.semaphore_build_before) ResetSignalVariant();
 
 	/* check if we reached end of the game */
-	if (_cur_year == _patches.ending_year) {
+	if (_cur_year == _settings.gui.ending_year) {
 			ShowEndGameChart();
 	/* check if we reached the maximum year, decrement dates by a year */
 	} else if (_cur_year == MAX_YEAR + 1) {
@@ -303,5 +303,5 @@
 		InitChatMessage();
 	}
 
-	if (_patches.auto_euro) CheckSwitchToEuro();
+	if (_settings.gui.auto_euro) CheckSwitchToEuro();
 }
--- a/src/debug.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/debug.cpp	Tue May 27 00:50:55 2008 +0000
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include "openttd.h"
-#include "console.h"
+#include "console_func.h"
 #include "debug.h"
 #include "string_func.h"
 #include "network/core/core.h"
--- a/src/depot_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/depot_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -107,7 +107,6 @@
 	WC_VEHICLE_DEPOT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_depot_widgets,
-	NULL
 };
 
 static const WindowDesc _road_depot_desc = {
@@ -115,7 +114,6 @@
 	WC_VEHICLE_DEPOT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_depot_widgets,
-	NULL
 };
 
 static const WindowDesc _ship_depot_desc = {
@@ -123,7 +121,6 @@
 	WC_VEHICLE_DEPOT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_depot_widgets,
-	NULL
 };
 
 static const WindowDesc _aircraft_depot_desc = {
@@ -131,11 +128,10 @@
 	WC_VEHICLE_DEPOT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_depot_widgets,
-	NULL
 };
 
 extern int WagonLengthToPixels(int len);
-extern void DepotSortList(Vehicle **v, uint16 length);
+extern void DepotSortList(VehicleList *list);
 
 /**
  * This is the Callback method after the cloning attempt of a vehicle
@@ -148,16 +144,14 @@
 {
 	if (!success) return;
 
-	Vehicle *v = GetVehicle(_new_vehicle_id);
+	const Vehicle *v = GetVehicle(_new_vehicle_id);
 
 	ShowVehicleViewWindow(v);
 }
 
-static void TrainDepotMoveVehicle(Vehicle *wagon, VehicleID sel, Vehicle *head)
+static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Vehicle *head)
 {
-	Vehicle *v;
-
-	v = GetVehicle(sel);
+	const Vehicle *v = GetVehicle(sel);
 
 	if (v == wagon) return;
 
@@ -246,20 +240,12 @@
 	VehicleID sel;
 	VehicleType type;
 	bool generate_list;
-	uint16 engine_list_length;
-	uint16 wagon_list_length;
-	uint16 engine_count;
-	uint16 wagon_count;
-	Vehicle **vehicle_list;
-	Vehicle **wagon_list;
+	VehicleList vehicle_list;
+	VehicleList wagon_list;
 
 	DepotWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 	{
 		this->sel = INVALID_VEHICLE;
-		this->vehicle_list  = NULL;
-		this->wagon_list    = NULL;
-		this->engine_count  = 0;
-		this->wagon_count   = 0;
 		this->generate_list = true;
 
 		this->FindWindowPlacementAndResize(desc);
@@ -268,8 +254,6 @@
 	~DepotWindow()
 	{
 		DeleteWindowById(WC_BUILD_VEHICLE, this->window_number);
-		free((void*)this->vehicle_list);
-		free((void*)this->wagon_list);
 	}
 
 	/** Draw a vehicle in the depot window in the box with the top left corner at x,y
@@ -320,11 +304,9 @@
 
 	void DrawDepotWindow(Window *w)
 	{
-		Vehicle **vl = this->vehicle_list;
 		TileIndex tile = this->window_number;
 		int x, y, i, maxval;
 		uint16 hnum;
-		uint16 num = this->engine_count;
 
 		/* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
 		uint16 rows_in_display   = this->widget[DEPOT_WIDGET_MATRIX].data >> 8;
@@ -345,15 +327,15 @@
 		/* determine amount of items for scroller */
 		if (this->type == VEH_TRAIN) {
 			hnum = 8;
-			for (num = 0; num < this->engine_count; num++) {
-				const Vehicle *v = vl[num];
+			for (uint num = 0; num < this->vehicle_list.Length(); num++) {
+				const Vehicle *v = this->vehicle_list[num];
 				hnum = max(hnum, v->u.rail.cached_total_length);
 			}
 			/* Always have 1 empty row, so people can change the setting of the train */
-			SetVScrollCount(w, this->engine_count + this->wagon_count + 1);
+			SetVScrollCount(w, this->vehicle_list.Length() + this->wagon_list.Length() + 1);
 			SetHScrollCount(w, WagonLengthToPixels(hnum));
 		} else {
-			SetVScrollCount(w, (num + this->hscroll.cap - 1) / this->hscroll.cap);
+			SetVScrollCount(w, (this->vehicle_list.Length() + this->hscroll.cap - 1) / this->hscroll.cap);
 		}
 
 		/* locate the depot struct */
@@ -368,24 +350,24 @@
 
 		w->DrawWidgets();
 
-		num = this->vscroll.pos * boxes_in_each_row;
-		maxval = min(this->engine_count, num + (rows_in_display * boxes_in_each_row));
+		uint16 num = this->vscroll.pos * boxes_in_each_row;
+		maxval = min(this->vehicle_list.Length(), num + (rows_in_display * boxes_in_each_row));
 
 		for (x = 2, y = 15; num < maxval; y += this->resize.step_height, x = 2) { // Draw the rows
 			byte i;
 
 			for (i = 0; i < boxes_in_each_row && num < maxval; i++, num++, x += this->resize.step_width) {
 				/* Draw all vehicles in the current row */
-				const Vehicle *v = vl[num];
+				const Vehicle *v = this->vehicle_list[num];
 				DrawVehicleInDepot(w, v, x, y);
 			}
 		}
 
-		maxval = min(this->engine_count + this->wagon_count, (this->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row));
+		maxval = min(this->vehicle_list.Length() + this->wagon_list.Length(), (this->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row));
 
 		/* draw the train wagons, that do not have an engine in front */
 		for (; num < maxval; num++, y += 14) {
-			const Vehicle *v = this->wagon_list[num - this->engine_count];
+			const Vehicle *v = this->wagon_list[num - this->vehicle_list.Length()];
 			const Vehicle *u;
 
 			DrawTrainImage(v, x + 50, y, this->sel, this->hscroll.cap - 29, 0);
@@ -401,8 +383,8 @@
 	}
 
 	struct GetDepotVehiclePtData {
-		Vehicle *head;
-		Vehicle *wagon;
+		const Vehicle *head;
+		const Vehicle *wagon;
 	};
 
 	enum DepotGUIAction {
@@ -412,9 +394,8 @@
 		MODE_START_STOP,
 	};
 
-	DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, Vehicle **veh, GetDepotVehiclePtData *d) const
+	DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d) const
 	{
-		Vehicle **vl = this->vehicle_list;
 		uint xt, row, xm = 0, ym = 0;
 		int pos, skip = 0;
 		uint16 boxes_in_each_row = this->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
@@ -435,7 +416,7 @@
 
 		pos = ((row + this->vscroll.pos) * boxes_in_each_row) + xt;
 
-		if (this->engine_count + this->wagon_count <= pos) {
+		if ((int)(this->vehicle_list.Length() + this->wagon_list.Length()) <= pos) {
 			if (this->type == VEH_TRAIN) {
 				d->head  = NULL;
 				d->wagon = NULL;
@@ -445,20 +426,19 @@
 			}
 		}
 
-		if (this->engine_count > pos) {
-			*veh = vl[pos];
+		if ((int)this->vehicle_list.Length() > pos) {
+			*veh = this->vehicle_list[pos];
 			skip = this->hscroll.pos;
 		} else {
-			vl = this->wagon_list;
-			pos -= this->engine_count;
-			*veh = vl[pos];
+			pos -= this->vehicle_list.Length();
+			*veh = this->wagon_list[pos];
 			/* free wagons don't have an initial loco. */
 			x -= _traininfo_vehicle_width;
 		}
 
 		switch (this->type) {
 			case VEH_TRAIN: {
-				Vehicle *v = *veh;
+				const Vehicle *v = *veh;
 				d->head = d->wagon = v;
 
 				/* either pressed the flag or the number, but only when it's a loco */
@@ -505,7 +485,7 @@
 	void DepotClick(int x, int y)
 	{
 		GetDepotVehiclePtData gdvp = { NULL, NULL };
-		Vehicle *v = NULL;
+		const Vehicle *v = NULL;
 		DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp);
 
 		/* share / copy orders */
@@ -765,11 +745,9 @@
 		if (this->generate_list) {
 			/* Generate the vehicle list
 			 * It's ok to use the wagon pointers for non-trains as they will be ignored */
-			BuildDepotVehicleList(this->type, this->window_number,
-				&this->vehicle_list, &this->engine_list_length, &this->engine_count,
-				&this->wagon_list,   &this->wagon_list_length,  &this->wagon_count);
+			BuildDepotVehicleList(this->type, this->window_number, &this->vehicle_list, &this->wagon_list);
 			this->generate_list = false;
-			DepotSortList(this->vehicle_list, this->engine_count);
+			DepotSortList(&this->vehicle_list);
 		}
 		DrawDepotWindow(this);
 	}
@@ -818,7 +796,7 @@
 
 			case DEPOT_WIDGET_SELL_ALL:
 				/* Only open the confimation window if there are anything to sell */
-				if (this->engine_count != 0 || this->wagon_count != 0) {
+				if (this->vehicle_list.Length() != 0 || this->wagon_list.Length() != 0) {
 					static const StringID confirm_captions[] = {
 						STR_8800_TRAIN_DEPOT,
 						STR_9003_ROAD_VEHICLE_DEPOT,
@@ -883,7 +861,7 @@
 	{
 		switch (widget) {
 			case DEPOT_WIDGET_MATRIX: {
-				Vehicle *v;
+				const Vehicle *v = NULL;
 				VehicleID sel = this->sel;
 
 				this->sel = INVALID_VEHICLE;
@@ -912,23 +890,20 @@
 			case DEPOT_WIDGET_SELL: case DEPOT_WIDGET_SELL_CHAIN:
 				if (!this->IsWidgetDisabled(DEPOT_WIDGET_SELL) &&
 					this->sel != INVALID_VEHICLE) {
-					Vehicle *v;
 					uint command;
-					int sell_cmd;
-					bool is_engine;
 
 					if (this->IsWidgetDisabled(widget)) return;
 					if (this->sel == INVALID_VEHICLE) return;
 
 					this->HandleButtonClick(widget);
 
-					v = GetVehicle(this->sel);
+					const Vehicle *v = GetVehicle(this->sel);
 					this->sel = INVALID_VEHICLE;
 					this->SetDirty();
 
-					sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
+					int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
 
-					is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v)));
+					bool is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v)));
 
 					if (is_engine) {
 						_backup_orders_tile = v->tile;
@@ -961,14 +936,14 @@
 		ResizeDepotButtons(this);
 	}
 
-	virtual bool OnCTRLStateChange()
+	virtual EventState OnCTRLStateChange()
 	{
 		if (this->sel != INVALID_VEHICLE) {
 			_cursor.vehchain = _ctrl_pressed;
 			this->InvalidateWidget(DEPOT_WIDGET_MATRIX);
 		}
 
-		return true;
+		return ES_HANDLED;
 	}
 };
 
--- a/src/disaster_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/disaster_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -1053,7 +1053,7 @@
 
 	ResetDisasterDelay();
 
-	if (_opt.diff.disasters != 0) DoDisaster();
+	if (_settings.difficulty.disasters != 0) DoDisaster();
 }
 
 void StartupDisasters()
--- a/src/dock_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/dock_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -25,8 +25,8 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 
-static void ShowBuildDockStationPicker();
-static void ShowBuildDocksDepotPicker();
+static void ShowBuildDockStationPicker(Window *parent);
+static void ShowBuildDocksDepotPicker(Window *parent);
 
 static Axis _ship_depot_direction;
 
@@ -69,14 +69,21 @@
 	DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_MSG(STR_CANT_BUILD_LOCKS));
 }
 
-
-enum {
-	DTW_CANAL    = 3,
-	DTW_LOCK     = 4,
-	DTW_DEMOLISH = 6,
-	DTW_DEPOT    = 7,
-	DTW_STATION  = 8,
-	DTW_BUOY     = 9
+/** Enum referring to the widgets of the build dock toolbar */
+enum DockToolbarWidgets {
+	DTW_BEGIN = 0,                 ///< Start of toolbar widgets
+	DTW_CLOSEBOX = DTW_BEGIN,      ///< Close window button
+	DTW_CAPTION,                   ///< Window caption
+	DTW_STICKY,                    ///< Sticky window button
+	DTW_BUTTONS_BEGIN,             ///< Begin of clickable buttons (except seperating panel)
+	DTW_CANAL = DTW_BUTTONS_BEGIN, ///< Build canal button
+	DTW_LOCK,                      ///< Build lock button
+	DTW_SEPERATOR,                 ///< Seperating panel between lock and demolish
+	DTW_DEMOLISH,                  ///< Demolish aka dynamite button
+	DTW_DEPOT,                     ///< Build depot button
+	DTW_STATION,                   ///< Build station button
+	DTW_BUOY,                      ///< Build buoy button
+	DTW_END,                       ///< End of toolbar widgets
 };
 
 
@@ -98,13 +105,13 @@
 static void BuildDocksClick_Depot(Window *w)
 {
 	if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
-	if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
+	if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker(w);
 }
 
 static void BuildDocksClick_Dock(Window *w)
 {
 	if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return;
-	if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker();
+	if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker(w);
 }
 
 static void BuildDocksClick_Buoy(Window *w)
@@ -125,91 +132,99 @@
 	BuildDocksClick_Buoy
 };
 
-static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_PAINT:
-		w->DrawWidgets();
-		w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), 7, 8, 9, WIDGET_LIST_END);
-		break;
-
-	case WE_CLICK:
-		if (e->we.click.widget - 3 >= 0 && e->we.click.widget != 5) _build_docks_button_proc[e->we.click.widget - 3](w);
-		break;
-
-	case WE_KEYPRESS:
-		switch (e->we.keypress.keycode) {
-			case '1': BuildDocksClick_Canal(w); break;
-			case '2': BuildDocksClick_Lock(w); break;
-			case '3': BuildDocksClick_Demolish(w); break;
-			case '4': BuildDocksClick_Depot(w); break;
-			case '5': BuildDocksClick_Dock(w); break;
-			case '6': BuildDocksClick_Buoy(w); break;
-			default:  return;
-		}
-		break;
-
-	case WE_PLACE_OBJ:
-		_place_proc(e->we.place.tile);
-		break;
-
-	case WE_PLACE_DRAG: {
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-		return;
+struct BuildDocksToolbarWindow : Window {
+	BuildDocksToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+		if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
 	}
 
-	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1) {
-			switch (e->we.place.select_proc) {
+	~BuildDocksToolbarWindow()
+	{
+		if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
+	}
+
+	virtual void OnPaint()
+	{
+		this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), DTW_DEPOT, DTW_STATION, DTW_BUOY, WIDGET_LIST_END);
+		this->DrawWidgets();
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget >= DTW_BUTTONS_BEGIN && widget != DTW_SEPERATOR) _build_docks_button_proc[widget - DTW_BUTTONS_BEGIN](this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		switch (keycode) {
+			case '1': BuildDocksClick_Canal(this); break;
+			case '2': BuildDocksClick_Lock(this); break;
+			case '3': BuildDocksClick_Demolish(this); break;
+			case '4': BuildDocksClick_Depot(this); break;
+			case '5': BuildDocksClick_Dock(this); break;
+			case '6': BuildDocksClick_Buoy(this); break;
+			default:  return ES_NOT_HANDLED;
+		}
+		return ES_HANDLED;
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
 				case DDSP_DEMOLISH_AREA:
-					GUIPlaceProcDragXY(e);
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
 				case DDSP_CREATE_WATER:
-					DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS));
+					DoCommandP(end_tile, start_tile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS));
 					break;
+
 				default: break;
 			}
 		}
-		break;
+	}
 
-	case WE_ABORT_PLACE_OBJ:
-		w->RaiseButtons();
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
 
 		delete FindWindowById(WC_BUILD_STATION, 0);
 		delete FindWindowById(WC_BUILD_DEPOT, 0);
-		break;
+	}
 
-	case WE_PLACE_PRESIZE: {
-		TileIndex tile_from;
-		TileIndex tile_to;
-
-		tile_from = e->we.place.tile;
-
+	virtual void OnPlacePresize(Point pt, TileIndex tile_from)
+	{
 		DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, NULL));
-		tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from);
+		TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from);
 
 		VpSetPresizeRange(tile_from, tile_to);
-	} break;
-
-	case WE_DESTROY:
-		if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
-		break;
 	}
-}
+};
 
 static const Widget _build_docks_toolb_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                   STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   123,     0,    13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{  WWT_STICKYBOX,   RESIZE_NONE,     7,   124,   135,     0,    13, 0x0,                        STR_STICKY_BUTTON},
-{     WWT_IMGBTN,   RESIZE_NONE,     7,     0,    21,    14,    35, SPR_IMG_BUILD_CANAL,        STR_BUILD_CANALS_TIP},
-{     WWT_IMGBTN,   RESIZE_NONE,     7,    22,    43,    14,    35, SPR_IMG_BUILD_LOCK,         STR_BUILD_LOCKS_TIP},
+{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                   STR_018B_CLOSE_WINDOW},                   // DTW_CLOSEBOX
+{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   123,     0,    13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},         // DTW_CAPTION
+{  WWT_STICKYBOX,   RESIZE_NONE,     7,   124,   135,     0,    13, 0x0,                        STR_STICKY_BUTTON},                       // DTW_STICKY
+{     WWT_IMGBTN,   RESIZE_NONE,     7,     0,    21,    14,    35, SPR_IMG_BUILD_CANAL,        STR_BUILD_CANALS_TIP},                    // DTW_CANAL
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    22,    43,    14,    35, SPR_IMG_BUILD_LOCK,         STR_BUILD_LOCKS_TIP},                     // DTW_LOCK
 
-{      WWT_PANEL,   RESIZE_NONE,     7,    44,    47,    14,    35, 0x0,                        STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,     7,    44,    47,    14,    35, 0x0,                        STR_NULL},                                // DTW_SEPERATOR
 
-{     WWT_IMGBTN,   RESIZE_NONE,     7,    48,    69,    14,    35, SPR_IMG_DYNAMITE,           STR_018D_DEMOLISH_BUILDINGS_ETC},
-{     WWT_IMGBTN,   RESIZE_NONE,     7,    70,    91,    14,    35, SPR_IMG_SHIP_DEPOT,         STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
-{     WWT_IMGBTN,   RESIZE_NONE,     7,    92,   113,    14,    35, SPR_IMG_SHIP_DOCK,          STR_981D_BUILD_SHIP_DOCK},
-{     WWT_IMGBTN,   RESIZE_NONE,     7,   114,   135,    14,    35, SPR_IMG_BOUY,               STR_9834_POSITION_BUOY_WHICH_CAN},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    48,    69,    14,    35, SPR_IMG_DYNAMITE,           STR_018D_DEMOLISH_BUILDINGS_ETC},         // DTW_DEMOLISH
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    70,    91,    14,    35, SPR_IMG_SHIP_DEPOT,         STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},  // DTW_DEPOT
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    92,   113,    14,    35, SPR_IMG_SHIP_DOCK,          STR_981D_BUILD_SHIP_DOCK},                // DTW_STATION
+{     WWT_IMGBTN,   RESIZE_NONE,     7,   114,   135,    14,    35, SPR_IMG_BOUY,               STR_9834_POSITION_BUOY_WHICH_CAN},        // DTW_BUOY
 {   WIDGETS_END},
 };
 
@@ -218,7 +233,6 @@
 	WC_BUILD_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_build_docks_toolb_widgets,
-	BuildDocksToolbWndProc
 };
 
 void ShowBuildDocksToolbar()
@@ -226,19 +240,32 @@
 	if (!IsValidPlayer(_current_player)) return;
 
 	DeleteWindowByClass(WC_BUILD_TOOLBAR);
-	Window *w = AllocateWindowDescFront<Window>(&_build_docks_toolbar_desc, TRANSPORT_WATER);
-	if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
+	AllocateWindowDescFront<BuildDocksToolbarWindow>(&_build_docks_toolbar_desc, TRANSPORT_WATER);
 }
 
-static void BuildDockStationWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_CREATE: w->LowerWidget(_station_show_coverage + 3); break;
+struct BuildDocksStationWindow : public PickerWindowBase {
+private:
+	enum BuildDockStationWidgets {
+		BDSW_CLOSE,
+		BDSW_CAPTION,
+		BDSW_BACKGROUND,
+		BDSW_LT_OFF,
+		BDSW_LT_ON,
+		BDSW_INFO,
+	};
 
-	case WE_PAINT: {
-		int rad = (_patches.modified_catchment) ? CA_DOCK : CA_UNMODIFIED;
+public:
+	BuildDocksStationWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
+	{
+		this->LowerWidget(_station_show_coverage + BDSW_LT_OFF);
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-		w->DrawWidgets();
+	virtual void OnPaint()
+	{
+		int rad = (_settings.station.modified_catchment) ? CA_DOCK : CA_UNMODIFIED;
+
+		this->DrawWidgets();
 
 		if (_station_show_coverage) {
 			SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
@@ -253,44 +280,40 @@
 
 		int text_end = DrawStationCoverageAreaText(4, 50, SCT_ALL, rad, false);
 		text_end = DrawStationCoverageAreaText(4, text_end + 4, SCT_ALL, rad, true) + 4;
-		if (text_end != w->widget[2].bottom) {
-			w->SetDirty();
-			ResizeWindowForWidget(w, 2, 0, text_end - w->widget[2].bottom);
-			w->SetDirty();
+		if (text_end != this->widget[BDSW_BACKGROUND].bottom) {
+			this->SetDirty();
+			ResizeWindowForWidget(this, 2, 0, text_end - this->widget[BDSW_BACKGROUND].bottom);
+			this->SetDirty();
 		}
-		break;
 	}
 
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-			case 3:
-			case 4:
-				w->RaiseWidget(_station_show_coverage + 3);
-				_station_show_coverage = (e->we.click.widget != 3);
-				w->LowerWidget(_station_show_coverage + 3);
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case BDSW_LT_OFF:
+			case BDSW_LT_ON:
+				this->RaiseWidget(_station_show_coverage + BDSW_LT_OFF);
+				_station_show_coverage = (widget != BDSW_LT_OFF);
+				this->LowerWidget(_station_show_coverage + BDSW_LT_OFF);
 				SndPlayFx(SND_15_BEEP);
-				w->SetDirty();
+				this->SetDirty();
 				break;
 		}
-		break;
+	}
 
-	case WE_TICK:
-		CheckRedrawStationCoverage(w);
-		break;
-
-	case WE_DESTROY:
-		ResetObjectToPlace();
-		break;
+	virtual void OnTick()
+	{
+		CheckRedrawStationCoverage(this);
 	}
-}
+};
 
 static const Widget _build_dock_station_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_3068_DOCK,                    STR_018C_WINDOW_TITLE_DRAG_THIS},
-{      WWT_PANEL,   RESIZE_NONE,     7,     0,   147,    14,    74, 0x0,                              STR_NULL},
-{    WWT_TEXTBTN,   RESIZE_NONE,    14,    14,    73,    30,    40, STR_02DB_OFF,                     STR_3065_DON_T_HIGHLIGHT_COVERAGE},
-{    WWT_TEXTBTN,   RESIZE_NONE,    14,    74,   133,    30,    40, STR_02DA_ON,                      STR_3064_HIGHLIGHT_COVERAGE_AREA},
-{      WWT_LABEL,   RESIZE_NONE,     7,     0,   147,    17,    30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
+{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},             // BDSW_CLOSE
+{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   147,     0,    13, STR_3068_DOCK,                    STR_018C_WINDOW_TITLE_DRAG_THIS},   // BDSW_CAPTION
+{      WWT_PANEL,   RESIZE_NONE,     7,     0,   147,    14,    74, 0x0,                              STR_NULL},                          // BDSW_BACKGROUND
+{    WWT_TEXTBTN,   RESIZE_NONE,    14,    14,    73,    30,    40, STR_02DB_OFF,                     STR_3065_DON_T_HIGHLIGHT_COVERAGE}, // BDSW_LT_OFF
+{    WWT_TEXTBTN,   RESIZE_NONE,    14,    74,   133,    30,    40, STR_02DA_ON,                      STR_3064_HIGHLIGHT_COVERAGE_AREA},  // BDSW_LT_ON
+{      WWT_LABEL,   RESIZE_NONE,     7,     0,   147,    17,    30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},                          // BDSW_INFO
 {   WIDGETS_END},
 };
 
@@ -299,63 +322,72 @@
 	WC_BUILD_STATION, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_dock_station_widgets,
-	BuildDockStationWndProc
 };
 
-static void ShowBuildDockStationPicker()
+static void ShowBuildDockStationPicker(Window *parent)
 {
-	new Window(&_build_dock_station_desc);
+	new BuildDocksStationWindow(&_build_dock_station_desc, parent);
 }
 
-static void UpdateDocksDirection()
-{
-	if (_ship_depot_direction != AXIS_X) {
-		SetTileSelectSize(1, 2);
-	} else {
-		SetTileSelectSize(2, 1);
+struct BuildDocksDepotWindow : public PickerWindowBase {
+private:
+	enum BuildDockDepotWidgets {
+		BDDW_CLOSE,
+		BDDW_CAPTION,
+		BDDW_BACKGROUND,
+		BDDW_X,
+		BDDW_Y,
+	};
+
+	static void UpdateDocksDirection()
+	{
+		if (_ship_depot_direction != AXIS_X) {
+			SetTileSelectSize(1, 2);
+		} else {
+			SetTileSelectSize(2, 1);
+		}
 	}
-}
 
-static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_CREATE: w->LowerWidget(_ship_depot_direction + 3); break;
+public:
+	BuildDocksDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
+	{
+		this->LowerWidget(_ship_depot_direction + BDDW_X);
+		UpdateDocksDirection();
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-	case WE_PAINT:
-		w->DrawWidgets();
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
 
 		DrawShipDepotSprite(67, 35, 0);
 		DrawShipDepotSprite(35, 51, 1);
 		DrawShipDepotSprite(135, 35, 2);
 		DrawShipDepotSprite(167, 51, 3);
-		return;
+	}
 
-	case WE_CLICK: {
-		switch (e->we.click.widget) {
-		case 3:
-		case 4:
-			w->RaiseWidget(_ship_depot_direction + 3);
-			_ship_depot_direction = (e->we.click.widget == 3 ? AXIS_X : AXIS_Y);
-			w->LowerWidget(_ship_depot_direction + 3);
-			SndPlayFx(SND_15_BEEP);
-			UpdateDocksDirection();
-			w->SetDirty();
-			break;
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case BDDW_X:
+			case BDDW_Y:
+				this->RaiseWidget(_ship_depot_direction + BDDW_X);
+				_ship_depot_direction = (widget == BDDW_X ? AXIS_X : AXIS_Y);
+				this->LowerWidget(_ship_depot_direction + BDDW_X);
+				SndPlayFx(SND_15_BEEP);
+				UpdateDocksDirection();
+				this->SetDirty();
+				break;
 		}
-	} break;
-
-	case WE_DESTROY:
-		ResetObjectToPlace();
-		break;
 	}
-}
+};
 
 static const Widget _build_docks_depot_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   203,     0,    13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{      WWT_PANEL,   RESIZE_NONE,     7,     0,   203,    14,    85, 0x0,                             STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,     3,   100,    17,    82, 0x0,                             STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
-{      WWT_PANEL,   RESIZE_NONE,    14,   103,   200,    17,    82, 0x0,                             STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
+{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},                  // BDDW_CLOSE
+{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   203,     0,    13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},        // BDDW_CAPTION
+{      WWT_PANEL,   RESIZE_NONE,     7,     0,   203,    14,    85, 0x0,                             STR_NULL},                               // BDDW_BACKGROUND
+{      WWT_PANEL,   RESIZE_NONE,    14,     3,   100,    17,    82, 0x0,                             STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_X
+{      WWT_PANEL,   RESIZE_NONE,    14,   103,   200,    17,    82, 0x0,                             STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_Y
 {   WIDGETS_END},
 };
 
@@ -364,14 +396,12 @@
 	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_docks_depot_widgets,
-	BuildDocksDepotWndProc
 };
 
 
-static void ShowBuildDocksDepotPicker()
+static void ShowBuildDocksDepotPicker(Window *parent)
 {
-	new Window(&_build_docks_depot_desc);
-	UpdateDocksDirection();
+	new BuildDocksDepotWindow(&_build_docks_depot_desc, parent);
 }
 
 
--- a/src/dummy_land.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/dummy_land.cpp	Tue May 27 00:50:55 2008 +0000
@@ -41,7 +41,7 @@
 static void GetTileDesc_Dummy(TileIndex tile, TileDesc *td)
 {
 	td->str = STR_EMPTY;
-	td->owner = OWNER_NONE;
+	td->owner[0] = OWNER_NONE;
 }
 
 static void AnimateTile_Dummy(TileIndex tile)
--- a/src/economy.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/economy.cpp	Tue May 27 00:50:55 2008 +0000
@@ -29,7 +29,6 @@
 #include "newgrf_station.h"
 #include "unmovable.h"
 #include "cargotype.h"
-#include "player_face.h"
 #include "group.h"
 #include "strings_func.h"
 #include "tile_cmd.h"
@@ -46,7 +45,6 @@
 #include "gfx_func.h"
 #include "autoreplace_func.h"
 #include "player_gui.h"
-#include "window_gui.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -589,67 +587,6 @@
 	}
 }
 
-void DrawNewsBankrupcy(Window *w, const NewsItem *ni)
-{
-	Player *p = GetPlayer((PlayerID)(ni->data_b));
-	DrawPlayerFace(p->face, p->player_color, 2, 23);
-	GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE));
-
-	SetDParam(0, p->index);
-
-	DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94);
-
-	switch (ni->subtype) {
-	case NS_COMPANY_TROUBLE:
-		DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING);
-
-		SetDParam(0, p->index);
-
-		DrawStringMultiCenter(
-			((w->width - 101) >> 1) + 98,
-			90,
-			STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED,
-			w->width - 101);
-		break;
-
-	case NS_COMPANY_MERGER:
-		DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING);
-		SetDParam(0, ni->params[2]);
-		SetDParam(1, p->index);
-		SetDParam(2, ni->params[4]);
-		DrawStringMultiCenter(
-			((w->width - 101) >> 1) + 98,
-			90,
-			ni->params[4] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR,
-			w->width - 101);
-		break;
-
-	case NS_COMPANY_BANKRUPT:
-		DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING);
-		SetDParam(0, p->index);
-		DrawStringMultiCenter(
-			((w->width - 101) >> 1) + 98,
-			90,
-			STR_705D_HAS_BEEN_CLOSED_DOWN_BY,
-			w->width - 101);
-		break;
-
-	case NS_COMPANY_NEW:
-		DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING);
-		SetDParam(0, p->index);
-		SetDParam(1, ni->params[3]);
-		DrawStringMultiCenter(
-			((w->width - 101) >> 1) + 98,
-			90,
-			STR_705F_STARTS_CONSTRUCTION_NEAR,
-			w->width - 101);
-		break;
-
-	default:
-		NOT_REACHED();
-	}
-}
-
 static void PlayersGenStatistics()
 {
 	Station *st;
@@ -717,7 +654,7 @@
 	 * inflation doesn't add anything after that either; it even makes playing
 	 * it impossible due to the diverging cost and income rates.
 	 */
-	if ((_cur_year - _patches.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
+	if ((_cur_year - _settings.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
 
 	/* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
 	 * scaled by 65536
@@ -767,7 +704,7 @@
 
 static void HandleEconomyFluctuations()
 {
-	if (_opt.diff.economy == 0) return;
+	if (_settings.difficulty.economy == 0) return;
 
 	if (--_economy.fluct == 0) {
 		_economy.fluct = -(int)GB(Random(), 0, 2);
@@ -876,7 +813,7 @@
 	for (i = 0; i != NUM_PRICES; i++) {
 		Money price = _price_base[i];
 		if (_price_category[i] != 0) {
-			uint mod = _price_category[i] == 1 ? _opt.diff.vehicle_costs : _opt.diff.construction_cost;
+			uint mod = _price_category[i] == 1 ? _settings.difficulty.vehicle_costs : _settings.difficulty.construction_cost;
 			if (mod < 1) {
 				price = price * 3 >> 2;
 			} else if (mod > 1) {
@@ -892,10 +829,10 @@
 		_price_frac[i] = 0;
 	}
 
-	_economy.interest_rate = _opt.diff.initial_interest;
-	_economy.infl_amount = _opt.diff.initial_interest;
-	_economy.infl_amount_pr = max(0, _opt.diff.initial_interest - 1);
-	_economy.max_loan_unround = _economy.max_loan = _opt.diff.max_loan * 1000;
+	_economy.interest_rate = _settings.difficulty.initial_interest;
+	_economy.infl_amount = _settings.difficulty.initial_interest;
+	_economy.infl_amount_pr = max(0, _settings.difficulty.initial_interest - 1);
+	_economy.max_loan_unround = _economy.max_loan = _settings.difficulty.max_loan;
 	_economy.fluct = GB(Random(), 0, 8) + 168;
 }
 
@@ -1225,7 +1162,7 @@
 	}
 
 	/* zero the distance (thus income) if it's the bank and very short transport. */
-	if (_opt.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
+	if (_settings.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
 
 
 	static const int MIN_TIME_FACTOR = 31;
@@ -1271,7 +1208,7 @@
 	 * XXX - Think of something better to
 	 *       1) Only deliver to industries which are withing the catchment radius
 	 *       2) Distribute between industries if more then one is present */
-	best_dist = (_patches.station_spread + 8) * 2;
+	best_dist = (_settings.station.station_spread + 8) * 2;
 	FOR_ALL_INDUSTRIES(ind) {
 		indspec = GetIndustrySpec(ind->type);
 		uint i;
@@ -1376,7 +1313,7 @@
 
 			SetDParam(0, _current_player);
 			AddNewsItem(
-				STR_2031_SERVICE_SUBSIDY_AWARDED + _opt.diff.subsidy_multiplier,
+				STR_2031_SERVICE_SUBSIDY_AWARDED + _settings.difficulty.subsidy_multiplier,
 				NS_SUBSIDIES,
 				pair.a, pair.b
 			);
@@ -1423,7 +1360,7 @@
 
 	/* Modify profit if a subsidy is in effect */
 	if (subsidised) {
-		switch (_opt.diff.subsidy_multiplier) {
+		switch (_settings.difficulty.subsidy_multiplier) {
 			case 0:  profit += profit >> 1; break;
 			case 1:  profit *= 2; break;
 			case 2:  profit *= 3; break;
@@ -1544,7 +1481,7 @@
 
 	/* We have not waited enough time till the next round of loading/unloading */
 	if (--v->load_unload_time_rem != 0) {
-		if (_patches.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
+		if (_settings.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
 			/* 'Reserve' this cargo for this vehicle, because we were first. */
 			for (; v != NULL; v = v->Next()) {
 				if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count();
@@ -1580,7 +1517,7 @@
 		if (v->cargo_cap == 0) continue;
 
 		byte load_amount = EngInfo(v->engine_type)->load_amount;
-		if (_patches.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
+		if (_settings.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
 			uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
 			if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8);
 		}
@@ -1589,7 +1526,7 @@
 
 		if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
 			uint cargo_count = v->cargo.Count();
-			uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
+			uint amount_unloaded = _settings.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
 			bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here?
 
 			if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
@@ -1615,7 +1552,7 @@
 			unloading_time += amount_unloaded;
 
 			anything_unloaded = true;
-			if (_patches.gradual_loading && remaining) {
+			if (_settings.order.gradual_loading && remaining) {
 				completely_emptied = false;
 			} else {
 				/* We have finished unloading (cargo count == 0) */
@@ -1649,14 +1586,14 @@
 
 			/* Skip loading this vehicle if another train/vehicle is already handling
 			 * the same cargo type at this station */
-			if (_patches.improved_load && cargo_left[v->cargo_type] <= 0) {
+			if (_settings.order.improved_load && cargo_left[v->cargo_type] <= 0) {
 				SetBit(cargo_not_full, v->cargo_type);
 				continue;
 			}
 
 			if (cap > count) cap = count;
-			if (_patches.gradual_loading) cap = min(cap, load_amount);
-			if (_patches.improved_load) {
+			if (_settings.order.gradual_loading) cap = min(cap, load_amount);
+			if (_settings.order.improved_load) {
 				/* Don't load stuff that is already 'reserved' for other vehicles */
 				cap = min((uint)cargo_left[v->cargo_type], cap);
 				cargo_left[v->cargo_type] -= cap;
@@ -1700,7 +1637,7 @@
 	 * all wagons at the same time instead of using the same 'improved'
 	 * loading algorithm for the wagons (only fill wagon when there is
 	 * enough to fill the previous wagons) */
-	if (_patches.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
+	if (_settings.order.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
 		/* Update left cargo */
 		for (v = u; v != NULL; v = v->Next()) {
 			if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count();
@@ -1710,7 +1647,7 @@
 	v = u;
 
 	if (anything_loaded || anything_unloaded) {
-		if (_patches.gradual_loading) {
+		if (_settings.order.gradual_loading) {
 			/* The time it takes to load one 'slice' of cargo or passengers depends
 			* on the vehicle type - the values here are those found in TTDPatch */
 			const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
@@ -1747,11 +1684,11 @@
 
 	/* Calculate the loading indicator fill percent and display
 	 * In the Game Menu do not display indicators
-	 * If _patches.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
-	 * if _patches.loading_indicators == 1, _local_player must be the owner or must be a spectator to show ind., so 1 > 0
-	 * if _patches.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
+	 * If _settings.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
+	 * if _settings.gui.loading_indicators == 1, _local_player must be the owner or must be a spectator to show ind., so 1 > 0
+	 * if _settings.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
 	 */
-	if (_game_mode != GM_MENU && (_patches.loading_indicators > (uint)(v->owner != _local_player && _local_player != PLAYER_SPECTATOR))) {
+	if (_game_mode != GM_MENU && (_settings.gui.loading_indicators > (uint)(v->owner != _local_player && _local_player != PLAYER_SPECTATOR))) {
 		StringID percent_up_down = STR_NULL;
 		int percent = CalcPercentVehicleFilled(v, &percent_up_down);
 		if (v->fill_percent_te_id == INVALID_TE_ID) {
@@ -1799,7 +1736,7 @@
 void PlayersMonthlyLoop()
 {
 	PlayersGenStatistics();
-	if (_patches.inflation && _cur_year < MAX_YEAR)
+	if (_settings.economy.inflation && _cur_year < MAX_YEAR)
 		AddInflation();
 	PlayersPayInterest();
 	/* Reset the _current_player flag */
@@ -1844,7 +1781,10 @@
 	p->is_active = false;
 
 	DeletePlayerWindows(pi);
-	RebuildVehicleLists(); //Updates the open windows to add the newly acquired vehicles to the lists
+	InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
+	InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
+	InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
+	InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 }
 
 extern int GetAmountOwnedBy(const Player *p, PlayerID owner);
@@ -1862,7 +1802,7 @@
 
 	/* Check if buying shares is allowed (protection against modified clients) */
 	/* Cannot buy own shares */
-	if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR;
+	if (!IsValidPlayer((PlayerID)p1) || !_settings.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR;
 
 	p = GetPlayer((PlayerID)p1);
 
@@ -1911,7 +1851,7 @@
 
 	/* Check if selling shares is allowed (protection against modified clients) */
 	/* Cannot sell own shares */
-	if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR;
+	if (!IsValidPlayer((PlayerID)p1) || !_settings.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR;
 
 	p = GetPlayer((PlayerID)p1);
 
--- a/src/elrail_func.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/elrail_func.h	Tue May 27 00:50:55 2008 +0000
@@ -25,7 +25,7 @@
  */
 static inline bool HasCatenaryDrawn(RailType rt)
 {
-	return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_patches.disable_elrails;
+	return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings.vehicle.disable_elrails;
 }
 
 /**
@@ -37,6 +37,6 @@
 void DrawCatenaryOnTunnel(const TileInfo *ti);
 void DrawCatenaryOnBridge(const TileInfo *ti);
 
-int32 SettingsDisableElrail(int32 p1); ///< _patches.disable_elrail callback
+int32 SettingsDisableElrail(int32 p1); ///< _settings.disable_elrail callback
 
 #endif /* ELRAIL_FUNC_H */
--- a/src/engine.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/engine.cpp	Tue May 27 00:50:55 2008 +0000
@@ -138,6 +138,7 @@
 {
 	assert(begin <= (uint)el->size());
 	assert(begin + num_items <= (uint)el->size());
+	if (num_items < 2) return;
 	qsort(&((*el)[begin]), num_items, sizeof(EngineID), compare);
 }
 
@@ -216,7 +217,7 @@
 	uint age = e->age;
 
 	/* Check for early retirement */
-	if (e->player_avail != 0 && !_patches.never_expire_vehicles) {
+	if (e->player_avail != 0 && !_settings.vehicle.never_expire_vehicles) {
 		int retire_early = e->info.retire_early;
 		uint retire_early_max_age = max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12);
 		if (retire_early != 0 && age >= retire_early_max_age) {
@@ -229,7 +230,7 @@
 	if (age < e->duration_phase_1) {
 		uint start = e->reliability_start;
 		e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start;
-	} else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _patches.never_expire_vehicles) {
+	} else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _settings.vehicle.never_expire_vehicles) {
 		/* We are at the peak of this engines life. It will have max reliability.
 		 * This is also true if the engines never expire. They will not go bad over time */
 		e->reliability = e->reliability_max;
@@ -292,10 +293,10 @@
 			CalcEngineReliability(e);
 		}
 
-		e->lifelength = ei->lifelength + _patches.extend_vehicle_life;
+		e->lifelength = ei->lifelength + _settings.vehicle.extend_vehicle_life;
 
 		/* prevent certain engines from ever appearing. */
-		if (!HasBit(ei->climates, _opt.landscape)) {
+		if (!HasBit(ei->climates, _settings.game_creation.landscape)) {
 			e->flags |= ENGINE_AVAILABLE;
 			e->player_avail = 0;
 		}
--- a/src/engine_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/engine_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -66,55 +66,54 @@
 	{ DrawAircraftEngine, DrawAircraftEngineInfo },
 };
 
-static void EnginePreviewWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_PAINT: {
-		EngineID engine = w->window_number;
-		const DrawEngineInfo* dei;
-		int width;
+struct EnginePreviewWindow : Window {
+	EnginePreviewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-		w->DrawWidgets();
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
 
+		EngineID engine = this->window_number;
 		SetDParam(0, GetEngineCategoryName(engine));
 		DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
 
 		SetDParam(0, engine);
-		DrawStringCentered(w->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK);
+		DrawStringCentered(this->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK);
 
-		dei = &_draw_engine_list[GetEngine(engine)->type];
+		const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type];
 
-		width = w->width;
+		int width = this->width;
 		dei->engine_proc(width >> 1, 100, engine, 0);
 		dei->info_proc(engine, width >> 1, 130, width - 52);
-		break;
 	}
 
-	case WE_CLICK:
-		switch (e->we.click.widget) {
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
 			case 4:
-				DoCommandP(0, w->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW);
+				DoCommandP(0, this->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW);
 				/* Fallthrough */
 			case 3:
-				delete w;
+				delete this;
 				break;
 		}
-		break;
 	}
-}
+};
 
 static const WindowDesc _engine_preview_desc = {
 	WDP_CENTER, WDP_CENTER, 300, 192, 300, 192,
 	WC_ENGINE_PREVIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_engine_preview_widgets,
-	EnginePreviewWndProc
 };
 
 
 void ShowEnginePreviewWindow(EngineID engine)
 {
-	AllocateWindowDescFront<Window>(&_engine_preview_desc, engine);
+	AllocateWindowDescFront<EnginePreviewWindow>(&_engine_preview_desc, engine);
 }
 
 static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw)
--- a/src/genworld.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/genworld.cpp	Tue May 27 00:50:55 2008 +0000
@@ -91,8 +91,8 @@
 		_generating_world = true;
 		if (_network_dedicated) DEBUG(net, 0, "Generating map, please wait...");
 		/* Set the Random() seed to generation_seed so we produce the same map with the same seed */
-		if (_patches.generation_seed == GENERATE_NEW_SEED) _patches.generation_seed = _patches_newgame.generation_seed = InteractiveRandom();
-		_random.SetSeed(_patches.generation_seed);
+		if (_settings.game_creation.generation_seed == GENERATE_NEW_SEED) _settings.game_creation.generation_seed = _settings_newgame.game_creation.generation_seed = InteractiveRandom();
+		_random.SetSeed(_settings.game_creation.generation_seed);
 		SetGeneratingWorldProgress(GWP_MAP_INIT, 2);
 		SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0);
 
@@ -105,7 +105,7 @@
 			SetGeneratingWorldProgress(GWP_UNMOVABLE, 1);
 
 			/* Make the map the height of the patch setting */
-			if (_game_mode != GM_MENU) FlatEmptyWorld(_patches.se_flat_world_height);
+			if (_game_mode != GM_MENU) FlatEmptyWorld(_settings.game_creation.se_flat_world_height);
 
 			ConvertGroundTilesIntoWaterTiles();
 			IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
@@ -165,7 +165,7 @@
 
 		if (_network_dedicated) DEBUG(net, 0, "Map generated, starting game");
 
-		if (_patches.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
+		if (_settings.gui.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
 	} catch (...) {
 		_generating_world = false;
 		throw;
@@ -273,7 +273,7 @@
 	_current_player = OWNER_NONE;
 
 	/* Set the date before loading sprites as some newgrfs check it */
-	SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1));
+	SetDate(ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1));
 
 	/* Load the right landscape stuff */
 	GfxLoadSprites();
--- a/src/genworld_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/genworld_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -48,7 +48,7 @@
 
 static inline void SetNewLandscapeType(byte landscape)
 {
-	_opt_newgame.landscape = landscape;
+	_settings_newgame.game_creation.landscape = landscape;
 	InvalidateWindowClasses(WC_SELECT_GAME);
 	InvalidateWindowClasses(WC_GENERATE_LANDSCAPE);
 }
@@ -205,9 +205,7 @@
 	DeleteAllNonVitalWindows();
 
 	/* Copy all XXX_newgame to XXX when coming from outside the editor */
-	UpdatePatches();
-	_opt = _opt_newgame;
-	_opt_ptr = &_opt;
+	_settings = _settings_newgame;
 	ResetGRFConfig(true);
 
 	SndPlayFx(SND_15_BEEP);
@@ -255,9 +253,9 @@
 
 	GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : QueryStringBaseWindow(desc, number)
 	{
-		this->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
+		this->LowerWidget(_settings_newgame.game_creation.landscape + GLAND_TEMPERATE);
 
-		snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+		snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _settings_newgame.game_creation.generation_seed);
 		InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
 		this->caption = STR_NULL;
 		this->afilter = CS_NUMERAL;
@@ -271,49 +269,49 @@
 	{
 		/* You can't select smoothness if not terragenesis */
 		if (mode == GLWP_GENERATE) {
-			this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0);
+			this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _settings_newgame.game_creation.land_generator == 0);
 		}
 		/* Disable snowline if not hilly */
-		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC);
+		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _settings_newgame.game_creation.landscape != LT_ARCTIC);
 		/* Disable town, industry and trees in SE */
 		this->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN,     _game_mode == GM_EDITOR);
 		this->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
 		this->SetWidgetDisabledState(GLAND_TREE_PULLDOWN,     _game_mode == GM_EDITOR);
 
-		this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR);
-		this->SetWidgetDisabledState(GLAND_START_DATE_UP,   _patches_newgame.starting_year >= MAX_YEAR);
-		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC);
-		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP,   _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC);
+		this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
+		this->SetWidgetDisabledState(GLAND_START_DATE_UP,   _settings_newgame.game_creation.starting_year >= MAX_YEAR);
+		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _settings_newgame.game_creation.snow_line_height <= 2 || _settings_newgame.game_creation.landscape != LT_ARCTIC);
+		this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP,   _settings_newgame.game_creation.snow_line_height >= MAX_SNOWLINE_HEIGHT || _settings_newgame.game_creation.landscape != LT_ARCTIC);
 
-		this->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
-		this->SetWidgetLoweredState(GLAND_ARCTIC,    _opt_newgame.landscape == LT_ARCTIC);
-		this->SetWidgetLoweredState(GLAND_TROPICAL,  _opt_newgame.landscape == LT_TROPIC);
-		this->SetWidgetLoweredState(GLAND_TOYLAND,   _opt_newgame.landscape == LT_TOYLAND);
+		this->SetWidgetLoweredState(GLAND_TEMPERATE, _settings_newgame.game_creation.landscape == LT_TEMPERATE);
+		this->SetWidgetLoweredState(GLAND_ARCTIC,    _settings_newgame.game_creation.landscape == LT_ARCTIC);
+		this->SetWidgetLoweredState(GLAND_TROPICAL,  _settings_newgame.game_creation.landscape == LT_TROPIC);
+		this->SetWidgetLoweredState(GLAND_TOYLAND,   _settings_newgame.game_creation.landscape == LT_TOYLAND);
 
 		if (_game_mode == GM_EDITOR) {
 			this->widget[GLAND_TOWN_PULLDOWN].data     = STR_6836_OFF;
 			this->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF;
 		} else {
-			this->widget[GLAND_TOWN_PULLDOWN].data     = _num_towns[_opt_newgame.diff.number_towns];
-			this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_opt_newgame.diff.number_industries];
+			this->widget[GLAND_TOWN_PULLDOWN].data     = _num_towns[_settings_newgame.difficulty.number_towns];
+			this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_settings_newgame.difficulty.number_industries];
 		}
 
 		if (mode == GLWP_GENERATE) {
-			this->widget[GLAND_LANDSCAPE_PULLDOWN].data  = _landscape[_patches_newgame.land_generator];
-			this->widget[GLAND_TREE_PULLDOWN].data       = _tree_placer[_patches_newgame.tree_placer];
-			this->widget[GLAND_TERRAIN_PULLDOWN].data    = _elevations[_opt_newgame.diff.terrain_type];
-			this->widget[GLAND_WATER_PULLDOWN].data      = _sea_lakes[_opt_newgame.diff.quantity_sea_lakes];
-			this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_patches_newgame.tgen_smoothness];
+			this->widget[GLAND_LANDSCAPE_PULLDOWN].data  = _landscape[_settings_newgame.game_creation.land_generator];
+			this->widget[GLAND_TREE_PULLDOWN].data       = _tree_placer[_settings_newgame.game_creation.tree_placer];
+			this->widget[GLAND_TERRAIN_PULLDOWN].data    = _elevations[_settings_newgame.difficulty.terrain_type];
+			this->widget[GLAND_WATER_PULLDOWN].data      = _sea_lakes[_settings_newgame.difficulty.quantity_sea_lakes];
+			this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_settings_newgame.game_creation.tgen_smoothness];
 		} else {
-			this->widget[GLAND_TREE_PULLDOWN].data               = _tree_placer[_patches_newgame.tree_placer];
-			this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_patches_newgame.heightmap_rotation];
+			this->widget[GLAND_TREE_PULLDOWN].data               = _tree_placer[_settings_newgame.game_creation.tree_placer];
+			this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_settings_newgame.game_creation.heightmap_rotation];
 		}
 
 		/* Set parameters for widget text that requires them. */
-		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
-		SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN
-		SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
-		SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
+		SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); // GLAND_START_DATE_TEXT
+		SetDParam(1, 1 << _settings_newgame.game_creation.map_x); // GLAND_MAPSIZE_X_PULLDOWN
+		SetDParam(2, 1 << _settings_newgame.game_creation.map_y); // GLAND_MAPSIZE_Y_PULLDOWN
+		SetDParam(3, _settings_newgame.game_creation.snow_line_height); // GLAND_SNOW_LEVEL_TEXT
 
 		this->DrawWidgets();
 
@@ -322,7 +320,7 @@
 		if (mode != GLWP_GENERATE) {
 			char buffer[512];
 
-			if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) {
+			if (_settings_newgame.game_creation.heightmap_rotation == HM_CLOCKWISE) {
 				SetDParam(0, this->y);
 				SetDParam(1, this->x);
 			} else {
@@ -347,29 +345,29 @@
 			case GLAND_ARCTIC:
 			case GLAND_TROPICAL:
 			case GLAND_TOYLAND:
-				this->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE);
+				this->RaiseWidget(_settings_newgame.game_creation.landscape + GLAND_TEMPERATE);
 				SetNewLandscapeType(widget - GLAND_TEMPERATE);
 				break;
 
 			case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X
-				ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, GLAND_MAPSIZE_X_PULLDOWN);
 				break;
 
 			case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y
-				ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, GLAND_MAPSIZE_Y_PULLDOWN);
 				break;
 
 			case GLAND_TOWN_PULLDOWN: // Number of towns
-				ShowDropDownMenu(this, _num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _num_towns, _settings_newgame.difficulty.number_towns, GLAND_TOWN_PULLDOWN, 0, 0);
 				break;
 
 			case GLAND_INDUSTRY_PULLDOWN: // Number of industries
-				ShowDropDownMenu(this, _num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _num_inds, _settings_newgame.difficulty.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0);
 				break;
 
 			case GLAND_RANDOM_BUTTON: // Random seed
-				_patches_newgame.generation_seed = InteractiveRandom();
-				snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _patches_newgame.generation_seed);
+				_settings_newgame.game_creation.generation_seed = InteractiveRandom();
+				snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _settings_newgame.game_creation.generation_seed);
 				UpdateTextBufferSize(&this->text);
 				this->SetDirty();
 				break;
@@ -379,19 +377,19 @@
 				break;
 
 			case GLAND_GENERATE_BUTTON: // Generate
-				UpdatePatches();
+				_settings = _settings_newgame;
 
-				if (_patches.town_layout == TL_NO_ROADS) {
+				if (_settings.economy.town_layout == TL_NO_ROADS) {
 					ShowQuery(
 						STR_TOWN_LAYOUT_WARNING_CAPTION,
 						STR_TOWN_LAYOUT_WARNING_MESSAGE,
 						this,
 						LandscapeGenerationCallback);
 				} else if (mode == GLWP_HEIGHTMAP &&
-						(this->x * 2 < (1U << _patches_newgame.map_x) ||
-						this->x / 2 > (1U << _patches_newgame.map_x) ||
-						this->y * 2 < (1U << _patches_newgame.map_y) ||
-						this->y / 2 > (1U << _patches_newgame.map_y))) {
+						(this->x * 2 < (1U << _settings_newgame.game_creation.map_x) ||
+						this->x / 2 > (1U << _settings_newgame.game_creation.map_x) ||
+						this->y * 2 < (1U << _settings_newgame.game_creation.map_y) ||
+						this->y / 2 > (1U << _settings_newgame.game_creation.map_y))) {
 					ShowQuery(
 						STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
 						STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
@@ -409,14 +407,14 @@
 					this->HandleButtonClick(widget);
 					this->SetDirty();
 
-					_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+					_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 				}
 				_left_button_clicked = false;
 				break;
 
 			case GLAND_START_DATE_TEXT: // Year text
 				this->widget_id = GLAND_START_DATE_TEXT;
-				SetDParam(0, _patches_newgame.starting_year);
+				SetDParam(0, _settings_newgame.game_creation.starting_year);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
 				break;
 
@@ -427,40 +425,40 @@
 					this->HandleButtonClick(widget);
 					this->SetDirty();
 
-					_patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
+					_settings_newgame.game_creation.snow_line_height = Clamp(_settings_newgame.game_creation.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
 				}
 				_left_button_clicked = false;
 				break;
 
 			case GLAND_SNOW_LEVEL_TEXT: // Snow line text
 				this->widget_id = GLAND_SNOW_LEVEL_TEXT;
-				SetDParam(0, _patches_newgame.snow_line_height);
+				SetDParam(0, _settings_newgame.game_creation.snow_line_height);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
 				break;
 
 			case GLAND_TREE_PULLDOWN: // Tree placer
-				ShowDropDownMenu(this, _tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _tree_placer, _settings_newgame.game_creation.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
 				break;
 
 			case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
 			/* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
 				if (mode == GLWP_HEIGHTMAP) {
-					ShowDropDownMenu(this, _rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
+					ShowDropDownMenu(this, _rotation, _settings_newgame.game_creation.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
 				} else {
-					ShowDropDownMenu(this, _landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
+					ShowDropDownMenu(this, _landscape, _settings_newgame.game_creation.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
 				}
 				break;
 
 			case GLAND_TERRAIN_PULLDOWN: // Terrain type
-				ShowDropDownMenu(this, _elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _elevations, _settings_newgame.difficulty.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
 				break;
 
 			case GLAND_WATER_PULLDOWN: // Water quantity
-				ShowDropDownMenu(this, _sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _sea_lakes, _settings_newgame.difficulty.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
 				break;
 
 			case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness
-				ShowDropDownMenu(this, _smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
+				ShowDropDownMenu(this, _smoothness, _settings_newgame.game_creation.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0);
 				break;
 		}
 	}
@@ -470,58 +468,58 @@
 		this->HandleEditBox(GLAND_RANDOM_EDITBOX);
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont;
-		this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, cont);
+		EventState state;
+		this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, state);
 		/* the seed is unsigned, therefore atoi cannot be used.
 			* As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value
 			* (use random seed) it should not be possible to be
 			* entered into the input field; the generate seed
 			* button can be used instead. */
-		_patches_newgame.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1);
-		return cont;
+		_settings_newgame.game_creation.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1);
+		return state;
 	}
 
 	virtual void OnDropdownSelect(int widget, int index)
 	{
 		switch (widget) {
-			case GLAND_MAPSIZE_X_PULLDOWN:  _patches_newgame.map_x = index; break;
-			case GLAND_MAPSIZE_Y_PULLDOWN:  _patches_newgame.map_y = index; break;
-			case GLAND_TREE_PULLDOWN:       _patches_newgame.tree_placer = index; break;
-			case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = index;  break;
+			case GLAND_MAPSIZE_X_PULLDOWN:  _settings_newgame.game_creation.map_x = index; break;
+			case GLAND_MAPSIZE_Y_PULLDOWN:  _settings_newgame.game_creation.map_y = index; break;
+			case GLAND_TREE_PULLDOWN:       _settings_newgame.game_creation.tree_placer = index; break;
+			case GLAND_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = index;  break;
 
 			case GLAND_TOWN_PULLDOWN:
-				_opt_newgame.diff.number_towns = index;
-				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
-				DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				_settings_newgame.difficulty.number_towns = index;
+				if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				IConsoleSetPatchSetting("difficulty.number_towns", _settings_newgame.difficulty.number_towns);
 				break;
 
 			case GLAND_INDUSTRY_PULLDOWN:
-				_opt_newgame.diff.number_industries = index;
-				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
-				DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				_settings_newgame.difficulty.number_industries = index;
+				if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				IConsoleSetPatchSetting("difficulty.number_industries", _settings_newgame.difficulty.number_industries);
 				break;
 
 			case GLAND_LANDSCAPE_PULLDOWN:
 			/* case GLAND_HEIGHTMAP_PULLDOWN: */
 				if (mode == GLWP_HEIGHTMAP) {
-					_patches_newgame.heightmap_rotation = index;
+					_settings_newgame.game_creation.heightmap_rotation = index;
 				} else {
-					_patches_newgame.land_generator = index;
+					_settings_newgame.game_creation.land_generator = index;
 				}
 				break;
 
 			case GLAND_TERRAIN_PULLDOWN:
-				_opt_newgame.diff.terrain_type = index;
-				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
-				DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				_settings_newgame.difficulty.terrain_type = index;
+				if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				IConsoleSetPatchSetting("difficulty.terrain_type", _settings_newgame.difficulty.terrain_type);
 				break;
 
 			case GLAND_WATER_PULLDOWN:
-				_opt_newgame.diff.quantity_sea_lakes = index;
-				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
-				DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+				_settings_newgame.difficulty.quantity_sea_lakes = index;
+				if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
+				IConsoleSetPatchSetting("difficulty.quantity_sea_lakes", _settings_newgame.difficulty.quantity_sea_lakes);
 				break;
 		}
 		this->SetDirty();
@@ -535,12 +533,12 @@
 			switch (this->widget_id) {
 				case GLAND_START_DATE_TEXT:
 					this->InvalidateWidget(GLAND_START_DATE_TEXT);
-					_patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
+					_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 					break;
 
 				case GLAND_SNOW_LEVEL_TEXT:
 					this->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
-					_patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
+					_settings_newgame.game_creation.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
 					break;
 			}
 
@@ -554,7 +552,6 @@
 	WC_GENERATE_LANDSCAPE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_generate_landscape_widgets,
-	NULL,
 };
 
 static const WindowDesc _heightmap_load_desc = {
@@ -562,7 +559,6 @@
 	WC_GENERATE_LANDSCAPE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
 	_heightmap_load_widgets,
-	NULL,
 };
 
 static void _ShowGenerateLandscape(glwp_modes mode)
@@ -573,7 +569,7 @@
 	DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
 
 	/* Always give a new seed if not editor */
-	if (_game_mode != GM_EDITOR) _patches_newgame.generation_seed = InteractiveRandom();
+	if (_game_mode != GM_EDITOR) _settings_newgame.game_creation.generation_seed = InteractiveRandom();
 
 	if (mode == GLWP_HEIGHTMAP) {
 		/* If the function returns negative, it means there was a problem loading the heightmap */
@@ -603,8 +599,8 @@
 
 void StartScenarioEditor()
 {
-	if (_patches_newgame.town_layout == TL_NO_ROADS) {
-		_patches_newgame.town_layout = TL_ORIGINAL;
+	if (_settings_newgame.economy.town_layout == TL_NO_ROADS) {
+		_settings_newgame.economy.town_layout = TL_ORIGINAL;
 	}
 
 	StartGeneratingLandscape(GLWP_SCENARIO);
@@ -613,7 +609,7 @@
 void StartNewGameWithoutGUI(uint seed)
 {
 	/* GenerateWorld takes care of the possible GENERATE_NEW_SEED value in 'seed' */
-	_patches_newgame.generation_seed = seed;
+	_settings_newgame.game_creation.generation_seed = seed;
 
 	StartGeneratingLandscape(GLWP_GENERATE);
 }
@@ -646,26 +642,27 @@
 
 	CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 	{
-		this->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+		this->LowerWidget(_settings_newgame.game_creation.landscape + CSCEN_TEMPERATE);
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
 	{
-		this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN,       _patches_newgame.starting_year <= MIN_YEAR);
-		this->SetWidgetDisabledState(CSCEN_START_DATE_UP,         _patches_newgame.starting_year >= MAX_YEAR);
-		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0);
-		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP,   _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT);
+		this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN,       _settings_newgame.game_creation.starting_year <= MIN_YEAR);
+		this->SetWidgetDisabledState(CSCEN_START_DATE_UP,         _settings_newgame.game_creation.starting_year >= MAX_YEAR);
+		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _settings_newgame.game_creation.se_flat_world_height <= 0);
+		this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP,   _settings_newgame.game_creation.se_flat_world_height >= MAX_TILE_HEIGHT);
 
-		this->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE);
-		this->SetWidgetLoweredState(CSCEN_ARCTIC,    _opt_newgame.landscape == LT_ARCTIC);
-		this->SetWidgetLoweredState(CSCEN_TROPICAL,  _opt_newgame.landscape == LT_TROPIC);
-		this->SetWidgetLoweredState(CSCEN_TOYLAND,   _opt_newgame.landscape == LT_TOYLAND);
+		this->SetWidgetLoweredState(CSCEN_TEMPERATE, _settings_newgame.game_creation.landscape == LT_TEMPERATE);
+		this->SetWidgetLoweredState(CSCEN_ARCTIC,    _settings_newgame.game_creation.landscape == LT_ARCTIC);
+		this->SetWidgetLoweredState(CSCEN_TROPICAL,  _settings_newgame.game_creation.landscape == LT_TROPIC);
+		this->SetWidgetLoweredState(CSCEN_TOYLAND,   _settings_newgame.game_creation.landscape == LT_TOYLAND);
 
 		/* Set parameters for widget text that requires them */
-		SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
-		SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
-		SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
-		SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
+		SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT
+		SetDParam(1, 1 << _settings_newgame.game_creation.map_x); // CSCEN_MAPSIZE_X_PULLDOWN
+		SetDParam(2, 1 << _settings_newgame.game_creation.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN
+		SetDParam(3, _settings_newgame.game_creation.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT
 
 		this->DrawWidgets();
 	}
@@ -677,16 +674,16 @@
 			case CSCEN_ARCTIC:
 			case CSCEN_TROPICAL:
 			case CSCEN_TOYLAND:
-				this->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE);
+				this->RaiseWidget(_settings_newgame.game_creation.landscape + CSCEN_TEMPERATE);
 				SetNewLandscapeType(widget - CSCEN_TEMPERATE);
 				break;
 
 			case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
-				ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, CSCEN_MAPSIZE_X_PULLDOWN);
 				break;
 
 			case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
-				ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
+				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, CSCEN_MAPSIZE_Y_PULLDOWN);
 				break;
 
 			case CSCEN_EMPTY_WORLD: // Empty world / flat world
@@ -704,14 +701,14 @@
 					this->HandleButtonClick(widget);
 					this->SetDirty();
 
-					_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
+					_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 				}
 				_left_button_clicked = false;
 				break;
 
 			case CSCEN_START_DATE_TEXT: // Year text
 				this->widget_id = CSCEN_START_DATE_TEXT;
-				SetDParam(0, _patches_newgame.starting_year);
+				SetDParam(0, _settings_newgame.game_creation.starting_year);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL);
 				break;
 
@@ -722,14 +719,14 @@
 					this->HandleButtonClick(widget);
 					this->SetDirty();
 
-					_patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
+					_settings_newgame.game_creation.se_flat_world_height = Clamp(_settings_newgame.game_creation.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
 				}
 				_left_button_clicked = false;
 				break;
 
 			case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
 				this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
-				SetDParam(0, _patches_newgame.se_flat_world_height);
+				SetDParam(0, _settings_newgame.game_creation.se_flat_world_height);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, this, CS_NUMERAL);
 				break;
 		}
@@ -738,8 +735,8 @@
 	virtual void OnDropdownSelect(int widget, int index)
 	{
 		switch (widget) {
-			case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break;
-			case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break;
+			case CSCEN_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
+			case CSCEN_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
 		}
 		this->SetDirty();
 	}
@@ -752,12 +749,12 @@
 			switch (this->widget_id) {
 				case CSCEN_START_DATE_TEXT:
 					this->InvalidateWidget(CSCEN_START_DATE_TEXT);
-					_patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
+					_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 					break;
 
 				case CSCEN_FLAT_LAND_HEIGHT_TEXT:
 					this->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
-					_patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
+					_settings_newgame.game_creation.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
 					break;
 			}
 
@@ -801,7 +798,6 @@
 	WC_GENERATE_LANDSCAPE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
 	_create_scenario_widgets,
-	NULL,
 };
 
 void ShowCreateScenario()
@@ -823,7 +819,6 @@
 	WC_GENERATE_PROGRESS_WINDOW, WC_NONE,
 	WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_generate_progress_widgets,
-	NULL
 };
 
 struct tp_info {
@@ -854,7 +849,10 @@
 	};
 
 public:
-	GenerateProgressWindow() : Window(&_generate_progress_desc) {};
+	GenerateProgressWindow() : Window(&_generate_progress_desc)
+	{
+		this->FindWindowPlacementAndResize(&_generate_progress_desc);
+	}
 
 	virtual void OnClick(Point pt, int widget)
 	{
--- a/src/gfx.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/gfx.cpp	Tue May 27 00:50:55 2008 +0000
@@ -427,9 +427,9 @@
 	}
 }
 
-/** Draw a given string with the centre around the given x coordinates
+/** Draw a given string with the centre around the given (x,y) coordinates
  * @param x Centre the string around this pixel width
- * @param y Draw the string at this pixel height (first line's bottom)
+ * @param y Centre the string around this pixel height
  * @param str String to draw
  * @param maxw Maximum width the string can have before it is wrapped */
 void DrawStringMultiCenter(int x, int y, StringID str, int maxw)
@@ -807,7 +807,7 @@
 	memcpy(old_val, d, c * sizeof(*old_val));
 
 	/* Dark blue water */
-	s = (_opt.landscape == LT_TOYLAND) ? ev->ac : ev->a;
+	s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->ac : ev->a;
 	j = EXTR(320, 5);
 	for (i = 0; i != 5; i++) {
 		*d++ = s[j];
@@ -816,7 +816,7 @@
 	}
 
 	/* Glittery water */
-	s = (_opt.landscape == LT_TOYLAND) ? ev->bc : ev->b;
+	s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->bc : ev->b;
 	j = EXTR(128, 15);
 	for (i = 0; i != 5; i++) {
 		*d++ = s[j];
@@ -876,7 +876,7 @@
 	/* Animate water for old DOS graphics */
 	if (_use_dos_palette) {
 		/* Dark blue water DOS */
-		s = (_opt.landscape == LT_TOYLAND) ? ev->ac : ev->a;
+		s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->ac : ev->a;
 		j = EXTR(320, 5);
 		for (i = 0; i != 5; i++) {
 			*d++ = s[j];
@@ -885,7 +885,7 @@
 		}
 
 		/* Glittery water DOS */
-		s = (_opt.landscape == LT_TOYLAND) ? ev->bc : ev->b;
+		s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->bc : ev->b;
 		j = EXTR(128, 15);
 		for (i = 0; i != 5; i++) {
 			*d++ = s[j];
--- a/src/gfxinit.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/gfxinit.cpp	Tue May 27 00:50:55 2008 +0000
@@ -214,10 +214,10 @@
 	 * This overwrites some of the temperate sprites, such as foundations
 	 * and the ground sprites.
 	 */
-	if (_opt.landscape != LT_TEMPERATE) {
+	if (_settings.game_creation.landscape != LT_TEMPERATE) {
 		LoadGrfIndexed(
-			files->landscape[_opt.landscape - 1].filename,
-			_landscape_spriteindexes[_opt.landscape - 1],
+			files->landscape[_settings.game_creation.landscape - 1].filename,
+			_landscape_spriteindexes[_settings.game_creation.landscape - 1],
 			i++
 		);
 	}
@@ -248,7 +248,7 @@
 
 void GfxLoadSprites()
 {
-	DEBUG(sprite, 2, "Loading sprite set %d", _opt.landscape);
+	DEBUG(sprite, 2, "Loading sprite set %d", _settings.game_creation.landscape);
 
 	GfxInitSpriteMem();
 	LoadSpriteTables();
--- a/src/graph_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/graph_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -24,295 +24,62 @@
 static uint _legend_excluded_players;
 static uint _legend_excluded_cargo;
 
-/************************/
-/* GENERIC GRAPH DRAWER */
-/************************/
-
-enum {
-	GRAPH_MAX_DATASETS = 32,
-	GRAPH_AXIS_LABEL_COLOUR = TC_BLACK,
-	GRAPH_AXIS_LINE_COLOUR  = 215,
-
-	GRAPH_X_POSITION_BEGINNING  = 44,  ///< Start the graph 44 pixels from gw->left
-	GRAPH_X_POSITION_SEPARATION = 22,  ///< There are 22 pixels between each X value
-
-	GRAPH_NUM_LINES_Y = 9, ///< How many horizontal lines to draw.
-	/* 9 is convenient as that means the distance between them is the height of the graph / 8,
-	 * which is the same
-	 * as height >> 3. */
-};
-
 /* Apparently these don't play well with enums. */
 static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
 static const uint INVALID_DATAPOINT_POS = UINT_MAX;  // Used to determine if the previous point was drawn.
 
-struct GraphDrawer {
-	uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
-	byte num_dataset;
-	byte num_on_x_axis;
-	bool has_negative_values;
-	byte num_vert_lines;
-
-	/* The starting month and year that values are plotted against. If month is
-	 * 0xFF, use x_values_start and x_values_increment below instead. */
-	byte month;
-	Year year;
-
-	/* These values are used if the graph is being plotted against values
-	 * rather than the dates specified by month and year. */
-	uint16 x_values_start;
-	uint16 x_values_increment;
-
-	int left, top;  ///< Where to start drawing the graph, in pixels.
-	uint height;    ///< The height of the graph in pixels.
-	StringID format_str_y_axis;
-	byte colors[GRAPH_MAX_DATASETS];
-	OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][24]; ///< last 2 years
-};
-
-static void DrawGraph(const GraphDrawer *gw)
-{
-	uint x, y;                       ///< Reused whenever x and y coordinates are needed.
-	OverflowSafeInt64 highest_value; ///< Highest value to be drawn.
-	int x_axis_offset;               ///< Distance from the top of the graph to the x axis.
-
-	/* the colors and cost array of GraphDrawer must accomodate
-	 * both values for cargo and players. So if any are higher, quit */
-	assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_PLAYERS);
-	assert(gw->num_vert_lines > 0);
-
-	byte grid_colour = _colour_gradient[14][4];
-
-	/* The coordinates of the opposite edges of the graph. */
-	int bottom = gw->top + gw->height - 1;
-	int right  = gw->left + GRAPH_X_POSITION_BEGINNING + gw->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1;
-
-	/* Draw the vertical grid lines. */
-
-	/* Don't draw the first line, as that's where the axis will be. */
-	x = gw->left + GRAPH_X_POSITION_BEGINNING + GRAPH_X_POSITION_SEPARATION;
-
-	for (int i = 0; i < gw->num_vert_lines; i++) {
-		GfxFillRect(x, gw->top, x, bottom, grid_colour);
-		x += GRAPH_X_POSITION_SEPARATION;
-	}
-
-	/* Draw the horizontal grid lines. */
-	x = gw->left + GRAPH_X_POSITION_BEGINNING;
-	y = gw->height + gw->top;
-
-	for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
-		GfxFillRect(x, y, right, y, grid_colour);
-		y -= (gw->height / (GRAPH_NUM_LINES_Y - 1));
-	}
-
-	/* Draw the y axis. */
-	GfxFillRect(x, gw->top, x, bottom, GRAPH_AXIS_LINE_COLOUR);
-
-	/* Find the distance from the top of the graph to the x axis. */
-	x_axis_offset = gw->height;
-
-	/* The graph is currently symmetrical about the x axis. */
-	if (gw->has_negative_values) x_axis_offset /= 2;
-
-	/* Draw the x axis. */
-	y = x_axis_offset + gw->top;
-	GfxFillRect(x, y, right, y, GRAPH_AXIS_LINE_COLOUR);
-
-	/* Find the largest value that will be drawn. */
-	if (gw->num_on_x_axis == 0)
-		return;
-
-	assert(gw->num_on_x_axis > 0);
-	assert(gw->num_dataset > 0);
-
-	/* Start of with a value of twice the height of the graph in pixels. It's a
-	 * bit arbitrary, but it makes the cargo payment graph look a little nicer,
-	 * and prevents division by zero when calculating where the datapoint
-	 * should be drawn. */
-	highest_value = x_axis_offset * 2;
-
-	for (int i = 0; i < gw->num_dataset; i++) {
-		if (!HasBit(gw->excluded_data, i)) {
-			for (int j = 0; j < gw->num_on_x_axis; j++) {
-				OverflowSafeInt64 datapoint = gw->cost[i][j];
-
-				if (datapoint != INVALID_DATAPOINT) {
-					/* For now, if the graph has negative values the scaling is
-					 * symmetrical about the x axis, so take the absolute value
-					 * of each data point. */
-					highest_value = max(highest_value, abs(datapoint));
-				}
-			}
-		}
-	}
-
-	/* Round up highest_value so that it will divide cleanly into the number of
-	 * axis labels used. */
-	int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1);
-	if (round_val != 0) highest_value += (GRAPH_NUM_LINES_Y - 1 - round_val);
-
-	/* draw text strings on the y axis */
-	int64 y_label = highest_value;
-	int64 y_label_separation = highest_value / (GRAPH_NUM_LINES_Y - 1);
-
-	/* If there are negative values, the graph goes from highest_value to
-	 * -highest_value, not highest_value to 0. */
-	if (gw->has_negative_values) y_label_separation *= 2;
-
-	x = gw->left + GRAPH_X_POSITION_BEGINNING + 1;
-	y = gw->top - 3;
-
-	for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
-		SetDParam(0, gw->format_str_y_axis);
-		SetDParam(1, y_label);
-		DrawStringRightAligned(x, y, STR_0170, GRAPH_AXIS_LABEL_COLOUR);
-
-		y_label -= y_label_separation;
-		y += (gw->height / (GRAPH_NUM_LINES_Y - 1));
-	}
-
-	/* draw strings on the x axis */
-	if (gw->month != 0xFF) {
-		x = gw->left + GRAPH_X_POSITION_BEGINNING;
-		y = gw->top + gw->height + 1;
-		byte month = gw->month;
-		Year year  = gw->year;
-		for (int i = 0; i < gw->num_on_x_axis; i++) {
-			SetDParam(0, month + STR_0162_JAN);
-			SetDParam(1, month + STR_0162_JAN + 2);
-			SetDParam(2, year);
-			DrawString(x, y, month == 0 ? STR_016F : STR_016E, GRAPH_AXIS_LABEL_COLOUR);
-
-			month += 3;
-			if (month >= 12) {
-				month = 0;
-				year++;
-			}
-			x += GRAPH_X_POSITION_SEPARATION;
-		}
-	} else {
-		/* Draw the label under the data point rather than on the grid line. */
-		x = gw->left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2) + 1;
-		y = gw->top + gw->height + 1;
-		uint16 label = gw->x_values_start;
-
-		for (int i = 0; i < gw->num_on_x_axis; i++) {
-			SetDParam(0, label);
-			DrawStringCentered(x, y, STR_01CB, GRAPH_AXIS_LABEL_COLOUR);
-
-			label += gw->x_values_increment;
-			x += GRAPH_X_POSITION_SEPARATION;
-		}
-	}
-
-	/* draw lines and dots */
-	for (int i = 0; i < gw->num_dataset; i++) {
-		if (!HasBit(gw->excluded_data, i)) {
-			/* Centre the dot between the grid lines. */
-			x = gw->left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2);
-
-			byte color  = gw->colors[i];
-			uint prev_x = INVALID_DATAPOINT_POS;
-			uint prev_y = INVALID_DATAPOINT_POS;
-
-			for (int j = 0; j < gw->num_on_x_axis; j++) {
-				OverflowSafeInt64 datapoint = gw->cost[i][j];
-
-				if (datapoint != INVALID_DATAPOINT) {
-					/*
-					 * Check whether we need to reduce the 'accuracy' of the
-					 * datapoint value and the highest value to splut overflows.
-					 * And when 'drawing' 'one million' or 'one million and one'
-					 * there is no significant difference, so the least
-					 * significant bits can just be removed.
-					 *
-					 * If there are more bits needed than would fit in a 32 bits
-					 * integer, so at about 31 bits because of the sign bit, the
-					 * least significant bits are removed.
-					 */
-					int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint));
-					int reduce_range = max(mult_range - 31, 0);
-
-					/* Handle negative values differently (don't shift sign) */
-					if (datapoint < 0) {
-						datapoint = -(abs(datapoint) >> reduce_range);
-					} else {
-						datapoint >>= reduce_range;
-					}
-
-					y = gw->top + x_axis_offset - (x_axis_offset * datapoint) / (highest_value >> reduce_range);
-
-					/* Draw the point. */
-					GfxFillRect(x - 1, y - 1, x + 1, y + 1, color);
-
-					/* Draw the line connected to the previous point. */
-					if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, color);
-
-					prev_x = x;
-					prev_y = y;
-				} else {
-					prev_x = INVALID_DATAPOINT_POS;
-					prev_y = INVALID_DATAPOINT_POS;
-				}
-
-				x += GRAPH_X_POSITION_SEPARATION;
-			}
-		}
-	}
-}
-
 /****************/
 /* GRAPH LEGEND */
 /****************/
 
-static void GraphLegendWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_CREATE:
-			for (uint i = 3; i < w->widget_count; i++) {
-				if (!HasBit(_legend_excluded_players, i - 3)) w->LowerWidget(i);
-			}
-			break;
-
-		case WE_PAINT: {
-			const Player *p;
-
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) continue;
-
-				SetBit(_legend_excluded_players, p->index);
-				w->RaiseWidget(p->index + 3);
-			}
-
-			w->DrawWidgets();
-
-			FOR_ALL_PLAYERS(p) {
-				if (!p->is_active) continue;
-
-				DrawPlayerIcon(p->index, 4, 18 + p->index * 12);
-
-				SetDParam(0, p->index);
-				SetDParam(1, p->index);
-				DrawString(21, 17 + p->index * 12, STR_7021, HasBit(_legend_excluded_players, p->index) ? TC_BLACK : TC_WHITE);
-			}
-			break;
+struct GraphLegendWindow : Window {
+	GraphLegendWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		for (uint i = 3; i < this->widget_count; i++) {
+			if (!HasBit(_legend_excluded_players, i - 3)) this->LowerWidget(i);
 		}
 
-		case WE_CLICK:
-			if (!IsInsideMM(e->we.click.widget, 3, 11)) return;
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			ToggleBit(_legend_excluded_players, e->we.click.widget - 3);
-			w->ToggleWidgetLoweredState(e->we.click.widget);
-			w->SetDirty();
-			InvalidateWindow(WC_INCOME_GRAPH, 0);
-			InvalidateWindow(WC_OPERATING_PROFIT, 0);
-			InvalidateWindow(WC_DELIVERED_CARGO, 0);
-			InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
-			InvalidateWindow(WC_COMPANY_VALUE, 0);
-			break;
+	virtual void OnPaint()
+	{
+		const Player *p;
+
+		FOR_ALL_PLAYERS(p) {
+			if (p->is_active) continue;
+
+			SetBit(_legend_excluded_players, p->index);
+			this->RaiseWidget(p->index + 3);
+		}
+
+		this->DrawWidgets();
+
+		FOR_ALL_PLAYERS(p) {
+			if (!p->is_active) continue;
+
+			DrawPlayerIcon(p->index, 4, 18 + p->index * 12);
+
+			SetDParam(0, p->index);
+			SetDParam(1, p->index);
+			DrawString(21, 17 + p->index * 12, STR_7021, HasBit(_legend_excluded_players, p->index) ? TC_BLACK : TC_WHITE);
+		}
 	}
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (!IsInsideMM(widget, 3, 11)) return;
+
+		ToggleBit(_legend_excluded_players, widget - 3);
+		this->ToggleWidgetLoweredState(widget);
+		this->SetDirty();
+		InvalidateWindow(WC_INCOME_GRAPH, 0);
+		InvalidateWindow(WC_OPERATING_PROFIT, 0);
+		InvalidateWindow(WC_DELIVERED_CARGO, 0);
+		InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
+		InvalidateWindow(WC_COMPANY_VALUE, 0);
+	}
+};
 
 static const Widget _graph_legend_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
@@ -334,90 +101,332 @@
 	WC_GRAPH_LEGEND, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_graph_legend_widgets,
-	GraphLegendWndProc
 };
 
 static void ShowGraphLegend()
 {
-	AllocateWindowDescFront<Window>(&_graph_legend_desc, 0);
+	AllocateWindowDescFront<GraphLegendWindow>(&_graph_legend_desc, 0);
 }
 
+/******************/
+/* BASE OF GRAPHS */
+/*****************/
+
+struct BaseGraphWindow : Window {
+protected:
+	enum {
+		GRAPH_MAX_DATASETS = 32,
+		GRAPH_AXIS_LABEL_COLOUR = TC_BLACK,
+		GRAPH_AXIS_LINE_COLOUR  = 215,
+
+		GRAPH_X_POSITION_BEGINNING  = 44,  ///< Start the graph 44 pixels from gd_left
+		GRAPH_X_POSITION_SEPARATION = 22,  ///< There are 22 pixels between each X value
+
+		GRAPH_NUM_LINES_Y = 9, ///< How many horizontal lines to draw.
+		/* 9 is convenient as that means the distance between them is the gd_height of the graph / 8,
+		* which is the same
+		* as height >> 3. */
+	};
+
+	uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
+	byte num_dataset;
+	byte num_on_x_axis;
+	bool has_negative_values;
+	byte num_vert_lines;
+
+	/* The starting month and year that values are plotted against. If month is
+	 * 0xFF, use x_values_start and x_values_increment below instead. */
+	byte month;
+	Year year;
+
+	/* These values are used if the graph is being plotted against values
+	 * rather than the dates specified by month and year. */
+	uint16 x_values_start;
+	uint16 x_values_increment;
+
+	int gd_left, gd_top;  ///< Where to start drawing the graph, in pixels.
+	uint gd_height;    ///< The height of the graph in pixels.
+	StringID format_str_y_axis;
+	byte colors[GRAPH_MAX_DATASETS];
+	OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][24]; ///< last 2 years
+
+	void DrawGraph() const
+	{
+		uint x, y;                       ///< Reused whenever x and y coordinates are needed.
+		OverflowSafeInt64 highest_value; ///< Highest value to be drawn.
+		int x_axis_offset;               ///< Distance from the top of the graph to the x axis.
+
+		/* the colors and cost array of GraphDrawer must accomodate
+		* both values for cargo and players. So if any are higher, quit */
+		assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_PLAYERS);
+		assert(this->num_vert_lines > 0);
+
+		byte grid_colour = _colour_gradient[14][4];
+
+		/* The coordinates of the opposite edges of the graph. */
+		int bottom = this->gd_top + this->gd_height - 1;
+		int right  = this->gd_left + GRAPH_X_POSITION_BEGINNING + this->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1;
+
+		/* Draw the vertical grid lines. */
+
+		/* Don't draw the first line, as that's where the axis will be. */
+		x = this->gd_left + GRAPH_X_POSITION_BEGINNING + GRAPH_X_POSITION_SEPARATION;
+
+		for (int i = 0; i < this->num_vert_lines; i++) {
+			GfxFillRect(x, this->gd_top, x, bottom, grid_colour);
+			x += GRAPH_X_POSITION_SEPARATION;
+		}
+
+		/* Draw the horizontal grid lines. */
+		x = this->gd_left + GRAPH_X_POSITION_BEGINNING;
+		y = this->gd_height + this->gd_top;
+
+		for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
+			GfxFillRect(x, y, right, y, grid_colour);
+			y -= (this->gd_height / (GRAPH_NUM_LINES_Y - 1));
+		}
+
+		/* Draw the y axis. */
+		GfxFillRect(x, this->gd_top, x, bottom, GRAPH_AXIS_LINE_COLOUR);
+
+		/* Find the distance from the gd_top of the graph to the x axis. */
+		x_axis_offset = this->gd_height;
+
+		/* The graph is currently symmetrical about the x axis. */
+		if (this->has_negative_values) x_axis_offset /= 2;
+
+		/* Draw the x axis. */
+		y = x_axis_offset + this->gd_top;
+		GfxFillRect(x, y, right, y, GRAPH_AXIS_LINE_COLOUR);
+
+		/* Find the largest value that will be drawn. */
+		if (this->num_on_x_axis == 0)
+			return;
+
+		assert(this->num_on_x_axis > 0);
+		assert(this->num_dataset > 0);
+
+		/* Start of with a value of twice the gd_height of the graph in pixels. It's a
+		* bit arbitrary, but it makes the cargo payment graph look a little nicer,
+		* and prevents division by zero when calculating where the datapoint
+		* should be drawn. */
+		highest_value = x_axis_offset * 2;
+
+		for (int i = 0; i < this->num_dataset; i++) {
+			if (!HasBit(this->excluded_data, i)) {
+				for (int j = 0; j < this->num_on_x_axis; j++) {
+					OverflowSafeInt64 datapoint = this->cost[i][j];
+
+					if (datapoint != INVALID_DATAPOINT) {
+						/* For now, if the graph has negative values the scaling is
+						* symmetrical about the x axis, so take the absolute value
+						* of each data point. */
+						highest_value = max(highest_value, abs(datapoint));
+					}
+				}
+			}
+		}
+
+		/* Round up highest_value so that it will divide cleanly into the number of
+		* axis labels used. */
+		int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1);
+		if (round_val != 0) highest_value += (GRAPH_NUM_LINES_Y - 1 - round_val);
+
+		/* draw text strings on the y axis */
+		int64 y_label = highest_value;
+		int64 y_label_separation = highest_value / (GRAPH_NUM_LINES_Y - 1);
+
+		/* If there are negative values, the graph goes from highest_value to
+		* -highest_value, not highest_value to 0. */
+		if (this->has_negative_values) y_label_separation *= 2;
+
+		x = this->gd_left + GRAPH_X_POSITION_BEGINNING + 1;
+		y = this->gd_top - 3;
+
+		for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) {
+			SetDParam(0, this->format_str_y_axis);
+			SetDParam(1, y_label);
+			DrawStringRightAligned(x, y, STR_0170, GRAPH_AXIS_LABEL_COLOUR);
+
+			y_label -= y_label_separation;
+			y += (this->gd_height / (GRAPH_NUM_LINES_Y - 1));
+		}
+
+		/* draw strings on the x axis */
+		if (this->month != 0xFF) {
+			x = this->gd_left + GRAPH_X_POSITION_BEGINNING;
+			y = this->gd_top + this->gd_height + 1;
+			byte month = this->month;
+			Year year  = this->year;
+			for (int i = 0; i < this->num_on_x_axis; i++) {
+				SetDParam(0, month + STR_0162_JAN);
+				SetDParam(1, month + STR_0162_JAN + 2);
+				SetDParam(2, year);
+				DrawString(x, y, month == 0 ? STR_016F : STR_016E, GRAPH_AXIS_LABEL_COLOUR);
+
+				month += 3;
+				if (month >= 12) {
+					month = 0;
+					year++;
+				}
+				x += GRAPH_X_POSITION_SEPARATION;
+			}
+		} else {
+			/* Draw the label under the data point rather than on the grid line. */
+			x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2) + 1;
+			y = this->gd_top + this->gd_height + 1;
+			uint16 label = this->x_values_start;
+
+			for (int i = 0; i < this->num_on_x_axis; i++) {
+				SetDParam(0, label);
+				DrawStringCentered(x, y, STR_01CB, GRAPH_AXIS_LABEL_COLOUR);
+
+				label += this->x_values_increment;
+				x += GRAPH_X_POSITION_SEPARATION;
+			}
+		}
+
+		/* draw lines and dots */
+		for (int i = 0; i < this->num_dataset; i++) {
+			if (!HasBit(this->excluded_data, i)) {
+				/* Centre the dot between the grid lines. */
+				x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2);
+
+				byte color  = this->colors[i];
+				uint prev_x = INVALID_DATAPOINT_POS;
+				uint prev_y = INVALID_DATAPOINT_POS;
+
+				for (int j = 0; j < this->num_on_x_axis; j++) {
+					OverflowSafeInt64 datapoint = this->cost[i][j];
+
+					if (datapoint != INVALID_DATAPOINT) {
+						/*
+						* Check whether we need to reduce the 'accuracy' of the
+						* datapoint value and the highest value to splut overflows.
+						* And when 'drawing' 'one million' or 'one million and one'
+						* there is no significant difference, so the least
+						* significant bits can just be removed.
+						*
+						* If there are more bits needed than would fit in a 32 bits
+						* integer, so at about 31 bits because of the sign bit, the
+						* least significant bits are removed.
+						*/
+						int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint));
+						int reduce_range = max(mult_range - 31, 0);
+
+						/* Handle negative values differently (don't shift sign) */
+						if (datapoint < 0) {
+							datapoint = -(abs(datapoint) >> reduce_range);
+						} else {
+							datapoint >>= reduce_range;
+						}
+
+						y = this->gd_top + x_axis_offset - (x_axis_offset * datapoint) / (highest_value >> reduce_range);
+
+						/* Draw the point. */
+						GfxFillRect(x - 1, y - 1, x + 1, y + 1, color);
+
+						/* Draw the line connected to the previous point. */
+						if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, color);
+
+						prev_x = x;
+						prev_y = y;
+					} else {
+						prev_x = INVALID_DATAPOINT_POS;
+						prev_y = INVALID_DATAPOINT_POS;
+					}
+
+					x += GRAPH_X_POSITION_SEPARATION;
+				}
+			}
+		}
+	}
+
+
+	BaseGraphWindow(const WindowDesc *desc, WindowNumber window_number, int left,
+									int top, int height, bool has_negative_values, StringID format_str_y_axis) :
+			Window(desc, window_number), has_negative_values(has_negative_values),
+			gd_left(left), gd_top(top), gd_height(height), format_str_y_axis(format_str_y_axis)
+	{
+		InvalidateWindow(WC_GRAPH_LEGEND, 0);
+	}
+
+public:
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+
+		uint excluded_players = _legend_excluded_players;
+
+		/* Exclude the players which aren't valid */
+		const Player* p;
+		FOR_ALL_PLAYERS(p) {
+			if (!p->is_active) SetBit(excluded_players, p->index);
+		}
+		this->excluded_data = excluded_players;
+		this->num_vert_lines = 24;
+
+		byte nums = 0;
+		FOR_ALL_PLAYERS(p) {
+			if (p->is_active) nums = max(nums, p->num_valid_stat_ent);
+		}
+		this->num_on_x_axis = min(nums, 24);
+
+		int mo = (_cur_month / 3 - nums) * 3;
+		int yr = _cur_year;
+		while (mo < 0) {
+			yr--;
+			mo += 12;
+		}
+
+		this->year = yr;
+		this->month = mo;
+
+		int numd = 0;
+		FOR_ALL_PLAYERS(p) {
+			if (p->is_active) {
+				this->colors[numd] = _colour_gradient[p->player_color][6];
+				for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
+					this->cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(p, j);
+					i++;
+				}
+			}
+			numd++;
+		}
+
+		this->num_dataset = numd;
+
+		this->DrawGraph();
+	}
+
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return INVALID_DATAPOINT;
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		/* Clicked on legend? */
+		if (widget == 2) ShowGraphLegend();
+	}
+};
+
 /********************/
 /* OPERATING PROFIT */
 /********************/
 
-static void SetupGraphDrawerForPlayers(GraphDrawer *gd)
-{
-	const Player* p;
-	uint excluded_players = _legend_excluded_players;
-	byte nums;
-	int mo, yr;
-
-	/* Exclude the players which aren't valid */
-	FOR_ALL_PLAYERS(p) {
-		if (!p->is_active) SetBit(excluded_players, p->index);
-	}
-	gd->excluded_data = excluded_players;
-	gd->num_vert_lines = 24;
-
-	nums = 0;
-	FOR_ALL_PLAYERS(p) {
-		if (p->is_active) nums = max(nums, p->num_valid_stat_ent);
-	}
-	gd->num_on_x_axis = min(nums, 24);
-
-	mo = (_cur_month / 3 - nums) * 3;
-	yr = _cur_year;
-	while (mo < 0) {
-		yr--;
-		mo += 12;
+struct OperatingProfitGraphWindow : BaseGraphWindow {
+	OperatingProfitGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 18, 136, true, STR_CURRCOMPACT)
+	{
+		this->FindWindowPlacementAndResize(desc);
 	}
 
-	gd->year = yr;
-	gd->month = mo;
-}
-
-static void OperatingProfitWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-			const Player* p;
-
-			w->DrawWidgets();
-
-			gd.left = 2;
-			gd.top = 18;
-			gd.height = 136;
-			gd.has_negative_values = true;
-			gd.format_str_y_axis = STR_CURRCOMPACT;
-
-			SetupGraphDrawerForPlayers(&gd);
-
-			int numd = 0;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) {
-					gd.colors[numd] = _colour_gradient[p->player_color][6];
-					for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) {
-						gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (p->old_economy[j].income + p->old_economy[j].expenses);
-						i++;
-					}
-				}
-				numd++;
-			}
-
-			gd.num_dataset = numd;
-
-			DrawGraph(&gd);
-			break;
-		}
-
-		case WE_CLICK:
-			/* Clicked on legend? */
-			if (e->we.click.widget == 2) ShowGraphLegend();
-			break;
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return p->old_economy[j].income + p->old_economy[j].expenses;
 	}
-}
+};
 
 static const Widget _operating_profit_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
@@ -432,15 +441,12 @@
 	WC_OPERATING_PROFIT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_operating_profit_widgets,
-	OperatingProfitWndProc
 };
 
 
 void ShowOperatingProfitGraph()
 {
-	if (AllocateWindowDescFront<Window>(&_operating_profit_desc, 0)) {
-		InvalidateWindow(WC_GRAPH_LEGEND, 0);
-	}
+	AllocateWindowDescFront<OperatingProfitGraphWindow>(&_operating_profit_desc, 0);
 }
 
 
@@ -448,45 +454,18 @@
 /* INCOME GRAPH */
 /****************/
 
-static void IncomeGraphWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-			const Player* p;
-
-			w->DrawWidgets();
-
-			gd.left = 2;
-			gd.top = 18;
-			gd.height = 104;
-			gd.has_negative_values = false;
-			gd.format_str_y_axis = STR_CURRCOMPACT;
-			SetupGraphDrawerForPlayers(&gd);
+struct IncomeGraphWindow : BaseGraphWindow {
+	IncomeGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_CURRCOMPACT)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			int numd = 0;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) {
-					gd.colors[numd] = _colour_gradient[p->player_color][6];
-					for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) {
-						gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : p->old_economy[j].income;
-						i++;
-					}
-				}
-				numd++;
-			}
-
-			gd.num_dataset = numd;
-
-			DrawGraph(&gd);
-			break;
-		}
-
-		case WE_CLICK:
-			if (e->we.click.widget == 2) ShowGraphLegend();
-			break;
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return p->old_economy[j].income;
 	}
-}
+};
 
 static const Widget _income_graph_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
@@ -501,59 +480,29 @@
 	WC_INCOME_GRAPH, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_income_graph_widgets,
-	IncomeGraphWndProc
 };
 
 void ShowIncomeGraph()
 {
-	if (AllocateWindowDescFront<Window>(&_income_graph_desc, 0)) {
-		InvalidateWindow(WC_GRAPH_LEGEND, 0);
-	}
+	AllocateWindowDescFront<IncomeGraphWindow>(&_income_graph_desc, 0);
 }
 
 /*******************/
 /* DELIVERED CARGO */
 /*******************/
 
-static void DeliveredCargoGraphWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-			const Player* p;
-
-			w->DrawWidgets();
-
-			gd.left = 2;
-			gd.top = 18;
-			gd.height = 104;
-			gd.has_negative_values = false;
-			gd.format_str_y_axis = STR_7024;
-			SetupGraphDrawerForPlayers(&gd);
+struct DeliveredCargoGraphWindow : BaseGraphWindow {
+	DeliveredCargoGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_7024)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			int numd = 0;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) {
-					gd.colors[numd] = _colour_gradient[p->player_color][6];
-					for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) {
-						gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (OverflowSafeInt64)p->old_economy[j].delivered_cargo;
-						i++;
-					}
-				}
-				numd++;
-			}
-
-			gd.num_dataset = numd;
-
-			DrawGraph(&gd);
-			break;
-		}
-
-		case WE_CLICK:
-			if (e->we.click.widget == 2) ShowGraphLegend();
-			break;
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return p->old_economy[j].delivered_cargo;
 	}
-}
+};
 
 static const Widget _delivered_cargo_graph_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
@@ -568,60 +517,35 @@
 	WC_DELIVERED_CARGO, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_delivered_cargo_graph_widgets,
-	DeliveredCargoGraphWndProc
 };
 
 void ShowDeliveredCargoGraph()
 {
-	if (AllocateWindowDescFront<Window>(&_delivered_cargo_graph_desc, 0)) {
-		InvalidateWindow(WC_GRAPH_LEGEND, 0);
-	}
+	AllocateWindowDescFront<DeliveredCargoGraphWindow>(&_delivered_cargo_graph_desc, 0);
 }
 
 /***********************/
 /* PERFORMANCE HISTORY */
 /***********************/
 
-static void PerformanceHistoryWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-			const Player* p;
-
-			w->DrawWidgets();
-
-			gd.left = 2;
-			gd.top = 18;
-			gd.height = 200;
-			gd.has_negative_values = false;
-			gd.format_str_y_axis = STR_7024;
-			SetupGraphDrawerForPlayers(&gd);
+struct PerformanceHistoryGraphWindow : BaseGraphWindow {
+	PerformanceHistoryGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_7024)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			int numd = 0;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) {
-					gd.colors[numd] = _colour_gradient[p->player_color][6];
-					for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) {
-						gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (OverflowSafeInt64)p->old_economy[j].performance_history;
-						i++;
-					}
-				}
-				numd++;
-			}
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return p->old_economy[j].performance_history;
+	}
 
-			gd.num_dataset = numd;
-
-			DrawGraph(&gd);
-			break;
-		}
-
-		case WE_CLICK:
-			if (e->we.click.widget == 2) ShowGraphLegend();
-			if (e->we.click.widget == 3) ShowPerformanceRatingDetail();
-			break;
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget == 3) ShowPerformanceRatingDetail();
+		this->BaseGraphWindow::OnClick(pt, widget);
 	}
-}
+};
 
 static const Widget _performance_history_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                             STR_018B_CLOSE_WINDOW},
@@ -637,59 +561,29 @@
 	WC_PERFORMANCE_HISTORY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_performance_history_widgets,
-	PerformanceHistoryWndProc
 };
 
 void ShowPerformanceHistoryGraph()
 {
-	if (AllocateWindowDescFront<Window>(&_performance_history_desc, 0)) {
-		InvalidateWindow(WC_GRAPH_LEGEND, 0);
-	}
+	AllocateWindowDescFront<PerformanceHistoryGraphWindow>(&_performance_history_desc, 0);
 }
 
 /*****************/
 /* COMPANY VALUE */
 /*****************/
 
-static void CompanyValueGraphWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-			const Player* p;
-
-			w->DrawWidgets();
-
-			gd.left = 2;
-			gd.top = 18;
-			gd.height = 200;
-			gd.has_negative_values = false;
-			gd.format_str_y_axis = STR_CURRCOMPACT;
-			SetupGraphDrawerForPlayers(&gd);
+struct CompanyValueGraphWindow : BaseGraphWindow {
+	CompanyValueGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_CURRCOMPACT)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			int numd = 0;
-			FOR_ALL_PLAYERS(p) {
-				if (p->is_active) {
-					gd.colors[numd] = _colour_gradient[p->player_color][6];
-					for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) {
-						gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : p->old_economy[j].company_value;
-						i++;
-					}
-				}
-				numd++;
-			}
-
-			gd.num_dataset = numd;
-
-			DrawGraph(&gd);
-			break;
-		}
-
-		case WE_CLICK:
-			if (e->we.click.widget == 2) ShowGraphLegend();
-			break;
+	virtual OverflowSafeInt64 GetGraphData(const Player *p, int j)
+	{
+		return p->old_economy[j].company_value;
 	}
-}
+};
 
 static const Widget _company_value_graph_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},
@@ -704,90 +598,117 @@
 	WC_COMPANY_VALUE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_company_value_graph_widgets,
-	CompanyValueGraphWndProc
 };
 
 void ShowCompanyValueGraph()
 {
-	if (AllocateWindowDescFront<Window>(&_company_value_graph_desc, 0)) {
-		InvalidateWindow(WC_GRAPH_LEGEND, 0);
-	}
+	AllocateWindowDescFront<CompanyValueGraphWindow>(&_company_value_graph_desc, 0);
 }
 
 /*****************/
 /* PAYMENT RATES */
 /*****************/
 
-static void CargoPaymentRatesWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			GraphDrawer gd;
-
-			w->DrawWidgets();
-
-			int x = 495;
-			int y = 24;
-
-			gd.excluded_data = _legend_excluded_cargo;
-			gd.left = 2;
-			gd.top = 24;
-			gd.height = w->height - 38;
-			gd.has_negative_values = false;
-			gd.format_str_y_axis = STR_CURRCOMPACT;
-			gd.num_on_x_axis = 20;
-			gd.num_vert_lines = 20;
-			gd.month = 0xFF;
-			gd.x_values_start     = 10;
-			gd.x_values_increment = 10;
-
-			uint i = 0;
-			for (CargoID c = 0; c < NUM_CARGO; c++) {
-				const CargoSpec *cs = GetCargo(c);
-				if (!cs->IsValid()) continue;
-
-				/* Only draw labels for widgets that exist. If the widget doesn't
-				 * exist then the local player has used the climate cheat or
-				 * changed the NewGRF configuration with this window open. */
-				if (i + 3 < w->widget_count) {
-					/* Since the buttons have no text, no images,
-					 * both the text and the colored box have to be manually painted.
-					 * clk_dif will move one pixel down and one pixel to the right
-					 * when the button is clicked */
-					byte clk_dif = w->IsWidgetLowered(i + 3) ? 1 : 0;
-
-					GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0);
-					GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour);
-					SetDParam(0, cs->name);
-					DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, TC_FROMSTRING);
-					y += 8;
-				}
-
-				gd.colors[i] = cs->legend_colour;
-				for (uint j = 0; j != 20; j++) {
-					gd.cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 6 + 6, c);
-				}
-
-				i++;
-			}
-			gd.num_dataset = i;
-
-			DrawGraph(&gd);
-
-			DrawString(2 + 46, 24 + gd.height + 7, STR_7062_DAYS_IN_TRANSIT, TC_FROMSTRING);
-			DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, TC_FROMSTRING);
-			break;
+struct PaymentRatesGraphWindow : BaseGraphWindow {
+	PaymentRatesGraphWindow(const WindowDesc *desc, WindowNumber window_number) :
+			BaseGraphWindow(desc, window_number, 2, 24, 200, false, STR_CURRCOMPACT)
+	{
+		uint num_active = 0;
+		for (CargoID c = 0; c < NUM_CARGO; c++) {
+			if (GetCargo(c)->IsValid()) num_active++;
 		}
 
-		case WE_CLICK:
-			if (e->we.click.widget >= 3) {
-				ToggleBit(_legend_excluded_cargo, e->we.click.widget - 3);
-				w->ToggleWidgetLoweredState(e->we.click.widget);
-				w->SetDirty();
+		/* Resize the window to fit the cargo types */
+		ResizeWindow(this, 0, max(num_active, 12U) * 8);
+
+		/* Add widgets for each cargo type */
+		this->widget_count += num_active;
+		this->widget = ReallocT(this->widget, this->widget_count + 1);
+		this->widget[this->widget_count].type = WWT_LAST;
+
+		/* Set the properties of each widget */
+		for (uint i = 0; i != num_active; i++) {
+			Widget *wi = &this->widget[3 + i];
+			wi->type     = WWT_PANEL;
+			wi->display_flags = RESIZE_NONE;
+			wi->color    = 12;
+			wi->left     = 493;
+			wi->right    = 562;
+			wi->top      = 24 + i * 8;
+			wi->bottom   = wi->top + 7;
+			wi->data     = 0;
+			wi->tooltips = STR_7064_TOGGLE_GRAPH_FOR_CARGO;
+
+			if (!HasBit(_legend_excluded_cargo, i)) this->LowerWidget(i + 3);
+		}
+
+		this->SetDirty();
+
+		this->gd_height = this->height - 38;
+		this->num_on_x_axis = 20;
+		this->num_vert_lines = 20;
+		this->month = 0xFF;
+		this->x_values_start     = 10;
+		this->x_values_increment = 10;
+
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+
+		this->excluded_data = _legend_excluded_cargo;
+
+		int x = 495;
+		int y = 24;
+
+		uint i = 0;
+		for (CargoID c = 0; c < NUM_CARGO; c++) {
+			const CargoSpec *cs = GetCargo(c);
+			if (!cs->IsValid()) continue;
+
+			/* Only draw labels for widgets that exist. If the widget doesn't
+				* exist then the local player has used the climate cheat or
+				* changed the NewGRF configuration with this window open. */
+			if (i + 3 < this->widget_count) {
+				/* Since the buttons have no text, no images,
+					* both the text and the colored box have to be manually painted.
+					* clk_dif will move one pixel down and one pixel to the right
+					* when the button is clicked */
+				byte clk_dif = this->IsWidgetLowered(i + 3) ? 1 : 0;
+
+				GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0);
+				GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour);
+				SetDParam(0, cs->name);
+				DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, TC_FROMSTRING);
+				y += 8;
 			}
-			break;
+
+			this->colors[i] = cs->legend_colour;
+			for (uint j = 0; j != 20; j++) {
+				this->cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 6 + 6, c);
+			}
+
+			i++;
+		}
+		this->num_dataset = i;
+
+		this->DrawGraph();
+
+		DrawString(2 + 46, 24 + this->gd_height + 7, STR_7062_DAYS_IN_TRANSIT, TC_FROMSTRING);
+		DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, TC_FROMSTRING);
 	}
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget >= 3) {
+			ToggleBit(_legend_excluded_cargo, widget - 3);
+			this->ToggleWidgetLoweredState(widget);
+			this->SetDirty();
+		}
+	}
+};
 
 static const Widget _cargo_payment_rates_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                     STR_018B_CLOSE_WINDOW},
@@ -801,46 +722,12 @@
 	WC_PAYMENT_RATES, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_cargo_payment_rates_widgets,
-	CargoPaymentRatesWndProc
 };
 
 
 void ShowCargoPaymentRates()
 {
-	Window *w = AllocateWindowDescFront<Window>(&_cargo_payment_rates_desc, 0);
-	if (w == NULL) return;
-
-	/* Count the number of active cargo types */
-	uint num_active = 0;
-	for (CargoID c = 0; c < NUM_CARGO; c++) {
-		if (GetCargo(c)->IsValid()) num_active++;
-	}
-
-	/* Resize the window to fit the cargo types */
-	ResizeWindow(w, 0, max(num_active, 12U) * 8);
-
-	/* Add widgets for each cargo type */
-	w->widget_count += num_active;
-	w->widget = ReallocT(w->widget, w->widget_count + 1);
-	w->widget[w->widget_count].type = WWT_LAST;
-
-	/* Set the properties of each widget */
-	for (uint i = 0; i != num_active; i++) {
-		Widget *wi = &w->widget[3 + i];
-		wi->type     = WWT_PANEL;
-		wi->display_flags = RESIZE_NONE;
-		wi->color    = 12;
-		wi->left     = 493;
-		wi->right    = 562;
-		wi->top      = 24 + i * 8;
-		wi->bottom   = wi->top + 7;
-		wi->data     = 0;
-		wi->tooltips = STR_7064_TOGGLE_GRAPH_FOR_CARGO;
-
-		if (!HasBit(_legend_excluded_cargo, i)) w->LowerWidget(i + 3);
-	}
-
-	w->SetDirty();
+	AllocateWindowDescFront<PaymentRatesGraphWindow>(&_cargo_payment_rates_desc, 0);
 }
 
 /************************/
@@ -879,35 +766,36 @@
 	return p2->old_economy[1].performance_history - p1->old_economy[1].performance_history;
 }
 
-static void CompanyLeagueWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			const Player* plist[MAX_PLAYERS];
-			const Player* p;
-
-			w->DrawWidgets();
-
-			uint pl_num = 0;
-			FOR_ALL_PLAYERS(p) if (p->is_active) plist[pl_num++] = p;
+struct CompanyLeagueWindow : Window {
+	CompanyLeagueWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			qsort((void*)plist, pl_num, sizeof(*plist), PerfHistComp);
+	virtual void OnPaint()
+	{
+		const Player *plist[MAX_PLAYERS];
+		const Player *p;
 
-			for (uint i = 0; i != pl_num; i++) {
-				p = plist[i];
-				SetDParam(0, i + STR_01AC_1ST);
-				SetDParam(1, p->index);
-				SetDParam(2, p->index);
-				SetDParam(3, GetPerformanceTitleFromValue(p->old_economy[1].performance_history));
+		this->DrawWidgets();
 
-				DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING);
-				DrawPlayerIcon(p->index, 27, 16 + i * 10);
-			}
+		uint pl_num = 0;
+		FOR_ALL_PLAYERS(p) if (p->is_active) plist[pl_num++] = p;
 
-			break;
+		qsort((void*)plist, pl_num, sizeof(*plist), PerfHistComp);
+
+		for (uint i = 0; i != pl_num; i++) {
+			p = plist[i];
+			SetDParam(0, i + STR_01AC_1ST);
+			SetDParam(1, p->index);
+			SetDParam(2, p->index);
+			SetDParam(3, GetPerformanceTitleFromValue(p->old_economy[1].performance_history));
+
+			DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING);
+			DrawPlayerIcon(p->index, 27, 16 + i * 10);
 		}
 	}
-}
+};
 
 
 static const Widget _company_league_widgets[] = {
@@ -923,12 +811,11 @@
 	WC_COMPANY_LEAGUE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_company_league_widgets,
-	CompanyLeagueWndProc
 };
 
 void ShowCompanyLeagueTable()
 {
-	AllocateWindowDescFront<Window>(&_company_league_desc, 0);
+	AllocateWindowDescFront<CompanyLeagueWindow>(&_company_league_desc, 0);
 }
 
 /*****************************/
@@ -949,7 +836,8 @@
 		this->UpdatePlayerStats();
 
 		if (player != INVALID_PLAYER) this->LowerWidget(player + 13);
-		this->SetDirty();
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	void UpdatePlayerStats()
@@ -1154,7 +1042,6 @@
 	WC_PERFORMANCE_DETAIL, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_performance_rating_detail_widgets,
-	NULL
 };
 
 void ShowPerformanceRatingDetail()
--- a/src/group_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/group_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -30,70 +30,6 @@
 
 typedef GUIList<const Group*> GUIGroupList;
 
-static void BuildGroupList(GUIGroupList *gl, PlayerID owner, VehicleType vehicle_type)
-{
-	uint n = 0;
-
-	if (!(gl->flags & VL_REBUILD)) return;
-
-	const Group **list = MallocT<const Group*>(GetGroupArraySize());
-
-	const Group *g;
-	FOR_ALL_GROUPS(g) {
-		if (g->owner == owner && g->vehicle_type == vehicle_type) list[n++] = g;
-	}
-
-	gl->sort_list = ReallocT(gl->sort_list, n);
-	gl->list_length = n;
-
-	for (uint i = 0; i < n; ++i) gl->sort_list[i] = list[i];
-	free(list);
-
-	gl->flags &= ~VL_REBUILD;
-	gl->flags |= VL_RESORT;
-}
-
-
-static int CDECL GroupNameSorter(const void *a, const void *b)
-{
-	static const Group *last_group[2] = { NULL, NULL };
-	static char         last_name[2][64] = { "", "" };
-
-	const Group *ga = *(const Group**)a;
-	const Group *gb = *(const Group**)b;
-	int r;
-
-	if (ga != last_group[0]) {
-		last_group[0] = ga;
-		SetDParam(0, ga->index);
-		GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
-	}
-
-	if (gb != last_group[1]) {
-		last_group[1] = gb;
-		SetDParam(0, gb->index);
-		GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
-	}
-
-	r = strcmp(last_name[0], last_name[1]); // sort by name
-
-	if (r == 0) return ga->index - gb->index;
-
-	return r;
-}
-
-
-static void SortGroupList(GUIGroupList *gl)
-{
-	if (!(gl->flags & VL_RESORT)) return;
-
-	qsort((void*)gl->sort_list, gl->list_length, sizeof(gl->sort_list[0]), GroupNameSorter);
-
-	gl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
-	gl->flags &= ~VL_RESORT;
-}
-
-
 enum GroupListWidgets {
 	GRP_WIDGET_CLOSEBOX = 0,
 	GRP_WIDGET_CAPTION,
@@ -182,11 +118,58 @@
 };
 
 
-struct VehicleGroupWindow : public Window, public VehicleListBase {
+class VehicleGroupWindow : public Window, public VehicleListBase {
+private:
 	GroupID group_sel;
 	VehicleID vehicle_sel;
 	GUIGroupList groups;
 
+	/**
+	 * (Re)Build the group list.
+	 *
+	 * @param owner The owner of the window
+	 */
+	void BuildGroupList(PlayerID owner)
+	{
+		if (!this->groups.NeedRebuild()) return;
+
+		this->groups.Clear();
+
+		const Group *g;
+		FOR_ALL_GROUPS(g) {
+			if (g->owner == owner && g->vehicle_type == this->vehicle_type) {
+				*this->groups.Append() = g;
+			}
+		}
+
+		this->groups.Compact();
+		this->groups.RebuildDone();
+	}
+
+	/** Sort the groups by their name */
+	static int CDECL GroupNameSorter(const Group* const *a, const Group* const *b)
+	{
+		static const Group *last_group[2] = { NULL, NULL };
+		static char         last_name[2][64] = { "", "" };
+
+		if (*a != last_group[0]) {
+			last_group[0] = *a;
+			SetDParam(0, (*a)->index);
+			GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
+		}
+
+		if (*b != last_group[1]) {
+			last_group[1] = *b;
+			SetDParam(0, (*b)->index);
+			GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
+		}
+
+		int r = strcmp(last_name[0], last_name[1]); // sort by name
+		if (r == 0) return (*a)->index - (*b)->index;
+		return r;
+	}
+
+public:
 	VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 	{
 		const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8);
@@ -223,14 +206,12 @@
 			case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
 		}
 
-		this->vehicles.sort_list = NULL;
 		this->vehicles.sort_type = this->sorting->criteria;
 		this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE);
 		this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
 
-		this->groups.sort_list = NULL;
-		this->groups.flags = VL_REBUILD | VL_NONE;
-		this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
+		this->groups.ForceRebuild();
+		this->groups.NeedResort();
 
 		this->group_sel = ALL_GROUP;
 		this->vehicle_sel = INVALID_VEHICLE;
@@ -280,14 +261,18 @@
 
 	~VehicleGroupWindow()
 	{
-		free((void*)this->vehicles.sort_list);
-		free((void*)this->groups.sort_list);
 	}
 
 	virtual void OnInvalidateData(int data)
 	{
-		this->vehicles.flags |= VL_REBUILD;
-		this->groups.flags |= VL_REBUILD;
+		this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+
+		if (data == 0) {
+			this->groups.ForceRebuild();
+		} else {
+			this->groups.ForceResort();
+		}
+
 		if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) {
 			this->group_sel = ALL_GROUP;
 			HideDropDownMenu(this);
@@ -309,21 +294,20 @@
 		BuildVehicleList(this, owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST);
 		SortVehicleList(this);
 
+		this->BuildGroupList(owner);
+		this->groups.Sort(&GroupNameSorter);
 
-		BuildGroupList(&this->groups, owner, this->vehicle_type);
-		SortGroupList(&this->groups);
-
-		SetVScrollCount(this, this->groups.list_length);
-		SetVScroll2Count(this, this->vehicles.list_length);
+		SetVScrollCount(this, this->groups.Length());
+		SetVScroll2Count(this, this->vehicles.Length());
 
 		/* The drop down menu is out, *but* it may not be used, retract it. */
-		if (this->vehicles.list_length == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
+		if (this->vehicles.Length() == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
 			this->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
 			HideDropDownMenu(this);
 		}
 
 		/* Disable all lists management button when the list is empty */
-		this->SetWidgetsDisabledState(this->vehicles.list_length == 0 || _local_player != owner,
+		this->SetWidgetsDisabledState(this->vehicles.Length() == 0 || _local_player != owner,
 				GRP_WIDGET_STOP_ALL,
 				GRP_WIDGET_START_ALL,
 				GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
@@ -352,7 +336,7 @@
 				We list all vehicles or ungrouped vehicles */
 		if (IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel)) {
 			SetDParam(0, owner);
-			SetDParam(1, this->vehicles.list_length);
+			SetDParam(1, this->vehicles.Length());
 
 			switch (this->vehicle_type) {
 				case VEH_TRAIN:
@@ -434,9 +418,9 @@
 
 		DrawString(10, y1, str_no_group_veh, IsDefaultGroupID(this->group_sel) ? TC_WHITE : TC_BLACK);
 
-		max = min(this->vscroll.pos + this->vscroll.cap, this->groups.list_length);
+		max = min(this->vscroll.pos + this->vscroll.cap, this->groups.Length());
 		for (i = this->vscroll.pos ; i < max ; ++i) {
-			const Group *g = this->groups.sort_list[i];
+			const Group *g = this->groups[i];
 
 			assert(g->owner == owner);
 
@@ -454,9 +438,9 @@
 		this->DrawSortButtonState(GRP_WIDGET_SORT_BY_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
 
 		/* Draw Matrix Vehicle according to the vehicle list built before */
-		max = min(this->vscroll2.pos + this->vscroll2.cap, this->vehicles.list_length);
+		max = min(this->vscroll2.pos + this->vscroll2.cap, this->vehicles.Length());
 		for (i = this->vscroll2.pos ; i < max ; ++i) {
-			const Vehicle* v = this->vehicles.sort_list[i];
+			const Vehicle* v = this->vehicles[i];
 
 			assert(v->type == this->vehicle_type && v->owner == owner);
 
@@ -521,9 +505,9 @@
 
 				id_g += this->vscroll.pos;
 
-				if (id_g >= this->groups.list_length) return;
+				if (id_g >= this->groups.Length()) return;
 
-				this->group_sel = this->groups.sort_list[id_g]->index;;
+				this->group_sel = this->groups[id_g]->index;;
 
 				this->vehicles.flags |= VL_REBUILD;
 				this->SetDirty();
@@ -538,9 +522,9 @@
 
 				id_v += this->vscroll2.pos;
 
-				if (id_v >= this->vehicles.list_length) return; // click out of list bound
+				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
-				v = this->vehicles.sort_list[id_v];
+				v = this->vehicles[id_v];
 
 				this->vehicle_sel = v->index;
 
@@ -628,9 +612,9 @@
 
 				id_g += this->vscroll.pos;
 
-				if (id_g >= this->groups.list_length) return;
+				if (id_g >= this->groups.Length()) return;
 
-				DoCommandP(0, this->groups.sort_list[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
+				DoCommandP(0, this->groups[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
 
 				break;
 			}
@@ -648,9 +632,9 @@
 
 				id_v += this->vscroll2.pos;
 
-				if (id_v >= this->vehicles.list_length) return; // click out of list bound
+				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
-				v = this->vehicles.sort_list[id_v];
+				v = this->vehicles[id_v];
 
 				if (vindex == v->index) {
 					ShowVehicleViewWindow(v);
@@ -693,7 +677,7 @@
 				break;
 
 			case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
-				assert(this->vehicles.list_length != 0);
+				assert(this->vehicles.Length() != 0);
 
 				switch (index) {
 					case GALF_REPLACE: // Replace window
@@ -736,9 +720,7 @@
 			this->vehicles.flags |= VL_RESORT;
 			this->SetDirty();
 		}
-		if (--this->groups.resort_timer == 0) {
-			this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
-			this->groups.flags |= VL_RESORT;
+		if (this->groups.NeedResort()) {
 			this->SetDirty();
 		}
 	}
@@ -757,7 +739,6 @@
 	WC_TRAINS_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_group_widgets,
-	NULL
 };
 
 void ShowPlayerGroup(PlayerID player, VehicleType vehicle_type)
--- a/src/heightmap.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/heightmap.cpp	Tue May 27 00:50:55 2008 +0000
@@ -297,7 +297,7 @@
 	TileIndex tile;
 
 	/* Get map size and calculate scale and padding values */
-	switch (_patches.heightmap_rotation) {
+	switch (_settings.game_creation.heightmap_rotation) {
 		default: NOT_REACHED();
 		case HM_COUNTER_CLOCKWISE:
 			width   = MapSizeX();
@@ -322,7 +322,7 @@
 	/* Form the landscape */
 	for (row = 0; row < height - 1; row++) {
 		for (col = 0; col < width - 1; col++) {
-			switch (_patches.heightmap_rotation) {
+			switch (_settings.game_creation.heightmap_rotation) {
 				default: NOT_REACHED();
 				case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break;
 				case HM_CLOCKWISE:         tile = TileXY(row, col); break;
@@ -337,7 +337,7 @@
 				/* Use nearest neighbor resizing to scale map data.
 				 *  We rotate the map 45 degrees (counter)clockwise */
 				img_row = (((row - row_pad) * num_div) / img_scale);
-				switch (_patches.heightmap_rotation) {
+				switch (_settings.game_creation.heightmap_rotation) {
 					default: NOT_REACHED();
 					case HM_COUNTER_CLOCKWISE:
 						img_col = (((width - 1 - col - col_pad) * num_div) / img_scale);
--- a/src/industry.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/industry.h	Tue May 27 00:50:55 2008 +0000
@@ -354,9 +354,6 @@
 #define FOR_ALL_INDUSTRIES_FROM(i, start) for (i = GetIndustry(start); i != NULL; i = (i->index + 1U < GetIndustryPoolSize()) ? GetIndustry(i->index + 1U) : NULL) if (i->IsValid())
 #define FOR_ALL_INDUSTRIES(i) FOR_ALL_INDUSTRIES_FROM(i, 0)
 
-extern const Industry **_industry_sort;
-extern bool _industry_sort_dirty;
-
 static const uint8 IT_INVALID = 255;
 
 #endif /* INDUSTRY_H */
--- a/src/industry_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/industry_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -55,9 +55,6 @@
 int _total_industries;                      //general counter
 uint16 _industry_counts[NUM_INDUSTRYTYPES]; // Number of industries per type ingame
 
-const Industry **_industry_sort;
-bool _industry_sort_dirty;
-
 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
 
@@ -73,7 +70,7 @@
 	/* once performed, enable only the current climate industries */
 	for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
 		_industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
-				HasBit(_origin_industry_specs[i].climate_availability, _opt.landscape);
+				HasBit(_origin_industry_specs[i].climate_availability, _settings.game_creation.landscape);
 	}
 
 	memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
@@ -87,7 +84,7 @@
 void ResetIndustryCreationProbility(IndustryType type)
 {
 	assert(type < INVALID_INDUSTRYTYPE);
-	_industry_specs[type].appear_creation[_opt.landscape] = 0;
+	_industry_specs[type].appear_creation[_settings.game_creation.landscape] = 0;
 }
 
 DEFINE_OLD_POOL_GENERIC(Industry, Industry)
@@ -168,12 +165,11 @@
 		} END_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiff(21, 21))
 	}
 
-	_industry_sort_dirty = true;
 	DecIndustryTypeCount(this->type);
 
 	DeleteSubsidyWithIndustry(this->index);
 	DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
-	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
+	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
 	this->xy = 0;
 }
 
@@ -381,7 +377,7 @@
 {
 	const Industry *i = GetIndustryByTile(tile);
 
-	td->owner = i->owner;
+	td->owner[0] = i->owner;
 	td->str = GetIndustrySpec(i->type)->name;
 	if (!IsIndustryCompleted(tile)) {
 		SetDParamX(td->dparam, 0, td->str);
@@ -892,14 +888,14 @@
 	uint field_type;
 	int type;
 
-	if (_opt.landscape == LT_ARCTIC) {
+	if (_settings.game_creation.landscape == LT_ARCTIC) {
 		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= GetSnowLine())
 			return;
 	}
 
 	/* determine field size */
 	r = (Random() & 0x303) + 0x404;
-	if (_opt.landscape == LT_ARCTIC) r += 0x404;
+	if (_settings.game_creation.landscape == LT_ARCTIC) r += 0x404;
 	size_x = GB(r, 0, 8);
 	size_y = GB(r, 8, 8);
 
@@ -930,7 +926,7 @@
 	END_TILE_LOOP(cur_tile, size_x, size_y, tile)
 
 	type = 3;
-	if (_opt.landscape != LT_ARCTIC && _opt.landscape != LT_TROPIC) {
+	if (_settings.game_creation.landscape != LT_ARCTIC && _settings.game_creation.landscape != LT_TROPIC) {
 		type = _plantfarmfield_type[Random() & 0xF];
 	}
 
@@ -1067,7 +1063,7 @@
 
 static bool CheckNewIndustry_Forest(TileIndex tile)
 {
-	if (_opt.landscape == LT_ARCTIC) {
+	if (_settings.game_creation.landscape == LT_ARCTIC) {
 		if (GetTileZ(tile) < HighestSnowLine() + TILE_HEIGHT * 2U) {
 			_error_message = STR_4831_FOREST_CAN_ONLY_BE_PLANTED;
 			return false;
@@ -1079,7 +1075,7 @@
 static bool CheckNewIndustry_OilRefinery(TileIndex tile)
 {
 	if (_game_mode == GM_EDITOR) return true;
-	if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
+	if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings.game_creation.oil_refinery_limit) return true;
 
 	_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
 	return false;
@@ -1091,7 +1087,7 @@
 {
 	if (_game_mode == GM_EDITOR && _ignore_restrictions) return true;
 	if (TileHeight(tile) == 0 &&
-			DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
+			DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings.game_creation.oil_refinery_limit) return true;
 
 	_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
 	return false;
@@ -1099,7 +1095,7 @@
 
 static bool CheckNewIndustry_Farm(TileIndex tile)
 {
-	if (_opt.landscape == LT_ARCTIC) {
+	if (_settings.game_creation.landscape == LT_ARCTIC) {
 		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= HighestSnowLine()) {
 			_error_message = STR_0239_SITE_UNSUITABLE;
 			return false;
@@ -1175,7 +1171,7 @@
 
 	t = ClosestTownFromTile(tile, (uint)-1);
 
-	if (_patches.multiple_industry_per_town) return t;
+	if (_settings.economy.multiple_industry_per_town) return t;
 
 	FOR_ALL_INDUSTRIES(i) {
 		if (i->type == (byte)type &&
@@ -1261,7 +1257,7 @@
 	/* It is almost impossible to have a fully flat land in TG, so what we
 	 *  do is that we check if we can make the land flat later on. See
 	 *  CheckIfCanLevelIndustryPlatform(). */
-	return !refused_slope || (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions);
+	return !refused_slope || (_settings.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions);
 }
 
 static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
@@ -1391,7 +1387,7 @@
 	const IndustrySpec *indspec = GetIndustrySpec(type);
 	const Industry *i;
 
-	if (_patches.same_industry_close && indspec->IsRawIndustry())
+	if (_settings.economy.same_industry_close && indspec->IsRawIndustry())
 		/* Allow primary industries to be placed close to any other industry */
 		return true;
 
@@ -1405,8 +1401,8 @@
 				indspec->accepts_cargo[0] == i->accepts_cargo[0] && (
 				/* at least one of those options must be true */
 				_game_mode != GM_EDITOR || // editor must not be stopped
-				!_patches.same_industry_close ||
-				!_patches.multiple_industry_per_town)) {
+				!_settings.economy.same_industry_close ||
+				!_settings.economy.multiple_industry_per_town)) {
 			_error_message = STR_INDUSTRY_TOO_CLOSE;
 			return false;
 		}
@@ -1453,7 +1449,7 @@
 	i->production_rate[1] = indspec->production_rate[1];
 
 	/* don't use smooth economy for industries using production related callbacks */
-	if (_patches.smooth_economy &&
+	if (_settings.economy.smooth_economy &&
 	    !(HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
 	    !(HasBit(indspec->callback_flags, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CHANGE))             // production change callbacks
 	) {
@@ -1556,8 +1552,7 @@
 	if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
 		for (j = 0; j != 50; j++) PlantRandomFarmField(i);
 	}
-	_industry_sort_dirty = true;
-	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
+	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
 }
 
 /** Helper function for Build/Fund an industry
@@ -1582,7 +1577,7 @@
 		if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
 	}
 
-	if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
+	if (!custom_shape_check && _settings.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
 	if (!CheckIfFarEnoughFromIndustry(tile, type)) return NULL;
 
 	const Town *t = CheckMultipleIndustryInTown(tile, type);
@@ -1626,11 +1621,11 @@
 
 	/* If the patch for raw-material industries is not on, you cannot build raw-material industries.
 	 * Raw material industries are industries that do not accept cargo (at least for now) */
-	if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
+	if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
 		return CMD_ERROR;
 	}
 
-	if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indspec->IsRawIndustry()) {
+	if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && indspec->IsRawIndustry()) {
 		if (flags & DC_EXEC) {
 			/* Prospecting has a chance to fail, however we cannot guarantee that something can
 			 * be built on the map, so the chance gets lower when the map is fuller, but there
@@ -1705,13 +1700,13 @@
 {
 	/* We need to bypass the amount given in parameter if it exceeds the maximum dimension of the
 	 * _numof_industry_table.  newgrf can specify a big amount */
-	int num = (amount > NB_NUMOFINDUSTRY) ? amount : _numof_industry_table[_opt.diff.number_industries][amount];
+	int num = (amount > NB_NUMOFINDUSTRY) ? amount : _numof_industry_table[_settings.difficulty.number_industries][amount];
 	const IndustrySpec *ind_spc = GetIndustrySpec(type);
 
 	/* These are always placed next to the coastline, so we scale by the perimeter instead. */
 	num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num);
 
-	if (_opt.diff.number_industries != 0) {
+	if (_settings.difficulty.number_industries != 0) {
 		PlayerID old_player = _current_player;
 		_current_player = OWNER_NONE;
 		assert(num > 0);
@@ -1740,7 +1735,7 @@
 	const IndustrySpec *ind_spc;
 
 	/* Find the total amount of industries */
-	if (_opt.diff.number_industries > 0) {
+	if (_settings.difficulty.number_industries > 0) {
 		for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
 
 			ind_spc = GetIndustrySpec(it);
@@ -1749,12 +1744,12 @@
 				ResetIndustryCreationProbility(it);
 			}
 
-			chance = ind_spc->appear_creation[_opt.landscape];
+			chance = ind_spc->appear_creation[_settings.game_creation.landscape];
 			if (ind_spc->enabled && chance > 0) {
 				/* once the chance of appearance is determind, it have to be scaled by
 				 * the difficulty level. The "chance" in question is more an index into
 				 * the _numof_industry_table,in fact */
-				int num = (chance > NB_NUMOFINDUSTRY) ? chance : _numof_industry_table[_opt.diff.number_industries][chance];
+				int num = (chance > NB_NUMOFINDUSTRY) ? chance : _numof_industry_table[_settings.difficulty.number_industries][chance];
 
 				/* These are always placed next to the coastline, so we scale by the perimeter instead. */
 				num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num);
@@ -1765,7 +1760,7 @@
 
 	SetGeneratingWorldProgress(GWP_INDUSTRY, i);
 
-	if (_opt.diff.number_industries > 0) {
+	if (_settings.difficulty.number_industries > 0) {
 		for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
 			/* Once the number of industries has been determined, let's really create them.
 			 * The test for chance allows us to try create industries that are available only
@@ -1774,7 +1769,7 @@
 			 *          processed that scaling above? No, don't think so.  Will find a way. */
 			ind_spc = GetIndustrySpec(it);
 			if (ind_spc->enabled) {
-				chance = ind_spc->appear_creation[_opt.landscape];
+				chance = ind_spc->appear_creation[_settings.game_creation.landscape];
 				if (chance > 0) PlaceInitialIndustry(it, chance);
 			}
 		}
@@ -1828,7 +1823,7 @@
 	/* Generate a list of all possible industries that can be built. */
 	for (j = 0; j < NUM_INDUSTRYTYPES; j++) {
 		ind_spc = GetIndustrySpec(j);
-		byte chance = ind_spc->appear_ingame[_opt.landscape];
+		byte chance = ind_spc->appear_ingame[_settings.game_creation.landscape];
 
 		if (!ind_spc->enabled || chance == 0) continue;
 
@@ -1886,7 +1881,7 @@
 	const IndustrySpec *indspec = GetIndustrySpec(type);
 
 	/* oil wells (or the industries with that flag set) are always allowed to closedown */
-	if (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD && _opt.landscape == LT_TEMPERATE) return false;
+	if (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD && _settings.game_creation.landscape == LT_TEMPERATE) return false;
 	return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && GetIndustryTypeCount(type) <= 1;
 }
 
@@ -1958,10 +1953,9 @@
 		bool c_accepts = false;
 		bool c_produces = false;
 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
-			const Vehicle *u = v;
-			BEGIN_ENUM_WAGONS(u)
+			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
 				CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
-			END_ENUM_WAGONS(u)
+			}
 		} else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
 			CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
 		} else {
@@ -2037,7 +2031,7 @@
 	bool standard = true;
 	bool suppress_message = false;
 	/* don't use smooth economy for industries using production related callbacks */
-	bool smooth_economy = _patches.smooth_economy &&
+	bool smooth_economy = _settings.economy.smooth_economy &&
 	                      !(HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
 	                      !(HasBit(indspec->callback_flags, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CHANGE));            // production change callbacks
 	byte div = 0;
@@ -2078,7 +2072,7 @@
 
 	if (standard && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) {
 		/* decrease or increase */
-		bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE;
+		bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings.game_creation.landscape == LT_TEMPERATE;
 
 		if (smooth_economy) {
 			closeit = true;
@@ -2240,8 +2234,7 @@
 	_current_player = old_player;
 
 	/* production-change */
-	_industry_sort_dirty = true;
-	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
+	InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
 }
 
 
@@ -2251,7 +2244,6 @@
 	_Industry_pool.AddBlockToPool();
 
 	ResetIndustryCounts();
-	_industry_sort_dirty = true;
 	_industry_sound_tile = 0;
 }
 
@@ -2265,7 +2257,7 @@
 Money IndustrySpec::GetConstructionCost() const
 {
 	return (_price.build_industry *
-			(_patches.raw_industry_construction == 1 && this->IsRawIndustry() ?
+			(_settings.construction.raw_industry_construction == 1 && this->IsRawIndustry() ?
 					this->raw_industry_cost_multiplier :
 					this->cost_multiplier
 			)) >> 8;
--- a/src/industry_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/industry_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -26,6 +26,7 @@
 #include "settings_type.h"
 #include "tilehighlight_func.h"
 #include "string_func.h"
+#include "sortlist_type.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -90,7 +91,6 @@
 	WC_BUILD_INDUSTRY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 	_build_industry_widgets,
-	NULL,
 };
 
 class BuildIndustryWindow : public Window {
@@ -131,7 +131,7 @@
 				/* Rule is that editor mode loads all industries.
 				 * In game mode, all non raw industries are loaded too
 				 * and raw ones are loaded only when setting allows it */
-				if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _patches.raw_industry_construction == 0) {
+				if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _settings.construction.raw_industry_construction == 0) {
 					/* Unselect if the industry is no longer in the list */
 					if (this->selected_type == ind) this->selected_index = -1;
 					continue;
@@ -195,10 +195,10 @@
 		 * In Editor, you just build, while ingame, or you fund or you prospect */
 		if (_game_mode == GM_EDITOR) {
 			/* We've chosen many random industries but no industries have been specified */
-			if (indsp == NULL) this->enabled[this->selected_index] = _opt.diff.number_industries != 0;
+			if (indsp == NULL) this->enabled[this->selected_index] = _settings.difficulty.number_industries != 0;
 			this->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
 		} else {
-			this->widget[DPIW_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
+			this->widget[DPIW_FUND_WIDGET].data = (_settings.construction.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
 		}
 		this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]);
 
@@ -304,7 +304,7 @@
 
 					this->SetDirty();
 
-					if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
+					if ((_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) ||
 							this->selected_type == INVALID_INDUSTRYTYPE) {
 						/* Reset the button state if going to prospecting or "build many industries" */
 						this->RaiseButtons();
@@ -325,7 +325,7 @@
 						GenerateIndustries();
 						_generating_world = false;
 					}
-				} else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
+				} else if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) {
 					DoCommandP(0, this->selected_type, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
 					this->HandleButtonClick(DPIW_FUND_WIDGET);
 				} else {
@@ -679,7 +679,6 @@
 	WC_INDUSTRY_VIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_industry_view_widgets,
-	NULL
 };
 
 void ShowIndustryViewWindow(int industry)
@@ -697,7 +696,7 @@
 	IDW_SORTBYPROD,
 	IDW_SORTBYTRANSPORT,
 	IDW_SPACER,
-	IDW_INDUSRTY_LIST,
+	IDW_INDUSTRY_LIST,
 	IDW_SCROLLBAR,
 	IDW_RESIZE,
 };
@@ -718,12 +717,37 @@
 {   WIDGETS_END},
 };
 
-static uint _num_industry_sort;
-
 static char _bufcache[96];
 static const Industry* _last_industry;
+static int _internal_sort_order;
 
-static byte _industry_sort_order;
+/** Returns percents of cargo transported if industry produces this cargo, else -1
+ * @param i industry to check
+ * @param id cargo slot
+ * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
+ */
+static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
+{
+	assert(id < lengthof(i->produced_cargo));
+
+	if (i->produced_cargo[id] == CT_INVALID) return 101;
+	return i->last_month_pct_transported[id] * 100 >> 8;
+}
+
+/** Returns value representing industry's transported cargo
+ * percentage for industry sorting
+ * @param i industry to check
+ * @return value used for sorting
+ */
+static int GetCargoTransportedSortValue(const Industry *i)
+{
+	int p1 = GetCargoTransportedPercentsIfValid(i, 0);
+	int p2 = GetCargoTransportedPercentsIfValid(i, 1);
+
+	if (p1 > p2) Swap(p1, p2); // lower value has higher priority
+
+	return (p1 << 8) + p2;
+}
 
 static int CDECL GeneralIndustrySorter(const void *a, const void *b)
 {
@@ -731,7 +755,7 @@
 	const Industry* j = *(const Industry**)b;
 	int r;
 
-	switch (_industry_sort_order >> 1) {
+	switch (_internal_sort_order >> 1) {
 		default: NOT_REACHED();
 		case 0: /* Sort by Name (handled later) */
 			r = 0;
@@ -756,30 +780,7 @@
 			break;
 
 		case 3: /* Sort by transported fraction */
-			if (i->produced_cargo[0] == CT_INVALID) {
-				r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1);
-			} else {
-				if (j->produced_cargo[0] == CT_INVALID) {
-					r = 1;
-				} else {
-					int pi;
-					int pj;
-
-					pi = i->last_month_pct_transported[0] * 100 >> 8;
-					if (i->produced_cargo[1] != CT_INVALID) {
-						int p = i->last_month_pct_transported[1] * 100 >> 8;
-						if (p < pi) pi = p;
-					}
-
-					pj = j->last_month_pct_transported[0] * 100 >> 8;
-					if (j->produced_cargo[1] != CT_INVALID) {
-						int p = j->last_month_pct_transported[1] * 100 >> 8;
-						if (p < pj) pj = p;
-					}
-
-					r = pi - pj;
-				}
-			}
+			r = GetCargoTransportedSortValue(i) - GetCargoTransportedSortValue(j);
 			break;
 	}
 
@@ -798,138 +799,164 @@
 		r = strcmp(buf1, _bufcache);
 	}
 
-	if (_industry_sort_order & 1) r = -r;
+	if (_internal_sort_order & 1) r = -r;
 	return r;
 }
 
+typedef GUIList<const Industry*> GUIIndustryList;
+
 /**
- * Makes a sorted industry list.
- * When there are no industries, the list has to be made. This so when one
- * starts a new game without industries after playing a game with industries
- * the list is not populated with invalid industries from the previous game.
+ * Rebuild industries list if the VL_REBUILD flag is set
+ *
+ * @param sl pointer to industry list
  */
-static void MakeSortedIndustryList()
+static void BuildIndustriesList(GUIIndustryList *sl)
 {
-	const Industry* i;
-	int n = 0;
+	if (!(sl->flags & VL_REBUILD)) return;
 
-	/* Create array for sorting */
-	_industry_sort = ReallocT(_industry_sort, GetMaxIndustryIndex() + 1);
+	sl->Clear();
 
-	/* Don't attempt a sort if there are no industries */
-	if (GetNumIndustries() != 0) {
-		FOR_ALL_INDUSTRIES(i) _industry_sort[n++] = i;
-		qsort((void*)_industry_sort, n, sizeof(_industry_sort[0]), GeneralIndustrySorter);
+	DEBUG(misc, 3, "Building industry list");
+
+	const Industry *i;
+	FOR_ALL_INDUSTRIES(i) {
+		*sl->Append() = i;
 	}
 
-	_num_industry_sort = n;
-	_last_industry = NULL; // used for "cache"
+	sl->Compact();
 
-	DEBUG(misc, 3, "Resorting industries list");
+	sl->flags &= ~VL_REBUILD;
+	sl->flags |= VL_RESORT;
 }
 
 
-static void IndustryDirectoryWndProc(Window *w, WindowEvent *e)
+/**
+ * Sort industry list if the VL_RESORT flag is set
+ *
+ * @param sl pointer to industry list
+ */
+static void SortIndustriesList(GUIIndustryList *sl)
 {
-	switch (e->event) {
-		case WE_PAINT: {
-			if (_industry_sort_dirty) {
-				_industry_sort_dirty = false;
-				MakeSortedIndustryList();
+	if (!(sl->flags & VL_RESORT)) return;
+
+	_internal_sort_order = (sl->sort_type << 1) | (sl->flags & VL_DESC);
+	_last_industry = NULL; // used for "cache" in namesorting
+	qsort((void*)sl->Begin(), sl->Length(), sizeof(sl->Begin()), &GeneralIndustrySorter);
+
+	sl->flags &= ~VL_RESORT;
+}
+
+/**
+ * The list of industries.
+ */
+struct IndustryDirectoryWindow : public Window, public GUIIndustryList {
+	static Listing industry_sort;
+
+	IndustryDirectoryWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
+	{
+		this->vscroll.cap = 16;
+		this->resize.height = this->height - 6 * 10; // minimum 10 items
+		this->resize.step_height = 10;
+		this->FindWindowPlacementAndResize(desc);
+
+		this->flags = VL_REBUILD;
+		this->sort_type = industry_sort.criteria;
+		if (industry_sort.order) this->flags |= VL_DESC;
+	}
+
+	virtual void OnPaint()
+	{
+		BuildIndustriesList(this);
+		SortIndustriesList(this);
+
+		SetVScrollCount(this, this->Length());
+
+		this->DrawWidgets();
+		this->DrawSortButtonState(IDW_SORTBYNAME + this->sort_type, this->flags & VL_DESC ? SBS_DOWN : SBS_UP);
+
+		int max = min(this->vscroll.pos + this->vscroll.cap, this->Length());
+		int y = 28; // start of the list-widget
+
+		for (int n = this->vscroll.pos; n < max; ++n) {
+			const Industry* i = *this->Get(n);
+			const IndustrySpec *indsp = GetIndustrySpec(i->type);
+			byte p = 0;
+
+			/* Industry name */
+			SetDParam(p++, i->index);
+
+			/* Industry productions */
+			for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
+				if (i->produced_cargo[j] == CT_INVALID) continue;
+				SetDParam(p++, i->produced_cargo[j]);
+				SetDParam(p++, i->last_month_production[j]);
+				SetDParam(p++, GetCargoSuffix(j + 3, CST_DIR, (Industry*)i, i->type, indsp));
 			}
 
-			SetVScrollCount(w, _num_industry_sort);
-
-			w->DrawWidgets();
-			w->DrawSortButtonState(IDW_SORTBYNAME + (_industry_sort_order >> 1), _industry_sort_order & 1 ? SBS_DOWN : SBS_UP);
-
-			uint pos = w->vscroll.pos;
-			int n = 0;
-
-			while (pos < _num_industry_sort) {
-				const Industry* i = _industry_sort[pos];
-				const IndustrySpec *indsp = GetIndustrySpec(i->type);
-				byte p = 0;
-
-				/* Industry name */
-				SetDParam(p++, i->index);
-
-				/* Industry productions */
-				for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
-					if (i->produced_cargo[j] == CT_INVALID) continue;
-					SetDParam(p++, i->produced_cargo[j]);
-					SetDParam(p++, i->last_month_production[j]);
-					SetDParam(p++, GetCargoSuffix(j + 3, CST_DIR, (Industry*)i, i->type, indsp));
-				}
-
-				/* Transported productions */
-				for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
-					if (i->produced_cargo[j] == CT_INVALID) continue;
-					SetDParam(p++, i->last_month_pct_transported[j] * 100 >> 8);
-				}
-
-				/* Drawing the right string */
-				StringID str = STR_INDUSTRYDIR_ITEM_NOPROD;
-				if (p != 1) str = (p == 5) ? STR_INDUSTRYDIR_ITEM : STR_INDUSTRYDIR_ITEM_TWO;
-				DrawStringTruncated(4, 28 + n * 10, str, TC_FROMSTRING, w->widget[IDW_INDUSRTY_LIST].right - 4);
-
-				pos++;
-				if (++n == w->vscroll.cap) break;
+			/* Transported productions */
+			for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
+				if (i->produced_cargo[j] == CT_INVALID) continue;
+				SetDParam(p++, i->last_month_pct_transported[j] * 100 >> 8);
 			}
-		} break;
 
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case IDW_SORTBYNAME: {
-					_industry_sort_order = _industry_sort_order == 0 ? 1 : 0;
-					_industry_sort_dirty = true;
-					w->SetDirty();
-				} break;
-
-				case IDW_SORTBYTYPE: {
-					_industry_sort_order = _industry_sort_order == 2 ? 3 : 2;
-					_industry_sort_dirty = true;
-					w->SetDirty();
-				} break;
-
-				case IDW_SORTBYPROD: {
-					_industry_sort_order = _industry_sort_order == 4 ? 5 : 4;
-					_industry_sort_dirty = true;
-					w->SetDirty();
-				} break;
-
-				case IDW_SORTBYTRANSPORT: {
-					_industry_sort_order = _industry_sort_order == 6 ? 7 : 6;
-					_industry_sort_dirty = true;
-					w->SetDirty();
-				} break;
+			/* Drawing the right string */
+			StringID str = STR_INDUSTRYDIR_ITEM_NOPROD;
+			if (p != 1) str = (p == 5) ? STR_INDUSTRYDIR_ITEM : STR_INDUSTRYDIR_ITEM_TWO;
+			DrawStringTruncated(4, y, str, TC_FROMSTRING, this->widget[IDW_INDUSTRY_LIST].right - 4);
 
-				case IDW_INDUSRTY_LIST: {
-					int y = (e->we.click.pt.y - 28) / 10;
-					uint16 p;
+			y += 10;
+		}
+	}
 
-					if (!IsInsideMM(y, 0, w->vscroll.cap)) return;
-					p = y + w->vscroll.pos;
-					if (p < _num_industry_sort) {
-						if (_ctrl_pressed) {
-							ShowExtraViewPortWindow(_industry_sort[p]->xy);
-						} else {
-							ScrollMainWindowToTile(_industry_sort[p]->xy);
-						}
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case IDW_SORTBYNAME:
+			case IDW_SORTBYTYPE:
+			case IDW_SORTBYPROD:
+			case IDW_SORTBYTRANSPORT:
+				if (this->sort_type == (widget - IDW_SORTBYNAME)) {
+					this->flags ^= VL_DESC;
+				} else {
+					this->sort_type = widget - IDW_SORTBYNAME;
+					this->flags &= ~VL_DESC;
+				}
+				industry_sort.criteria = this->sort_type;
+				industry_sort.order = HasBit(this->flags, 0);
+				this->flags |= VL_RESORT;
+				this->SetDirty();
+				break;
+
+			case IDW_INDUSTRY_LIST: {
+				int y = (pt.y - 28) / 10;
+				uint16 p;
+
+				if (!IsInsideMM(y, 0, this->vscroll.cap)) return;
+				p = y + this->vscroll.pos;
+				if (p < this->Length()) {
+					if (_ctrl_pressed) {
+						ShowExtraViewPortWindow((*this->Get(p))->xy);
+					} else {
+						ScrollMainWindowToTile((*this->Get(p))->xy);
 					}
-				} break;
-			}
-			break;
+				}
+			} break;
+		}
+	}
 
-		case WE_100_TICKS:
-			w->SetDirty();
-			break;
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->vscroll.cap += delta.y / 10;
+	}
 
-		case WE_RESIZE:
-			w->vscroll.cap += e->we.sizing.diff.y / 10;
-			break;
+	virtual void OnInvalidateData(int data)
+	{
+		this->flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+		this->InvalidateWidget(IDW_INDUSTRY_LIST);
 	}
-}
+};
+
+Listing IndustryDirectoryWindow::industry_sort = {0, 0};
 
 /** Window definition of the industy directory gui */
 static const WindowDesc _industry_directory_desc = {
@@ -937,17 +964,9 @@
 	WC_INDUSTRY_DIRECTORY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_industry_directory_widgets,
-	IndustryDirectoryWndProc
 };
 
 void ShowIndustryDirectory()
 {
-	Window *w = AllocateWindowDescFront<Window>(&_industry_directory_desc, 0);
-
-	if (w != NULL) {
-		w->vscroll.cap = 16;
-		w->resize.height = w->height - 6 * 10; // minimum 10 items
-		w->resize.step_height = 10;
-		w->SetDirty();
-	}
+	AllocateWindowDescFront<IndustryDirectoryWindow>(&_industry_directory_desc, 0);
 }
--- a/src/intro_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/intro_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -49,91 +49,95 @@
 
 static inline void SetNewLandscapeType(byte landscape)
 {
-	_opt_newgame.landscape = landscape;
+	_settings_newgame.game_creation.landscape = landscape;
 	InvalidateWindowClasses(WC_SELECT_GAME);
 }
 
-enum SelectGameIntroWidgets {
-	SGI_GENERATE_GAME = 2,
-	SGI_LOAD_GAME,
-	SGI_PLAY_SCENARIO,
-	SGI_PLAY_HEIGHTMAP,
-	SGI_EDIT_SCENARIO,
-	SGI_PLAY_NETWORK,
-	SGI_TEMPERATE_LANDSCAPE,
-	SGI_ARCTIC_LANDSCAPE,
-	SGI_TROPIC_LANDSCAPE,
-	SGI_TOYLAND_LANDSCAPE,
-	SGI_OPTIONS,
-	SGI_DIFFICULTIES,
-	SGI_PATCHES_OPTIONS,
-	SGI_GRF_SETTINGS,
-	SGI_EXIT,
-};
+struct SelectGameWindow : public Window {
+private:
+	enum SelectGameIntroWidgets {
+		SGI_GENERATE_GAME = 2,
+		SGI_LOAD_GAME,
+		SGI_PLAY_SCENARIO,
+		SGI_PLAY_HEIGHTMAP,
+		SGI_EDIT_SCENARIO,
+		SGI_PLAY_NETWORK,
+		SGI_TEMPERATE_LANDSCAPE,
+		SGI_ARCTIC_LANDSCAPE,
+		SGI_TROPIC_LANDSCAPE,
+		SGI_TOYLAND_LANDSCAPE,
+		SGI_OPTIONS,
+		SGI_DIFFICULTIES,
+		SGI_PATCHES_OPTIONS,
+		SGI_GRF_SETTINGS,
+		SGI_EXIT,
+	};
 
-static void SelectGameWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_CREATE: w->LowerWidget(_opt_newgame.landscape + 8); break;
+public:
+	SelectGameWindow(const WindowDesc *desc) : Window(desc)
+	{
+		this->LowerWidget(_settings_newgame.game_creation.landscape + SGI_TEMPERATE_LANDSCAPE);
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-		case WE_PAINT:
-			w->SetWidgetLoweredState(SGI_TEMPERATE_LANDSCAPE, _opt_newgame.landscape == LT_TEMPERATE);
-			w->SetWidgetLoweredState(SGI_ARCTIC_LANDSCAPE, _opt_newgame.landscape == LT_ARCTIC);
-			w->SetWidgetLoweredState(SGI_TROPIC_LANDSCAPE, _opt_newgame.landscape == LT_TROPIC);
-			w->SetWidgetLoweredState(SGI_TOYLAND_LANDSCAPE, _opt_newgame.landscape == LT_TOYLAND);
-			SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level);
-			w->DrawWidgets();
-			break;
+	virtual void OnPaint()
+	{
+		this->SetWidgetLoweredState(SGI_TEMPERATE_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TEMPERATE);
+		this->SetWidgetLoweredState(SGI_ARCTIC_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_ARCTIC);
+		this->SetWidgetLoweredState(SGI_TROPIC_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TROPIC);
+		this->SetWidgetLoweredState(SGI_TOYLAND_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TOYLAND);
+		SetDParam(0, STR_6801_EASY + _settings_newgame.difficulty.diff_level);
+		this->DrawWidgets();
+	}
 
-		case WE_CLICK:
+	virtual void OnClick(Point pt, int widget)
+	{
 #ifdef ENABLE_NETWORK
-			/* Do not create a network server when you (just) have closed one of the game
-			 * creation/load windows for the network server. */
-			if (SGI_GENERATE_GAME <= e->we.click.widget && e->we.click.widget <= SGI_EDIT_SCENARIO) _is_network_server = false;
+		/* Do not create a network server when you (just) have closed one of the game
+		 * creation/load windows for the network server. */
+		if (IsInsideMM(widget, SGI_GENERATE_GAME, SGI_EDIT_SCENARIO + 1)) _is_network_server = false;
 #endif /* ENABLE_NETWORK */
 
-			switch (e->we.click.widget) {
-				case SGI_GENERATE_GAME:  ShowGenerateLandscape(); break;
-				case SGI_LOAD_GAME:      ShowSaveLoadDialog(SLD_LOAD_GAME); break;
-				case SGI_PLAY_SCENARIO:  ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
-				case SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
-				case SGI_EDIT_SCENARIO:  StartScenarioEditor(); break;
-
-				case SGI_PLAY_NETWORK:
-					if (!_network_available) {
-						ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
-					} else {
-						ShowNetworkGameWindow();
-					}
-					break;
+		switch (widget) {
+			case SGI_GENERATE_GAME:  ShowGenerateLandscape(); break;
+			case SGI_LOAD_GAME:      ShowSaveLoadDialog(SLD_LOAD_GAME); break;
+			case SGI_PLAY_SCENARIO:  ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
+			case SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
+			case SGI_EDIT_SCENARIO:  StartScenarioEditor(); break;
 
-				case SGI_TEMPERATE_LANDSCAPE: case SGI_ARCTIC_LANDSCAPE:
-				case SGI_TROPIC_LANDSCAPE: case SGI_TOYLAND_LANDSCAPE:
-					w->RaiseWidget(_opt_newgame.landscape + SGI_TEMPERATE_LANDSCAPE);
-					SetNewLandscapeType(e->we.click.widget - SGI_TEMPERATE_LANDSCAPE);
-					break;
+			case SGI_PLAY_NETWORK:
+				if (!_network_available) {
+					ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
+				} else {
+					ShowNetworkGameWindow();
+				}
+				break;
 
-				case SGI_OPTIONS:         ShowGameOptions(); break;
-				case SGI_DIFFICULTIES:    ShowGameDifficulty(); break;
-				case SGI_PATCHES_OPTIONS: ShowPatchesSelection(); break;
-				case SGI_GRF_SETTINGS:    ShowNewGRFSettings(true, true, false, &_grfconfig_newgame); break;
-				case SGI_EXIT:            HandleExitGameRequest(); break;
-			}
-			break;
+			case SGI_TEMPERATE_LANDSCAPE: case SGI_ARCTIC_LANDSCAPE:
+			case SGI_TROPIC_LANDSCAPE: case SGI_TOYLAND_LANDSCAPE:
+				this->RaiseWidget(_settings_newgame.game_creation.landscape + SGI_TEMPERATE_LANDSCAPE);
+				SetNewLandscapeType(widget - SGI_TEMPERATE_LANDSCAPE);
+				break;
+
+			case SGI_OPTIONS:         ShowGameOptions(); break;
+			case SGI_DIFFICULTIES:    ShowGameDifficulty(); break;
+			case SGI_PATCHES_OPTIONS: ShowPatchesSelection(); break;
+			case SGI_GRF_SETTINGS:    ShowNewGRFSettings(true, true, false, &_grfconfig_newgame); break;
+			case SGI_EXIT:            HandleExitGameRequest(); break;
+		}
 	}
-}
+};
 
 static const WindowDesc _select_game_desc = {
 	WDP_CENTER, WDP_CENTER, 336, 195, 336, 195,
 	WC_SELECT_GAME, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_select_game_widgets,
-	SelectGameWndProc
 };
 
 void ShowSelectGameWindow()
 {
-	new Window(&_select_game_desc);
+	new SelectGameWindow(&_select_game_desc);
 }
 
 static void AskExitGameCallback(Window *w, bool confirmed)
--- a/src/landscape.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/landscape.cpp	Tue May 27 00:50:55 2008 +0000
@@ -526,7 +526,7 @@
  */
 byte GetSnowLine(void)
 {
-	if (_snow_line == NULL) return _opt.snow_line;
+	if (_snow_line == NULL) return _settings.game_creation.snow_line;
 
 	YearMonthDay ymd;
 	ConvertDateToYMD(_date, &ymd);
@@ -539,7 +539,7 @@
  */
 byte HighestSnowLine(void)
 {
-	return _snow_line == NULL ? _opt.snow_line : _snow_line->highest_value;
+	return _snow_line == NULL ? _settings.game_creation.snow_line : _snow_line->highest_value;
 }
 
 /**
@@ -818,14 +818,14 @@
 	static const int gwp_desert_amount = 4 + 8;
 
 	if (mode == GW_HEIGHTMAP) {
-		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1);
+		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings.game_creation.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1);
 		LoadHeightmap(_file_to_saveload.name);
 		IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
-	} else if (_patches.land_generator == LG_TERRAGENESIS) {
-		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3);
+	} else if (_settings.game_creation.land_generator == LG_TERRAGENESIS) {
+		SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings.game_creation.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3);
 		GenerateTerrainPerlin();
 	} else {
-		switch (_opt.landscape) {
+		switch (_settings.game_creation.landscape) {
 			case LT_ARCTIC: {
 				SetGeneratingWorldProgress(GWP_LANDSCAPE, 2);
 
@@ -872,9 +872,9 @@
 
 				uint32 r = Random();
 
-				uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
+				uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _settings.difficulty.quantity_sea_lakes) * 256 + 100);
 				for (; i != 0; --i) {
-					GenerateTerrain(_opt.diff.terrain_type, 0);
+					GenerateTerrain(_settings.difficulty.terrain_type, 0);
 				}
 				IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
 			} break;
@@ -883,7 +883,7 @@
 
 	ConvertGroundTilesIntoWaterTiles();
 
-	if (_opt.landscape == LT_TROPIC) CreateDesertOrRainForest();
+	if (_settings.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
 }
 
 void OnTick_Town();
--- a/src/lang/english.txt	Mon May 26 20:45:25 2008 +0000
+++ b/src/lang/english.txt	Tue May 27 00:50:55 2008 +0000
@@ -486,6 +486,9 @@
 STR_01A5_COST_TO_CLEAR                                          :{BLACK}Cost to clear: {LTBLUE}{CURRENCY}
 STR_01A6_N_A                                                    :N/A
 STR_01A7_OWNER                                                  :{BLACK}Owner: {LTBLUE}{STRING1}
+STR_ROAD_OWNER                                                  :{BLACK}Road owner: {LTBLUE}{STRING1}
+STR_TRAM_OWNER                                                  :{BLACK}Tramway owner: {LTBLUE}{STRING1}
+STR_RAIL_OWNER                                                  :{BLACK}Railroad owner: {LTBLUE}{STRING1}
 STR_01A8_LOCAL_AUTHORITY                                        :{BLACK}Local authority: {LTBLUE}{STRING1}
 STR_01A9_NONE                                                   :None
 STR_01AA_NAME                                                   :{BLACK}Name
@@ -1714,6 +1717,7 @@
 STR_1816_TREE_LINED_ROAD                                        :Tree-lined road
 STR_1817_ROAD_VEHICLE_DEPOT                                     :Road vehicle depot
 STR_1818_ROAD_RAIL_LEVEL_CROSSING                               :Road/rail level crossing
+STR_TRAMWAY                                                     :Tramway
 STR_CAN_T_REMOVE_BUS_STATION                                    :{WHITE}Can't remove bus station...
 STR_CAN_T_REMOVE_TRUCK_STATION                                  :{WHITE}Can't remove lorry station...
 STR_CAN_T_REMOVE_PASSENGER_TRAM_STATION                         :{WHITE}Can't remove passenger tram station...
@@ -3549,3 +3553,9 @@
 STR_OSK_KEYBOARD_LAYOUT                                         :`1234567890-=\qwertyuiop[]asdfghjkl;'  zxcvbnm,./ .
 STR_OSK_KEYBOARD_LAYOUT_CAPS                                    :~!@#$%^&*()_+|QWERTYUIOP{{}}ASDFGHJKL:"  ZXCVBNM<>? .
 ########
+
+############ town controlled noise level
+STR_CONFIG_PATCHES_NOISE_LEVEL                                  :{LTBLUE}Allow town controlled noise level for airports: {ORANGE}{STRING}
+STR_NOISE_IN_TOWN                                               :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK}  max: {ORANGE}{COMMA}
+STR_STATION_NOISE                                               :{BLACK}Noise generated: {GOLD}{COMMA}
+########
--- a/src/main_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/main_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -13,7 +13,7 @@
 #include "viewport_func.h"
 #include "command_func.h"
 #include "news_gui.h"
-#include "console.h"
+#include "console_gui.h"
 #include "waypoint.h"
 #include "genworld.h"
 #include "transparency_gui.h"
@@ -48,7 +48,7 @@
 void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
 #ifdef ENABLE_NETWORK
-	if (!success || !_patches.give_money) return;
+	if (!success || !_settings.economy.give_money) return;
 
 	char msg[20];
 	/* Inform the player of this action */
@@ -217,7 +217,7 @@
 
 struct MainWindow : Window
 {
-	MainWindow(int width, int height) : Window(0, 0, width, height, NULL, WC_MAIN_WINDOW, NULL)
+	MainWindow(int width, int height) : Window(0, 0, width, height, WC_MAIN_WINDOW, NULL)
 	{
 		InitializeWindowViewport(this, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
 	}
@@ -239,34 +239,34 @@
 		}
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		switch (keycode) {
 			case 'Q' | WKC_CTRL:
 			case 'Q' | WKC_META:
 				HandleExitGameRequest();
-				return true;
+				return ES_HANDLED;
 		}
 
 		/* Disable all key shortcuts, except quit shortcuts when
 		* generating the world, otherwise they create threading
 		* problem during the generating, resulting in random
 		* assertions that are hard to trigger and debug */
-		if (IsGeneratingWorld()) return true;
+		if (IsGeneratingWorld()) return ES_NOT_HANDLED;
 
 		if (keycode == WKC_BACKQUOTE) {
 			IConsoleSwitch();
-			return false;
+			return ES_HANDLED;
 		}
 
 		if (keycode == ('B' | WKC_CTRL)) {
 			extern bool _draw_bounding_boxes;
 			_draw_bounding_boxes = !_draw_bounding_boxes;
 			MarkWholeScreenDirty();
-			return false;
+			return ES_HANDLED;
 		}
 
-		if (_game_mode == GM_MENU) return true;
+		if (_game_mode == GM_MENU) return ES_NOT_HANDLED;
 
 		switch (keycode) {
 			case 'C':
@@ -344,7 +344,7 @@
 					if (cio == NULL) break;
 
 					/* Only players actually playing can speak to team. Eg spectators cannot */
-					if (_patches.prefer_teamchat && IsValidPlayer(cio->client_playas)) {
+					if (_settings.gui.prefer_teamchat && IsValidPlayer(cio->client_playas)) {
 						const NetworkClientInfo *ci;
 						FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
 							if (ci->client_playas == cio->client_playas && ci != cio) {
@@ -372,9 +372,9 @@
 				break;
 #endif
 
-			default: return true;
+			default: return ES_NOT_HANDLED;
 		}
-		return false;
+		return ES_HANDLED;
 	}
 
 	virtual void OnScroll(Point delta)
--- a/src/misc.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/misc.cpp	Tue May 27 00:50:55 2008 +0000
@@ -27,6 +27,7 @@
 #include "core/alloc_type.hpp"
 #include "animated_tile_func.h"
 #include "tilehighlight_func.h"
+#include "core/bitmath_func.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -66,9 +67,10 @@
 	_realtime_tick = 0;
 	_date_fract = 0;
 	_cur_tileloop_tile = 0;
+	_settings = _settings_newgame;
 
 	if ((mode & IG_DATE_RESET) == IG_DATE_RESET) {
-		SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1));
+		SetDate(ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1));
 		InitializeOldNames();
 	}
 
--- a/src/misc/smallvec.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/misc/smallvec.h	Tue May 27 00:50:55 2008 +0000
@@ -1,11 +1,12 @@
 /* $Id$ */
 
-/** @file smallvec.h Simple vector class that allows allocating an item without the need to copy data needlessly. */
+/** @file smallvec.h Simple vector class that allows allocating an item without the need to copy this->data needlessly. */
 
 #ifndef SMALLVEC_H
 #define SMALLVEC_H
 
-template <typename T, uint S> struct SmallVector {
+template <typename T, uint S>
+struct SmallVector {
 	T *data;
 	uint items;
 	uint capacity;
@@ -14,7 +15,30 @@
 
 	~SmallVector()
 	{
-		free(data);
+		free(this->data);
+	}
+
+	/**
+	 * Remove all items from the list.
+	 */
+	void Clear()
+	{
+		/* In fact we just reset the item counter avoiding the need to
+		 * probably reallocate the same amount of memory the list was
+		 * previously using. */
+		this->items = 0;
+	}
+
+	/**
+	 * Compact the list down to the smallest block size boundary.
+	 */
+	void Compact()
+	{
+		uint capacity = Align(this->items, S);
+		if (capacity >= this->capacity) return;
+
+		this->capacity = capacity;
+		this->data = ReallocT(this->data, this->capacity);
 	}
 
 	/**
@@ -22,42 +46,60 @@
 	 */
 	T *Append()
 	{
-		if (items == capacity) {
-			capacity += S;
-			data = ReallocT(data, capacity);
+		if (this->items == this->capacity) {
+			this->capacity += S;
+			this->data = ReallocT(this->data, this->capacity);
 		}
 
-		return &data[items++];
+		return &this->data[this->items++];
+	}
+
+	/**
+	 * Get the number of items in the list.
+	 */
+	uint Length() const
+	{
+		return this->items;
 	}
 
 	const T *Begin() const
 	{
-		return data;
+		return this->data;
 	}
 
 	T *Begin()
 	{
-		return data;
+		return this->data;
 	}
 
 	const T *End() const
 	{
-		return &data[items];
+		return &this->data[this->items];
 	}
 
 	T *End()
 	{
-		return &data[items];
+		return &this->data[this->items];
 	}
 
-	const T *Get(size_t index) const
+	const T *Get(uint index) const
 	{
-		return &data[index];
+		return &this->data[index];
 	}
 
-	T *Get(size_t index)
+	T *Get(uint index)
 	{
-		return &data[index];
+		return &this->data[index];
+	}
+
+	const T &operator[](uint index) const
+	{
+		return this->data[index];
+	}
+
+	T &operator[](uint index)
+	{
+		return this->data[index];
 	}
 };
 
--- a/src/misc_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/misc_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -145,7 +145,7 @@
 	switch (p2) {
 		default: return CMD_ERROR; // Invalid method
 		case 0: // Take some extra loan
-			loan = (IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI;
+			loan = (IsHumanPlayer(_current_player) || _settings.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI;
 			break;
 		case 1: // Take a loan as big as possible
 			loan = _economy.max_loan - p->current_loan;
@@ -181,7 +181,7 @@
 	switch (p2) {
 		default: return CMD_ERROR; // Invalid method
 		case 0: // Pay back one step
-			loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI);
+			loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _settings.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI);
 			break;
 		case 1: // Pay back as much as possible
 			loan = max(min(p->current_loan, p->player_money), (Money)LOAN_INTERVAL);
@@ -359,7 +359,7 @@
  */
 CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	if (!_patches.give_money) return CMD_ERROR;
+	if (!_settings.economy.give_money) return CMD_ERROR;
 
 	const Player *p = GetPlayer(_current_player);
 	CommandCost amount(EXPENSES_OTHER, min((Money)p1, (Money)20000000LL));
@@ -379,35 +379,3 @@
 	/* Subtract money from local-player */
 	return amount;
 }
-
-/** Change difficulty level/settings (server-only).
- * We cannot really check for valid values of p2 (too much work mostly); stored
- * in file 'settings_gui.c' _game_setting_info[]; we'll just trust the server it knows
- * what to do and does this correctly
- * @param tile unused
- * @param flags operation to perform
- * @param p1 the difficulty setting being changed. If it is -1, the difficulty level
- *           itself is changed. The new value is inside p2
- * @param p2 new value for a difficulty setting or difficulty level
- */
-CommandCost CmdChangeDifficultyLevel(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
-{
-	if (p1 != (uint32)-1L && ((int32)p1 >= GAME_DIFFICULTY_NUM || (int32)p1 < 0)) return CMD_ERROR;
-
-	if (flags & DC_EXEC) {
-		if (p1 != (uint32)-1L) {
-			((GDType*)&_opt_ptr->diff)[p1] = p2;
-			_opt_ptr->diff_level = 3; // custom difficulty level
-		} else {
-			_opt_ptr->diff_level = p2;
-		}
-
-		/* If we are a network-client, update the difficult setting (if it is open).
-		 * Use this instead of just dirtying the window because we need to load in
-		 * the new difficulty settings */
-		if (_networking && !_network_server && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) {
-			ShowGameDifficulty();
-		}
-	}
-	return CommandCost();
-}
--- a/src/misc_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/misc_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -69,34 +69,40 @@
 	WC_LAND_INFO, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_land_info_widgets,
-	NULL
 };
 
 class LandInfoWindow : public Window {
 	enum {
-		LAND_INFO_LINES          =   7,
+		LAND_INFO_CENTERED_LINES   = 9,                        ///< Up to 9 centered lines
+		LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line
+		LAND_INFO_LINE_END,
+
 		LAND_INFO_LINE_BUFF_SIZE = 512,
 	};
 
 public:
-	char landinfo_data[LAND_INFO_LINES][LAND_INFO_LINE_BUFF_SIZE];
+	char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE];
 
 	virtual void OnPaint()
 	{
 		this->DrawWidgets();
 
-		DoDrawStringCentered(140, 16, this->landinfo_data[0], TC_LIGHT_BLUE);
-		DoDrawStringCentered(140, 27, this->landinfo_data[1], TC_FROMSTRING);
-		DoDrawStringCentered(140, 38, this->landinfo_data[2], TC_FROMSTRING);
-		DoDrawStringCentered(140, 49, this->landinfo_data[3], TC_FROMSTRING);
-		DoDrawStringCentered(140, 60, this->landinfo_data[4], TC_FROMSTRING);
-		if (!StrEmpty(this->landinfo_data[5])) DrawStringMultiCenter(140, 76, BindCString(this->landinfo_data[5]), this->width - 4);
-		if (!StrEmpty(this->landinfo_data[6])) DoDrawStringCentered(140, 71, this->landinfo_data[6], TC_FROMSTRING);
+		uint y = 16;
+		for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) {
+			if (StrEmpty(this->landinfo_data[i])) continue;
+
+			DoDrawStringCentered(140, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING);
+			y += 11;
+		}
+
+		y += 5;
+
+		if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) DrawStringMultiCenter(140, y, BindCString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]), this->width - 4);
 	}
 
 	LandInfoWindow(TileIndex tile) : Window(&_land_info_desc) {
 		Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST);
-		Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
+		Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority);
 
 		Money old_money = p->player_money;
 		p->player_money = INT64_MAX;
@@ -108,38 +114,81 @@
 		AcceptedCargo ac;
 
 		td.build_date = 0;
+
+		/* Most tiles have only one owner, but
+		 *  - drivethrough roadstops can be build on town owned roads (up to 2 owners) and
+		 *  - roads can have up to four owners (railroad, road, tram, 3rd-roadtype "highway").
+		 */
+		td.owner_type[0] = STR_01A7_OWNER; // At least one owner is displayed, though it might be "N/A".
+		td.owner_type[1] = STR_NULL;       // STR_NULL results in skipping the owner
+		td.owner_type[2] = STR_NULL;
+		td.owner_type[3] = STR_NULL;
+		td.owner[0] = OWNER_NONE;
+		td.owner[1] = OWNER_NONE;
+		td.owner[2] = OWNER_NONE;
+		td.owner[3] = OWNER_NONE;
+
 		GetAcceptedCargo(tile, ac);
 		GetTileDesc(tile, &td);
 
-		SetDParam(0, td.dparam[0]);
-		GetString(this->landinfo_data[0], td.str, lastof(this->landinfo_data[0]));
+		uint line_nr = 0;
 
-		SetDParam(0, STR_01A6_N_A);
-		if (td.owner != OWNER_NONE && td.owner != OWNER_WATER) GetNameOfOwner(td.owner, tile);
-		GetString(this->landinfo_data[1], STR_01A7_OWNER, lastof(this->landinfo_data[1]));
+		/* Tiletype */
+		SetDParam(0, td.dparam[0]);
+		GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr]));
+		line_nr++;
 
+		/* Up to four owners */
+		for (uint i = 0; i < 4; i++) {
+			if (td.owner_type[i] == STR_NULL) continue;
+
+			SetDParam(0, STR_01A6_N_A);
+			if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile);
+			GetString(this->landinfo_data[line_nr], td.owner_type[i], lastof(this->landinfo_data[line_nr]));
+			line_nr++;
+		}
+
+		/* Cost to clear */
 		StringID str = STR_01A4_COST_TO_CLEAR_N_A;
 		if (CmdSucceeded(costclear)) {
 			SetDParam(0, costclear.GetCost());
 			str = STR_01A5_COST_TO_CLEAR;
 		}
-		GetString(this->landinfo_data[2], str, lastof(this->landinfo_data[2]));
+		GetString(this->landinfo_data[line_nr], str, lastof(this->landinfo_data[line_nr]));
+		line_nr++;
 
+		/* Location */
 		snprintf(_userstring, lengthof(_userstring), "0x%.4X", tile);
 		SetDParam(0, TileX(tile));
 		SetDParam(1, TileY(tile));
 		SetDParam(2, TileHeight(tile));
 		SetDParam(3, STR_SPEC_USERSTRING);
-		GetString(this->landinfo_data[3], STR_LANDINFO_COORDS, lastof(this->landinfo_data[3]));
+		GetString(this->landinfo_data[line_nr], STR_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr]));
+		line_nr++;
 
+		/* Local authority */
 		SetDParam(0, STR_01A9_NONE);
 		if (t != NULL && t->IsValid()) {
 			SetDParam(0, STR_TOWN);
 			SetDParam(1, t->index);
 		}
-		GetString(this->landinfo_data[4], STR_01A8_LOCAL_AUTHORITY, lastof(this->landinfo_data[4]));
+		GetString(this->landinfo_data[line_nr], STR_01A8_LOCAL_AUTHORITY, lastof(this->landinfo_data[line_nr]));
+		line_nr++;
 
-		char *strp = GetString(this->landinfo_data[5], STR_01CE_CARGO_ACCEPTED, lastof(this->landinfo_data[5]));
+		/* Build date */
+		if (td.build_date != 0) {
+			SetDParam(0, td.build_date);
+			GetString(this->landinfo_data[line_nr], STR_BUILD_DATE, lastof(this->landinfo_data[line_nr]));
+			line_nr++;
+		}
+
+		/* Remaining lines stay empty */
+		for (; line_nr < LAND_INFO_CENTERED_LINES; line_nr++) {
+			this->landinfo_data[line_nr][0] = '\0';
+		}
+
+		/* Cargo acceptance is displayed in a extra multiline */
+		char *strp = GetString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE], STR_01CE_CARGO_ACCEPTED, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
 		bool found = false;
 
 		for (CargoID i = 0; i < NUM_CARGO; ++i) {
@@ -155,20 +204,13 @@
 				if (ac[i] < 8) {
 					SetDParam(0, ac[i]);
 					SetDParam(1, GetCargo(i)->name);
-					strp = GetString(strp, STR_01D1_8, lastof(this->landinfo_data[5]));
+					strp = GetString(strp, STR_01D1_8, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
 				} else {
-					strp = GetString(strp, GetCargo(i)->name, lastof(this->landinfo_data[5]));
+					strp = GetString(strp, GetCargo(i)->name, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
 				}
 			}
 		}
-		if (!found) this->landinfo_data[5][0] = '\0';
-
-		if (td.build_date != 0) {
-			SetDParam(0, td.build_date);
-			GetString(this->landinfo_data[6], STR_BUILD_DATE, lastof(this->landinfo_data[6]));
-		} else {
-			this->landinfo_data[6][0] = '\0';
-		}
+		if (!found) this->landinfo_data[LAND_INFO_MULTICENTER_LINE][0] = '\0';
 
 #if defined(_DEBUG)
 #	define LANDINFOD_LEVEL 0
@@ -219,7 +261,6 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_about_widgets,
-	NULL
 };
 
 struct AboutWindow : public Window {
@@ -352,10 +393,10 @@
 
 public:
 	ErrmsgWindow(Point pt, int width, int height, StringID msg1, StringID msg2, const Widget *widget, bool show_player_face) :
-			Window(pt.x, pt.y, width, height, NULL, WC_ERRMSG, widget),
+			Window(pt.x, pt.y, width, height, WC_ERRMSG, widget),
 			show_player_face(show_player_face)
 	{
-		this->duration = _patches.errmsg_duration;
+		this->duration = _settings.gui.errmsg_duration;
 		CopyOutDParam(this->decode_params, 0, lengthof(this->decode_params));
 		this->message_1 = msg1;
 		this->message_2 = msg2;
@@ -412,11 +453,11 @@
 		_switch_mode_errorstr = INVALID_STRING_ID;
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		if (keycode != WKC_SPACE) return true;
+		if (keycode != WKC_SPACE) return ES_NOT_HANDLED;
 		delete this;
-		return false;
+		return ES_HANDLED;
 	}
 };
 
@@ -424,7 +465,7 @@
 {
 	DeleteWindowById(WC_ERRMSG, 0);
 
-	if (!_patches.errmsg_duration) return;
+	if (!_settings.gui.errmsg_duration) return;
 
 	if (msg_2 == STR_NULL) msg_2 = STR_EMPTY;
 
@@ -532,7 +573,7 @@
 
 	TooltipsWindow(int x, int y, int width, int height, const Widget *widget,
 								 StringID str, uint paramcount, const uint64 params[]) :
-			Window(x, y, width, height, NULL, WC_TOOLTIPS, widget)
+			Window(x, y, width, height, WC_TOOLTIPS, widget)
 	{
 		this->string_id = str;
 		assert(sizeof(this->params[0]) == sizeof(params[0]));
@@ -579,7 +620,7 @@
 	DeleteWindowById(WC_TOOLTIPS, 0);
 
 	/* We only show measurement tooltips with patch setting on */
-	if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return;
+	if (str == STR_NULL || (paramcount != 0 && !_settings.gui.measure_tooltip)) return;
 
 	for (uint i = 0; i != paramcount; i++) SetDParam(i, params[i]);
 	char buffer[512];
@@ -883,9 +924,9 @@
 	return false;
 }
 
-int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont)
+int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, Window::EventState &state)
 {
-	cont = false;
+	state = Window::ES_HANDLED;
 
 	switch (keycode) {
 		case WKC_ESC: return 2;
@@ -913,7 +954,7 @@
 			if (IsValidChar(key, this->afilter)) {
 				if (InsertTextBufferChar(&this->text, key)) w->InvalidateWidget(wid);
 			} else { // key wasn't caught. Continue only if standard entry specified
-				cont = (this->afilter == CS_ALPHANUMERAL);
+				state = (this->afilter == CS_ALPHANUMERAL) ? Window::ES_HANDLED : Window::ES_NOT_HANDLED;
 			}
 	}
 
@@ -963,9 +1004,9 @@
 	_cur_dpi = old_dpi;
 }
 
-int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont)
+int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, EventState &state)
 {
-	return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, cont);
+	return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, state);
 }
 
 void QueryStringBaseWindow::HandleEditBox(int wid)
@@ -1038,15 +1079,15 @@
 		this->HandleEditBox(QUERY_STR_WIDGET_TEXT);
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont;
-		switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, cont)) {
+		EventState state;
+		switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, state)) {
 			case 1: this->OnOk(); // Enter pressed, confirms change
 			/* FALL THROUGH */
 			case 2: delete this; break; // ESC pressed, closes window, abandons changes
 		}
-		return cont;
+		return state;
 	}
 
 	~QueryStringWindow()
@@ -1074,17 +1115,16 @@
 	WC_QUERY_STRING, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_query_string_widgets,
-	NULL
 };
 
 /** Show a query popup window with a textbox in it.
  * @param str StringID for the text shown in the textbox
  * @param caption StringID of text shown in caption of querywindow
  * @param maxlen maximum length in characters allowed. If bit 12 is set we
- * will not check the resulting string against to original string to return success
+ *               will not check the resulting string against to original string to return success
  * @param maxwidth maximum width in pixels allowed
  * @param parent pointer to a Window that will handle the events (ok/cancel) of this
- * window. If NULL, results are handled by global function HandleOnEditText
+ *        window. If NULL, results are handled by global function HandleOnEditText
  * @param afilter filters out unwanted character input */
 void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, Window *parent, CharSetFilter afilter)
 {
@@ -1124,11 +1164,11 @@
  * Window used for asking the user a YES/NO question.
  */
 struct QueryWindow : public Window {
-	void (*proc)(Window*, bool); ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
-	uint64 params[10];           ///< local copy of _decode_parameters
-	StringID message;            ///< message shown for query window
+	QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
+	uint64 params[10];       ///< local copy of _decode_parameters
+	StringID message;        ///< message shown for query window
 
-	QueryWindow(const WindowDesc *desc, StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool)) : Window(desc)
+	QueryWindow(const WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc)
 	{
 		if (parent == NULL) parent = FindWindowById(WC_MAIN_WINDOW, 0);
 		this->parent = parent;
@@ -1162,19 +1202,24 @@
 	virtual void OnClick(Point pt, int widget)
 	{
 		switch (widget) {
-			case QUERY_WIDGET_YES:
-				if (this->proc != NULL) {
-					this->proc(this->parent, true);
-					this->proc = NULL;
+			case QUERY_WIDGET_YES: {
+				/* in the Generate New World window, clicking 'Yes' causes
+				 * DeleteNonVitalWindows() to be called - we shouldn't be in a window then */
+				QueryCallbackProc *proc = this->proc;
+				Window *parent = this->parent;
+				delete this;
+				if (proc != NULL) {
+					proc(parent, true);
+					proc = NULL;
 				}
-				/* Fallthrough */
+			} break;
 			case QUERY_WIDGET_NO:
 				delete this;
 				break;
 		}
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		/* ESC closes the window, Enter confirms the action */
 		switch (keycode) {
@@ -1187,9 +1232,9 @@
 				/* Fallthrough */
 			case WKC_ESC:
 				delete this;
-				return false;
+				return ES_HANDLED;
 		}
-		return true;
+		return ES_NOT_HANDLED;
 	}
 };
 
@@ -1208,7 +1253,6 @@
 	WC_CONFIRM_POPUP_QUERY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_DEF_WIDGET | WDF_MODAL,
 	_query_widgets,
-	NULL
 };
 
 /** Show a modal confirmation window with standard 'yes' and 'no' buttons
@@ -1219,7 +1263,7 @@
  * @param parent pointer to parent window, if this pointer is NULL the parent becomes
  * the main window WC_MAIN_WINDOW
  * @param callback callback function pointer to set in the window descriptor*/
-void ShowQuery(StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool))
+void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback)
 {
 	new QueryWindow(&_query_desc, caption, message, parent, callback);
 }
@@ -1523,20 +1567,20 @@
 		}
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		if (keycode == WKC_ESC) {
 			delete this;
-			return false;
+			return ES_HANDLED;
 		}
 
-		bool cont = true;
+		EventState state = ES_NOT_HANDLED;
 		if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) &&
-				this->HandleEditBoxKey(10, key, keycode, cont) == 1) { // Press Enter
+				this->HandleEditBoxKey(10, key, keycode, state) == 1) { // Press Enter
 			this->HandleButtonClick(12);
 		}
 
-		return cont;
+		return state;
 	}
 
 	virtual void OnTimeout()
@@ -1589,7 +1633,6 @@
 	WC_SAVELOAD, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_load_dialog_widgets,
-	NULL,
 };
 
 static const WindowDesc _save_dialog_desc = {
@@ -1597,7 +1640,6 @@
 	WC_SAVELOAD, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_save_dialog_widgets,
-	NULL,
 };
 
 /** These values are used to convert the file/operations mode into a corresponding file type.
--- a/src/music_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/music_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -193,18 +193,40 @@
 	}
 }
 
-static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_PAINT: {
+struct MusicTrackSelectionWindow : public Window {
+private:
+	enum MusicTrackSelectionWidgets {
+		MTSW_CLOSE,
+		MTSW_CAPTION,
+		MTSW_BACKGROUND,
+		MTSW_LIST_LEFT,
+		MTSW_LIST_RIGHT,
+		MTSW_ALL,
+		MTSW_OLD,
+		MTSW_NEW,
+		MTSW_EZY,
+		MTSW_CUSTOM1,
+		MTSW_CUSTOM2,
+		MTSW_CLEAR,
+		MTSW_SAVE,
+	};
+
+public:
+	MusicTrackSelectionWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	virtual void OnPaint()
+	{
 		const byte* p;
 		uint i;
 		int y;
 
-		w->SetWidgetDisabledState(11, msf.playlist <= 3);
-		w->LowerWidget(3);
-		w->LowerWidget(4);
-		w->DrawWidgets();
+		this->SetWidgetDisabledState(MTSW_CLEAR, msf.playlist <= 3);
+		this->LowerWidget(MTSW_LIST_LEFT);
+		this->LowerWidget(MTSW_LIST_RIGHT);
+		this->DrawWidgets();
 
 		GfxFillRect(3, 23, 3 + 177, 23 + 191, 0);
 		GfxFillRect(251, 23, 251 + 177, 23 + 191, 0);
@@ -238,88 +260,88 @@
 			DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, TC_FROMSTRING);
 			y += 6;
 		}
-		break;
 	}
 
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-		case 3: { // add to playlist
-			int y = (e->we.click.pt.y - 23) / 6;
-			uint i;
-			byte *p;
-
-			if (msf.playlist < 4) return;
-			if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case MTSW_LIST_LEFT: { // add to playlist
+				int y = (pt.y - 23) / 6;
+				uint i;
+				byte *p;
 
-			p = _playlists[msf.playlist];
-			for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
-				if (p[i] == 0) {
-					p[i] = y + 1;
-					p[i + 1] = 0;
-					w->SetDirty();
-					SelectSongToPlay();
-					break;
+				if (msf.playlist < 4) return;
+				if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
+
+				p = _playlists[msf.playlist];
+				for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) {
+					if (p[i] == 0) {
+						p[i] = y + 1;
+						p[i + 1] = 0;
+						this->SetDirty();
+						SelectSongToPlay();
+						break;
+					}
 				}
-			}
-		} break;
+			} break;
 
-		case 4: { // remove from playlist
-			int y = (e->we.click.pt.y - 23) / 6;
-			uint i;
-			byte *p;
+			case MTSW_LIST_RIGHT: { // remove from playlist
+				int y = (pt.y - 23) / 6;
+				uint i;
+				byte *p;
 
-			if (msf.playlist < 4) return;
-			if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
+				if (msf.playlist < 4) return;
+				if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return;
 
-			p = _playlists[msf.playlist];
-			for (i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
-				p[i] = p[i + 1];
+				p = _playlists[msf.playlist];
+				for (i = y; i != NUM_SONGS_PLAYLIST - 1; i++) {
+					p[i] = p[i + 1];
 				}
 
-			w->SetDirty();
-			SelectSongToPlay();
-		} break;
+				this->SetDirty();
+				SelectSongToPlay();
+			} break;
 
-		case 11: // clear
-			_playlists[msf.playlist][0] = 0;
-			w->SetDirty();
-			StopMusic();
-			SelectSongToPlay();
-			break;
+			case MTSW_CLEAR: // clear
+				_playlists[msf.playlist][0] = 0;
+				this->SetDirty();
+				StopMusic();
+				SelectSongToPlay();
+				break;
 
 #if 0
-		case 12: // save
-			ShowInfo("MusicTrackSelectionWndProc:save not implemented");
-			break;
+			case MTSW_SAVE: // save
+				ShowInfo("MusicTrackSelectionWndProc:save not implemented");
+				break;
 #endif
 
-		case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */
-			msf.playlist = e->we.click.widget - 5;
-			w->SetDirty();
-			InvalidateWindow(WC_MUSIC_WINDOW, 0);
-			StopMusic();
-			SelectSongToPlay();
-			break;
+			case MTSW_ALL: case MTSW_OLD: case MTSW_NEW:
+			case MTSW_EZY: case MTSW_CUSTOM1: case MTSW_CUSTOM2: // set playlist
+				msf.playlist = widget - MTSW_ALL;
+				this->SetDirty();
+				InvalidateWindow(WC_MUSIC_WINDOW, 0);
+				StopMusic();
+				SelectSongToPlay();
+				break;
 		}
-		break;
 	}
-}
+};
 
 static const Widget _music_track_selection_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   431,     0,    13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{      WWT_PANEL,   RESIZE_NONE,    14,     0,   431,    14,   217, 0x0,                              STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,     2,   181,    22,   215, 0x0,                              STR_01FA_CLICK_ON_MUSIC_TRACK_TO},
-{      WWT_PANEL,   RESIZE_NONE,    14,   250,   429,    22,   215, 0x0,                              STR_CLICK_ON_TRACK_TO_REMOVE},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    44,    51, 0x0,                              STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    52,    59, 0x0,                              STR_01F4_SELECT_OLD_STYLE_MUSIC},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    60,    67, 0x0,                              STR_01F5_SELECT_NEW_STYLE_MUSIC},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    68,    75, 0x0,                              STR_0330_SELECT_EZY_STREET_STYLE},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    76,    83, 0x0,                              STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    84,    91, 0x0,                              STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,   108,   115, 0x0,                              STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1},
+{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},                  // MTSW_CLOSE
+{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   431,     0,    13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},        // MTSW_CAPTION
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   431,    14,   217, 0x0,                              STR_NULL},                               // MTSW_BACKGROUND
+{      WWT_PANEL,   RESIZE_NONE,    14,     2,   181,    22,   215, 0x0,                              STR_01FA_CLICK_ON_MUSIC_TRACK_TO},       // MTSW_LIST_LEFT
+{      WWT_PANEL,   RESIZE_NONE,    14,   250,   429,    22,   215, 0x0,                              STR_CLICK_ON_TRACK_TO_REMOVE},           // MTSW_LIST_RIGHT
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    44,    51, 0x0,                              STR_01F3_SELECT_ALL_TRACKS_PROGRAM},     // MTSW_ALL
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    52,    59, 0x0,                              STR_01F4_SELECT_OLD_STYLE_MUSIC},        // MTSW_OLD
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    60,    67, 0x0,                              STR_01F5_SELECT_NEW_STYLE_MUSIC},        // MTSW_NEW
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    68,    75, 0x0,                              STR_0330_SELECT_EZY_STREET_STYLE},       // MTSW_EZY
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    76,    83, 0x0,                              STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},  // MTSW_CUSTOM1
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,    84,    91, 0x0,                              STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},  // MTSW_CUSTOM2
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,   108,   115, 0x0,                              STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1}, // MTSW_CLEAR
 #if 0
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,   124,   131, 0x0,                              STR_01F9_SAVE_MUSIC_SETTINGS},
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   186,   245,   124,   131, 0x0,                              STR_01F9_SAVE_MUSIC_SETTINGS},           // MTSW_SAVE
 #endif
 {   WIDGETS_END},
 };
@@ -329,24 +351,50 @@
 	WC_MUSIC_TRACK_SELECTION, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_music_track_selection_widgets,
-	MusicTrackSelectionWndProc
 };
 
 static void ShowMusicTrackSelection()
 {
-	AllocateWindowDescFront<Window>(&_music_track_selection_desc, 0);
+	AllocateWindowDescFront<MusicTrackSelectionWindow>(&_music_track_selection_desc, 0);
 }
 
-static void MusicWindowWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_PAINT: {
+struct MusicWindow : public Window {
+private:
+	enum MusicWidgets {
+		MW_CLOSE,
+		MW_CAPTION,
+		MW_PREV,
+		MW_NEXT,
+		MW_STOP,
+		MW_PLAY,
+		MW_SLIDERS,
+		MW_GAUGE,
+		MW_BACKGROUND,
+		MW_INFO,
+		MW_SHUFFLE,
+		MW_PROGRAMME,
+		MW_ALL,
+		MW_OLD,
+		MW_NEW,
+		MW_EZY,
+		MW_CUSTOM1,
+		MW_CUSTOM2,
+	};
+
+public:
+	MusicWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	virtual void OnPaint()
+	{
 		uint i;
 		StringID str;
 
-		w->RaiseWidget(7);
-		w->RaiseWidget(9);
-		w->DrawWidgets();
+		this->RaiseWidget(MW_GAUGE);
+		this->RaiseWidget(MW_INFO);
+		this->DrawWidgets();
 
 		GfxFillRect(187, 16, 200, 33, 0);
 
@@ -403,92 +451,99 @@
 		DrawFrameRect(
 			214 + msf.effect_vol / 2, 22, 217 + msf.effect_vol / 2, 28, 14, FR_NONE
 		);
-	} break;
-
-	case WE_CLICK:
-		switch (e->we.click.widget) {
-		case 2: // skip to prev
-			if (!_song_is_active)
-				return;
-			SkipToPrevSong();
-			break;
-		case 3: // skip to next
-			if (!_song_is_active)
-				return;
-			SkipToNextSong();
-			break;
-		case 4: // stop playing
-			msf.playing = false;
-			break;
-		case 5: // start playing
-			msf.playing = true;
-			break;
-		case 6: { // volume sliders
-			byte *vol, new_vol;
-			int x = e->we.click.pt.x - 88;
-
-			if (x < 0) return;
-
-			vol = &msf.music_vol;
-			if (x >= 106) {
-				vol = &msf.effect_vol;
-				x -= 106;
-			}
-
-			new_vol = min(max(x - 21, 0) * 2, 127);
-			if (new_vol != *vol) {
-				*vol = new_vol;
-				if (vol == &msf.music_vol)
-					MusicVolumeChanged(new_vol);
-				w->SetDirty();
-			}
-
-			_left_button_clicked = false;
-		} break;
-		case 10: //toggle shuffle
-			msf.shuffle ^= 1;
-			StopMusic();
-			SelectSongToPlay();
-			break;
-		case 11: //show track selection
-			ShowMusicTrackSelection();
-			break;
-		case 12: case 13: case 14: case 15: case 16: case 17: // playlist
-			msf.playlist = e->we.click.widget - 12;
-			w->SetDirty();
-			InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0);
-			StopMusic();
-			SelectSongToPlay();
-			break;
-		}
-		break;
-
-	case WE_TICK:
-		InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7);
-		break;
 	}
 
-}
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case MW_PREV: // skip to prev
+				if (!_song_is_active) return;
+				SkipToPrevSong();
+				break;
+
+			case MW_NEXT: // skip to next
+				if (!_song_is_active) return;
+				SkipToNextSong();
+				break;
+
+			case MW_STOP: // stop playing
+				msf.playing = false;
+				break;
+
+			case MW_PLAY: // start playing
+				msf.playing = true;
+				break;
+
+			case MW_SLIDERS: { // volume sliders
+				byte *vol, new_vol;
+				int x = pt.x - 88;
+
+				if (x < 0) return;
+
+				vol = &msf.music_vol;
+				if (x >= 106) {
+					vol = &msf.effect_vol;
+					x -= 106;
+				}
+
+				new_vol = min(max(x - 21, 0) * 2, 127);
+				if (new_vol != *vol) {
+					*vol = new_vol;
+					if (vol == &msf.music_vol) MusicVolumeChanged(new_vol);
+					this->SetDirty();
+				}
+
+				_left_button_clicked = false;
+			} break;
+
+			case MW_SHUFFLE: //toggle shuffle
+				msf.shuffle ^= 1;
+				StopMusic();
+				SelectSongToPlay();
+				break;
+
+			case MW_PROGRAMME: //show track selection
+				ShowMusicTrackSelection();
+				break;
+
+			case MW_ALL: case MW_OLD: case MW_NEW:
+			case MW_EZY: case MW_CUSTOM1: case MW_CUSTOM2: // playlist
+				msf.playlist = widget - MW_ALL;
+				this->SetDirty();
+				InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0);
+				StopMusic();
+				SelectSongToPlay();
+				break;
+		}
+	}
+
+#if 0
+	virtual void OnTick()
+	{
+		this->InvalidateWidget(MW_GAUGE);
+	}
+#endif
+};
 
 static const Widget _music_window_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   299,     0,    13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,     0,    21,    14,    35, SPR_IMG_SKIP_TO_PREV,  STR_01DE_SKIP_TO_PREVIOUS_TRACK},
-{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    22,    43,    14,    35, SPR_IMG_SKIP_TO_NEXT,  STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION},
-{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    44,    65,    14,    35, SPR_IMG_STOP_MUSIC,    STR_01E0_STOP_PLAYING_MUSIC},
-{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    66,    87,    14,    35, SPR_IMG_PLAY_MUSIC,    STR_01E1_START_PLAYING_MUSIC},
-{      WWT_PANEL,   RESIZE_NONE,    14,    88,   299,    14,    35, 0x0,                   STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC},
-{      WWT_PANEL,   RESIZE_NONE,    14,   186,   201,    15,    34, 0x0,                   STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,     0,   299,    36,    57, 0x0,                   STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,    59,   240,    45,    53, 0x0,                   STR_NULL},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,     6,    55,    42,    49, 0x0,                   STR_01FB_TOGGLE_PROGRAM_SHUFFLE},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   244,   293,    42,    49, 0x0,                   STR_01FC_SHOW_MUSIC_TRACK_SELECTION},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,     0,    49,    58,    65, 0x0,                   STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,    50,    99,    58,    65, 0x0,                   STR_01F4_SELECT_OLD_STYLE_MUSIC},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   100,   149,    58,    65, 0x0,                   STR_01F5_SELECT_NEW_STYLE_MUSIC},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   150,   199,    58,    65, 0x0,                   STR_0330_SELECT_EZY_STREET_STYLE},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   200,   249,    58,    65, 0x0,                   STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
-{    WWT_PUSHBTN,   RESIZE_NONE,    14,   250,   299,    58,    65, 0x0,                   STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
+{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},                    // MW_CLOSE
+{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   299,     0,    13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS},          // MW_CAPTION
+{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,     0,    21,    14,    35, SPR_IMG_SKIP_TO_PREV,  STR_01DE_SKIP_TO_PREVIOUS_TRACK},          // MW_PREV
+{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    22,    43,    14,    35, SPR_IMG_SKIP_TO_NEXT,  STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION}, // MW_NEXT
+{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    44,    65,    14,    35, SPR_IMG_STOP_MUSIC,    STR_01E0_STOP_PLAYING_MUSIC},              // MW_STOP
+{ WWT_PUSHIMGBTN,   RESIZE_NONE,    14,    66,    87,    14,    35, SPR_IMG_PLAY_MUSIC,    STR_01E1_START_PLAYING_MUSIC},             // MW_PLAY
+{      WWT_PANEL,   RESIZE_NONE,    14,    88,   299,    14,    35, 0x0,                   STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC},       // MW_SLIDERS
+{      WWT_PANEL,   RESIZE_NONE,    14,   186,   201,    15,    34, 0x0,                   STR_NULL},                                 // MW_GAUGE
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   299,    36,    57, 0x0,                   STR_NULL},                                 // MW_BACKGROUND
+{      WWT_PANEL,   RESIZE_NONE,    14,    59,   240,    45,    53, 0x0,                   STR_NULL},                                 // MW_INFO
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,     6,    55,    42,    49, 0x0,                   STR_01FB_TOGGLE_PROGRAM_SHUFFLE},          // MW_SHUFFLE
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   244,   293,    42,    49, 0x0,                   STR_01FC_SHOW_MUSIC_TRACK_SELECTION},      // MW_PROGRAMME
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,     0,    49,    58,    65, 0x0,                   STR_01F3_SELECT_ALL_TRACKS_PROGRAM},       // MW_ALL
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,    50,    99,    58,    65, 0x0,                   STR_01F4_SELECT_OLD_STYLE_MUSIC},          // MW_OLD
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   100,   149,    58,    65, 0x0,                   STR_01F5_SELECT_NEW_STYLE_MUSIC},          // MW_NEW
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   150,   199,    58,    65, 0x0,                   STR_0330_SELECT_EZY_STREET_STYLE},         // MW_EZY
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   200,   249,    58,    65, 0x0,                   STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},    // MW_CUSTOM1
+{    WWT_PUSHBTN,   RESIZE_NONE,    14,   250,   299,    58,    65, 0x0,                   STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},    // MW_CUSTOM2
 {   WIDGETS_END},
 };
 
@@ -497,10 +552,9 @@
 	WC_MUSIC_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_music_window_widgets,
-	MusicWindowWndProc
 };
 
 void ShowMusicWindow()
 {
-	AllocateWindowDescFront<Window>(&_music_window_desc, 0);
+	AllocateWindowDescFront<MusicWindow>(&_music_window_desc, 0);
 }
--- a/src/network/network.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network.cpp	Tue May 27 00:50:55 2008 +0000
@@ -23,7 +23,7 @@
 #include "core/tcp.h"
 #include "core/core.h"
 #include "network_gui.h"
-#include "../console.h" /* IConsoleCmdExec */
+#include "../console_func.h"
 #include <stdarg.h> /* va_list */
 #include "../md5.h"
 #include "../fileio.h"
@@ -141,7 +141,7 @@
 // This puts a text-message to the console, or in the future, the chat-box,
 //  (to keep it all a bit more general)
 // If 'self_send' is true, this is the client who is sending the message
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...)
+void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...)
 {
 	char buf[1024];
 	va_list va;
@@ -155,16 +155,16 @@
 
 	switch (action) {
 		case NETWORK_ACTION_SERVER_MESSAGE:
-			color = 1;
+			color = CC_DEFAULT;
 			snprintf(message, sizeof(message), "*** %s", buf);
 			break;
 		case NETWORK_ACTION_JOIN:
-			color = 1;
+			color = CC_DEFAULT;
 			GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp));
 			snprintf(message, sizeof(message), "*** %s %s", name, temp);
 			break;
 		case NETWORK_ACTION_LEAVE:
-			color = 1;
+			color = CC_DEFAULT;
 			GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp));
 			snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf);
 			break;
@@ -651,7 +651,7 @@
 
 		GetNetworkErrorMsg(str, errorno, lastof(str));
 
-		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str);
 
 		// Inform other clients of this... strange leaving ;)
 		FOR_ALL_CLIENTS(new_cs) {
@@ -1009,10 +1009,10 @@
 	_network_game_info.spectators_on = 0;
 
 	_network_game_info.game_date = _date;
-	_network_game_info.start_date = ConvertYMDToDate(_patches.starting_year, 0, 1);
+	_network_game_info.start_date = ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1);
 	_network_game_info.map_width = MapSizeX();
 	_network_game_info.map_height = MapSizeY();
-	_network_game_info.map_set = _opt.landscape;
+	_network_game_info.map_set = _settings.game_creation.landscape;
 
 	_network_game_info.use_password = (_network_server_password[0] != '\0');
 
--- a/src/network/network_client.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network_client.cpp	Tue May 27 00:50:55 2008 +0000
@@ -14,7 +14,7 @@
 #include "network_gui.h"
 #include "../saveload.h"
 #include "../command_func.h"
-#include "../console.h"
+#include "../console_func.h"
 #include "../variables.h"
 #include "../ai/ai.h"
 #include "../core/alloc_func.hpp"
@@ -83,7 +83,7 @@
 {
 	if (StrEmpty(_network_player_info[_local_player].password)) return;
 
-	_password_game_seed = _patches.generation_seed;
+	_password_game_seed = _settings.game_creation.generation_seed;
 	ttd_strlcpy(_password_server_unique_id, _network_unique_id, sizeof(_password_server_unique_id));
 
 	const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password);
@@ -414,7 +414,7 @@
 	if (ci != NULL) {
 		if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
 			// Client name changed, display the change
-			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
+			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name);
 		} else if (playas != ci->client_playas) {
 			// The player changed from client-player..
 			// Do not display that for now
@@ -622,8 +622,6 @@
 		/* If the savegame has successfully loaded, ALL windows have been removed,
 		 * only toolbar/statusbar and gamefield are visible */
 
-		_opt_ptr = &_opt; // during a network game you are always in-game
-
 		// Say we received the map and loaded it correctly!
 		SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
 
@@ -761,7 +759,7 @@
 	}
 
 	if (ci != NULL)
-		NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
+		NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
@@ -776,7 +774,7 @@
 
 	ci = NetworkFindClientInfoFromIndex(index);
 	if (ci != NULL) {
-		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
+		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
 
 		// The client is gone, give the NetworkClientInfo free
 		ci->client_index = NETWORK_EMPTY_INDEX;
@@ -798,7 +796,7 @@
 
 	ci = NetworkFindClientInfoFromIndex(index);
 	if (ci != NULL) {
-		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
+		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str);
 
 		// The client is gone, give the NetworkClientInfo free
 		ci->client_index = NETWORK_EMPTY_INDEX;
@@ -821,7 +819,7 @@
 
 	ci = NetworkFindClientInfoFromIndex(index);
 	if (ci != NULL)
-		NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, "");
+		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name, "");
 
 	InvalidateWindow(WC_CLIENT_LIST, 0);
 
@@ -850,9 +848,8 @@
 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
 {
 	char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
-	uint16 color_code;
 
-	color_code = p->Recv_uint16();
+	ConsoleColour color_code = (ConsoleColour)p->Recv_uint16();
 	p->Recv_string(rcon_out, sizeof(rcon_out));
 
 	IConsolePrint(color_code, rcon_out);
--- a/src/network/network_data.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network_data.h	Tue May 27 00:50:55 2008 +0000
@@ -6,6 +6,7 @@
 #define NETWORK_DATA_H
 
 #include "../openttd.h"
+#include "../console_type.h"
 #include "network.h"
 #include "network_internal.h"
 
@@ -105,7 +106,7 @@
 
 // from network.c
 void NetworkCloseClient(NetworkTCPSocketHandler *cs);
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...);
+void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
 void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
 uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
 byte NetworkGetCurrentLanguageIndex();
--- a/src/network/network_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -190,7 +190,6 @@
 		this->field = NGWW_PLAYER;
 		this->server = NULL;
 
-		this->servers.sort_list = NULL;
 		this->servers.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
 		this->servers.sort_type = _ng_sorting.criteria;
 
@@ -199,7 +198,6 @@
 
 	~NetworkGameWindow()
 	{
-		free(this->servers.sort_list);
 	}
 
 	/**
@@ -208,23 +206,17 @@
 	 */
 	void BuildNetworkGameList()
 	{
-		NetworkGameList *ngl_temp;
-		uint n = 0;
-
 		if (!(this->servers.flags & VL_REBUILD)) return;
 
-		/* Count the number of games in the list */
-		for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
-		if (n == 0) return;
-
 		/* Create temporary array of games to use for listing */
-		this->servers.sort_list = ReallocT(this->servers.sort_list, n);
-		this->servers.list_length = n;
+		this->servers.Clear();
 
-		for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
-			this->servers.sort_list[n++] = ngl_temp;
+		for (NetworkGameList *ngl = _network_game_list; ngl != NULL; ngl = ngl->next) {
+			*this->servers.Append() = ngl;
 		}
 
+		this->servers.Compact();
+
 		/* Force resort */
 		this->servers.flags &= ~VL_REBUILD;
 		this->servers.flags |= VL_RESORT;
@@ -242,17 +234,17 @@
 		uint i;
 
 		if (!(this->servers.flags & VL_RESORT)) return;
-		if (this->servers.list_length == 0) return;
+		if (this->servers.Length() == 0) return;
 
 		_internal_sort_order = !!(this->servers.flags & VL_DESC);
-		qsort(this->servers.sort_list, this->servers.list_length, sizeof(this->servers.sort_list[0]), ngame_sorter[this->servers.sort_type]);
+		qsort(this->servers.Begin(), this->servers.Length(), sizeof(this->servers.Begin()), ngame_sorter[this->servers.sort_type]);
 
 		/* After sorting ngl->sort_list contains the sorted items. Put these back
 		 * into the original list. Basically nothing has changed, we are only
 		 * shuffling the ->next pointers */
-		_network_game_list = this->servers.sort_list[0];
-		for (item = _network_game_list, i = 1; i != this->servers.list_length; i++) {
-			item->next = this->servers.sort_list[i];
+		_network_game_list = this->servers[0];
+		for (item = _network_game_list, i = 1; i != this->servers.Length(); i++) {
+			item->next = this->servers[i];
 			item = item->next;
 		}
 		item->next = NULL;
@@ -300,7 +292,7 @@
 
 		if (this->servers.flags & VL_REBUILD) {
 			this->BuildNetworkGameList();
-			SetVScrollCount(this, this->servers.list_length);
+			SetVScrollCount(this, this->servers.Length());
 		}
 		if (this->servers.flags & VL_RESORT) this->SortNetworkGameList();
 
@@ -543,9 +535,9 @@
 		this->SetDirty();
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont = true;
+		EventState state = ES_NOT_HANDLED;
 		if (this->field != NGWW_PLAYER) {
 			if (this->server != NULL) {
 				if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
@@ -554,10 +546,10 @@
 					this->server = NULL;
 				}
 			}
-			return cont;
+			return state;
 		}
 
-		if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, cont) == 1) return cont; // enter pressed
+		if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, state) == 1) return state; // enter pressed
 
 		/* The name is only allowed when it starts with a letter! */
 		if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
@@ -565,7 +557,7 @@
 		} else {
 			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
 		}
-		return cont;
+		return state;
 	}
 
 	virtual void OnQueryTextFinished(char *str)
@@ -582,7 +574,7 @@
 
 		this->widget[NGWW_MATRIX].data = (this->vscroll.cap << 8) + 1;
 
-		SetVScrollCount(this, this->servers.list_length);
+		SetVScrollCount(this, this->servers.Length());
 
 		int widget_width = this->widget[NGWW_FIND].right - this->widget[NGWW_FIND].left;
 		int space = (this->width - 4 * widget_width - 25) / 3;
@@ -642,7 +634,6 @@
 	WC_NETWORK_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_network_game_window_widgets,
-	NULL,
 };
 
 void ShowNetworkGameWindow()
@@ -892,16 +883,16 @@
 		if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont = true;
+		EventState state = ES_NOT_HANDLED;
 		if (this->field == NSSW_GAMENAME) {
-			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, cont) == 1) return cont; // enter pressed
+			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == 1) return state; // enter pressed
 
 			ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
 		}
 
-		return cont;
+		return state;
 	}
 
 	virtual void OnQueryTextFinished(char *str)
@@ -977,7 +968,6 @@
 	WC_NETWORK_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_network_start_server_window_widgets,
-	NULL,
 };
 
 static void ShowNetworkStartServerWindow()
@@ -1191,7 +1181,6 @@
 	WC_NETWORK_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_network_lobby_window_widgets,
-	NULL,
 };
 
 /* Show the networklobbywindow with the selected server
@@ -1237,12 +1226,11 @@
 {   WIDGETS_END},
 };
 
-static WindowDesc _client_list_desc = {
+static const WindowDesc _client_list_desc = {
 	WDP_AUTO, WDP_AUTO, 250, 1, 250, 1,
 	WC_CLIENT_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_client_list_widgets,
-	NULL
 };
 
 // Finds the Xth client-info that is active
@@ -1321,7 +1309,7 @@
 	ClientList_Action_Proc *proc[MAX_CLIENTLIST_ACTION];
 
 	NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) :
-			Window(x, y, 150, 100, NULL, WC_TOOLBAR_MENU, widgets),
+			Window(x, y, 150, 100, WC_TOOLBAR_MENU, widgets),
 			sel_index(0), client_no(client_no)
 	{
 		/*
@@ -1346,7 +1334,7 @@
 
 		if (_network_own_client_index != ci->client_index) {
 			/* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */
-			if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) {
+			if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _settings.economy.give_money) {
 				GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i]));
 				this->proc[i++] = &ClientList_GiveMoney;
 			}
@@ -1665,7 +1653,6 @@
 	WC_NETWORK_STATUS_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
 	_network_join_status_window_widget,
-	NULL,
 };
 
 void ShowJoinStatusWindow()
@@ -1878,21 +1865,21 @@
 		this->HandleEditBox(2);
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont = true;
+		EventState state = ES_NOT_HANDLED;
 		if (keycode == WKC_TAB) {
 			ChatTabCompletion();
 		} else {
 			_chat_tab_completion_active = false;
-			switch (this->HandleEditBoxKey(2, key, keycode, cont)) {
+			switch (this->HandleEditBoxKey(2, key, keycode, state)) {
 				case 1: /* Return */
 					SendChat(this->text.buf, this->dtype, this->dest);
 				/* FALLTHROUGH */
 				case 2: /* Escape */ delete this; break;
 			}
 		}
-		return cont;
+		return state;
 	}
 };
 
@@ -1909,7 +1896,6 @@
 	WC_SEND_NETWORK_MSG, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
 	_chat_window_widgets,
-	NULL
 };
 
 void ShowNetworkChatQueryWindow(DestType type, int dest)
@@ -1985,10 +1971,10 @@
 		this->HandleEditBox(4);
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont;
-		switch (this->HandleEditBoxKey(4, key, keycode, cont)) {
+		EventState state;
+		switch (this->HandleEditBoxKey(4, key, keycode, state)) {
 			case 1: // Return
 				this->OnOk();
 				/* FALL THROUGH */
@@ -1997,7 +1983,7 @@
 				delete this;
 				break;
 		}
-		return cont;
+		return state;
 	}
 };
 
@@ -2018,7 +2004,6 @@
 	WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
 	_ncp_window_widgets,
-	NULL
 };
 
 void ShowNetworkCompanyPasswordWindow(Window *parent)
--- a/src/network/network_server.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network_server.cpp	Tue May 27 00:50:55 2008 +0000
@@ -15,7 +15,7 @@
 #include "../date_func.h"
 #include "network_server.h"
 #include "network_udp.h"
-#include "../console.h"
+#include "../console_func.h"
 #include "../command_func.h"
 #include "../saveload.h"
 #include "../station_base.h"
@@ -160,7 +160,7 @@
 
 		DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
 
-		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str);
 
 		FOR_ALL_CLIENTS(new_cs) {
 			if (new_cs->status > STATUS_AUTH && new_cs != cs) {
@@ -229,7 +229,7 @@
 
 	Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
 	p->Send_uint8(type);
-	p->Send_uint32(_patches.generation_seed);
+	p->Send_uint32(_settings.game_creation.generation_seed);
 	p->Send_string(_network_unique_id);
 	cs->Send_Packet(p);
 }
@@ -254,7 +254,7 @@
 
 	p = NetworkSend_Init(PACKET_SERVER_WELCOME);
 	p->Send_uint16(cs->index);
-	p->Send_uint32(_patches.generation_seed);
+	p->Send_uint32(_settings.game_creation.generation_seed);
 	p->Send_string(_network_unique_id);
 	cs->Send_Packet(p);
 
@@ -779,7 +779,7 @@
 
 		NetworkGetClientName(client_name, sizeof(client_name), cs);
 
-		NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
+		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, "");
 
 		// Mark the client as pre-active, and wait for an ACK
 		//  so we know he is done loading and in sync with us
@@ -822,17 +822,17 @@
 	byte flags = GetCommandFlags(cp->cmd);
 
 	if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
-		IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
+		IConsolePrintF(CC_ERROR, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
 		return false;
 	}
 
 	if (flags & CMD_OFFLINE) {
-		IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
+		IConsolePrintF(CC_ERROR, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
 		return false;
 	}
 
 	if (cp->cmd != CMD_PLAYER_CTRL && !IsValidPlayer(cp->player) && ci->client_index != NETWORK_SERVER_INDEX) {
-		IConsolePrintF(_icolour_err, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
+		IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
 		return false;
 	}
 
@@ -875,7 +875,7 @@
 
 	/* Check if cp->cmd is valid */
 	if (!IsValidCommand(cp->cmd)) {
-		IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
+		IConsolePrintF(CC_ERROR, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
 		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 		free(cp);
 		return;
@@ -892,7 +892,7 @@
 	 * something pretty naughty (or a bug), and will be kicked
 	 */
 	if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) {
-		IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
+		IConsolePrintF(CC_ERROR, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
 		               ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
 		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
 		free(cp);
@@ -969,7 +969,7 @@
 
 	DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
 
-	NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+	NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str);
 
 	FOR_ALL_CLIENTS(new_cs) {
 		if (new_cs->status > STATUS_AUTH) {
@@ -998,7 +998,7 @@
 
 	NetworkGetClientName(client_name, sizeof(client_name), cs);
 
-	NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
+	NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str);
 
 	FOR_ALL_CLIENTS(new_cs) {
 		if (new_cs->status > STATUS_AUTH) {
@@ -1052,7 +1052,7 @@
 			ci = NetworkFindClientInfoFromIndex(from_index);
 			/* Display the text locally, and that is it */
 			if (ci != NULL)
-				NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+				NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
 		} else {
 			/* Else find the client to send the message to */
 			FOR_ALL_CLIENTS(cs) {
@@ -1069,7 +1069,7 @@
 				ci = NetworkFindClientInfoFromIndex(from_index);
 				ci_to = NetworkFindClientInfoFromIndex(dest);
 				if (ci != NULL && ci_to != NULL)
-					NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
+					NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
 			} else {
 				FOR_ALL_CLIENTS(cs) {
 					if (cs->index == from_index) {
@@ -1097,7 +1097,7 @@
 		ci = NetworkFindClientInfoFromIndex(from_index);
 		ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 		if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
-			NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+			NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
 			if (from_index == NETWORK_SERVER_INDEX) show_local = false;
 			ci_to = ci_own;
 		}
@@ -1112,7 +1112,7 @@
 				StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
 				SetDParam(0, ci_to->client_playas);
 				GetString(name, str, lastof(name));
-				NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
+				NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
 			} else {
 				FOR_ALL_CLIENTS(cs) {
 					if (cs->index == from_index) {
@@ -1132,7 +1132,7 @@
 		}
 		ci = NetworkFindClientInfoFromIndex(from_index);
 		if (ci != NULL)
-			NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
+			NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
 		break;
 	}
 }
@@ -1175,7 +1175,7 @@
 	if (ci != NULL) {
 		// Display change
 		if (NetworkFindName(client_name)) {
-			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
+			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", client_name);
 			ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
 			NetworkUpdateClientInfo(ci->client_index);
 		}
@@ -1412,13 +1412,13 @@
 			if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
 				/* Shut the company down */
 				DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
-				IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
+				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d", p->index + 1);
 			}
 			/* Is the compnay empty for autoclean_protected-months, and there is a protection? */
 			if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
 				/* Unprotect the company */
 				_network_player_info[p->index].password[0] = '\0';
-				IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
+				IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", p->index+1);
 				_network_player_info[p->index].months_empty = 0;
 			}
 		} else {
@@ -1527,14 +1527,14 @@
 				if (lag > 3) {
 					// Client did still not report in after 4 game-day, drop him
 					//  (that is, the 3 of above, + 1 before any lag is counted)
-					IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
+					IConsolePrintF(CC_ERROR,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
 					NetworkCloseClient(cs);
 					continue;
 				}
 
 				// Report once per time we detect the lag
 				if (cs->lag_test == 0) {
-					IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
+					IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
 					cs->lag_test = 1;
 				}
 			} else {
@@ -1543,13 +1543,13 @@
 		} else if (cs->status == STATUS_PRE_ACTIVE) {
 			int lag = NetworkCalculateLag(cs);
 			if (lag > _network_max_join_time) {
-				IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
+				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
 				NetworkCloseClient(cs);
 			}
 		} else if (cs->status == STATUS_INACTIVE) {
 			int lag = NetworkCalculateLag(cs);
 			if (lag > 4 * DAY_TICKS) {
-				IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
+				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
 				NetworkCloseClient(cs);
 			}
 		}
--- a/src/network/network_udp.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/network/network_udp.cpp	Tue May 27 00:50:55 2008 +0000
@@ -77,7 +77,7 @@
 	_network_game_info.game_date     = _date;
 	_network_game_info.map_width     = MapSizeX();
 	_network_game_info.map_height    = MapSizeY();
-	_network_game_info.map_set       = _opt.landscape;
+	_network_game_info.map_set       = _settings.game_creation.landscape;
 	_network_game_info.companies_on  = ActivePlayerCount();
 	_network_game_info.spectators_on = NetworkSpectatorCount();
 	_network_game_info.grfconfig     = _grfconfig;
--- a/src/newgrf.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/newgrf.cpp	Tue May 27 00:50:55 2008 +0000
@@ -328,7 +328,7 @@
 	/* Hack for add-on GRFs that need to modify another GRF's engines. This lets
 	 * them use the same engine slots. */
 	const GRFFile *grf_match = NULL;
-	if (_patches.dynamic_engines) {
+	if (_settings.vehicle.dynamic_engines) {
 		uint32 override = _grf_id_overrides[file->grfid];
 		if (override != 0) {
 			grf_match = GetFileByGRFID(override);
@@ -343,7 +343,7 @@
 	/* Check if this vehicle is already defined... */
 	Engine *e = NULL;
 	FOR_ALL_ENGINES(e) {
-		if (_patches.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue;
+		if (_settings.vehicle.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue;
 		if (e->type != type) continue;
 		if (e->internal_id != internal_id) continue;
 
@@ -379,14 +379,14 @@
 	extern uint32 GetNewGRFOverride(uint32 grfid);
 
 	const GRFFile *grf_match = NULL;
-	if (_patches.dynamic_engines) {
+	if (_settings.vehicle.dynamic_engines) {
 		uint32 override = _grf_id_overrides[file->grfid];
 		if (override != 0) grf_match = GetFileByGRFID(override);
 	}
 
 	const Engine *e = NULL;
 	FOR_ALL_ENGINES(e) {
-		if (_patches.dynamic_engines && e->grffile != file && (grf_match == NULL || e->grffile != grf_match)) continue;
+		if (_settings.vehicle.dynamic_engines && e->grffile != file && (grf_match == NULL || e->grffile != grf_match)) continue;
 		if (e->type != type) continue;
 		if (e->internal_id != internal_id) continue;
 
@@ -1447,8 +1447,8 @@
 
 				/* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
 				 * Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
-				CargoID cid = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
-						((_opt.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
+				CargoID cid = (goods >= 0) ? ((_settings.game_creation.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
+						((_settings.game_creation.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
 
 				/* Make sure the cargo type is valid in this climate. */
 				if (!GetCargo(cid)->IsValid()) goods = 0;
@@ -2177,11 +2177,11 @@
 				break;
 
 			case 0x17: // Probability in random game
-				indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf);
+				indsp->appear_creation[_settings.game_creation.landscape] = grf_load_byte(&buf);
 				break;
 
 			case 0x18: // Probability during gameplay
-				indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf);
+				indsp->appear_ingame[_settings.game_creation.landscape] = grf_load_byte(&buf);
 				break;
 
 			case 0x19: // Map color
@@ -2567,6 +2567,10 @@
 				}
 				break;
 
+			case 0x24: // Noise of airport
+				fsmportspec->portFSM->noise_level = grf_load_byte(&buf);
+				break;
+
 			default:
 				ret = true;
 				break;
@@ -3984,11 +3988,11 @@
 			return true;
 
 		case 0x03: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
-			*value = _opt.landscape;
+			*value = _settings.game_creation.landscape;
 			return true;
 
 		case 0x06: // road traffic side, bit 4 clear=left, set=right
-			*value = _opt.road_side << 4;
+			*value = _settings.vehicle.road_side << 4;
 			return true;
 
 		case 0x09: // date fraction
@@ -4019,7 +4023,7 @@
 		case 0x0F: // Rail track type cost factors
 			*value = 0;
 			SB(*value, 0, 8, _railtype_cost_multiplier[0]); // normal rail
-			if (_patches.disable_elrails) {
+			if (_settings.vehicle.disable_elrails) {
 				/* skip elrail multiplier - disabled */
 				SB(*value, 8, 8, _railtype_cost_multiplier[2]); // monorail
 			} else {
@@ -4062,7 +4066,7 @@
 		/* case 0x1F: // locale dependent settings not implemented */
 
 		case 0x20: // snow line height
-			*value = _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF;
+			*value = _settings.game_creation.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF;
 			return true;
 
 		case 0x21: // OpenTTD version
@@ -4070,7 +4074,7 @@
 			return true;
 
 		case 0x22: // difficulty level
-			*value = _opt.diff_level;
+			*value = _settings.difficulty.diff_level;
 			return true;
 
 		default: return false;
@@ -4615,10 +4619,10 @@
 {
 	switch (param) {
 		/* start year - 1920 */
-		case 0x0B: return max(_patches.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR;
+		case 0x0B: return max(_settings.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR;
 
 		/* freight trains weight factor */
-		case 0x0E: return _patches.freight_trains;
+		case 0x0E: return _settings.vehicle.freight_trains;
 
 		/* empty wagon speed increase */
 		case 0x0F: return 0;
@@ -4627,7 +4631,7 @@
 		 * the following is good for 1x, 2x and 4x (most common?) and...
 		 * well not really for 3x. */
 		case 0x10:
-			switch (_patches.plane_speed) {
+			switch (_settings.vehicle.plane_speed) {
 				default:
 				case 4: return 1;
 				case 3: return 2;
@@ -4809,7 +4813,7 @@
 						case 0x01: // Road Vehicles
 						case 0x02: // Ships
 						case 0x03: // Aircraft
-							if (!_patches.dynamic_engines) {
+							if (!_settings.vehicle.dynamic_engines) {
 								src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles");
 								if (_skip_sprites == -1) return;
 							} else {
@@ -4971,7 +4975,7 @@
 
 		case 0x8F: // Rail track type cost factors
 			_railtype_cost_multiplier[0] = GB(res, 0, 8);
-			if (_patches.disable_elrails) {
+			if (_settings.vehicle.disable_elrails) {
 				_railtype_cost_multiplier[1] = GB(res, 0, 8);
 				_railtype_cost_multiplier[2] = GB(res, 8, 8);
 			} else {
@@ -5506,84 +5510,84 @@
 
 static void InitializeGRFSpecial()
 {
-	_ttdpatch_flags[0] =  ((_patches.always_small_airport ? 1 : 0) << 0x0C)  // keepsmallairport
-	                   |                                        (1 << 0x0D)  // newairports
-	                   |                                        (1 << 0x0E)  // largestations
-	                   |           ((_patches.longbridges ? 1 : 0) << 0x0F)  // longbridges
-	                   |                                        (0 << 0x10)  // loadtime
-	                   |                                        (1 << 0x12)  // presignals
-	                   |                                        (1 << 0x13)  // extpresignals
-	                   | ((_patches.never_expire_vehicles ? 1 : 0) << 0x16)  // enginespersist
-	                   |                                        (1 << 0x1B)  // multihead
-	                   |                                        (1 << 0x1D)  // lowmemory
-	                   |                                        (1 << 0x1E); // generalfixes
-
-	_ttdpatch_flags[1] =                                        (0 << 0x07)  // moreairports - based on units of noise
-	                   |        ((_patches.mammoth_trains ? 1 : 0) << 0x08)  // mammothtrains
-	                   |                                        (1 << 0x09)  // trainrefit
-	                   |                                        (0 << 0x0B)  // subsidiaries
-	                   |       ((_patches.gradual_loading ? 1 : 0) << 0x0C)  // gradualloading
-	                   |                                        (1 << 0x12)  // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD
-	                   |                                        (1 << 0x13)  // unifiedmaglevmode - set bit 1 mode
-	                   |                                        (1 << 0x14)  // bridgespeedlimits
-	                   |                                        (1 << 0x16)  // eternalgame
-	                   |                                        (1 << 0x17)  // newtrains
-	                   |                                        (1 << 0x18)  // newrvs
-	                   |                                        (1 << 0x19)  // newships
-	                   |                                        (1 << 0x1A)  // newplanes
-	                   |           ((_patches.signal_side ? 1 : 0) << 0x1B)  // signalsontrafficside
-	                   |       ((_patches.disable_elrails ? 0 : 1) << 0x1C); // electrifiedrailway
-
-	_ttdpatch_flags[2] =                                        (1 << 0x01)  // loadallgraphics - obsolote
-	                   |                                        (1 << 0x03)  // semaphores
-	                   |                                        (0 << 0x0B)  // enhancedgui
-	                   |                                        (0 << 0x0C)  // newagerating
-	                   |       ((_patches.build_on_slopes ? 1 : 0) << 0x0D)  // buildonslopes
-	                   |                                        (1 << 0x0E)  // fullloadany
-	                   |                                        (1 << 0x0F)  // planespeed
-	                   |                                        (0 << 0x10)  // moreindustriesperclimate - obsolete
-	                   |                                        (0 << 0x11)  // moretoylandfeatures
-	                   |                                        (1 << 0x12)  // newstations
-	                   |                                        (1 << 0x13)  // tracktypecostdiff
-	                   |                                        (1 << 0x14)  // manualconvert
-	                   |       ((_patches.build_on_slopes ? 1 : 0) << 0x15)  // buildoncoasts
-	                   |                                        (1 << 0x16)  // canals
-	                   |                                        (1 << 0x17)  // newstartyear
-	                   |    ((_patches.freight_trains > 1 ? 1 : 0) << 0x18)  // freighttrains
-	                   |                                        (1 << 0x19)  // newhouses
-	                   |                                        (1 << 0x1A)  // newbridges
-	                   |                                        (1 << 0x1B)  // newtownnames
-	                   |                                        (1 << 0x1C)  // moreanimation
-	                   |    ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D)  // wagonspeedlimits
-	                   |                                        (1 << 0x1E)  // newshistory
-	                   |                                        (0 << 0x1F); // custombridgeheads
-
-	_ttdpatch_flags[3] =                                        (0 << 0x00)  // newcargodistribution
-	                   |                                        (1 << 0x01)  // windowsnap
-	                   |                                        (0 << 0x02)  // townbuildnoroad
-	                   |                                        (0 << 0x03)  // pathbasedsignalling. To enable if ever pbs is back
-	                   |                                        (0 << 0x04)  // aichoosechance
-	                   |                                        (1 << 0x05)  // resolutionwidth
-	                   |                                        (1 << 0x06)  // resolutionheight
-	                   |                                        (1 << 0x07)  // newindustries
-	                   |         ((_patches.improved_load ? 1 : 0) << 0x08)  // fifoloading
-	                   |                                        (0 << 0x09)  // townroadbranchprob
-	                   |                                        (0 << 0x0A)  // tempsnowline
-	                   |                                        (1 << 0x0B)  // newcargo
-	                   |                                        (1 << 0x0C)  // enhancemultiplayer
-	                   |                                        (1 << 0x0D)  // onewayroads
-	                   |   ((_patches.nonuniform_stations ? 1 : 0) << 0x0E)  // irregularstations
-	                   |                                        (1 << 0x0F)  // statistics
-	                   |                                        (1 << 0x10)  // newsounds
-	                   |                                        (1 << 0x11)  // autoreplace
-	                   |                                        (1 << 0x12)  // autoslope
-	                   |                                        (0 << 0x13)  // followvehicle
-	                   |                                        (1 << 0x14)  // trams
-	                   |                                        (0 << 0x15)  // enhancetunnels
-	                   |                                        (1 << 0x16)  // shortrvs
-	                   |                                        (1 << 0x17)  // articulatedrvs
-	                   |       ((_patches.dynamic_engines ? 1 : 0) << 0x18)  // dynamic engines
-	                   |                                        (1 << 0x1E); // variablerunningcosts
+	_ttdpatch_flags[0] =  ((_settings.station.always_small_airport ? 1 : 0) << 0x0C)  // keepsmallairport
+	                   |                                                 (1 << 0x0D)  // newairports
+	                   |                                                 (1 << 0x0E)  // largestations
+	                   |      ((_settings.construction.longbridges ? 1 : 0) << 0x0F)  // longbridges
+	                   |                                                 (0 << 0x10)  // loadtime
+	                   |                                                 (1 << 0x12)  // presignals
+	                   |                                                 (1 << 0x13)  // extpresignals
+	                   | ((_settings.vehicle.never_expire_vehicles ? 1 : 0) << 0x16)  // enginespersist
+	                   |                                                 (1 << 0x1B)  // multihead
+	                   |                                                 (1 << 0x1D)  // lowmemory
+	                   |                                                 (1 << 0x1E); // generalfixes
+
+	_ttdpatch_flags[1] =   ((_settings.economy.station_noise_level ? 1 : 0) << 0x07)  // moreairports - based on units of noise
+	                   |        ((_settings.vehicle.mammoth_trains ? 1 : 0) << 0x08)  // mammothtrains
+	                   |                                                 (1 << 0x09)  // trainrefit
+	                   |                                                 (0 << 0x0B)  // subsidiaries
+	                   |         ((_settings.order.gradual_loading ? 1 : 0) << 0x0C)  // gradualloading
+	                   |                                                 (1 << 0x12)  // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD
+	                   |                                                 (1 << 0x13)  // unifiedmaglevmode - set bit 1 mode
+	                   |                                                 (1 << 0x14)  // bridgespeedlimits
+	                   |                                                 (1 << 0x16)  // eternalgame
+	                   |                                                 (1 << 0x17)  // newtrains
+	                   |                                                 (1 << 0x18)  // newrvs
+	                   |                                                 (1 << 0x19)  // newships
+	                   |                                                 (1 << 0x1A)  // newplanes
+	                   |      ((_settings.construction.signal_side ? 1 : 0) << 0x1B)  // signalsontrafficside
+	                   |       ((_settings.vehicle.disable_elrails ? 0 : 1) << 0x1C); // electrifiedrailway
+
+	_ttdpatch_flags[2] =                                                 (1 << 0x01)  // loadallgraphics - obsolote
+	                   |                                                 (1 << 0x03)  // semaphores
+	                   |                                                 (0 << 0x0B)  // enhancedgui
+	                   |                                                 (0 << 0x0C)  // newagerating
+	                   |  ((_settings.construction.build_on_slopes ? 1 : 0) << 0x0D)  // buildonslopes
+	                   |                                                 (1 << 0x0E)  // fullloadany
+	                   |                                                 (1 << 0x0F)  // planespeed
+	                   |                                                 (0 << 0x10)  // moreindustriesperclimate - obsolete
+	                   |                                                 (0 << 0x11)  // moretoylandfeatures
+	                   |                                                 (1 << 0x12)  // newstations
+	                   |                                                 (1 << 0x13)  // tracktypecostdiff
+	                   |                                                 (1 << 0x14)  // manualconvert
+	                   |  ((_settings.construction.build_on_slopes ? 1 : 0) << 0x15)  // buildoncoasts
+	                   |                                                 (1 << 0x16)  // canals
+	                   |                                                 (1 << 0x17)  // newstartyear
+	                   |    ((_settings.vehicle.freight_trains > 1 ? 1 : 0) << 0x18)  // freighttrains
+	                   |                                                 (1 << 0x19)  // newhouses
+	                   |                                                 (1 << 0x1A)  // newbridges
+	                   |                                                 (1 << 0x1B)  // newtownnames
+	                   |                                                 (1 << 0x1C)  // moreanimation
+	                   |    ((_settings.vehicle.wagon_speed_limits ? 1 : 0) << 0x1D)  // wagonspeedlimits
+	                   |                                                 (1 << 0x1E)  // newshistory
+	                   |                                                 (0 << 0x1F); // custombridgeheads
+
+	_ttdpatch_flags[3] =                                                 (0 << 0x00)  // newcargodistribution
+	                   |                                                 (1 << 0x01)  // windowsnap
+	                   |                                                 (0 << 0x02)  // townbuildnoroad
+	                   |                                                 (0 << 0x03)  // pathbasedsignalling. To enable if ever pbs is back
+	                   |                                                 (0 << 0x04)  // aichoosechance
+	                   |                                                 (1 << 0x05)  // resolutionwidth
+	                   |                                                 (1 << 0x06)  // resolutionheight
+	                   |                                                 (1 << 0x07)  // newindustries
+	                   |           ((_settings.order.improved_load ? 1 : 0) << 0x08)  // fifoloading
+	                   |                                                 (0 << 0x09)  // townroadbranchprob
+	                   |                                                 (0 << 0x0A)  // tempsnowline
+	                   |                                                 (1 << 0x0B)  // newcargo
+	                   |                                                 (1 << 0x0C)  // enhancemultiplayer
+	                   |                                                 (1 << 0x0D)  // onewayroads
+	                   |   ((_settings.station.nonuniform_stations ? 1 : 0) << 0x0E)  // irregularstations
+	                   |                                                 (1 << 0x0F)  // statistics
+	                   |                                                 (1 << 0x10)  // newsounds
+	                   |                                                 (1 << 0x11)  // autoreplace
+	                   |                                                 (1 << 0x12)  // autoslope
+	                   |                                                 (0 << 0x13)  // followvehicle
+	                   |                                                 (1 << 0x14)  // trams
+	                   |                                                 (0 << 0x15)  // enhancetunnels
+	                   |                                                 (1 << 0x16)  // shortrvs
+	                   |                                                 (1 << 0x17)  // articulatedrvs
+	                   |       ((_settings.vehicle.dynamic_engines ? 1 : 0) << 0x18)  // dynamic engines
+	                   |                                                 (1 << 0x1E); // variablerunningcosts
 }
 
 static void ResetCustomStations()
@@ -5782,7 +5786,7 @@
 	ResetNewGRFErrors();
 
 	/* Set up the default cargo types */
-	SetupCargoForClimate(_opt.landscape);
+	SetupCargoForClimate(_settings.game_creation.landscape);
 
 	/* Reset misc GRF features and train list display variables */
 	_misc_grf_features = 0;
--- a/src/newgrf_commons.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/newgrf_commons.cpp	Tue May 27 00:50:55 2008 +0000
@@ -278,7 +278,7 @@
  *         Terrain type: 0 normal, 1 desert, 2 rainforest, 4 on or above snowline */
 uint32 GetTerrainType(TileIndex tile)
 {
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_TROPIC: return GetTropicZone(tile);
 		case LT_ARCTIC: return GetTileZ(tile) > GetSnowLine() ? 4 : 0;
 		default:        return 0;
--- a/src/newgrf_engine.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/newgrf_engine.cpp	Tue May 27 00:50:55 2008 +0000
@@ -1107,7 +1107,7 @@
 		/* Populate map with current list positions */
 		Engine *e;
 		FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
-			if (!_patches.dynamic_engines || e->grffile == source_e->grffile) {
+			if (!_settings.vehicle.dynamic_engines || e->grffile == source_e->grffile) {
 				if (e->internal_id == target) target_e = e;
 				lptr_map[e->list_position] = e;
 			}
--- a/src/newgrf_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/newgrf_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -250,7 +250,6 @@
 	WC_SAVELOAD, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_newgrf_add_dlg_widgets,
-	NULL,
 };
 
 
@@ -552,7 +551,6 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_newgrf_widgets,
-	NULL,
 };
 
 /** Callback function for the newgrf 'apply changes' confirmation window
--- a/src/newgrf_town.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/newgrf_town.cpp	Tue May 27 00:50:55 2008 +0000
@@ -21,7 +21,7 @@
 	switch (variable) {
 		/* Larger towns */
 		case 0x40:
-			if (_patches.larger_towns == 0) return 2;
+			if (_settings.economy.larger_towns == 0) return 2;
 			if (t->larger_town) return 1;
 			return 0;
 
--- a/src/news_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/news_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -19,6 +19,7 @@
 #include "widgets/dropdown_func.h"
 #include "map_func.h"
 #include "statusbar_gui.h"
+#include "player_face.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -73,12 +74,68 @@
 
 typedef void DrawNewsCallbackProc(struct Window *w, const NewsItem *ni);
 void DrawNewsNewVehicleAvail(Window *w, const NewsItem *ni);
-void DrawNewsBankrupcy(Window *w, const NewsItem *ni);
 
-static DrawNewsCallbackProc * const _draw_news_callback[] = {
-	DrawNewsNewVehicleAvail,  ///< DNC_VEHICLEAVAIL
-	DrawNewsBankrupcy,        ///< DNC_BANKRUPCY
-};
+static void DrawNewsBankrupcy(Window *w, const NewsItem *ni)
+{
+	Player *p = GetPlayer((PlayerID)(ni->data_b));
+	DrawPlayerFace(p->face, p->player_color, 2, 23);
+	GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE));
+
+	SetDParam(0, p->index);
+
+	DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94);
+
+	switch (ni->subtype) {
+		case NS_COMPANY_TROUBLE:
+			DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING);
+
+			SetDParam(0, p->index);
+
+			DrawStringMultiCenter(
+				((w->width - 101) >> 1) + 98,
+				90,
+				STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED,
+				w->width - 101);
+			break;
+
+		case NS_COMPANY_MERGER:
+			DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING);
+			SetDParam(0, ni->params[2]);
+			SetDParam(1, p->index);
+			SetDParam(2, ni->params[4]);
+			DrawStringMultiCenter(
+				((w->width - 101) >> 1) + 98,
+				90,
+				ni->params[4] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR,
+				w->width - 101);
+			break;
+
+		case NS_COMPANY_BANKRUPT:
+			DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING);
+			SetDParam(0, p->index);
+			DrawStringMultiCenter(
+				((w->width - 101) >> 1) + 98,
+				90,
+				STR_705D_HAS_BEEN_CLOSED_DOWN_BY,
+				w->width - 101);
+			break;
+
+		case NS_COMPANY_NEW:
+			DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING);
+			SetDParam(0, p->index);
+			SetDParam(1, ni->params[3]);
+			DrawStringMultiCenter(
+				((w->width - 101) >> 1) + 98,
+				90,
+				STR_705F_STARTS_CONSTRUCTION_NEAR,
+				w->width - 101);
+			break;
+
+		default:
+			NOT_REACHED();
+	}
+}
+
 
 /**
  * Data common to all news items of a given subtype (structure)
@@ -87,7 +144,7 @@
 	NewsType type;         ///< News category @see NewsType
 	NewsMode display_mode; ///< Display mode value @see NewsMode
 	NewsFlag flags;        ///< Initial NewsFlags bits @see NewsFlag
-	NewsCallback callback; ///< Call-back function
+	DrawNewsCallbackProc *callback; ///< Call-back function
 };
 
 /**
@@ -95,24 +152,24 @@
  */
 static const struct NewsSubtypeData _news_subtype_data[NS_END] = {
 	/* type,             display_mode, flags,                  callback */
-	{ NT_ARRIVAL_PLAYER,  NM_THIN,     NF_VIEWPORT|NF_VEHICLE, DNC_NONE         }, ///< NS_ARRIVAL_PLAYER
-	{ NT_ARRIVAL_OTHER,   NM_THIN,     NF_VIEWPORT|NF_VEHICLE, DNC_NONE         }, ///< NS_ARRIVAL_OTHER
-	{ NT_ACCIDENT,        NM_THIN,     NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_ACCIDENT_TILE
-	{ NT_ACCIDENT,        NM_THIN,     NF_VIEWPORT|NF_VEHICLE, DNC_NONE         }, ///< NS_ACCIDENT_VEHICLE
-	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DNC_BANKRUPCY    }, ///< NS_COMPANY_TROUBLE
-	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DNC_BANKRUPCY    }, ///< NS_COMPANY_MERGER
-	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DNC_BANKRUPCY    }, ///< NS_COMPANY_BANKRUPT
-	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_TILE,                DNC_BANKRUPCY    }, ///< NS_COMPANY_NEW
-	{ NT_OPENCLOSE,       NM_THIN,     NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_OPENCLOSE
-	{ NT_ECONOMY,         NM_NORMAL,   NF_NONE,                DNC_NONE         }, ///< NS_ECONOMY
-	{ NT_INDUSTRY_PLAYER, NM_THIN,     NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_INDUSTRY_PLAYER
-	{ NT_INDUSTRY_OTHER,  NM_THIN,     NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_INDUSTRY_OTHER
-	{ NT_INDUSTRY_NOBODY, NM_THIN,     NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_INDUSTRY_NOBODY
-	{ NT_ADVICE,          NM_SMALL,    NF_VIEWPORT|NF_VEHICLE, DNC_NONE         }, ///< NS_ADVICE
-	{ NT_NEW_VEHICLES,    NM_CALLBACK, NF_NONE,                DNC_VEHICLEAVAIL }, ///< NS_NEW_VEHICLES
-	{ NT_ACCEPTANCE,      NM_SMALL,    NF_VIEWPORT|NF_TILE,    DNC_NONE         }, ///< NS_ACCEPTANCE
-	{ NT_SUBSIDIES,       NM_NORMAL,   NF_TILE|NF_TILE2,       DNC_NONE         }, ///< NS_SUBSIDIES
-	{ NT_GENERAL,         NM_NORMAL,   NF_TILE,                DNC_NONE         }, ///< NS_GENERAL
+	{ NT_ARRIVAL_PLAYER,  NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ARRIVAL_PLAYER
+	{ NT_ARRIVAL_OTHER,   NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ARRIVAL_OTHER
+	{ NT_ACCIDENT,        NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_ACCIDENT_TILE
+	{ NT_ACCIDENT,        NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ACCIDENT_VEHICLE
+	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_TROUBLE
+	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_MERGER
+	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_BANKRUPT
+	{ NT_COMPANY_INFO,    NM_CALLBACK, NF_TILE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_NEW
+	{ NT_OPENCLOSE,       NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_OPENCLOSE
+	{ NT_ECONOMY,         NM_NORMAL,   NF_NONE,                NULL                    }, ///< NS_ECONOMY
+	{ NT_INDUSTRY_PLAYER, NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_PLAYER
+	{ NT_INDUSTRY_OTHER,  NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_OTHER
+	{ NT_INDUSTRY_NOBODY, NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_NOBODY
+	{ NT_ADVICE,          NM_SMALL,    NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ADVICE
+	{ NT_NEW_VEHICLES,    NM_CALLBACK, NF_NONE,                DrawNewsNewVehicleAvail }, ///< NS_NEW_VEHICLES
+	{ NT_ACCEPTANCE,      NM_SMALL,    NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_ACCEPTANCE
+	{ NT_SUBSIDIES,       NM_NORMAL,   NF_TILE|NF_TILE2,       NULL                    }, ///< NS_SUBSIDIES
+	{ NT_GENERAL,         NM_NORMAL,   NF_TILE,                NULL                    }, ///< NS_GENERAL
 };
 
 /** Initialize the news-items data structures */
@@ -200,7 +257,7 @@
 
 			case NM_CALLBACK:
 				this->DrawNewsBorder();
-				_draw_news_callback[_news_subtype_data[this->ni->subtype].callback](this, ni);
+				(_news_subtype_data[this->ni->subtype].callback)(this, ni);
 				break;
 
 			default:
@@ -246,14 +303,14 @@
 		}
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		if (keycode == WKC_SPACE) {
 			/* Don't continue. */
 			delete this;
-			return false;
+			return ES_HANDLED;
 		}
-		return true;
+		return ES_NOT_HANDLED;
 	}
 
 	virtual void OnInvalidateData(int data)
@@ -341,7 +398,7 @@
 	ni->flags = _news_subtype_data[subtype].flags;
 
 	/* show this news message in color? */
-	if (_cur_year >= _patches.colored_news_year) ni->flags |= NF_INCOLOR;
+	if (_cur_year >= _settings.gui.colored_news_year) ni->flags |= NF_INCOLOR;
 
 	ni->data_a = data_a;
 	ni->data_b = data_b;
@@ -388,7 +445,6 @@
 	WC_NEWS_WINDOW, WC_NONE,
 	WDF_DEF_WIDGET,
 	_news_type13_widgets,
-	NULL
 };
 
 static const Widget _news_type2_widgets[] = {
@@ -402,7 +458,6 @@
 	WC_NEWS_WINDOW, WC_NONE,
 	WDF_DEF_WIDGET,
 	_news_type2_widgets,
-	NULL
 };
 
 static const Widget _news_type0_widgets[] = {
@@ -418,7 +473,6 @@
 	WC_NEWS_WINDOW, WC_NONE,
 	WDF_DEF_WIDGET,
 	_news_type0_widgets,
-	NULL
 };
 
 
@@ -640,45 +694,56 @@
 }
 
 
-static void MessageHistoryWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			int y = 19;
-
-			SetVScrollCount(w, _total_news);
-			w->DrawWidgets();
-
-			if (_total_news == 0) break;
-			NewsID show = min(_total_news, w->vscroll.cap);
-
-			for (NewsID p = w->vscroll.pos; p < w->vscroll.pos + show; p++) {
-				/* get news in correct order */
-				const NewsItem *ni = &_news_items[getNews(p)];
-
-				SetDParam(0, ni->date);
-				DrawString(4, y, STR_SHORT_DATE, TC_WHITE);
+struct MessageHistoryWindow : Window {
+	MessageHistoryWindow(const WindowDesc *desc) : Window(desc)
+	{
+		this->vscroll.cap = 10;
+		this->vscroll.count = _total_news;
+		this->resize.step_height = 12;
+		this->resize.height = this->height - 12 * 6; // minimum of 4 items in the list, each item 12 high
+		this->resize.step_width = 1;
+		this->resize.width = 200; // can't make window any smaller than 200 pixel
 
-				DrawNewsString(82, y, TC_WHITE, ni, w->width - 95);
-				y += 12;
-			}
-			break;
-		}
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-		case WE_CLICK:
-			if (e->we.click.widget == 3) {
-				int y = (e->we.click.pt.y - 19) / 12;
-				NewsID p = getNews(y + w->vscroll.pos);
+	virtual void OnPaint()
+	{
+		int y = 19;
 
-				if (p != INVALID_NEWS) ShowNewsMessage(p);
-			}
-			break;
+		SetVScrollCount(this, _total_news);
+		this->DrawWidgets();
 
-		case WE_RESIZE:
-			w->vscroll.cap += e->we.sizing.diff.y / 12;
-			break;
+		if (_total_news == 0) return;
+		NewsID show = min(_total_news, this->vscroll.cap);
+
+		for (NewsID p = this->vscroll.pos; p < this->vscroll.pos + show; p++) {
+			/* get news in correct order */
+			const NewsItem *ni = &_news_items[getNews(p)];
+
+			SetDParam(0, ni->date);
+			DrawString(4, y, STR_SHORT_DATE, TC_WHITE);
+
+			DrawNewsString(82, y, TC_WHITE, ni, this->width - 95);
+			y += 12;
+		}
 	}
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget == 3) {
+			int y = (pt.y - 19) / 12;
+			NewsID p = getNews(y + this->vscroll.pos);
+
+			if (p != INVALID_NEWS) ShowNewsMessage(p);
+		}
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->vscroll.cap += delta.y / 12;
+	}
+};
 
 static const Widget _message_history_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    13,     0,    10,     0,    13, STR_00C5,            STR_018B_CLOSE_WINDOW},
@@ -695,24 +760,13 @@
 	WC_MESSAGE_HISTORY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_message_history_widgets,
-	MessageHistoryWndProc
 };
 
 /** Display window with news messages history */
 void ShowMessageHistory()
 {
 	DeleteWindowById(WC_MESSAGE_HISTORY, 0);
-	Window *w = new Window(&_message_history_desc);
-
-	if (w == NULL) return;
-
-	w->vscroll.cap = 10;
-	w->vscroll.count = _total_news;
-	w->resize.step_height = 12;
-	w->resize.height = w->height - 12 * 6; // minimum of 4 items in the list, each item 12 high
-	w->resize.step_width = 1;
-	w->resize.width = 200; // can't make window any smaller than 200 pixel
-	w->SetDirty();
+	new MessageHistoryWindow(&_message_history_desc);
 }
 
 
@@ -741,6 +795,8 @@
 		}
 		/* If all values are the same value, the ALL-button will take over this value */
 		this->state = all_val;
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	/**
@@ -913,7 +969,6 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_message_options_widgets,
-	NULL
 };
 
 void ShowMessageOptions()
--- a/src/news_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/news_type.h	Tue May 27 00:50:55 2008 +0000
@@ -82,15 +82,6 @@
 
 
 /**
- * Special news items
- */
-enum NewsCallback {
-	DNC_VEHICLEAVAIL  = 0,    ///< Show new vehicle available message. StringID is EngineID
-	DNC_BANKRUPCY     = 1,    ///< Show bankrupcy message. StringID is PlayerID (0-3) and NewsBankrupcy (4-7)
-	DNC_NONE          = 0xFF, ///< No news callback.
-};
-
-/**
  * News display options
  */
 enum NewsDisplay {
--- a/src/npf.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/npf.cpp	Tue May 27 00:50:55 2008 +0000
@@ -213,7 +213,7 @@
 
 	if (z2 - z1 > 1) {
 		/* Slope up */
-		return _patches.npf_rail_slope_penalty;
+		return _settings.pf.npf.npf_rail_slope_penalty;
 	}
 	return 0;
 	/* Should we give a bonus for slope down? Probably not, we
@@ -260,10 +260,10 @@
 	cost = _trackdir_length[trackdir]; // Should be different for diagonal tracks
 
 	if (IsBuoyTile(current->tile) && IsDiagonalTrackdir(trackdir))
-		cost += _patches.npf_buoy_penalty; // A small penalty for going over buoys
+		cost += _settings.pf.npf.npf_buoy_penalty; // A small penalty for going over buoys
 
 	if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction))
-		cost += _patches.npf_water_curve_penalty;
+		cost += _settings.pf.npf.npf_water_curve_penalty;
 
 	/* @todo More penalties? */
 
@@ -285,13 +285,13 @@
 		case MP_ROAD:
 			cost = NPF_TILE_LENGTH;
 			/* Increase the cost for level crossings */
-			if (IsLevelCrossing(tile)) cost += _patches.npf_crossing_penalty;
+			if (IsLevelCrossing(tile)) cost += _settings.pf.npf.npf_crossing_penalty;
 			break;
 
 		case MP_STATION:
 			cost = NPF_TILE_LENGTH;
 			/* Increase the cost for drive-through road stops */
-			if (IsDriveThroughStopTile(tile)) cost += _patches.npf_road_drive_through_penalty;
+			if (IsDriveThroughStopTile(tile)) cost += _settings.pf.npf.npf_road_drive_through_penalty;
 			break;
 
 		default:
@@ -306,7 +306,7 @@
 	/* Check for turns. Road vehicles only really drive diagonal, turns are
 	 * represented by non-diagonal tracks */
 	if (!IsDiagonalTrackdir((Trackdir)current->direction))
-		cost += _patches.npf_road_curve_penalty;
+		cost += _settings.pf.npf.npf_road_curve_penalty;
 
 	NPFMarkTile(tile);
 	DEBUG(npf, 4, "Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost);
@@ -344,7 +344,7 @@
 			 * give any station tile a penalty, because every possible route will get
 			 * this penalty exactly once, on its end tile (if it's a station) and it
 			 * will therefore not make a difference. */
-			cost = NPF_TILE_LENGTH + _patches.npf_rail_station_penalty;
+			cost = NPF_TILE_LENGTH + _settings.pf.npf.npf_rail_station_penalty;
 			break;
 
 		default:
@@ -366,9 +366,9 @@
 				SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir));
 				if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) {
 					/* Penalise exit and combo signals differently (heavier) */
-					cost += _patches.npf_rail_firstred_exit_penalty;
+					cost += _settings.pf.npf.npf_rail_firstred_exit_penalty;
 				} else {
-					cost += _patches.npf_rail_firstred_penalty;
+					cost += _settings.pf.npf.npf_rail_firstred_penalty;
 				}
 			}
 			/* Record the state of this signal */
@@ -386,14 +386,14 @@
 	 * of course... */
 	new_node.path.node = *current;
 	if (as->EndNodeCheck(as, &new_node) == AYSTAR_FOUND_END_NODE && NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_RED))
-		cost += _patches.npf_rail_lastred_penalty;
+		cost += _settings.pf.npf.npf_rail_lastred_penalty;
 
 	/* Check for slope */
 	cost += NPFSlopeCost(current);
 
 	/* Check for turns */
 	if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction))
-		cost += _patches.npf_rail_curve_penalty;
+		cost += _settings.pf.npf.npf_rail_curve_penalty;
 	/*TODO, with realistic acceleration, also the amount of straight track between
 	 *      curves should be taken into account, as this affects the speed limit. */
 
@@ -402,7 +402,7 @@
 		/* Penalise any depot tile that is not the last tile in the path. This
 		 * _should_ penalise every occurence of reversing in a depot (and only
 		 * that) */
-		cost += _patches.npf_rail_depot_reverse_penalty;
+		cost += _settings.pf.npf.npf_rail_depot_reverse_penalty;
 	}
 
 	/* Check for occupied track */
@@ -634,7 +634,7 @@
 	trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);
 
 	/* Filter out trackdirs that would make 90 deg turns for trains */
-	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
+	if (_settings.pf.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
 
 	DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);
 
@@ -970,7 +970,7 @@
 	//_npf_aystar.max_search_nodes = 0;
 	/* We will limit the number of nodes for now, until we have a better
 	 * solution to really fix performance */
-	_npf_aystar.max_search_nodes = _patches.npf_max_search_nodes;
+	_npf_aystar.max_search_nodes = _settings.pf.npf.npf_max_search_nodes;
 }
 
 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v)
--- a/src/oldloader.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/oldloader.cpp	Tue May 27 00:50:55 2008 +0000
@@ -319,8 +319,8 @@
 	/* Convert town-names if needed */
 	FOR_ALL_TOWNS(town) {
 		if (IsInsideMM(town->townnametype, 0x20C1, 0x20C3)) {
-			town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _opt.town_name;
-			town->townnameparts = GetOldTownName(town->townnameparts, _opt.town_name);
+			town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _settings.game_creation.town_name;
+			town->townnameparts = GetOldTownName(town->townnameparts, _settings.game_creation.town_name);
 		}
 	}
 }
@@ -1370,29 +1370,31 @@
 }
 
 static const OldChunks game_difficulty_chunk[] = {
-	OCL_SVAR( OC_UINT16, GameDifficulty, max_no_competitors ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, competitor_start_time ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, number_towns ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, number_industries ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, max_loan ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, initial_interest ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, vehicle_costs ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, competitor_speed ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, competitor_intelligence ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, vehicle_breakdowns ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, subsidy_multiplier ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, construction_cost ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, terrain_type ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, quantity_sea_lakes ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, economy ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, line_reverse_mode ),
-	OCL_SVAR( OC_UINT16, GameDifficulty, disasters ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, max_no_competitors ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, competitor_start_time ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, number_towns ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, number_industries ),
+	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, DifficultySettings, max_loan ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, initial_interest ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, vehicle_costs ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, competitor_speed ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, competitor_intelligence ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, vehicle_breakdowns ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, subsidy_multiplier ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, construction_cost ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, terrain_type ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, quantity_sea_lakes ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, economy ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, line_reverse_mode ),
+	OCL_SVAR( OC_FILE_U16 |  OC_VAR_U8, DifficultySettings, disasters ),
 	OCL_END()
 };
 
 static inline bool LoadOldGameDifficulty(LoadgameState *ls, int num)
 {
-	return LoadChunk(ls, &_opt.diff, game_difficulty_chunk);
+	bool ret = LoadChunk(ls, &_settings.difficulty, game_difficulty_chunk);
+	_settings.difficulty.max_loan *= 1000;
+	return ret;
 }
 
 
@@ -1570,8 +1572,8 @@
 
 	OCL_VAR ( OC_FILE_U8 | OC_VAR_U16,    1, &_station_tick_ctr ),
 
-	OCL_VAR (  OC_UINT8,    1, &_opt.currency ),
-	OCL_VAR (  OC_UINT8,    1, &_opt.units ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.gui.currency ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.gui.units ),
 	OCL_VAR ( OC_FILE_U8 | OC_VAR_U32,    1, &_cur_player_tick_index ),
 
 	OCL_NULL( 2 ),               ///< Date stuff, calculated automatically
@@ -1581,19 +1583,19 @@
 	OCL_VAR (  OC_UINT8,    1, &_economy.infl_amount_pr ),
 	OCL_VAR (  OC_UINT8,    1, &_economy.interest_rate ),
 	OCL_NULL( 1 ), // available airports
-	OCL_VAR (  OC_UINT8,    1, &_opt.road_side ),
-	OCL_VAR (  OC_UINT8,    1, &_opt.town_name ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.vehicle.road_side ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.game_creation.town_name ),
 
 	OCL_CHUNK( 1, LoadOldGameDifficulty ),
 
 	OCL_ASSERT( 0x77130 ),
 
-	OCL_VAR (  OC_UINT8,    1, &_opt.diff_level ),
-	OCL_VAR (  OC_UINT8,    1, &_opt.landscape ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.difficulty.diff_level ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.game_creation.landscape ),
 	OCL_VAR (  OC_UINT8,    1, &_trees_tick_ctr ),
 
 	OCL_NULL( 1 ),               ///< Custom vehicle types yes/no, no longer used
-	OCL_VAR (  OC_UINT8,    1, &_opt.snow_line ),
+	OCL_VAR (  OC_UINT8,    1, &_settings.game_creation.snow_line ),
 
 	OCL_NULL( 32 ),              ///< new_industry_randtable, no longer used (because of new design)
 	OCL_NULL( 36 ),              ///< cargo-stuff, calculated in InitializeLandscapeVariables
@@ -1628,7 +1630,7 @@
 	DEBUG(oldloader, 3, "Done, converting game data...");
 
 	/* Fix some general stuff */
-	_opt.landscape = _opt.landscape & 0xF;
+	_settings.game_creation.landscape = _settings.game_creation.landscape & 0xF;
 
 	/* Remap some pointers */
 	_cur_town_ctr      = REMAP_TOWN_IDX(_old_cur_town_ctr);
@@ -1690,7 +1692,7 @@
 	FixOldVehicles();
 
 	/* We have a new difficulty setting */
-	_opt.diff.town_council_tolerance = Clamp(_opt.diff_level, 0, 2);
+	_settings.difficulty.town_council_tolerance = Clamp(_settings.difficulty.diff_level, 0, 2);
 
 	DEBUG(oldloader, 3, "Finished converting game data");
 	DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted");
--- a/src/openttd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/openttd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -41,7 +41,7 @@
 #include "fios.h"
 #include "airport.h"
 #include "aircraft.h"
-#include "console.h"
+#include "console_func.h"
 #include "screenshot.h"
 #include "network/network.h"
 #include "signs_base.h"
@@ -100,7 +100,7 @@
 void ProcessAsyncSaveFinish();
 void CallWindowTickEvent();
 
-extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
+extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
 extern Player* DoStartupNewPlayer(bool is_ai);
 extern void ShowOSErrorBox(const char *buf);
 extern void InitializeRailGUI();
@@ -284,7 +284,6 @@
 {
 	/* Dynamic stuff needs to be initialized somewhere... */
 	_town_sort     = NULL;
-	_industry_sort = NULL;
 	_industry_mngr.ResetMapping();
 	_industile_mngr.ResetMapping();
 }
@@ -318,7 +317,6 @@
 	_Engine_pool.CleanPool();
 
 	free((void*)_town_sort);
-	free((void*)_industry_sort);
 
 	free(_config_file);
 
@@ -330,7 +328,6 @@
 {
 	_game_mode = GM_MENU;
 
-	_opt_ptr = &_opt_newgame;
 	ResetGRFConfig(false);
 
 	/* Setup main window */
@@ -486,8 +483,8 @@
 	if (!StrEmpty(videodriver)) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver));
 	if (!StrEmpty(blitter))     ttd_strlcpy(_ini_blitter, blitter, sizeof(_ini_blitter));
 	if (resolution[0] != 0) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; }
-	if (startyear != INVALID_YEAR) _patches_newgame.starting_year = startyear;
-	if (generation_seed != GENERATE_NEW_SEED) _patches_newgame.generation_seed = generation_seed;
+	if (startyear != INVALID_YEAR) _settings_newgame.game_creation.starting_year = startyear;
+	if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed;
 
 	/* The width and height must be at least 1 pixel, this
 	 * way all internal drawing routines work correctly. */
@@ -581,17 +578,13 @@
 
 	ScanNewGRFFiles();
 
-	_opt_ptr = &_opt_newgame;
 	ResetGRFConfig(false);
 
 	/* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */
-	if (_opt_newgame.diff_level == 9) SetDifficultyLevel(0, &_opt_newgame);
+	if (_settings_newgame.difficulty.diff_level == 9) SetDifficultyLevel(0, &_settings_newgame.difficulty);
 
-	/* Make sure _patches is filled with _patches_newgame if we switch to a game directly */
-	if (_switch_mode != SM_NONE) {
-		_opt = _opt_newgame;
-		UpdatePatches();
-	}
+	/* Make sure _settings is filled with _settings_newgame if we switch to a game directly */
+	if (_switch_mode != SM_NONE) _settings = _settings_newgame;
 
 	/* initialize the ingame console */
 	IConsoleInit();
@@ -651,7 +644,7 @@
 {
 	if (_game_mode == GM_MENU) { // do not ask to quit on the main screen
 		_exit_game = true;
-	} else if (_patches.autosave_on_exit) {
+	} else if (_settings.gui.autosave_on_exit) {
 		DoExitSave();
 		_exit_game = true;
 	} else {
@@ -683,9 +676,9 @@
 
 	SetLocalPlayer(PLAYER_FIRST);
 	_current_player = _local_player;
-	DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
+	DoCommandP(0, (_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
 
-	SettingsDisableElrail(_patches.disable_elrails);
+	SettingsDisableElrail(_settings.vehicle.disable_elrails);
 	InitializeRailGUI();
 
 #ifdef ENABLE_NETWORK
@@ -710,7 +703,7 @@
 	_industry_mngr.ResetMapping();
 
 	GenerateWorldSetCallback(&MakeNewGameDone);
-	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
+	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y);
 }
 
 static void MakeNewEditorWorldDone()
@@ -727,7 +720,7 @@
 	ResetGRFConfig(true);
 
 	GenerateWorldSetCallback(&MakeNewEditorWorldDone);
-	GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y);
+	GenerateWorld(GW_EMPTY, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y);
 }
 
 void StartupPlayers();
@@ -766,9 +759,7 @@
 		ShowErrorMessage(INVALID_STRING_ID, STR_012D, 0, 0);
 	}
 
-	_opt_ptr = &_opt;
-	_opt_ptr->diff = _opt_newgame.diff;
-	_opt.diff_level = _opt_newgame.diff_level;
+	_settings.difficulty = _settings_newgame.difficulty;
 
 	/* Inititalize data */
 	StartupEconomy();
@@ -778,7 +769,7 @@
 
 	SetLocalPlayer(PLAYER_FIRST);
 	_current_player = _local_player;
-	DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
+	DoCommandP(0, (_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
 
 	MarkWholeScreenDirty();
 }
@@ -837,8 +828,7 @@
 				/* check if we should reload the config */
 				if (_network_reload_cfg) {
 					LoadFromConfig();
-					_patches = _patches_newgame;
-					_opt = _opt_newgame;
+					_settings = _settings_newgame;
 					ResetGRFConfig(false);
 				}
 				NetworkServerStart();
@@ -874,7 +864,6 @@
 			break;
 
 		case SM_LOAD: { /* Load game, Play Scenario */
-			_opt_ptr = &_opt;
 			ResetGRFConfig(true);
 			ResetWindowSystem();
 
@@ -912,16 +901,14 @@
 		case SM_LOAD_HEIGHTMAP: /* Load heightmap from scenario editor */
 			SetLocalPlayer(OWNER_NONE);
 
-			GenerateWorld(GW_HEIGHTMAP, 1 << _patches.map_x, 1 << _patches.map_y);
+			GenerateWorld(GW_HEIGHTMAP, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y);
 			MarkWholeScreenDirty();
 			break;
 
 		case SM_LOAD_SCENARIO: { /* Load scenario from scenario editor */
 			if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) {
-				_opt_ptr = &_opt;
-
 				SetLocalPlayer(OWNER_NONE);
-				_patches_newgame.starting_year = _cur_year;
+				_settings_newgame.game_creation.starting_year = _cur_year;
 			} else {
 				SetDParamStr(0, GetSaveLoadErrorString());
 				ShowErrorMessage(INVALID_STRING_ID, STR_012D, 0, 0);
@@ -947,7 +934,7 @@
 
 		case SM_GENRANDLAND: /* Generate random land within scenario editor */
 			SetLocalPlayer(OWNER_NONE);
-			GenerateWorld(GW_RANDOM, 1 << _patches.map_x, 1 << _patches.map_y);
+			GenerateWorld(GW_RANDOM, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y);
 			/* XXX: set date */
 			MarkWholeScreenDirty();
 			break;
@@ -1063,16 +1050,16 @@
 	if (_networking) return;
 #endif /* PSP */
 
-	if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) {
+	if (_settings.gui.keep_all_autosave && _local_player != PLAYER_SPECTATOR) {
 		SetDParam(0, _local_player);
 		SetDParam(1, _date);
 		GetString(buf, STR_4004, lastof(buf));
 		ttd_strlcat(buf, ".sav", lengthof(buf));
 	} else {
-		/* generate a savegame name and number according to _patches.max_num_autosaves */
+		/* generate a savegame name and number according to _settings.gui.max_num_autosaves */
 		snprintf(buf, sizeof(buf), "autosave%d.sav", _autosave_ctr);
 
-		if (++_autosave_ctr >= _patches.max_num_autosaves) _autosave_ctr = 0;
+		if (++_autosave_ctr >= _settings.gui.max_num_autosaves) _autosave_ctr = 0;
 	}
 
 	DEBUG(sl, 2, "Autosaving to '%s'", buf);
@@ -1262,7 +1249,7 @@
 /* since savegame version 4.2 the currencies are arranged differently */
 static void UpdateCurrencies()
 {
-	_opt.currency = convert_currency[_opt.currency];
+	_settings.gui.currency = convert_currency[_settings.gui.currency];
 }
 
 /* Up to revision 1413 the invisible tiles at the southern border have not been
@@ -1370,6 +1357,11 @@
 
 	SetCachedEngineCounts();
 
+	/* Towns have a noise controlled number of airports system
+	 * So each airport's noise value must be added to the town->noise_reached value
+	 * Reset each town's noise_reached value to '0' before. */
+	UpdateAirportsNoise();
+
 	return true;
 }
 
@@ -1420,7 +1412,7 @@
 		Town *t;
 		FOR_ALL_TOWNS(t) {
 			t->name = CopyFromOldName(t->townnametype);
-			if (t->name != NULL) t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
+			if (t->name != NULL) t->townnametype = SPECSTR_TOWNNAME_START + _settings.game_creation.town_name;
 		}
 
 		Waypoint *wp;
@@ -1434,7 +1426,7 @@
 	ResetOldNames();
 
 	/* convert road side to my format. */
-	if (_opt.road_side) _opt.road_side = 1;
+	if (_settings.vehicle.road_side) _settings.vehicle.road_side = 1;
 
 	/* Check if all NewGRFs are present, we are very strict in MP mode */
 	GRFListCompatibility gcf_res = IsGoodGRFConfigList();
@@ -1454,7 +1446,7 @@
 	SetDate(_date);
 
 	/* Force dynamic engines off when loading older savegames */
-	if (CheckSavegameVersion(95)) _patches.dynamic_engines = 0;
+	if (CheckSavegameVersion(95)) _settings.vehicle.dynamic_engines = 0;
 
 	/* Load the sprites */
 	GfxLoadSprites();
@@ -1687,9 +1679,9 @@
 		 */
 		if (!_network_dedicated && IsValidPlayer(PLAYER_FIRST)) {
 			p = GetPlayer(PLAYER_FIRST);
-			p->engine_renew        = _patches.autorenew;
-			p->engine_renew_months = _patches.autorenew_months;
-			p->engine_renew_money  = _patches.autorenew_money;
+			p->engine_renew        = _settings.gui.autorenew;
+			p->engine_renew_months = _settings.gui.autorenew_months;
+			p->engine_renew_money  = _settings.gui.autorenew_money;
 		}
 	}
 
@@ -1971,8 +1963,6 @@
 		}
 	}
 
-	if (CheckSavegameVersion(22))  UpdatePatches();
-
 	if (CheckSavegameVersion(25)) {
 		Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
@@ -2074,9 +2064,9 @@
 
 	/* from version 38 we have optional elrails, since we cannot know the
 	 * preference of a user, let elrails enabled; it can be disabled manually */
-	if (CheckSavegameVersion(38)) _patches.disable_elrails = false;
+	if (CheckSavegameVersion(38)) _settings.vehicle.disable_elrails = false;
 	/* do the same as when elrails were enabled/disabled manually just now */
-	SettingsDisableElrail(_patches.disable_elrails);
+	SettingsDisableElrail(_settings.vehicle.disable_elrails);
 	InitializeRailGUI();
 
 	/* From version 53, the map array was changed for house tiles to allow
@@ -2241,7 +2231,7 @@
 		Town *t;
 
 		FOR_ALL_TOWNS(t) {
-			if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) {
+			if (_settings.economy.larger_towns != 0 && (t->index % _settings.economy.larger_towns) == 0) {
 				t->larger_town = true;
 			}
 		}
@@ -2278,12 +2268,12 @@
 	if (CheckSavegameVersion(58)) {
 		/* patch difficulty number_industries other then zero get bumped to +1
 		 * since a new option (very low at position1) has been added */
-		if (_opt.diff.number_industries > 0) {
-			_opt.diff.number_industries++;
+		if (_settings.difficulty.number_industries > 0) {
+			_settings.difficulty.number_industries++;
 		}
 
 		/* Same goes for number of towns, although no test is needed, just an increment */
-		_opt.diff.number_towns++;
+		_settings.difficulty.number_towns++;
 	}
 
 	if (CheckSavegameVersion(64)) {
@@ -2516,22 +2506,22 @@
 		}
 
 		/* Convert old PF settings to new */
-		if (_patches.yapf.rail_use_yapf || CheckSavegameVersion(28)) {
-			_patches.pathfinder_for_trains = VPF_YAPF;
+		if (_settings.pf.yapf.rail_use_yapf || CheckSavegameVersion(28)) {
+			_settings.pf.pathfinder_for_trains = VPF_YAPF;
 		} else {
-			_patches.pathfinder_for_trains = (_patches.new_pathfinding_all ? VPF_NPF : VPF_NTP);
+			_settings.pf.pathfinder_for_trains = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_NTP);
 		}
 
-		if (_patches.yapf.road_use_yapf || CheckSavegameVersion(28)) {
-			_patches.pathfinder_for_roadvehs = VPF_YAPF;
+		if (_settings.pf.yapf.road_use_yapf || CheckSavegameVersion(28)) {
+			_settings.pf.pathfinder_for_roadvehs = VPF_YAPF;
 		} else {
-			_patches.pathfinder_for_roadvehs = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF);
+			_settings.pf.pathfinder_for_roadvehs = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_OPF);
 		}
 
-		if (_patches.yapf.ship_use_yapf) {
-			_patches.pathfinder_for_ships = VPF_YAPF;
+		if (_settings.pf.yapf.ship_use_yapf) {
+			_settings.pf.pathfinder_for_ships = VPF_YAPF;
 		} else {
-			_patches.pathfinder_for_ships = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF);
+			_settings.pf.pathfinder_for_ships = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_OPF);
 		}
 	}
 
--- a/src/order_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/order_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -152,11 +152,15 @@
 
 void Order::ConvertFromOldSavegame()
 {
-	/* First handle non-stop, because those bits are going to be reused. */
-	if (_patches.sg_new_nonstop) {
-		this->SetNonStopType((this->flags & 0x08) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+	uint8 old_flags = this->flags;
+	this->flags = 0;
+
+	/* First handle non-stop */
+	if (_settings.gui.sg_new_nonstop) {
+		/* OFB_NON_STOP */
+		this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 	} else {
-		this->SetNonStopType((this->flags & 0x08) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
+		this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
 	}
 
 	switch (this->GetType()) {
@@ -165,31 +169,31 @@
 		default: return;
 	}
 
-	/* Then the load/depot action flags because those bits are going to be reused too
-	 * and they reuse the non-stop bits. */
 	if (this->GetType() != OT_GOTO_DEPOT) {
-		if ((this->flags & 4) == 0) {
+		/* Then the load flags */
+		if ((old_flags & 2) != 0) { // OFB_UNLOAD
+			this->SetLoadType(OLFB_NO_LOAD);
+		} else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
 			this->SetLoadType(OLF_LOAD_IF_POSSIBLE);
 		} else {
-			this->SetLoadType(_patches.sg_full_load_any ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
+			this->SetLoadType(_settings.gui.sg_full_load_any ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
+		}
+
+		/* Finally fix the unload flags */
+		if ((old_flags & 1) != 0) { // OFB_TRANSFER
+			this->SetUnloadType(OUFB_TRANSFER);
+		} else if ((old_flags & 2) != 0) { // OFB_UNLOAD
+			this->SetUnloadType(OUFB_UNLOAD);
+		} else {
+			this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
 		}
 	} else {
-		this->SetDepotActionType(((this->flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY);
-	}
+		/* Then the depot action flags */
+		this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY);
 
-	/* Finally fix the unload/depot type flags. */
-	if (this->GetType() != OT_GOTO_DEPOT) {
-		uint t = ((this->flags & 1) == 0) ? OUF_UNLOAD_IF_POSSIBLE : OUFB_TRANSFER;
-		if ((this->flags & 2) != 0) t |= OUFB_UNLOAD;
-		this->SetUnloadType((OrderUnloadFlags)t);
-
-		if ((this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) {
-			this->SetUnloadType(OUFB_TRANSFER);
-			this->SetLoadType(OLFB_NO_LOAD);
-		}
-	} else {
-		uint t = ((this->flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL;
-		if ((this->flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS;
+		/* Finally fix the depot type flags */
+		uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL;
+		if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS;
 		this->SetDepotOrderType((OrderDepotTypeFlags)t);
 	}
 }
@@ -451,7 +455,7 @@
 
 	if (!HasOrderPoolFree(1)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 
-	if (v->type == VEH_SHIP && IsHumanPlayer(v->owner) && _patches.pathfinder_for_ships != VPF_NPF) {
+	if (v->type == VEH_SHIP && IsHumanPlayer(v->owner) && _settings.pf.pathfinder_for_ships != VPF_NPF) {
 		/* Make sure the new destination is not too far away from the previous */
 		const Order *prev = NULL;
 		uint n = 0;
@@ -546,7 +550,7 @@
 		}
 
 		/* Make sure to rebuild the whole list */
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
 	}
 
 	return CommandCost();
@@ -561,7 +565,7 @@
 	if (flags & DC_EXEC) {
 		DeleteVehicleOrders(dst);
 		InvalidateVehicleOrder(dst);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
 	}
 	return CommandCost();
 }
@@ -673,7 +677,7 @@
 			cur_order_id++;
 		}
 
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
 	}
 
 	return CommandCost();
@@ -811,7 +815,7 @@
 		}
 
 		/* Make sure to rebuild the whole list */
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
 	}
 
 	return CommandCost();
@@ -1075,7 +1079,7 @@
 				InvalidateVehicleOrder(dst);
 				InvalidateVehicleOrder(src);
 
-				RebuildVehicleLists();
+				InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
 			}
 		} break;
 
@@ -1134,7 +1138,7 @@
 
 				InvalidateVehicleOrder(dst);
 
-				RebuildVehicleLists();
+				InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
 			}
 		} break;
 
@@ -1273,7 +1277,7 @@
 			}
 
 			/* Copy timetable if enabled */
-			if (_patches.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25),
+			if (_settings.order.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25),
 					bak->order[i].wait_time << 16 | bak->order[i].travel_time, NULL,
 					CMD_CHANGE_TIMETABLE | CMD_NO_TEST_IF_IN_NETWORK)) {
 				break;
@@ -1386,13 +1390,13 @@
 void CheckOrders(const Vehicle* v)
 {
 	/* Does the user wants us to check things? */
-	if (_patches.order_review_system == 0) return;
+	if (_settings.gui.order_review_system == 0) return;
 
 	/* Do nothing for crashed vehicles */
 	if (v->vehstatus & VS_CRASHED) return;
 
 	/* Do nothing for stopped vehicles if setting is '1' */
-	if (_patches.order_review_system == 1 && v->vehstatus & VS_STOPPED)
+	if (_settings.gui.order_review_system == 1 && v->vehstatus & VS_STOPPED)
 		return;
 
 	/* do nothing we we're not the first vehicle in a share-chain */
@@ -1571,7 +1575,7 @@
 
 Date GetServiceIntervalClamped(uint index)
 {
-	return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
+	return (_settings.vehicle.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
 }
 
 /**
--- a/src/order_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/order_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -265,13 +265,13 @@
 	order.index = 0;
 
 	/* check depot first */
-	if (_patches.gotodepot) {
+	if (_settings.order.gotodepot) {
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY:
 				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);
+						if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 						return order;
 					}
 				}
@@ -280,7 +280,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);
+					if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 					return order;
 				}
 				break;
@@ -313,7 +313,7 @@
 			IsTileOwner(tile, _local_player) &&
 			IsRailWaypoint(tile)) {
 		order.MakeGoToWaypoint(GetWaypointByTile(tile)->index);
-		if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+		if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 		return order;
 	}
 
@@ -330,7 +330,7 @@
 			(facil = FACIL_TRUCK_STOP, 1);
 			if (st->facilities & facil) {
 				order.MakeGoToStation(st_index);
-				if (_patches.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+				if (_settings.gui.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
 				return order;
 			}
 		}
@@ -611,7 +611,7 @@
 		this->resize.step_height = 10;
 		this->selected_order = -1;
 		this->vehicle = v;
-		if (_patches.timetabling) {
+		if (_settings.order.timetabling) {
 			this->widget[ORDER_WIDGET_CAPTION].right -= 61;
 		} else {
 			this->HideWidget(ORDER_WIDGET_TIMETABLE_VIEW);
@@ -926,7 +926,7 @@
 		ResetObjectToPlace();
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
 		static const KeyToEvent keytoevent[] = {
 			{'D', OrderClick_Skip},
@@ -939,15 +939,15 @@
 			//('?', OrderClick_Service},
 		};
 
-		if (this->vehicle->owner != _local_player) return true;
+		if (this->vehicle->owner != _local_player) return ES_NOT_HANDLED;
 
 		for (uint i = 0; i < lengthof(keytoevent); i++) {
 			if (keycode == keytoevent[i].keycode) {
 				keytoevent[i].proc(this, -1);
-				return false;
+				return ES_HANDLED;
 			}
 		}
-		return true;
+		return ES_NOT_HANDLED;
 	}
 
 	virtual void OnPlaceObject(Point pt, TileIndex tile)
@@ -1063,7 +1063,6 @@
 	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 	_orders_train_widgets,
-	NULL
 };
 
 /**
@@ -1104,7 +1103,6 @@
 	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 	_orders_widgets,
-	NULL
 };
 
 /**
@@ -1145,7 +1143,6 @@
 	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_other_orders_widgets,
-	NULL
 };
 
 void ShowOrdersWindow(const Vehicle *v)
--- a/src/osk_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/osk_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -283,12 +283,11 @@
 {   WIDGETS_END},
 };
 
-WindowDesc _osk_desc = {
+static const WindowDesc _osk_desc = {
 	WDP_CENTER, WDP_CENTER, 256, 140, 256, 140,
 	WC_OSK, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_osk_widgets,
-	NULL
 };
 
 /**
@@ -346,7 +345,7 @@
 }
 
 /**
- * Show the osk associated with a given textbox
+ * Show the on-screen keyboard (osk) associated with a given textbox
  * @param parent pointer to the Window where this keyboard originated from
  * @param q      querystr_d pointer to the query string of the parent, which is
  *               shared for both windows
--- a/src/pathfind.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/pathfind.cpp	Tue May 27 00:50:55 2008 +0000
@@ -778,7 +778,7 @@
 	tpf->enum_proc = enum_proc;
 	tpf->tracktype = TRANSPORT_RAIL;
 	tpf->railtypes = railtypes;
-	tpf->maxlength = min(_patches.pf_maxlength * 3, 10000);
+	tpf->maxlength = min(_settings.pf.opf.pf_maxlength * 3, 10000);
 	tpf->nstack = 0;
 	tpf->new_link = tpf->links;
 	tpf->num_links_left = lengthof(tpf->links);
--- a/src/player_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/player_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -165,6 +165,8 @@
 			this->top = top;
 			this->left = left;
 		}
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
@@ -230,7 +232,6 @@
 	WC_FINANCES, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
 	_player_finances_widgets,
-	NULL
 };
 
 static const WindowDesc _player_finances_small_desc = {
@@ -238,7 +239,6 @@
 	WC_FINANCES, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
 	_player_finances_small_widgets,
-	NULL
 };
 
 /**
@@ -543,7 +543,6 @@
 	WC_PLAYER_COLOR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_select_player_livery_widgets,
-	NULL
 };
 
 /**
@@ -758,10 +757,9 @@
 	}
 
 public:
-	SelectPlayerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced) : Window(desc, parent->window_number)
+	SelectPlayerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced, int top, int left) : Window(desc, parent->window_number)
 	{
 		this->parent = parent;
-		this->FindWindowPlacementAndResize(desc);
 		this->caption_color = this->window_number;
 		this->face = GetPlayer((PlayerID)this->window_number)->face;
 		this->advanced = advanced;
@@ -773,6 +771,8 @@
 			this->top = top;
 			this->left = left;
 		}
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
@@ -1010,7 +1010,6 @@
 	WC_PLAYER_FACE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_select_player_face_widgets,
-	NULL
 };
 
 /** advanced player face selection window description */
@@ -1019,7 +1018,6 @@
 	WC_PLAYER_FACE, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_select_player_face_adv_widgets,
-	NULL
 };
 
 /**
@@ -1037,7 +1035,7 @@
 	if (!IsValidPlayer((PlayerID)parent->window_number)) return;
 
 	if (BringWindowToFrontById(WC_PLAYER_FACE, parent->window_number)) return;
-	new SelectPlayerFaceWindow(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, parent, adv); // simple or advanced window
+	new SelectPlayerFaceWindow(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, parent, adv, top, left); // simple or advanced window
 }
 
 
@@ -1172,6 +1170,7 @@
 	PlayerCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 	{
 		this->caption_color = this->window_number;
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
@@ -1192,7 +1191,7 @@
 		this->SetWidgetHiddenState(PCW_WIDGET_COMPANY_PASSWORD, !local || !_networking);
 
 		if (!local) {
-			if (_patches.allow_shares) { // Shares are allowed
+			if (_settings.economy.allow_shares) { // Shares are allowed
 				/* If all shares are owned by someone (none by nobody), disable buy button */
 				this->SetWidgetDisabledState(PCW_WIDGET_BUY_SHARE, GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0 ||
 						/* Only 25% left to buy. If the player is human, disable buying it up.. TODO issues! */
@@ -1348,7 +1347,6 @@
 	WC_COMPANY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_player_company_widgets,
-	NULL
 };
 
 void ShowPlayerCompany(PlayerID player)
@@ -1360,35 +1358,39 @@
 
 
 
-static void BuyCompanyWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			Player *p = GetPlayer((PlayerID)w->window_number);
-			SetDParam(0, STR_COMPANY_NAME);
-			SetDParam(1, p->index);
-			w->DrawWidgets();
-
-			DrawPlayerFace(p->face, p->player_color, 2, 16);
+struct BuyCompanyWindow : Window {
+	BuyCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			SetDParam(0, p->index);
-			SetDParam(1, p->bankrupt_value);
-			DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238);
-		} break;
+	virtual void OnPaint()
+	{
+		Player *p = GetPlayer((PlayerID)this->window_number);
+		SetDParam(0, STR_COMPANY_NAME);
+		SetDParam(1, p->index);
+		this->DrawWidgets();
 
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case 3:
-					delete w;
-					break;
-				case 4: {
-					DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY));
-					break;
-				}
-			}
-			break;
+		DrawPlayerFace(p->face, p->player_color, 2, 16);
+
+		SetDParam(0, p->index);
+		SetDParam(1, p->bankrupt_value);
+		DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238);
 	}
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case 3:
+				delete this;
+				break;
+
+			case 4:
+				DoCommandP(0, this->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY));
+				break;
+		}
+	}
+};
 
 static const Widget _buy_company_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,     5,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
@@ -1404,13 +1406,12 @@
 	WC_BUY_COMPANY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_buy_company_widgets,
-	BuyCompanyWndProc
 };
 
 
 void ShowBuyCompanyDialog(uint player)
 {
-	AllocateWindowDescFront<Window>(&_buy_company_desc, player);
+	AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, player);
 }
 
 /********** HIGHSCORE and ENDGAME windows */
@@ -1476,7 +1477,7 @@
 		} else {
 			/* in single player _local player is always valid */
 			const Player *p = GetPlayer(_local_player);
-			this->window_number = _opt.diff_level;
+			this->window_number = _settings.difficulty.diff_level;
 			this->rank = SaveHighScoreValue(p);
 		}
 
@@ -1544,7 +1545,7 @@
 
 		this->SetupHighScoreEndWindow(&x, &y);
 
-		SetDParam(0, _patches.ending_year);
+		SetDParam(0, _settings.gui.ending_year);
 		SetDParam(1, this->window_number + STR_6801_EASY);
 		DrawStringMultiCenter(x + (640 / 2), y + 62, !_networking ? STR_0211_TOP_COMPANIES_WHO_REACHED : STR_TOP_COMPANIES_NETWORK_GAME, 500);
 
@@ -1575,7 +1576,6 @@
 	WC_HIGHSCORE, WC_NONE,
 	0,
 	_highscore_widgets,
-	NULL
 };
 
 static const WindowDesc _endgame_desc = {
@@ -1583,7 +1583,6 @@
 	WC_ENDSCREEN, WC_NONE,
 	0,
 	_highscore_widgets,
-	NULL
 };
 
 /** Show the highscore table for a given difficulty. When called from
--- a/src/players.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/players.cpp	Tue May 27 00:50:55 2008 +0000
@@ -65,9 +65,9 @@
 	/* Do not update the patches if we are in the intro GUI */
 	if (IsValidPlayer(new_player) && _game_mode != GM_MENU) {
 		const Player *p = GetPlayer(new_player);
-		_patches.autorenew        = p->engine_renew;
-		_patches.autorenew_months = p->engine_renew_months;
-		_patches.autorenew_money  = p->engine_renew_money;
+		_settings.gui.autorenew        = p->engine_renew;
+		_settings.gui.autorenew_months = p->engine_renew_months;
+		_settings.gui.autorenew_money  = p->engine_renew_money;
 		InvalidateWindow(WC_GAME_OPTIONS, 0);
 	}
 }
@@ -541,9 +541,9 @@
 	/* Engine renewal settings */
 	p->engine_renew_list = NULL;
 	p->renew_keep_length = false;
-	p->engine_renew = _patches_newgame.autorenew;
-	p->engine_renew_months = _patches_newgame.autorenew_months;
-	p->engine_renew_money = _patches_newgame.autorenew_money;
+	p->engine_renew = _settings_newgame.gui.autorenew;
+	p->engine_renew_months = _settings_newgame.gui.autorenew_months;
+	p->engine_renew_money = _settings_newgame.gui.autorenew_money;
 
 	GeneratePresidentName(p);
 
@@ -563,7 +563,7 @@
 void StartupPlayers()
 {
 	/* The AI starts like in the setting with +2 month max */
-	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1;
+	_next_competitor_start = _settings.difficulty.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1;
 }
 
 static void MaybeStartNewPlayer()
@@ -578,10 +578,10 @@
 	}
 
 	/* when there's a lot of computers in game, the probability that a new one starts is lower */
-	if (n < (uint)_opt.diff.max_no_competitors &&
+	if (n < (uint)_settings.difficulty.max_no_competitors &&
 			n < (_network_server ?
-				InteractiveRandomRange(_opt.diff.max_no_competitors + 2) :
-				RandomRange(_opt.diff.max_no_competitors + 2)
+				InteractiveRandomRange(_settings.difficulty.max_no_competitors + 2) :
+				RandomRange(_settings.difficulty.max_no_competitors + 2)
 			)) {
 		/* Send a command to all clients to start up a new AI.
 		 * Works fine for Multiplayer and Singleplayer */
@@ -589,7 +589,7 @@
 	}
 
 	/* The next AI starts like the difficulty setting said, with +2 month max */
-	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + 1;
+	_next_competitor_start = _settings.difficulty.competitor_start_time * 90 * DAY_TICKS + 1;
 	_next_competitor_start += _network_server ? InteractiveRandomRange(60 * DAY_TICKS) : RandomRange(60 * DAY_TICKS);
 }
 
@@ -630,7 +630,7 @@
 		}
 	}
 
-	if (_patches.show_finances && _local_player != PLAYER_SPECTATOR) {
+	if (_settings.gui.show_finances && _local_player != PLAYER_SPECTATOR) {
 		ShowPlayerFinances(_local_player);
 		p = GetPlayer(_local_player);
 		if (p->num_valid_stat_ent > 5 && p->old_economy[0].performance_history < p->old_economy[4].performance_history) {
@@ -695,7 +695,7 @@
 			if (flags & DC_EXEC) {
 				p->engine_renew = HasBit(p2, 0);
 				if (IsLocalPlayer()) {
-					_patches.autorenew = p->engine_renew;
+					_settings.gui.autorenew = p->engine_renew;
 					InvalidateWindow(WC_GAME_OPTIONS, 0);
 				}
 			}
@@ -708,7 +708,7 @@
 			if (flags & DC_EXEC) {
 				p->engine_renew_months = (int16)p2;
 				if (IsLocalPlayer()) {
-					_patches.autorenew_months = p->engine_renew_months;
+					_settings.gui.autorenew_months = p->engine_renew_months;
 					InvalidateWindow(WC_GAME_OPTIONS, 0);
 				}
 			}
@@ -721,7 +721,7 @@
 			if (flags & DC_EXEC) {
 				p->engine_renew_money = p2;
 				if (IsLocalPlayer()) {
-					_patches.autorenew_money = p->engine_renew_money;
+					_settings.gui.autorenew_money = p->engine_renew_money;
 					InvalidateWindow(WC_GAME_OPTIONS, 0);
 				}
 			}
@@ -771,9 +771,9 @@
 				p->engine_renew_money = p2;
 
 				if (IsLocalPlayer()) {
-					_patches.autorenew = p->engine_renew;
-					_patches.autorenew_months = p->engine_renew_months;
-					_patches.autorenew_money = p->engine_renew_money;
+					_settings.gui.autorenew = p->engine_renew;
+					_settings.gui.autorenew_months = p->engine_renew_months;
+					_settings.gui.autorenew_money = p->engine_renew_money;
 					InvalidateWindow(WC_GAME_OPTIONS, 0);
 				}
 			}
@@ -876,8 +876,8 @@
 		/* Now that we have a new player, broadcast its autorenew settings to
 		 * all clients so everything is in sync */
 		DoCommand(0,
-			(_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4,
-			_patches.autorenew_money,
+			(_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4,
+			_settings.gui.autorenew_money,
 			DC_EXEC,
 			CMD_SET_AUTOREPLACE
 		);
@@ -994,7 +994,7 @@
 /** Save the highscore for the player */
 int8 SaveHighScoreValue(const Player *p)
 {
-	HighScore *hs = _highscore_table[_opt.diff_level];
+	HighScore *hs = _highscore_table[_settings.difficulty.diff_level];
 	uint i;
 	uint16 score = p->old_economy[0].performance_history;
 
@@ -1122,7 +1122,7 @@
 	}
 
 	/* Initialize end of game variable (when to show highscore chart) */
-	_patches.ending_year = 2051;
+	_settings.gui.ending_year = 2051;
 }
 
 /* Save/load of players */
--- a/src/querystring_gui.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/querystring_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -17,7 +17,7 @@
 
 	void DrawEditBox(Window *w, int wid);
 	void HandleEditBox(Window *w, int wid);
-	int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont);
+	int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, Window::EventState &state);
 };
 
 struct QueryStringBaseWindow : public Window, public QueryString {
@@ -30,7 +30,7 @@
 
 	void DrawEditBox(int wid);
 	void HandleEditBox(int wid);
-	int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont);
+	int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, EventState &state);
 };
 
 void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok);
--- a/src/rail.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/rail.cpp	Tue May 27 00:50:55 2008 +0000
@@ -207,7 +207,7 @@
 	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
 		const EngineInfo *ei = &e->info;
 
-		if (HasBit(ei->climates, _opt.landscape) &&
+		if (HasBit(ei->climates, _settings.game_creation.landscape) &&
 				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
 			const RailVehicleInfo *rvi = &e->u.rail;
 
--- a/src/rail_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/rail_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -292,7 +292,7 @@
 
 	/* check track/slope combination */
 	if ((f_new == FOUNDATION_INVALID) ||
-	    ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player))
+	    ((f_new != FOUNDATION_NONE) && (!_settings.construction.build_on_slopes || _is_old_ai_player))
 	   ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
 	Foundation f_old = GetRailFoundation(tileh, existing);
@@ -756,7 +756,7 @@
 
 	if (tileh != SLOPE_FLAT && (
 				_is_old_ai_player ||
-				!_patches.build_on_slopes ||
+				!_settings.construction.build_on_slopes ||
 				IsSteepSlope(tileh) ||
 				!CanBuildDepotByTileh(dir, tileh)
 			)) {
@@ -1224,7 +1224,7 @@
 			RailType type = GetRailType(tile);
 
 			/* Converting to the same type or converting 'hidden' elrail -> rail */
-			if (type == totype || (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
+			if (type == totype || (_settings.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
 
 			/* Trying to convert other's rail */
 			if (!CheckTileOwnership(tile)) continue;
@@ -1420,7 +1420,7 @@
 
 static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos)
 {
-	bool side = (_opt.road_side != 0) && _patches.signal_side;
+	bool side = (_settings.vehicle.road_side != 0) && _settings.construction.signal_side;
 	static const Point SignalPositions[2][12] = {
 		{      /* Signals on the left side */
 		/*  LEFT      LEFT      RIGHT     RIGHT     UPPER     UPPER */
@@ -1789,7 +1789,7 @@
 
 			/* adjust ground tile for desert
 			 * don't adjust for snow, because snow in depots looks weird */
-			if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) {
+			if (IsSnowRailGround(ti->tile) && _settings.game_creation.landscape == LT_TROPIC) {
 				if (image != SPR_FLAT_GRASS_TILE) {
 					image += rti->snow_offset; // tile with tracks
 				} else {
@@ -1953,7 +1953,7 @@
 		return;
 	}
 
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_ARCTIC: {
 			uint z;
 			Slope slope = GetTileSlope(tile, &z);
@@ -2173,7 +2173,7 @@
 
 static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
 {
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 	switch (GetRailTileType(tile)) {
 		case RAIL_TILE_NORMAL:
 			td->str = STR_1021_RAILROAD_TRACK;
@@ -2329,7 +2329,7 @@
  */
 static CommandCost TestAutoslopeOnRailTile(TileIndex tile, uint flags, uint z_old, Slope tileh_old, uint z_new, Slope tileh_new, TrackBits rail_bits)
 {
-	if (!_patches.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR;
+	if (!_settings.construction.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR;
 
 	/* Is the slope-rail_bits combination valid in general? I.e. is it save to call GetRailFoundation() ? */
 	if (CmdFailed(CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile))) return CMD_ERROR;
@@ -2405,7 +2405,7 @@
 		/* allow terraforming */
 		return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0);
 	} else {
-		if (_patches.build_on_slopes && AutoslopeEnabled()) {
+		if (_settings.construction.build_on_slopes && AutoslopeEnabled()) {
 			switch (GetRailTileType(tile)) {
 				case RAIL_TILE_WAYPOINT: {
 					CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
--- a/src/rail_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/rail_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -42,33 +42,33 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 
-static RailType _cur_railtype;
-static bool _remove_button_clicked;
-static DiagDirection _build_depot_direction;
-static byte _waypoint_count = 1;
-static byte _cur_waypoint_type;
-static bool _convert_signal_button;       ///< convert signal button in the signal GUI pressed
-static SignalVariant _cur_signal_variant; ///< set the signal variant (for signal GUI)
-static SignalType _cur_signal_type;       ///< set the signal type (for signal GUI)
+static RailType _cur_railtype;               ///< Rail type of the current build-rail toolbar.
+static bool _remove_button_clicked;          ///< Flag whether 'remove' toggle-button is currently enabled
+static DiagDirection _build_depot_direction; ///< Currently selected depot direction
+static byte _waypoint_count = 1;             ///< Number of waypoint types
+static byte _cur_waypoint_type;              ///< Currently selected waypoint type
+static bool _convert_signal_button;          ///< convert signal button in the signal GUI pressed
+static SignalVariant _cur_signal_variant;    ///< set the signal variant (for signal GUI)
+static SignalType _cur_signal_type;          ///< set the signal type (for signal GUI)
 
 static struct {
-	byte orientation;
-	byte numtracks;
-	byte platlength;
-	bool dragdrop;
+	byte orientation;                 ///< Currently selected rail station orientation
+	byte numtracks;                   ///< Currently selected number of tracks in station (if not \c dragdrop )
+	byte platlength;                  ///< Currently selected platform length of station (if not \c dragdrop )
+	bool dragdrop;                    ///< Use drag & drop to place a station
 
-	bool newstations;
-	StationClassIDByte station_class;
-	byte station_type;
-	byte station_count;
+	bool newstations;                 ///< Are custom station definitions available?
+	StationClassIDByte station_class; ///< Currently selected custom station class (if newstations is \c true )
+	byte station_type;                ///< Station type within the currently selected custom station class (if newstations is \c true )
+	byte station_count;               ///< Number of custom stations (if newstations is \c true )
 } _railstation;
 
 
 static void HandleStationPlacement(TileIndex start, TileIndex end);
-static void ShowBuildTrainDepotPicker();
-static void ShowBuildWaypointPicker();
-static void ShowStationBuilder();
-static void ShowSignalBuilder();
+static void ShowBuildTrainDepotPicker(Window *parent);
+static void ShowBuildWaypointPicker(Window *parent);
+static void ShowStationBuilder(Window *parent);
+static void ShowSignalBuilder(Window *parent);
 
 void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
@@ -111,6 +111,12 @@
 	VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL);
 }
 
+/**
+ * Try to add an additional rail-track at the entrance of a depot
+ * @param tile  Tile to use for adding the rail-track
+ * @param extra Track to add
+ * @see CcRailDepot()
+ */
 static void PlaceExtraDepotRail(TileIndex tile, uint16 extra)
 {
 	if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return;
@@ -119,10 +125,11 @@
 	DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_NO_WATER);
 }
 
+/** Additional pieces of track to add at the entrance of a depot. */
 static const uint16 _place_depot_extra[12] = {
-	0x0604, 0x2102, 0x1202, 0x0505,
-	0x2400, 0x2801, 0x1800, 0x1401,
-	0x2203, 0x0904, 0x0A05, 0x1103,
+	0x0604, 0x2102, 0x1202, 0x0505,  // First additional track for directions 0..3
+	0x2400, 0x2801, 0x1800, 0x1401,  // Second additional track
+	0x2203, 0x0904, 0x0A05, 0x1103,  // Third additional track
 };
 
 
@@ -175,7 +182,7 @@
 		VpSetPlaceSizingLimit(-1);
 	} else if (_railstation.dragdrop) {
 		VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION);
-		VpSetPlaceSizingLimit(_patches.station_spread);
+		VpSetPlaceSizingLimit(_settings.station.station_spread);
 	} else {
 		DoCommandP(tile,
 				_railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16) | (_ctrl_pressed << 24),
@@ -220,7 +227,7 @@
 			SB(p1, 7, 1, _convert_signal_button);
 		} else {
 			SB(p1, 3, 1, _ctrl_pressed);
-			SB(p1, 4, 1, (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
+			SB(p1, 4, 1, (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
 			SB(p1, 5, 2, SIGTYPE_NORMAL);
 			SB(p1, 7, 1, 0);
 		}
@@ -235,6 +242,7 @@
 	VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
 }
 
+/** Command callback for building a tunnel */
 void CcBuildRailTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
 	if (success) {
@@ -285,7 +293,7 @@
 };
 
 
-/** Toogles state of the Remove button of Build rail toolbar
+/** Toggles state of the Remove button of Build rail toolbar
  * @param w window the button belongs to
  */
 static void ToggleRailButton_Remove(Window *w)
@@ -316,77 +324,143 @@
 }
 
 
+/**
+ * The "rail N"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_N(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, VHM_RECT, PlaceRail_N);
 }
 
+/**
+ * The "rail NE"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_NE(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_X, GetRailTypeInfo(_cur_railtype)->cursor.rail_swne, VHM_RECT, PlaceRail_NE);
 }
 
+/**
+ * The "rail E"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_E(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_EW, GetRailTypeInfo(_cur_railtype)->cursor.rail_ew, VHM_RECT, PlaceRail_E);
 }
 
+/**
+ * The "rail NW"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_NW(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_Y, GetRailTypeInfo(_cur_railtype)->cursor.rail_nwse, VHM_RECT, PlaceRail_NW);
 }
 
+/**
+ * The "auto-rail"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_AutoRail(Window *w)
 {
 	HandlePlacePushButton(w, RTW_AUTORAIL, GetRailTypeInfo(_cur_railtype)->cursor.autorail, VHM_RAIL, PlaceRail_AutoRail);
 }
 
+/**
+ * The "demolish"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Demolish(Window *w)
 {
 	HandlePlacePushButton(w, RTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea);
 }
 
+/**
+ * The "build depot"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Depot(Window *w)
 {
 	if (HandlePlacePushButton(w, RTW_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, VHM_RECT, PlaceRail_Depot)) {
-		ShowBuildTrainDepotPicker();
+		ShowBuildTrainDepotPicker(w);
 	}
 }
 
+/**
+ * The "build waypoint"-button click proc of the build-rail toolbar.
+ * If there are newGRF waypoints, also open a window to pick the waypoint type.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Waypoint(Window *w)
 {
 	_waypoint_count = GetNumCustomStations(STAT_CLASS_WAYP);
 	if (HandlePlacePushButton(w, RTW_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, VHM_RECT, PlaceRail_Waypoint) &&
 			_waypoint_count > 1) {
-		ShowBuildWaypointPicker();
+		ShowBuildWaypointPicker(w);
 	}
 }
 
+/**
+ * The "build station"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Station(Window *w)
 {
-	if (HandlePlacePushButton(w, RTW_BUILD_STATION, SPR_CURSOR_RAIL_STATION, VHM_RECT, PlaceRail_Station)) ShowStationBuilder();
+	if (HandlePlacePushButton(w, RTW_BUILD_STATION, SPR_CURSOR_RAIL_STATION, VHM_RECT, PlaceRail_Station)) ShowStationBuilder(w);
 }
 
-/** The "build signal"-button proc from BuildRailToolbWndProc() (start ShowSignalBuilder() and/or HandleAutoSignalPlacement()) */
+/**
+ * The "build signal"-button click proc of the build-rail toolbar.
+ * Start ShowSignalBuilder() and/or HandleAutoSignalPlacement().
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_AutoSignals(Window *w)
 {
-	if (_patches.enable_signal_gui != _ctrl_pressed) {
-		if (HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals)) ShowSignalBuilder();
+	if (_settings.gui.enable_signal_gui != _ctrl_pressed) {
+		if (HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals)) ShowSignalBuilder(w);
 	} else {
 		HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals);
 	}
 }
 
+/**
+ * The "build bridge"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Bridge(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, VHM_RECT, PlaceRail_Bridge);
 }
 
+/**
+ * The "build tunnel"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Tunnel(Window *w)
 {
 	HandlePlacePushButton(w, RTW_BUILD_TUNNEL, GetRailTypeInfo(_cur_railtype)->cursor.tunnel, VHM_SPECIAL, PlaceRail_Tunnel);
 }
 
+/**
+ * The "remove"-button click proc of the build-rail toolbar.
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Remove(Window *w)
 {
 	if (w->IsWidgetDisabled(RTW_REMOVE)) return;
@@ -410,12 +484,18 @@
 				if (_railstation.orientation == 0) Swap(x, y);
 				SetTileSelectSize(x, y);
 			} else {
-				VpSetPlaceSizingLimit(_patches.station_spread);
+				VpSetPlaceSizingLimit(_settings.station.station_spread);
 			}
 		}
 	}
 }
 
+/**
+ * The "convert-rail"-button click proc of the build-rail toolbar.
+ * Switches to 'convert-rail' mode
+ * @param w Build-rail toolbar window
+ * @see BuildRailToolbWndProc()
+ */
 static void BuildRailClick_Convert(Window *w)
 {
 	HandlePlacePushButton(w, RTW_CONVERT_RAIL, GetRailTypeInfo(_cur_railtype)->cursor.convert, VHM_RECT, PlaceRail_ConvertRail);
@@ -467,15 +547,15 @@
 		SB(p2,  3, 1, 0);
 		SB(p2,  4, 1, _cur_signal_variant);
 		SB(p2,  6, 1, _ctrl_pressed);
-		SB(p2, 24, 8, _patches.drag_signals_density);
+		SB(p2, 24, 8, _settings.gui.drag_signals_density);
 	} else {
 		SB(p2,  3, 1, 0);
-		SB(p2,  4, 1, (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
+		SB(p2,  4, 1, (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
 		SB(p2,  6, 1, _ctrl_pressed);
-		SB(p2, 24, 8, _patches.drag_signals_density);
+		SB(p2, 24, 8, _settings.gui.drag_signals_density);
 	}
 
-	/* _patches.drag_signals_density is given as a parameter such that each user
+	/* _settings.gui.drag_signals_density is given as a parameter such that each user
 	 * in a network game can specify his/her own signal density */
 	DoCommandP(
 		TileVirtXY(thd->selstart.x, thd->selstart.y),
@@ -526,90 +606,105 @@
 };
 
 
-static void UpdateRemoveWidgetStatus(Window *w, int clicked_widget)
-{
-	switch (clicked_widget) {
-		case RTW_REMOVE:
-			/* If it is the removal button that has been clicked, do nothing,
-			 * as it is up to the other buttons to drive removal status */
-			return;
-			break;
-		case RTW_BUILD_NS:
-		case RTW_BUILD_X:
-		case RTW_BUILD_EW:
-		case RTW_BUILD_Y:
-		case RTW_AUTORAIL:
-		case RTW_BUILD_WAYPOINT:
-		case RTW_BUILD_STATION:
-		case RTW_BUILD_SIGNALS:
-			/* Removal button is enabled only if the rail/signal/waypoint/station
-			 * button is still lowered.  Once raised, it has to be disabled */
-			w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget));
-			break;
-
-		default:
-			/* When any other buttons than rail/signal/waypoint/station, raise and
-			 * disable the removal button */
-			w->DisableWidget(RTW_REMOVE);
-			w->RaiseWidget(RTW_REMOVE);
-			break;
-	}
-}
+/**
+ * Based on the widget clicked, update the status of the 'remove' button.
+ * @param w              Rail toolbar window
+ * @param clicked_widget Widget clicked in the toolbar
+ */
+struct BuildRailToolbarWindow : Window {
+	BuildRailToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->DisableWidget(RTW_REMOVE);
 
-/**
- * Railway toolbar window event definition
- *
- * @param w window pointer
- * @param e event been triggered
- */
-static void BuildRailToolbWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_CREATE: w->DisableWidget(RTW_REMOVE); break;
-
-	case WE_PAINT: w->DrawWidgets(); break;
+		this->FindWindowPlacementAndResize(desc);
+		if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
+	}
 
-	case WE_CLICK:
-		if (e->we.click.widget >= RTW_BUILD_NS) {
-			_remove_button_clicked = false;
-			_build_railroad_button_proc[e->we.click.widget - RTW_BUILD_NS](w);
+	~BuildRailToolbarWindow()
+	{
+		if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
+	}
+
+	void UpdateRemoveWidgetStatus(int clicked_widget)
+	{
+		switch (clicked_widget) {
+			case RTW_REMOVE:
+				/* If it is the removal button that has been clicked, do nothing,
+				* as it is up to the other buttons to drive removal status */
+				return;
+				break;
+			case RTW_BUILD_NS:
+			case RTW_BUILD_X:
+			case RTW_BUILD_EW:
+			case RTW_BUILD_Y:
+			case RTW_AUTORAIL:
+			case RTW_BUILD_WAYPOINT:
+			case RTW_BUILD_STATION:
+			case RTW_BUILD_SIGNALS:
+				/* Removal button is enabled only if the rail/signal/waypoint/station
+				* button is still lowered.  Once raised, it has to be disabled */
+				this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget));
+				break;
+
+			default:
+				/* When any other buttons than rail/signal/waypoint/station, raise and
+				* disable the removal button */
+				this->DisableWidget(RTW_REMOVE);
+				this->RaiseWidget(RTW_REMOVE);
+				break;
 		}
-		UpdateRemoveWidgetStatus(w, e->we.click.widget);
-		if (_ctrl_pressed) RailToolbar_CtrlChanged(w);
-		break;
+	}
 
-	case WE_KEYPRESS:
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget >= RTW_BUILD_NS) {
+			_remove_button_clicked = false;
+			_build_railroad_button_proc[widget - RTW_BUILD_NS](this);
+		}
+		this->UpdateRemoveWidgetStatus(widget);
+		if (_ctrl_pressed) RailToolbar_CtrlChanged(this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		EventState state = ES_NOT_HANDLED;
 		for (uint8 i = 0; i != lengthof(_rail_keycodes); i++) {
-			if (e->we.keypress.keycode == _rail_keycodes[i]) {
-				e->we.keypress.cont = false;
+			if (keycode == _rail_keycodes[i]) {
 				_remove_button_clicked = false;
-				_build_railroad_button_proc[i](w);
-				UpdateRemoveWidgetStatus(w, i + RTW_BUILD_NS);
-				if (_ctrl_pressed) RailToolbar_CtrlChanged(w);
+				_build_railroad_button_proc[i](this);
+				this->UpdateRemoveWidgetStatus(i + RTW_BUILD_NS);
+				if (_ctrl_pressed) RailToolbar_CtrlChanged(this);
+				state = ES_HANDLED;
 				break;
 			}
 		}
 		MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection
-		break;
-
-	case WE_PLACE_OBJ:
-		_place_proc(e->we.place.tile);
-		return;
-
-	case WE_PLACE_DRAG: {
-		/* no dragging if you have pressed the convert button */
-		if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && w->IsWidgetLowered(RTW_BUILD_SIGNALS)) return;
-
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-		return;
+		return state;
 	}
 
-	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1) {
-			TileIndex start_tile = e->we.place.starttile;
-			TileIndex end_tile = e->we.place.tile;
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
 
-			switch (e->we.place.select_proc) {
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		/* no dragging if you have pressed the convert button */
+		if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && this->IsWidgetLowered(RTW_BUILD_SIGNALS)) return;
+
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				default: NOT_REACHED();
 				case DDSP_BUILD_BRIDGE:
 					ResetObjectToPlace();
 					ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
@@ -624,7 +719,7 @@
 					break;
 
 				case DDSP_DEMOLISH_AREA:
-					GUIPlaceProcDragXY(e);
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
 
 				case DDSP_CONVERT_RAIL:
@@ -642,39 +737,36 @@
 
 				case DDSP_PLACE_RAIL_NE:
 				case DDSP_PLACE_RAIL_NW:
-					DoRailroadTrack(e->we.place.select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
+					DoRailroadTrack(select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
 					break;
 			}
 		}
-		break;
+	}
 
-	case WE_ABORT_PLACE_OBJ:
-		w->RaiseButtons();
-		w->DisableWidget(RTW_REMOVE);
-		w->InvalidateWidget(RTW_REMOVE);
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
+		this->DisableWidget(RTW_REMOVE);
+		this->InvalidateWidget(RTW_REMOVE);
 
 		delete FindWindowById(WC_BUILD_SIGNAL, 0);
 		delete FindWindowById(WC_BUILD_STATION, 0);
 		delete FindWindowById(WC_BUILD_DEPOT, 0);
-		break;
+	}
 
-	case WE_PLACE_PRESIZE: {
-		TileIndex tile = e->we.place.tile;
-
+	virtual void OnPlacePresize(Point pt, TileIndex tile)
+	{
 		DoCommand(tile, 0, 0, DC_AUTO, CMD_BUILD_TUNNEL);
 		VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
-	} break;
-
-	case WE_DESTROY:
-		if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
-		break;
+	}
 
-	case WE_CTRL_CHANGED:
+	virtual EventState OnCTRLStateChange()
+	{
 		/* do not toggle Remove button by Ctrl when placing station */
-		if (!w->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(w)) e->we.ctrl.cont = false;
-		break;
+		if (!this->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(this)) return ES_HANDLED;
+		return ES_NOT_HANDLED;
 	}
-}
+};
 
 /** Widget definition for the rail toolbar */
 static const Widget _build_rail_widgets[] = {
@@ -709,7 +801,6 @@
 	WC_BUILD_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_build_rail_widgets,
-	BuildRailToolbWndProc
 };
 
 
@@ -733,27 +824,37 @@
 	w->widget[RTW_BUILD_TUNNEL].data = rti->gui_sprites.build_tunnel;
 }
 
+/**
+ * Open the build rail toolbar window for a specific rail type.
+ * The window may be opened in the 'normal' way by clicking at the rail icon in
+ * the main toolbar, or by means of selecting one of the functions of the
+ * toolbar. In the latter case, the corresponding widget is also selected.
+ *
+ * If the terraform toolbar is linked to the toolbar, that window is also opened.
+ *
+ * @param railtype Rail type to open the window for
+ * @param button   Widget clicked (\c -1 means no button clicked)
+ */
 void ShowBuildRailToolbar(RailType railtype, int button)
 {
-	Window *w;
+	BuildRailToolbarWindow *w;
 
 	if (!IsValidPlayer(_current_player)) return;
 	if (!ValParamRailtype(railtype)) return;
 
 	// don't recreate the window if we're clicking on a button and the window exists.
-	if (button < 0 || !(w = FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL))) {
+	if (button < 0 || !(w = dynamic_cast<BuildRailToolbarWindow*>(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL)))) {
 		DeleteWindowByClass(WC_BUILD_TOOLBAR);
 		_cur_railtype = railtype;
-		w = AllocateWindowDescFront<Window>(&_build_rail_desc, TRANSPORT_RAIL);
+		w = AllocateWindowDescFront<BuildRailToolbarWindow>(&_build_rail_desc, TRANSPORT_RAIL);
 		SetupRailToolbar(railtype, w);
 	}
 
 	_remove_button_clicked = false;
 	if (w != NULL && button >= RTW_CLOSEBOX) {
 		_build_railroad_button_proc[button](w);
-		UpdateRemoveWidgetStatus(w, button + RTW_BUILD_NS);
+		w->UpdateRemoveWidgetStatus(button + RTW_BUILD_NS);
 	}
-	if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
 }
 
 /* TODO: For custom stations, respect their allowed platforms/lengths bitmasks!
@@ -818,11 +919,16 @@
 		BRSW_NEWST_SCROLL
 	};
 
-	/* Check if the currently selected station size is allowed */
+	/**
+	 * Verify whether the currently selected station size is allowed after selecting a new station class/type.
+	 * If not, change the station size variables ( _railstation.numtracks and _railstation.platlength ).
+	 * @param statspec Specification of the new station class/type
+	 */
 	void CheckSelectedSize(const StationSpec *statspec)
 	{
 		if (statspec == NULL || _railstation.dragdrop) return;
 
+		/* If current number of tracks is not allowed, make it as big as possible (which is always less than currently selected) */
 		if (HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) {
 			this->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
 			_railstation.numtracks = 1;
@@ -842,6 +948,7 @@
 		}
 	}
 
+	/** Build a dropdown list of available station classes */
 	static DropDownList *BuildStationClassDropDown()
 	{
 		DropDownList *list = new DropDownList();
@@ -853,9 +960,14 @@
 
 		return list;
 	}
+/**
+ * Window event handler of station build window.
+ * @param w Staion build window
+ * @param e Window event to handle
+ */
 
 public:
-	BuildRailStationWindow(const WindowDesc *desc, bool newstation) : PickerWindowBase(desc)
+	BuildRailStationWindow(const WindowDesc *desc, Window *parent, bool newstation) : PickerWindowBase(desc, parent)
 	{
 		this->LowerWidget(_railstation.orientation + BRSW_PLATFORM_DIR_X);
 		if (_railstation.dragdrop) {
@@ -899,13 +1011,13 @@
 				SetTileSelectSize(x, y);
 		}
 
-		int rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
+		int rad = (_settings.station.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
 
 		if (_station_show_coverage)
 			SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
 
 		for (uint bits = 0; bits < 7; bits++) {
-			bool disable = bits >= _patches.station_spread;
+			bool disable = bits >= _settings.station.station_spread;
 			if (statspec == NULL) {
 				this->SetWidgetDisabledState(bits + BRSW_PLATFORM_NUM_1, disable);
 				this->SetWidgetDisabledState(bits + BRSW_PLATFORM_LEN_1, disable);
@@ -1207,28 +1319,29 @@
 {   WIDGETS_END},
 };
 
+/** High level window description of the default station-build window */
 static const WindowDesc _station_builder_desc = {
 	WDP_AUTO, WDP_AUTO, 148, 200, 148, 200,
 	WC_BUILD_STATION, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_station_builder_widgets,
-	NULL
 };
 
+/** High level window description of the newGRF station-build window */
 static const WindowDesc _newstation_builder_desc = {
 	WDP_AUTO, WDP_AUTO, 148, 290, 148, 290,
 	WC_BUILD_STATION, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_newstation_builder_widgets,
-	NULL
 };
 
-static void ShowStationBuilder()
+/** Open station build window */
+static void ShowStationBuilder(Window *parent)
 {
 	if (GetNumStationClasses() <= 2 && GetNumCustomStations(STAT_CLASS_DFLT) == 1) {
-		new BuildRailStationWindow(&_station_builder_desc, false);
+		new BuildRailStationWindow(&_station_builder_desc, parent, false);
 	} else {
-		new BuildRailStationWindow(&_newstation_builder_desc, true);
+		new BuildRailStationWindow(&_newstation_builder_desc, parent, true);
 	}
 }
 
@@ -1269,7 +1382,7 @@
 	}
 
 public:
-	BuildSignalWindow(const WindowDesc *desc) : PickerWindowBase(desc)
+	BuildSignalWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
 	{
 		this->FindWindowPlacementAndResize(desc);
 	};
@@ -1280,8 +1393,8 @@
 
 		this->SetWidgetLoweredState(BSW_CONVERT, _convert_signal_button);
 
-		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _patches.drag_signals_density == 1);
-		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _patches.drag_signals_density == 20);
+		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _settings.gui.drag_signals_density == 1);
+		this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _settings.gui.drag_signals_density == 20);
 
 		this->DrawWidgets();
 
@@ -1296,7 +1409,7 @@
 		this->DrawSignalSprite(BSW_ELECTRIC_COMBO,  SPR_IMG_SIGNAL_ELECTRIC_COMBO,  -2,  6);
 
 		/* Draw dragging signal density value in the BSW_DRAG_SIGNALS_DENSITY widget */
-		SetDParam(0, _patches.drag_signals_density);
+		SetDParam(0, _settings.gui.drag_signals_density);
 		DrawStringCentered(this->widget[BSW_DRAG_SIGNALS_DENSITY].left + (this->widget[BSW_DRAG_SIGNALS_DENSITY].right -
 				this->widget[BSW_DRAG_SIGNALS_DENSITY].left) / 2 + 1,
 				this->widget[BSW_DRAG_SIGNALS_DENSITY].top + 2, STR_JUST_INT, TC_ORANGE);
@@ -1324,15 +1437,15 @@
 				break;
 
 			case BSW_DRAG_SIGNALS_DENSITY_DECREASE:
-				if (_patches.drag_signals_density > 1) {
-					_patches.drag_signals_density--;
+				if (_settings.gui.drag_signals_density > 1) {
+					_settings.gui.drag_signals_density--;
 					SetWindowDirty(FindWindowById(WC_GAME_OPTIONS, 0));
 				}
 				break;
 
 			case BSW_DRAG_SIGNALS_DENSITY_INCREASE:
-				if (_patches.drag_signals_density < 20) {
-					_patches.drag_signals_density++;
+				if (_settings.gui.drag_signals_density < 20) {
+					_settings.gui.drag_signals_density++;
 					SetWindowDirty(FindWindowById(WC_GAME_OPTIONS, 0));
 				}
 				break;
@@ -1373,15 +1486,14 @@
 	WC_BUILD_SIGNAL, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_signal_builder_widgets,
-	NULL
 };
 
 /**
  * Open the signal selection window
  */
-static void ShowSignalBuilder()
+static void ShowSignalBuilder(Window *parent)
 {
-	new BuildSignalWindow(&_signal_builder_desc);
+	new BuildSignalWindow(&_signal_builder_desc, parent);
 }
 
 struct BuildRailDepotWindow : public PickerWindowBase {
@@ -1398,7 +1510,7 @@
 	};
 
 public:
-	BuildRailDepotWindow(const WindowDesc *desc) : PickerWindowBase(desc)
+	BuildRailDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
 	{
 		this->LowerWidget(_build_depot_direction + BRDW_DEPOT_NE);
 		this->FindWindowPlacementAndResize(desc);
@@ -1448,12 +1560,11 @@
 	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_depot_widgets,
-	NULL
 };
 
-static void ShowBuildTrainDepotPicker()
+static void ShowBuildTrainDepotPicker(Window *parent)
 {
-	new BuildRailDepotWindow(&_build_depot_desc);
+	new BuildRailDepotWindow(&_build_depot_desc, parent);
 }
 
 struct BuildRailWaypointWindow : PickerWindowBase {
@@ -1472,7 +1583,7 @@
 	};
 
 public:
-	BuildRailWaypointWindow(const WindowDesc *desc) : PickerWindowBase(desc)
+	BuildRailWaypointWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
 	{
 		this->hscroll.cap = 5;
 		this->hscroll.count = _waypoint_count;
@@ -1550,15 +1661,16 @@
 	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_waypoint_widgets,
-	NULL
 };
 
-static void ShowBuildWaypointPicker()
+static void ShowBuildWaypointPicker(Window *parent)
 {
-	new BuildRailWaypointWindow(&_build_waypoint_desc);
+	new BuildRailWaypointWindow(&_build_waypoint_desc, parent);
 }
 
-
+/**
+ * Initialize rail building GUI settings
+ */
 void InitializeRailGui()
 {
 	_build_depot_direction = DIAGDIR_NW;
@@ -1567,6 +1679,10 @@
 	_railstation.dragdrop = true;
 }
 
+/**
+ * Re-initialize rail-build toolbar after toggling support for electric trains
+ * @param disable Boolean whether electric trains are disabled (removed from the game)
+ */
 void ReinitGuiAfterToggleElrail(bool disable)
 {
 	extern RailType _last_built_railtype;
@@ -1582,12 +1698,13 @@
 	MarkWholeScreenDirty();
 }
 
+/** Set the initial (default) railtype to use */
 static void SetDefaultRailGui()
 {
 	if (_local_player == PLAYER_SPECTATOR || !IsValidPlayer(_local_player)) return;
 
 	extern RailType _last_built_railtype;
-	RailType rt = (RailType)_patches.default_rail_type;
+	RailType rt = (RailType)_settings.gui.default_rail_type;
 	if (rt >= RAILTYPE_END) {
 		if (rt == RAILTYPE_END + 2) {
 			/* Find the most used rail type */
@@ -1639,7 +1756,7 @@
  */
 int32 ResetSignalVariant(int32 = 0)
 {
-	SignalVariant new_variant = (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
+	SignalVariant new_variant = (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
 
 	if (new_variant != _cur_signal_variant) {
 		Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
--- a/src/road.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/road.cpp	Tue May 27 00:50:55 2008 +0000
@@ -103,7 +103,7 @@
 	FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
 		const EngineInfo *ei = &e->info;
 
-		if (HasBit(ei->climates, _opt.landscape) &&
+		if (HasBit(ei->climates, _settings.game_creation.landscape) &&
 				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
 			SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
 		}
--- a/src/road_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/road_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -43,6 +43,41 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 
+
+bool RoadVehiclesAreBuilt()
+{
+	const Vehicle* v;
+
+	FOR_ALL_VEHICLES(v) {
+		if (v->type == VEH_ROAD) return true;
+	}
+	return false;
+}
+
+/**
+ * Change the side of the road vehicles drive on (server only).
+ * @param tile unused
+ * @param flags operation to perform
+ * @param p1 the side of the road; 0 = left side and 1 = right side
+ * @param p2 unused
+ */
+CommandCost CmdSetRoadDriveSide(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	/* Check boundaries and you can only change this if NO vehicles have been built yet,
+	 * except in the intro-menu where of course it's always possible to do so. */
+	if (p1 > 1 || (_game_mode != GM_MENU && RoadVehiclesAreBuilt())) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		if (_game_mode == GM_MENU) {
+			_settings.vehicle.road_side = p1;
+		} else {
+			_settings.vehicle.road_side = p1;
+		}
+		InvalidateWindow(WC_GAME_OPTIONS, 0);
+	}
+	return CommandCost();
+}
+
 #define M(x) (1 << (x))
 /* Level crossings may only be built on these slopes */
 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT));
@@ -99,10 +134,18 @@
 
 Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
 
-bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
+/**
+ * Is it allowed to remove the given road bits from the given tile?
+ * @param tile      the tile to remove the road from
+ * @param remove    the roadbits that are going to be removed
+ * @param owner     the actual owner of the roadbits of the tile
+ * @param rt        the road type to remove the bits from
+ * @param flags     command flags
+ * @param town_check Shall the town rating checked/affected
+ * @return true when it is allowed to remove the road bits
+ */
+bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, uint32 flags, bool town_check)
 {
-	*edge_road = true;
-
 	if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
 
 	/* Water can always flood and towns can always remove "normal" road pieces.
@@ -115,8 +158,17 @@
 	 * by a town */
 	if (owner != OWNER_TOWN) return (owner == OWNER_NONE) || CheckOwnership(owner);
 
+	if (!town_check) return true;
+
 	if (_cheats.magic_bulldozer.value) return true;
 
+	Town *t = ClosestTownFromTile(tile, UINT_MAX);
+	if (t == NULL) return true;
+
+	/* 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 false;
+
 	/* Get a bitmask of which neighbouring roads has a tile */
 	RoadBits n = ROAD_NONE;
 	RoadBits present = GetAnyRoadBits(tile, rt);
@@ -125,28 +177,23 @@
 	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile,  1,  0), rt) & ROAD_NE) n |= ROAD_SW;
 	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile,  0, -1), rt) & ROAD_SE) n |= ROAD_NW;
 
+	int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE;
 	/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
 	 * then allow it */
 	if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) {
-		*edge_road = false;
 		/* you can remove all kind of roads with extra dynamite */
-		if (_patches.extra_dynamite) return true;
-
-		const Town *t = ClosestTownFromTile(tile, (uint)-1);
-
-		SetDParam(0, t->index);
-		_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
-		return false;
+		if (!_settings.construction.extra_dynamite) {
+			SetDParam(0, t->index);
+			_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
+			return false;
+		}
+		rating_decrease = RATING_ROAD_DOWN_STEP_INNER;
 	}
+	ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM);
 
 	return true;
 }
 
-static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
-{
-	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
-}
-
 
 /** Delete a piece of road.
  * @param tile tile where to remove road from
@@ -157,22 +204,20 @@
  */
 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};
+	RoadTypes rts = GetRoadTypes(tile);
+	/* The tile doesn't have the given road type */
+	if (!HasBit(rts, rt)) return CMD_ERROR;
 
-	/* true if the roadpiece was always removeable,
-	 * false if it was a center piece. Affects town ratings drop */
-	bool edge_road;
+	bool town_road_under_stop = false;
 
-	Town *t = NULL;
 	switch (GetTileType(tile)) {
 		case MP_ROAD:
-			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 			break;
 
 		case MP_STATION:
 			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
+			if (rt == ROADTYPE_ROAD) town_road_under_stop = GetStopBuiltOnTownRoad(tile);
 			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 			break;
 
@@ -185,15 +230,7 @@
 			return CMD_ERROR;
 	}
 
-	RoadTypes rts = GetRoadTypes(tile);
-	/* The tile doesn't have the given road type */
-	if (!HasBit(rts, rt)) return CMD_ERROR;
-
-	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
-
-	/* check if you're allowed to remove the street owned by a town
-	 * removal allowance depends on difficulty setting */
-	if (town_check && !CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
+	if (!CheckAllowRemoveRoad(tile, pieces, town_road_under_stop ? OWNER_TOWN : GetRoadOwner(tile, rt), rt, flags, town_check)) return CMD_ERROR;
 
 	if (!IsTileType(tile, MP_ROAD)) {
 		/* If it's the last roadtype, just clear the whole tile */
@@ -242,7 +279,7 @@
 			 * @li if build on slopes is disabled */
 			if (IsSteepSlope(tileh) || (IsStraightRoad(other) &&
 					(other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
-					(tileh != SLOPE_FLAT && !_patches.build_on_slopes)) {
+					(tileh != SLOPE_FLAT && !_settings.construction.build_on_slopes)) {
 				pieces |= MirrorRoadBits(pieces);
 			}
 
@@ -259,7 +296,6 @@
 				return CMD_ERROR;
 			}
 
-			if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
 			if (flags & DC_EXEC) {
 				if (HasRoadWorks(tile)) {
 					/* flooding tile with road works, don't forget to remove the effect vehicle too */
@@ -305,10 +341,6 @@
 			 * we can't draw the crossing without trambits ;) */
 			if (rt == ROADTYPE_ROAD && HasTileRoadType(tile, ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR;
 
-			if (rt == ROADTYPE_ROAD) {
-				if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
-			}
-
 			if (flags & DC_EXEC) {
 				RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
 				if (rts == ROADTYPES_NONE) {
@@ -387,7 +419,7 @@
 	RoadBits type_bits = existing | *pieces;
 
 	/* Roads on slopes */
-	if (_patches.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
+	if (_settings.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) {
 
 		/* If we add leveling we've got to pay for it */
 		if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
@@ -407,7 +439,7 @@
 		if (IsSlopeWithOneCornerRaised(tileh)) {
 
 			/* Prevent build on slopes if it isn't allowed */
-			if (_patches.build_on_slopes) {
+			if (_settings.construction.build_on_slopes) {
 
 				/* If we add foundation we've got to pay for it */
 				if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
@@ -470,7 +502,7 @@
 					}
 					if ((existing & pieces) == pieces) {
 						/* We only want to set the (dis)allowed road directions */
-						if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && GetRoadOwner(tile, ROADTYPE_ROAD) == _current_player) {
+						if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && IsRoadOwner(tile, ROADTYPE_ROAD, _current_player)) {
 							if (crossing) return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
 
 							if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
@@ -562,7 +594,7 @@
 		CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits);
 		/* Return an error if we need to build a foundation (ret != 0) but the
 		 * current patch-setting is turned off (or stupid AI@work) */
-		if (CmdFailed(ret) || (ret.GetCost() != 0 && !_patches.build_on_slopes)) {
+		if (CmdFailed(ret) || (ret.GetCost() != 0 && !_settings.construction.build_on_slopes)) {
 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 		}
 		cost.AddCost(ret);
@@ -628,6 +660,7 @@
 
 			case MP_STATION:
 				SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
+				if (IsDriveThroughStopTile(tile) && rt == ROADTYPE_ROAD) SetStopBuiltOnTownRoad(tile, false);
 				break;
 
 			default:
@@ -816,7 +849,7 @@
 
 	Slope tileh = GetTileSlope(tile, NULL);
 	if (tileh != SLOPE_FLAT && (
-				!_patches.build_on_slopes ||
+				!_settings.construction.build_on_slopes ||
 				IsSteepSlope(tileh) ||
 				!CanBuildDepotByTileh(dir, tileh)
 			)) {
@@ -863,7 +896,7 @@
 			/* Clear the road if only one piece is on the tile OR the AI tries
 			 * to clear town road OR we are not using the DC_AUTO flag */
 			if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) ||
-			    ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) ||
+			    ((flags & DC_AI_BUILDING) && GetOtherRoadBits(tile, ROADTYPE_ROAD) == ROAD_NONE && IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) ||
 			    !(flags & DC_AUTO)
 				) {
 				RoadTypes rts = GetRoadTypes(tile);
@@ -967,7 +1000,7 @@
 static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside)
 {
 	return (IsOnSnow(tile) &&
-			!(_opt.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
+			!(_settings.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) &&
 				roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS));
 }
 
@@ -1258,7 +1291,7 @@
 
 static void TileLoop_Road(TileIndex tile)
 {
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_ARCTIC:
 			if (IsOnSnow(tile) != (GetTileZ(tile) > GetSnowLine())) {
 				ToggleSnow(tile);
@@ -1304,7 +1337,7 @@
 
 		{
 			/* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
-			const Roadside* new_rs = (_opt.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp];
+			const Roadside* new_rs = (_settings.game_creation.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp];
 			Roadside cur_rs = GetRoadside(tile);
 
 			/* We have our desired type, do nothing */
@@ -1326,7 +1359,7 @@
 	} else if (IncreaseRoadWorksCounter(tile)) {
 		TerminateRoadWorks(tile);
 
-		if (_patches.mod_road_rebuild) {
+		if (_settings.economy.mod_road_rebuild) {
 			/* Generate a nicer town surface */
 			const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
 			const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
@@ -1415,11 +1448,53 @@
 
 static void GetTileDesc_Road(TileIndex tile, TileDesc *td)
 {
-	td->owner = GetTileOwner(tile);
+	Owner rail_owner = INVALID_OWNER;
+	Owner road_owner = INVALID_OWNER;
+	Owner tram_owner = INVALID_OWNER;
+
 	switch (GetRoadTileType(tile)) {
-		case ROAD_TILE_CROSSING: td->str = STR_1818_ROAD_RAIL_LEVEL_CROSSING; break;
-		case ROAD_TILE_DEPOT: td->str = STR_1817_ROAD_VEHICLE_DEPOT; break;
-		default: td->str = _road_tile_strings[GetRoadside(tile)]; break;
+		case ROAD_TILE_CROSSING: {
+			td->str = STR_1818_ROAD_RAIL_LEVEL_CROSSING;
+			RoadTypes rts = GetRoadTypes(tile);
+			rail_owner = GetTileOwner(tile);
+			if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
+			if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
+			break;
+		}
+
+		case ROAD_TILE_DEPOT:
+			td->str = STR_1817_ROAD_VEHICLE_DEPOT;
+			road_owner = GetTileOwner(tile); // Tile has only one owner, roadtype does not matter
+			break;
+
+		default: {
+			RoadTypes rts = GetRoadTypes(tile);
+			td->str = (HasBit(rts, ROADTYPE_ROAD) ? _road_tile_strings[GetRoadside(tile)] : STR_TRAMWAY);
+			if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
+			if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
+			break;
+		}
+	}
+
+	/* Now we have to discover, if the tile has only one owner or many:
+	 *   - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available)
+	 *   - Compare the found owner with the other owners, and test if they differ.
+	 * Note: If road exists it will be the first_owner.
+	 */
+	Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner);
+	bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner);
+
+	if (mixed_owners) {
+		/* Multiple owners */
+		td->owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_RAIL_OWNER);
+		td->owner[0] = rail_owner;
+		td->owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_ROAD_OWNER);
+		td->owner[1] = road_owner;
+		td->owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_TRAM_OWNER);
+		td->owner[2] = tram_owner;
+	} else {
+		/* One to rule them all */
+		td->owner[0] = first_owner;
 	}
 }
 
@@ -1476,9 +1551,7 @@
 	}
 
 	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
-		/* ROADTYPE_ROAD denotes the tile owner, so update it too */
-		if (rt != ROADTYPE_ROAD && !HasTileRoadType(tile, rt)) continue;
-
+		/* Update all roadtypes, no matter if they are present */
 		if (GetRoadOwner(tile, rt) == old_player) {
 			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
 		}
@@ -1497,7 +1570,7 @@
 
 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
-	if (_patches.build_on_slopes && AutoslopeEnabled()) {
+	if (_settings.construction.build_on_slopes && AutoslopeEnabled()) {
 		switch (GetRoadTileType(tile)) {
 			case ROAD_TILE_CROSSING:
 				if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
--- a/src/road_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/road_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -28,8 +28,8 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 
-static void ShowRVStationPicker(RoadStopType rs);
-static void ShowRoadDepotPicker();
+static void ShowRVStationPicker(Window *parent, RoadStopType rs);
+static void ShowRoadDepotPicker(Window *parent);
 
 static bool _remove_button_clicked;
 static bool _one_way_button_clicked;
@@ -324,19 +324,19 @@
 static void BuildRoadClick_Depot(Window *w)
 {
 	if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
-	if (HandlePlacePushButton(w, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, VHM_RECT, PlaceRoad_Depot)) ShowRoadDepotPicker();
+	if (HandlePlacePushButton(w, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, VHM_RECT, PlaceRoad_Depot)) ShowRoadDepotPicker(w);
 }
 
 static void BuildRoadClick_BusStation(Window *w)
 {
 	if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
-	if (HandlePlacePushButton(w, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, VHM_RECT, PlaceRoad_BusStation)) ShowRVStationPicker(ROADSTOP_BUS);
+	if (HandlePlacePushButton(w, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, VHM_RECT, PlaceRoad_BusStation)) ShowRVStationPicker(w, ROADSTOP_BUS);
 }
 
 static void BuildRoadClick_TruckStation(Window *w)
 {
 	if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
-	if (HandlePlacePushButton(w, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, VHM_RECT, PlaceRoad_TruckStation)) ShowRVStationPicker(ROADSTOP_TRUCK);
+	if (HandlePlacePushButton(w, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, VHM_RECT, PlaceRoad_TruckStation)) ShowRVStationPicker(w, ROADSTOP_TRUCK);
 }
 
 /**
@@ -400,217 +400,222 @@
 	'R',
 };
 
-/**
- * Update the remove button lowered state of the road toolbar
- *
- * @param w The toolbar window
- * @param clicked_widget The widget which the player clicked just now
- */
-static void UpdateOptionWidgetStatus(Window *w, RoadToolbarWidgets clicked_widget)
-{
-	/* The remove and the one way button state is driven
-	 * by the other buttons so they don't act on themselfs.
-	 * Both are only valid if they are able to apply as options. */
-	switch (clicked_widget) {
-		case RTW_REMOVE:
-			w->RaiseWidget(RTW_ONE_WAY);
-			w->InvalidateWidget(RTW_ONE_WAY);
-			break;
-
-		case RTW_ONE_WAY:
-			w->RaiseWidget(RTW_REMOVE);
-			w->InvalidateWidget(RTW_REMOVE);
-			break;
-
-		case RTW_BUS_STATION:
-		case RTW_TRUCK_STATION:
-			w->DisableWidget(RTW_ONE_WAY);
-			w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget));
-			break;
+struct BuildRoadToolbarWindow : Window {
+	BuildRoadToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->SetWidgetsDisabledState(true,
+			RTW_REMOVE,
+			RTW_ONE_WAY,
+			WIDGET_LIST_END);
 
-		case RTW_ROAD_X:
-		case RTW_ROAD_Y:
-		case RTW_AUTOROAD:
-			w->SetWidgetsDisabledState(!w->IsWidgetLowered(clicked_widget),
-				RTW_REMOVE,
-				RTW_ONE_WAY,
-				WIDGET_LIST_END);
-			break;
-
-		default:
-			/* When any other buttons than road/station, raise and
-			 * disable the removal button */
-			w->SetWidgetsDisabledState(true,
-				RTW_REMOVE,
-				RTW_ONE_WAY,
-				WIDGET_LIST_END);
-			w->SetWidgetsLoweredState (false,
-				RTW_REMOVE,
-				RTW_ONE_WAY,
-				WIDGET_LIST_END);
-			break;
+		this->FindWindowPlacementAndResize(desc);
+		if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
 	}
-}
 
-static void BuildRoadToolbWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_CREATE:
-			w->SetWidgetsDisabledState(true,
-				RTW_REMOVE,
-				RTW_ONE_WAY,
-				WIDGET_LIST_END);
-			break;
+	~BuildRoadToolbarWindow()
+	{
+		if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
+	}
 
-		case WE_PAINT:
-			w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
-				RTW_DEPOT,
-				RTW_BUS_STATION,
-				RTW_TRUCK_STATION,
-				WIDGET_LIST_END);
-			w->DrawWidgets();
-			break;
+	/**
+	 * Update the remove button lowered state of the road toolbar
+	 *
+	 * @param clicked_widget The widget which the player clicked just now
+	 */
+	void UpdateOptionWidgetStatus(RoadToolbarWidgets clicked_widget)
+	{
+		/* The remove and the one way button state is driven
+		 * by the other buttons so they don't act on themselfs.
+		 * Both are only valid if they are able to apply as options. */
+		switch (clicked_widget) {
+			case RTW_REMOVE:
+				this->RaiseWidget(RTW_ONE_WAY);
+				this->InvalidateWidget(RTW_ONE_WAY);
+				break;
 
-		case WE_CLICK:
-			if (e->we.click.widget >= RTW_ROAD_X) {
+			case RTW_ONE_WAY:
+				this->RaiseWidget(RTW_REMOVE);
+				this->InvalidateWidget(RTW_REMOVE);
+				break;
+
+			case RTW_BUS_STATION:
+			case RTW_TRUCK_STATION:
+				this->DisableWidget(RTW_ONE_WAY);
+				this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget));
+				break;
+
+			case RTW_ROAD_X:
+			case RTW_ROAD_Y:
+			case RTW_AUTOROAD:
+				this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget),
+					RTW_REMOVE,
+					RTW_ONE_WAY,
+					WIDGET_LIST_END);
+				break;
+
+			default:
+				/* When any other buttons than road/station, raise and
+				 * disable the removal button */
+				this->SetWidgetsDisabledState(true,
+					RTW_REMOVE,
+					RTW_ONE_WAY,
+					WIDGET_LIST_END);
+				this->SetWidgetsLoweredState (false,
+					RTW_REMOVE,
+					RTW_ONE_WAY,
+					WIDGET_LIST_END);
+				break;
+		}
+	}
+
+	virtual void OnPaint()
+	{
+		this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
+			RTW_DEPOT,
+			RTW_BUS_STATION,
+			RTW_TRUCK_STATION,
+			WIDGET_LIST_END);
+		this->DrawWidgets();
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget >= RTW_ROAD_X) {
+			_remove_button_clicked = false;
+			_one_way_button_clicked = false;
+			_build_road_button_proc[widget - RTW_ROAD_X](this);
+		}
+		this->UpdateOptionWidgetStatus((RoadToolbarWidgets)widget);
+		if (_ctrl_pressed) RoadToolbar_CtrlChanged(this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		EventState state = ES_NOT_HANDLED;
+		for (uint i = 0; i != lengthof(_road_keycodes); i++) {
+			if (keycode == _road_keycodes[i]) {
 				_remove_button_clicked = false;
 				_one_way_button_clicked = false;
-				_build_road_button_proc[e->we.click.widget - RTW_ROAD_X](w);
+				_build_road_button_proc[i](this);
+				this->UpdateOptionWidgetStatus((RoadToolbarWidgets)(i + RTW_ROAD_X));
+				if (_ctrl_pressed) RoadToolbar_CtrlChanged(this);
+				state = ES_HANDLED;
+				break;
 			}
-			UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)e->we.click.widget);
-			if (_ctrl_pressed) RoadToolbar_CtrlChanged(w);
-			break;
-
-		case WE_KEYPRESS:
-			for (uint i = 0; i != lengthof(_road_keycodes); i++) {
-				if (e->we.keypress.keycode == _road_keycodes[i]) {
-					e->we.keypress.cont = false;
-					_remove_button_clicked = false;
-					_one_way_button_clicked = false;
-					_build_road_button_proc[i](w);
-					UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)(i + RTW_ROAD_X));
-					if (_ctrl_pressed) RoadToolbar_CtrlChanged(w);
-					break;
-				}
-			}
-			MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection
-			break;
-
-		case WE_PLACE_OBJ:
-			_remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
-			_one_way_button_clicked = w->IsWidgetLowered(RTW_ONE_WAY);
-			_place_proc(e->we.place.tile);
-			break;
+		}
+		MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection
+		return state;
+	}
 
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseButtons();
-			w->SetWidgetsDisabledState(true,
-				RTW_REMOVE,
-				RTW_ONE_WAY,
-				WIDGET_LIST_END);
-			w->InvalidateWidget(RTW_REMOVE);
-			w->InvalidateWidget(RTW_ONE_WAY);
-
-			delete FindWindowById(WC_BUS_STATION, 0);
-			delete FindWindowById(WC_TRUCK_STATION, 0);
-			delete FindWindowById(WC_BUILD_DEPOT, 0);
-			break;
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_remove_button_clicked = this->IsWidgetLowered(RTW_REMOVE);
+		_one_way_button_clicked = this->IsWidgetLowered(RTW_ONE_WAY);
+		_place_proc(tile);
+	}
 
-		case WE_PLACE_DRAG:
-			/* Here we update the end tile flags
-			* of the road placement actions.
-			* At first we reset the end halfroad
-			* bits and if needed we set them again. */
-			switch (e->we.place.select_proc) {
-				case DDSP_PLACE_ROAD_X_DIR:
-					_place_road_flag &= ~RF_END_HALFROAD_X;
-					if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
-					break;
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
+		this->SetWidgetsDisabledState(true,
+			RTW_REMOVE,
+			RTW_ONE_WAY,
+			WIDGET_LIST_END);
+		this->InvalidateWidget(RTW_REMOVE);
+		this->InvalidateWidget(RTW_ONE_WAY);
 
-				case DDSP_PLACE_ROAD_Y_DIR:
-					_place_road_flag &= ~RF_END_HALFROAD_Y;
-					if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
+		delete FindWindowById(WC_BUS_STATION, 0);
+		delete FindWindowById(WC_TRUCK_STATION, 0);
+		delete FindWindowById(WC_BUILD_DEPOT, 0);
+	}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		/* Here we update the end tile flags
+		 * of the road placement actions.
+		 * At first we reset the end halfroad
+		 * bits and if needed we set them again. */
+		switch (select_proc) {
+			case DDSP_PLACE_ROAD_X_DIR:
+				_place_road_flag &= ~RF_END_HALFROAD_X;
+				if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
+				break;
+
+			case DDSP_PLACE_ROAD_Y_DIR:
+				_place_road_flag &= ~RF_END_HALFROAD_Y;
+				if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
+				break;
+
+			case DDSP_PLACE_AUTOROAD:
+				_place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
+				if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
+				if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
+
+				/* For autoroad we need to update the
+				 * direction of the road */
+				if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
+						( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
+						(_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
+					/* Set dir = X */
+					_place_road_flag &= ~RF_DIR_Y;
+				} else {
+					/* Set dir = Y */
+					_place_road_flag |= RF_DIR_Y;
+				}
+
+				break;
+
+			default:
+				break;
+		}
+
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				default: NOT_REACHED();
+				case DDSP_BUILD_BRIDGE:
+					ResetObjectToPlace();
+					ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
 					break;
 
-				case DDSP_PLACE_AUTOROAD:
-					_place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
-					if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
-					if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
-
-					/* For autoroad we need to update the
-					* direction of the road */
-					if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
-							( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
-							(_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
-						/* Set dir = X */
-						_place_road_flag &= ~RF_DIR_Y;
-					} else {
-						/* Set dir = Y */
-						_place_road_flag |= RF_DIR_Y;
-					}
-
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
 
-				default:
+				case DDSP_PLACE_ROAD_X_DIR:
+				case DDSP_PLACE_ROAD_Y_DIR:
+				case DDSP_PLACE_AUTOROAD:
+					/* Flag description:
+					* Use the first three bits (0x07) if dir == Y
+					* else use the last 2 bits (X dir has
+					* not the 3rd bit set) */
+					_place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
+
+					DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D,
+						(_ctrl_pressed || _remove_button_clicked) ?
+						CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
+						CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road));
 					break;
 			}
-
-			VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-			return;
-
-		case WE_PLACE_MOUSEUP:
-			if (e->we.place.pt.x != -1) {
-				TileIndex start_tile = e->we.place.starttile;
-				TileIndex end_tile = e->we.place.tile;
-
-				switch (e->we.place.select_proc) {
-					default: NOT_REACHED();
-					case DDSP_BUILD_BRIDGE:
-						ResetObjectToPlace();
-						ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
-						break;
-
-					case DDSP_DEMOLISH_AREA:
-						GUIPlaceProcDragXY(e);
-						break;
+		}
+	}
 
-					case DDSP_PLACE_ROAD_X_DIR:
-					case DDSP_PLACE_ROAD_Y_DIR:
-					case DDSP_PLACE_AUTOROAD:
-						/* Flag description:
-						* Use the first three bits (0x07) if dir == Y
-						* else use the last 2 bits (X dir has
-						* not the 3rd bit set) */
-						_place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
-
-						DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D,
-							(_ctrl_pressed || _remove_button_clicked) ?
-							CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
-							CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road));
-						break;
-				}
-			}
-			break;
+	virtual void OnPlacePresize(Point pt, TileIndex tile)
+	{
+		DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL);
+		VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
+	}
 
-		case WE_PLACE_PRESIZE: {
-			TileIndex tile = e->we.place.tile;
-
-			DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL);
-			VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
-		} break;
-
-		case WE_DESTROY:
-			if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
-			break;
-
-		case WE_CTRL_CHANGED:
-			if (RoadToolbar_CtrlChanged(w)) e->we.ctrl.cont = false;
-			break;
-
-		default:
-			break;
+	virtual EventState OnCTRLStateChange()
+	{
+		if (RoadToolbar_CtrlChanged(this)) return ES_HANDLED;
+		return ES_NOT_HANDLED;
 	}
-}
+};
 
 /** Widget definition of the build road toolbar */
 static const Widget _build_road_widgets[] = {
@@ -638,7 +643,6 @@
 	WC_BUILD_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_build_road_widgets,
-	BuildRoadToolbWndProc
 };
 
 /** Widget definition of the build tram toolbar */
@@ -667,7 +671,6 @@
 	WC_BUILD_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_build_tramway_widgets,
-	BuildRoadToolbWndProc
 };
 
 void ShowBuildRoadToolbar(RoadType roadtype)
@@ -676,8 +679,7 @@
 	_cur_roadtype = roadtype;
 
 	DeleteWindowByClass(WC_BUILD_TOOLBAR);
-	Window *w = AllocateWindowDescFront<Window>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
-	if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
+	AllocateWindowDescFront<BuildRoadToolbarWindow>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
 }
 
 /** Widget definition of the build road toolbar in the scenario editor */
@@ -705,13 +707,12 @@
 	WC_SCEN_BUILD_ROAD, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_build_road_scen_widgets,
-	BuildRoadToolbWndProc
 };
 
 void ShowBuildRoadScenToolbar()
 {
 	_cur_roadtype = ROADTYPE_ROAD;
-	AllocateWindowDescFront<Window>(&_build_road_scen_desc, 0);
+	AllocateWindowDescFront<BuildRoadToolbarWindow>(&_build_road_scen_desc, 0);
 }
 
 struct BuildRoadDepotWindow : public PickerWindowBase {
@@ -728,7 +729,7 @@
 	};
 
 public:
-	BuildRoadDepotWindow(const WindowDesc *desc) : PickerWindowBase(desc)
+	BuildRoadDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
 	{
 		this->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE);
 		if ( _cur_roadtype == ROADTYPE_TRAM) {
@@ -785,12 +786,11 @@
 	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_road_depot_widgets,
-	NULL
 };
 
-static void ShowRoadDepotPicker()
+static void ShowRoadDepotPicker(Window *parent)
 {
-	new BuildRoadDepotWindow(&_build_road_depot_desc);
+	new BuildRoadDepotWindow(&_build_road_depot_desc, parent);
 }
 
 struct BuildRoadStationWindow : public PickerWindowBase {
@@ -812,7 +812,7 @@
 	};
 
 public:
-	BuildRoadStationWindow(const WindowDesc *desc, RoadStopType rs) : PickerWindowBase(desc)
+	BuildRoadStationWindow(const WindowDesc *desc, Window *parent, RoadStopType rs) : PickerWindowBase(desc, parent)
 	{
 		/* Trams don't have non-drivethrough stations */
 		if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
@@ -842,7 +842,7 @@
 			_thd.FSMportMask = NULL;
 
 			if (_station_show_coverage) {
-				int rad = _patches.modified_catchment ? CA_TRUCK /* = CA_BUS */ : CA_UNMODIFIED;
+				int rad = _settings.station.modified_catchment ? CA_TRUCK /* = CA_BUS */ : CA_UNMODIFIED;
 				SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
 			} else {
 				SetTileSelectSize(1, 1);
@@ -931,12 +931,11 @@
 	WC_BUS_STATION, WC_BUILD_TOOLBAR,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_rv_station_picker_widgets,
-	NULL
 };
 
-static void ShowRVStationPicker(RoadStopType rs)
+static void ShowRVStationPicker(Window *parent, RoadStopType rs)
 {
-	new BuildRoadStationWindow(&_rv_station_picker_desc, rs);
+	new BuildRoadStationWindow(&_rv_station_picker_desc, parent, rs);
 }
 
 void InitializeRoadGui()
--- a/src/road_internal.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/road_internal.h	Tue May 27 00:50:55 2008 +0000
@@ -20,11 +20,12 @@
  * @param tile      the tile to remove the road from
  * @param remove    the roadbits that are going to be removed
  * @param owner     the actual owner of the roadbits of the tile
- * @param edge_road are the removed bits from a town?
  * @param rt        the road type to remove the bits from
+ * @param flags     command flags
+ * @param town_check Shall the town rating checked/affected
  * @return true when it is allowed to remove the road bits
  */
-bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt);
+bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, uint32 flags, bool town_check = true);
 
 /**
  * Draw the catenary for tram road bits
--- a/src/road_map.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/road_map.h	Tue May 27 00:50:55 2008 +0000
@@ -187,6 +187,12 @@
 	}
 }
 
+static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o)
+{
+	assert(HasTileRoadType(t, rt));
+	return (GetRoadOwner(t, rt) == o);
+}
+
 /** Which directions are disallowed ? */
 enum DisallowedRoadDirections {
 	DRD_NONE,       ///< None of the directions are disallowed
--- a/src/roadveh_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/roadveh_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -205,7 +205,7 @@
 
 	/* find the first free roadveh id */
 	unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD);
-	if (unit_num > _patches.max_roadveh)
+	if (unit_num > _settings.vehicle.max_roadveh)
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 	if (flags & DC_EXEC) {
@@ -257,7 +257,7 @@
 
 		v->name = NULL;
 
-		v->service_interval = _patches.servint_roadveh;
+		v->service_interval = _settings.vehicle.servint_roadveh;
 
 		v->date_of_last_service = _date;
 		v->build_year = _cur_year;
@@ -280,7 +280,7 @@
 		VehiclePositionChanged(v);
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 		InvalidateWindow(WC_COMPANY, v->owner);
 		if (IsLocalPlayer())
 			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window
@@ -381,7 +381,7 @@
 	if (flags & DC_EXEC) {
 		// Invalidate depot
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 		InvalidateWindow(WC_COMPANY, v->owner);
 		DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 		DeleteDepotHighlightOfVehicle(v);
@@ -419,7 +419,7 @@
 
 static const Depot* FindClosestRoadDepot(const Vehicle* v)
 {
-	switch (_patches.pathfinder_for_roadvehs) {
+	switch (_settings.pf.pathfinder_for_roadvehs) {
 		case VPF_YAPF: /* YAPF */
 			return YapfFindNearestRoadDepot(v);
 
@@ -574,7 +574,7 @@
 
 	DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 
-	RebuildVehicleLists();
+	InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 	InvalidateWindow(WC_COMPANY, v->owner);
 
 	if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
@@ -702,7 +702,7 @@
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
 		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
-			SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ?
+			SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ?
 				SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
 		}
 
@@ -863,7 +863,7 @@
 	/* updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
 		v->cur_speed = spd;
-		if (_patches.vehicle_speed) {
+		if (_settings.gui.vehicle_speed) {
 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 		}
 	}
@@ -1085,7 +1085,7 @@
 				trackdirs = TRACKDIR_BIT_NONE;
 			} else {
 				/* Proper station type, check if there is free loading bay */
-				if (!_patches.roadveh_queue && IsStandardRoadStopTile(tile) &&
+				if (!_settings.pf.roadveh_queue && IsStandardRoadStopTile(tile) &&
 						!GetRoadStopByTile(tile, rstype)->HasFreeBay()) {
 					/* Station is full and RV queuing is off */
 					trackdirs = TRACKDIR_BIT_NONE;
@@ -1124,7 +1124,7 @@
 		return_track(FindFirstBit2x64(trackdirs));
 	}
 
-	switch (_patches.pathfinder_for_roadvehs) {
+	switch (_settings.pf.pathfinder_for_roadvehs) {
 		case VPF_YAPF: { /* YAPF */
 			Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir);
 			if (trackdir != INVALID_TRACKDIR) return_track(trackdir);
@@ -1211,7 +1211,7 @@
 
 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
 {
-	if (_patches.pathfinder_for_roadvehs == VPF_YAPF) {
+	if (_settings.pf.pathfinder_for_roadvehs == VPF_YAPF) {
 		/* use YAPF */
 		return YapfRoadVehDistanceToTile(v, tile);
 	}
@@ -1273,7 +1273,7 @@
 	v->direction = DiagDirToDir(dir);
 
 	Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
-	const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir];
+	const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
 
 	int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
 	int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
@@ -1451,7 +1451,7 @@
 	 * In this case v->u.road.state is masked to give the road stop entry direction. */
 	rd = _road_drive_data[v->u.road.roadtype][(
 		(HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
-		(_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
+		(_settings.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
 
 	if (rd.x & RDE_NEXT_TILE) {
 		TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
@@ -1529,7 +1529,7 @@
 		}
 
 		/* Get position data for first frame on the new tile */
-		rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
+		rdp = _road_drive_data[v->u.road.roadtype][(dir + (_settings.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
 
 		x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
 		y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
@@ -1632,7 +1632,7 @@
 			return false;
 		}
 
-		rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir];
+		rdp = _road_drive_data[v->u.road.roadtype][(_settings.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
 
 		x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
 		y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
@@ -1711,7 +1711,7 @@
 	 * (the station test and stop type test ensure that other vehicles, using the road stop as
 	 * a through route, do not stop) */
 	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) ||
+			_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_settings.vehicle.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.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
 			GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
@@ -1887,7 +1887,7 @@
 static void CheckIfRoadVehNeedsService(Vehicle *v)
 {
 	/* If we already got a slot at a stop, use that FIRST, and go to a depot later */
-	if (v->u.road.slot != NULL || _patches.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
+	if (v->u.road.slot != NULL || _settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
 	if (v->IsInDepot()) {
 		VehicleServiceInDepot(v);
 		return;
@@ -2116,7 +2116,7 @@
 			v->cargo_subtype = new_subtype;
 			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-			RebuildVehicleLists();
+			InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 		}
 
 		if (only_this) break;
--- a/src/saveload.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/saveload.cpp	Tue May 27 00:50:55 2008 +0000
@@ -1534,7 +1534,7 @@
 	SaveFileDone();
 }
 
-static ThreadObject *save_thread;
+static ThreadObject *_save_thread;
 
 /** We have written the whole game into memory, _Savegame_pool, now find
  * and appropiate compressor and start writing to file.
@@ -1604,10 +1604,10 @@
 
 void WaitTillSaved()
 {
-	if (save_thread == NULL) return;
+	if (_save_thread == NULL) return;
 
-	save_thread->Join();
-	save_thread = NULL;
+	_save_thread->Join();
+	_save_thread = NULL;
 }
 
 /**
@@ -1679,7 +1679,7 @@
 
 			SaveFileStart();
 			if (_network_server ||
-						(save_thread = ThreadObject::New(&SaveFileToDiskThread, NULL)) == NULL) {
+						(_save_thread = ThreadObject::New(&SaveFileToDiskThread, NULL)) == NULL) {
 				if (!_network_server) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
 
 				SaveOrLoadResult result = SaveFileToDisk(false);
@@ -1776,7 +1776,7 @@
 	}
 }
 
-/** Do a save when exiting the game (patch option) _patches.autosave_on_exit */
+/** Do a save when exiting the game (patch option) _settings.gui.autosave_on_exit */
 void DoExitSave()
 {
 	SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR);
--- a/src/saveload.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/saveload.h	Tue May 27 00:50:55 2008 +0000
@@ -13,7 +13,7 @@
 
 #define SIZE_MAX ((size_t)-1)
 
-static const uint NEWGRF_AIRPORTS_SAVEGAME = 96;
+static const uint NEWGRF_AIRPORTS_SAVEGAME = 98;
 
 enum SaveOrLoadResult {
 	SL_OK     = 0, ///< completed successfully
--- a/src/settings.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/settings.cpp	Tue May 27 00:50:55 2008 +0000
@@ -28,7 +28,7 @@
 #include "network/network_internal.h"
 #include "settings_internal.h"
 #include "command_func.h"
-#include "console.h"
+#include "console_func.h"
 #include "saveload.h"
 #include "npf.h"
 #include "yapf/yapf.h"
@@ -60,14 +60,12 @@
 #include "sound/sound_driver.hpp"
 #include "music/music_driver.hpp"
 #include "blitter/factory.hpp"
+#include "station_func.h"
 
 #include "table/strings.h"
 
-GameOptions _opt;
-GameOptions _opt_newgame;
-GameOptions *_opt_ptr;
-Patches _patches;
-Patches _patches_newgame;
+Settings _settings;
+Settings _settings_newgame;
 
 struct IniFile;
 struct IniItem;
@@ -332,9 +330,11 @@
 	if (len == 0) len = strlen(name);
 
 	/* does it exist already? */
-	for (group = ini->group; group; group = group->next)
-		if (!memcmp(group->name, name, len) && group->name[len] == 0)
+	for (group = ini->group; group != NULL; group = group->next) {
+		if (!memcmp(group->name, name, len) && group->name[len] == 0) {
 			return group;
+		}
+	}
 
 	/* otherwise make a new one */
 	group = ini_group_alloc(ini, name, len);
@@ -342,14 +342,37 @@
 	return group;
 }
 
+static void ini_removegroup(IniFile *ini, const char *name)
+{
+	size_t len = strlen(name);
+	IniGroup *prev = NULL;
+	IniGroup *group;
+
+	/* does it exist already? */
+	for (group = ini->group; group != NULL; prev = group, group = group->next) {
+		if (memcmp(group->name, name, len) == 0) {
+			break;
+		}
+	}
+
+	if (group == NULL) return;
+
+	if (prev != NULL) {
+		prev->next = prev->next->next;
+	} else {
+		ini->group = ini->group->next;
+	}
+}
+
 /** lookup an item or make a new one */
 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create)
 {
 	IniItem *item;
 	size_t len = strlen(name);
 
-	for (item = group->item; item; item = item->next)
+	for (item = group->item; item != NULL; item = item->next) {
 		if (strcmp(item->name, name) == 0) return item;
+	}
 
 	if (!create) return NULL;
 
@@ -718,7 +741,7 @@
 
 		if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue;
 
-		/* XXX - wtf is this?? (group override?) */
+		/* For patches.xx.yy load the settings from [xx] yy = ? */
 		s = strchr(sdb->name, '.');
 		if (s != NULL) {
 			group = ini_getgroup(ini, sdb->name, s - sdb->name);
@@ -729,8 +752,20 @@
 		}
 
 		item = ini_getitem(group, s, false);
+		if (item == NULL && group != group_def) {
+			/* For patches.xx.yy load the settings from [patches] yy = ? in case the previous
+			 * did not exist (e.g. loading old config files with a [patches] section */
+			item = ini_getitem(group_def, s, false);
+		}
+		if (item == NULL) {
+			/* For patches.xx.zz.yy load the settings from [zz] yy = ? in case the previous
+			 * did not exist (e.g. loading old config files with a [yapf] section */
+			const char *sc = strchr(s, '.');
+			if (sc != NULL) item = ini_getitem(ini_getgroup(ini, s, sc - s), sc + 1, false);
+		}
+
 		p = (item == NULL) ? sdb->def : string_to_val(sdb, item->value);
-		ptr = GetVariableAddress(object, sld);
+		ptr = GetVariableAddress(sld->global ? NULL : object, sld);
 
 		switch (sdb->cmd) {
 		case SDT_BOOLX: /* All four are various types of (integer) numbers */
@@ -758,8 +793,11 @@
 			break;
 
 		case SDT_INTLIST: {
-			if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv)))
+			if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) {
 				ShowInfoF("ini: error in array '%s'", sdb->name);
+			} else if (sd->desc.proc_cnvt != NULL) {
+				sd->desc.proc_cnvt((const char*)p);
+			}
 			break;
 		}
 		default: NOT_REACHED(); break;
@@ -1054,8 +1092,8 @@
 	SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
 #define SDT_LIST(base, var, type, flags, guiflags, def, str, proc)\
 	SDT_CONDLIST(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
-#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc)\
-	SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, NULL, from, to)
+#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc, load)\
+	SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, load, from, to)
 
 #define SDT_CONDSTR(base, var, type, from, to, flags, guiflags, def, str, proc)\
 	SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to)
@@ -1096,6 +1134,7 @@
 #define NO SGF_NETWORK_ONLY
 #define CR SGF_CURRENCY
 #define NN SGF_NO_NETWORK
+#define NG SGF_NEWGAME_ONLY
 
 /* Begin - Callback Functions for the various settings */
 /* virtual PositionMainToolbar function, calls the right one.*/
@@ -1115,7 +1154,7 @@
 {
 	if (p1 == 1) {
 		ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_MULTIPLAYER, 0, 0);
-		_patches.ainew_active = true;
+		_settings.ai.ainew_active = true;
 	}
 	return 0;
 }
@@ -1161,6 +1200,12 @@
 	return 0;
 }
 
+static int32 InvalidateTownViewWindow(int32 p1)
+{
+	InvalidateWindowClassesData(WC_TOWN_VIEW, p1);
+	return 0;
+}
+
 static int32 UpdateConsists(int32 p1)
 {
 	Vehicle *v;
@@ -1175,7 +1220,7 @@
 static int32 CheckInterval(int32 p1)
 {
 	bool warning;
-	const Patches *ptc = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches;
+	const VehicleSettings *ptc = (_game_mode == GM_MENU) ? &_settings_newgame.vehicle : &_settings.vehicle;
 
 	if (p1) {
 		warning = ( (IsInsideMM(ptc->servint_trains,   5, 90 + 1) || ptc->servint_trains   == 0) &&
@@ -1197,19 +1242,19 @@
 
 static int32 EngineRenewUpdate(int32 p1)
 {
-	DoCommandP(0, 0, _patches.autorenew, NULL, CMD_SET_AUTOREPLACE);
+	DoCommandP(0, 0, _settings.gui.autorenew, NULL, CMD_SET_AUTOREPLACE);
 	return 0;
 }
 
 static int32 EngineRenewMonthsUpdate(int32 p1)
 {
-	DoCommandP(0, 1, _patches.autorenew_months, NULL, CMD_SET_AUTOREPLACE);
+	DoCommandP(0, 1, _settings.gui.autorenew_months, NULL, CMD_SET_AUTOREPLACE);
 	return 0;
 }
 
 static int32 EngineRenewMoneyUpdate(int32 p1)
 {
-	DoCommandP(0, 2, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
+	DoCommandP(0, 2, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE);
 	return 0;
 }
 
@@ -1231,6 +1276,92 @@
 	return 0;
 }
 
+/*
+ * A: competitors
+ * B: start time in months / 3
+ * C: town count (3 = high, 0 = very low)
+ * D: industry count (4 = high, 0 = none)
+ * E: inital loan (in GBP)
+ * F: interest rate
+ * G: running costs (0 = low, 2 = high)
+ * H: construction speed of competitors (0 = very slow, 4 = very fast)
+ * I: intelligence (0-2)
+ * J: breakdowns (0 = off, 2 = normal)
+ * K: subsidy multiplier (0 = 1.5, 3 = 4.0)
+ * L: construction cost (0-2)
+ * M: terrain type (0 = very flat, 3 = mountainous)
+ * N: amount of water (0 = very low, 3 = high)
+ * O: economy (0 = steady, 1 = fluctuating)
+ * P: Train reversing (0 = end of line + stations, 1 = end of line)
+ * Q: disasters
+ * R: area restructuring (0 = permissive, 2 = hostile)
+ * S: the difficulty level
+ */
+static const DifficultySettings _default_game_diff[3] = { /*
+	 A, B, C, D,      E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S*/
+	{2, 2, 2, 4, 300000, 2, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0}, ///< easy
+	{4, 1, 2, 3, 150000, 3, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1}, ///< medium
+	{7, 0, 3, 3, 100000, 4, 1, 3, 2, 2, 0, 2, 3, 2, 1, 1, 1, 2, 2}, ///< hard
+};
+
+void SetDifficultyLevel(int mode, DifficultySettings *gm_opt)
+{
+	assert(mode <= 3);
+
+	if (mode != 3) {
+		*gm_opt = _default_game_diff[mode];
+	} else {
+		gm_opt->diff_level = 3;
+	}
+}
+
+/**
+ * Checks the difficulty levels read from the configuration and
+ * forces them to be correct when invalid.
+ */
+void CheckDifficultyLevels()
+{
+	if (_settings_newgame.difficulty.diff_level != 3) {
+		SetDifficultyLevel(_settings_newgame.difficulty.diff_level, &_settings_newgame.difficulty);
+	}
+}
+
+static int32 DifficultyReset(int32 level)
+{
+	SetDifficultyLevel(level, (_game_mode == GM_MENU) ? &_settings_newgame.difficulty : &_settings.difficulty);
+	return 0;
+}
+
+static int32 DifficultyChange(int32)
+{
+	if (_game_mode == GM_MENU) {
+		_settings_newgame.difficulty.diff_level = 3;
+	} else {
+		_settings.difficulty.diff_level = 3;
+	}
+
+	/* If we are a network-client, update the difficult setting (if it is open).
+	 * Use this instead of just dirtying the window because we need to load in
+	 * the new difficulty settings */
+	if (_networking && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) {
+		ShowGameDifficulty();
+	}
+
+	return 0;
+}
+
+static int32 DifficultyNoiseChange(int32 i)
+{
+	if (_game_mode == GM_NORMAL) {
+		UpdateAirportsNoise();
+		if (_settings.economy.station_noise_level) {
+			InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
+		}
+	}
+
+	return DifficultyChange(i);
+}
+
 /**
  * Check for right TownLayout usage in editor mode.
  * The No Road mode is not desirable since towns have to be
@@ -1241,9 +1372,9 @@
  */
 static int32 CheckTownLayout(int32 p1)
 {
-	if (_patches.town_layout == TL_NO_ROADS && _game_mode == GM_EDITOR) {
+	if (_settings.economy.town_layout == TL_NO_ROADS && _game_mode == GM_EDITOR) {
 		ShowErrorMessage(INVALID_STRING_ID, STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID, 0, 0);
-		_patches.town_layout = TL_ORIGINAL;
+		_settings.economy.town_layout = TL_ORIGINAL;
 	}
 	return 0;
 }
@@ -1260,6 +1391,21 @@
 	return lookup_oneofmany("normal|hilly|desert|candy", value);
 }
 
+/**
+ * Check for decent values been supplied by the user for the noise tolerance setting.
+ * The primary idea is to avoid division by zero in game mode.
+ * The secondary idea is to make it so the values will be somewhat sane and that towns will
+ * not be overcrowed with airports.  It would be easy to abuse such a feature
+ * So basically, 200, 400, 800 are the lowest allowed values */
+static int32 CheckNoiseToleranceLevel(const char *value)
+{
+	Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
+	for (uint16 i = 0; i < lengthof(s->economy.town_noise_population); i++) {
+		s->economy.town_noise_population[i] = max(uint16(200 * (i + 1)), s->economy.town_noise_population[i]);
+	}
+	return 0;
+}
+
 /* End - Callback Functions */
 
 #ifndef EXTERNAL_PLAYER
@@ -1359,6 +1505,9 @@
 };
 #endif /* ENABLE_NETWORK */
 
+static const uint GAME_DIFFICULTY_NUM = 18;
+uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
+
 static const SettingDesc _gameopt_settings[] = {
 	/* In version 4 a new difficulty setting has been added to the difficulty settings,
 	 * town attitude towards demolishing. Needs special handling because some dimwit thought
@@ -1369,18 +1518,19 @@
 	 * and why not byte for example?
 	 * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack
 	 * for savegames version 0 - though it is an array, it has to go through the byteswap process */
-	SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_FILE_I16 | SLE_VAR_U16, 0, 0, GameOptions, diff, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 0, 3),
-	SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16, 0, 0, GameOptions, diff, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 4, SL_MAX_VERSION),
-	    SDT_VAR(GameOptions, diff_level, SLE_UINT8, 0, 0, 0, 0,  3, 0, STR_NULL, NULL),
-	  SDT_OMANY(GameOptions, currency,  SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL),
-	  SDT_OMANY(GameOptions, units,     SLE_UINT8, N, 0, 1,     2, "imperial|metric|si", STR_NULL, NULL, NULL),
+	 SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_FILE_I16 | SLE_VAR_U16,    C, 0, _old_diff_custom, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, 0,  3),
+	 SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16,                    C, 0, _old_diff_custom, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, 4, 96),
+
+	      SDT_VAR(Settings, difficulty.diff_level,    SLE_UINT8,                     0, 0, 0, 0,  3, 0, STR_NULL, NULL),
+	    SDT_OMANY(Settings, gui.currency,             SLE_UINT8,                     N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL),
+	    SDT_OMANY(Settings, gui.units,                SLE_UINT8,                     N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL),
 	/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
-	  SDT_OMANY(GameOptions, town_name, SLE_UINT8, 0, 0, 0,   255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
-	  SDT_OMANY(GameOptions, landscape, SLE_UINT8, 0, 0, 0,     3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
-	    SDT_VAR(GameOptions, snow_line, SLE_UINT8, 0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
-	SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8, 0, 22,             N, 0, 0, 0, "", STR_NULL, NULL, NULL),
-	SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8,23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL),
-	  SDT_OMANY(GameOptions, road_side, SLE_UINT8, 0, 0, 1,   1, "left|right", STR_NULL, NULL, NULL),
+	    SDT_OMANY(Settings, game_creation.town_name,  SLE_UINT8,                     0, 0, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
+	    SDT_OMANY(Settings, game_creation.landscape,  SLE_UINT8,                     0, 0, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
+	      SDT_VAR(Settings, game_creation.snow_line,  SLE_UINT8,                     0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
+	SDT_CONDOMANY(Settings, gui.autosave,             SLE_UINT8,  0, 22,             N, 0, 0, 0, "", STR_NULL, NULL, NULL),
+	SDT_CONDOMANY(Settings, gui.autosave,             SLE_UINT8, 23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL),
+	    SDT_OMANY(Settings, vehicle.road_side,        SLE_UINT8,                     0, 0, 1, 1, "left|right", STR_NULL, NULL, NULL),
 	    SDT_END()
 };
 
@@ -1395,244 +1545,218 @@
  * service depot, causing desyncs on a massive scale. */
 const SettingDesc _patch_settings[] = {
 	/***************************************************************************/
-	/* User-interface section of the GUI-configure patches window */
-	SDT_BOOL(Patches, vehicle_speed,                 S, 0,  true,        STR_CONFIG_PATCHES_VEHICLESPEED,          NULL),
-	SDT_BOOL(Patches, status_long_date,              S, 0,  true,        STR_CONFIG_PATCHES_LONGDATE,              NULL),
-	SDT_BOOL(Patches, show_finances,                 S, 0,  true,        STR_CONFIG_PATCHES_SHOWFINANCES,          NULL),
-	SDT_BOOL(Patches, autoscroll,                    S, 0, false,        STR_CONFIG_PATCHES_AUTOSCROLL,            NULL),
-	SDT_BOOL(Patches, reverse_scroll,                S, 0, false,        STR_CONFIG_PATCHES_REVERSE_SCROLLING,     NULL),
-	SDT_BOOL(Patches, smooth_scroll,                 S, 0, false,        STR_CONFIG_PATCHES_SMOOTH_SCROLLING,      NULL),
-	SDT_BOOL(Patches, measure_tooltip,               S, 0, false,        STR_CONFIG_PATCHES_MEASURE_TOOLTIP,       NULL),
-	 SDT_VAR(Patches, errmsg_duration,    SLE_UINT8, S, 0,  5, 0, 20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION,       NULL),
-	 SDT_VAR(Patches, toolbar_pos,        SLE_UINT8, S,MS,  0, 0,  2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS,           v_PositionMainToolbar),
-	 SDT_VAR(Patches, window_snap_radius, SLE_UINT8, S,D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS,           NULL),
-	SDT_BOOL(Patches, population_in_label,           S, 0,  true,        STR_CONFIG_PATCHES_POPULATION_IN_LABEL,   PopulationInLabelActive),
-	 SDT_VAR(Patches, map_x,              SLE_UINT8, S, 0,  8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_X,                 NULL),
-	 SDT_VAR(Patches, map_y,              SLE_UINT8, S, 0,  8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_Y,                 NULL),
-	SDT_BOOL(Patches, link_terraform_toolbar,        S, 0, false,        STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,NULL),
-	 SDT_VAR(Patches, liveries,           SLE_UINT8, S,MS,  2, 0,  2, 0, STR_CONFIG_PATCHES_LIVERIES,              RedrawScreen),
-	SDT_BOOL(Patches, prefer_teamchat,               S, 0, false,        STR_CONFIG_PATCHES_PREFER_TEAMCHAT,       NULL),
-	SDT_VAR(Patches, scrollwheel_scrolling,SLE_UINT8,S,MS, 0,  0,  2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL),
-	SDT_VAR(Patches,scrollwheel_multiplier,SLE_UINT8,S, 0, 5,  1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,NULL),
-	SDT_BOOL(Patches, pause_on_newgame,              S, 0, false,        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,     NULL),
-	 SDT_VAR(Patches,advanced_vehicle_list,SLE_UINT8,S,MS, 1,  0,  2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,NULL),
-	SDT_BOOL(Patches, timetable_in_ticks,            S, 0, false,        STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS,    NULL),
-	 SDT_VAR(Patches, loading_indicators, SLE_UINT8, S,MS,  1, 0,  2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS,    RedrawScreen),
-	 SDT_VAR(Patches, default_rail_type,  SLE_UINT8, S,MS,  4, 0,  6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE,     NULL),
-
-	/***************************************************************************/
-	/* Construction section of the GUI-configure patches window */
-	SDT_BOOL(Patches, build_on_slopes,               0,NN,  true,        STR_CONFIG_PATCHES_BUILDONSLOPES,       NULL),
-	SDT_CONDBOOL(Patches, autoslope,                75, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_AUTOSLOPE,            NULL),
-	SDT_BOOL(Patches, extra_dynamite,                0, 0, false,        STR_CONFIG_PATCHES_EXTRADYNAMITE,       NULL),
-	SDT_BOOL(Patches, longbridges,                   0,NN,  true,        STR_CONFIG_PATCHES_LONGBRIDGES,         NULL),
-	SDT_BOOL(Patches, signal_side,                   N,NN,  true,        STR_CONFIG_PATCHES_SIGNALSIDE,          RedrawScreen),
-	SDT_BOOL(Patches, always_small_airport,          0,NN, false,        STR_CONFIG_PATCHES_SMALL_AIRPORTS,      NULL),
-	SDT_BOOL(Patches, enable_signal_gui,             S, 0, false,        STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI,   CloseSignalGUI),
-	 SDT_VAR(Patches, drag_signals_density,SLE_UINT8,S, 0,  4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,DragSignalsDensityChanged),
-	 SDT_VAR(Patches, semaphore_build_before,SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
-	SDT_CONDVAR(Patches, town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0, MS, TL_ORIGINAL, TL_NO_ROADS, NUM_TLS - 1, 1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout),
-
-	/***************************************************************************/
-	/* Vehicle section of the GUI-configure patches window */
-	SDT_BOOL(Patches, realistic_acceleration,        0, 0, false,                    STR_CONFIG_PATCHES_REALISTICACCEL,       RealisticAccelerationChanged),
-	SDT_BOOL(Patches, forbid_90_deg,                 0, 0, false,                    STR_CONFIG_PATCHES_FORBID_90_DEG,        NULL),
-	SDT_BOOL(Patches, mammoth_trains,                0,NN,  true,                    STR_CONFIG_PATCHES_MAMMOTHTRAINS,        NULL),
-	SDT_BOOL(Patches, gotodepot,                     0, 0,  true,                    STR_CONFIG_PATCHES_GOTODEPOT,            NULL),
-	SDT_BOOL(Patches, roadveh_queue,                 0, 0,  true,                    STR_CONFIG_PATCHES_ROADVEH_QUEUE,        NULL),
-
-	SDT_CONDBOOL(Patches, new_pathfinding_all, 0,86, 0, 0, false,                    STR_NULL,                                NULL),
-	SDT_CONDBOOL(Patches, yapf.ship_use_yapf, 28,86, 0, 0, false,                    STR_NULL,                                NULL),
-	SDT_CONDBOOL(Patches, yapf.road_use_yapf, 28,86, 0, 0,  true,                    STR_NULL,                                NULL),
-	SDT_CONDBOOL(Patches, yapf.rail_use_yapf, 28,86, 0, 0,  true,                    STR_NULL,                                NULL),
-
-	SDT_CONDVAR(Patches, pathfinder_for_trains,   SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_TRAINS,  NULL),
-	SDT_CONDVAR(Patches, pathfinder_for_roadvehs, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_ROADVEH, NULL),
-	SDT_CONDVAR(Patches, pathfinder_for_ships,    SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 0, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_SHIPS,   NULL),
+	/* Saved patch variables. */
+	/* Do not ADD or REMOVE something in this "difficulty.XXX" table or before it. It breaks savegame compatability. */
+	 SDT_CONDVAR(Settings, difficulty.max_no_competitors,        SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     2,     0,      7,  1, STR_NULL,                                  DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.competitor_start_time,     SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     2,     0,      3,  1, STR_6830_IMMEDIATE,                        DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.number_towns,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     2,     0,      3,  1, STR_NUM_VERY_LOW,                          DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.number_industries,         SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     4,     0,      4,  1, STR_NONE,                                  DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.max_loan,                 SLE_UINT32, 97, SL_MAX_VERSION, 0,NG|CR,300000,100000,500000,50000,STR_NULL,                               DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.initial_interest,          SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     2,     2,      4,  1, STR_NULL,                                  DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.vehicle_costs,             SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      2,  1, STR_6820_LOW,                              DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.competitor_speed,          SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     2,     0,      4,  1, STR_681B_VERY_SLOW,                        DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.competitor_intelligence,   SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      2,  1, STR_6820_LOW,                              DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.vehicle_breakdowns,        SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     1,     0,      2,  1, STR_6823_NONE,                             DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.subsidy_multiplier,        SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     2,     0,      3,  1, STR_6826_X1_5,                             DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.construction_cost,         SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     0,     0,      2,  1, STR_6820_LOW,                              DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.terrain_type,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     1,     0,      3,  1, STR_682A_VERY_FLAT,                        DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.quantity_sea_lakes,        SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     0,     0,      3,  1, STR_VERY_LOW,                              DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.economy,                   SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      1,  1, STR_682E_STEADY,                           DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.line_reverse_mode,         SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      1,  1, STR_6834_AT_END_OF_LINE_AND_AT_STATIONS,   DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.disasters,                 SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      1,  1, STR_6836_OFF,                              DifficultyChange),
+	 SDT_CONDVAR(Settings, difficulty.town_council_tolerance,    SLE_UINT8, 97, SL_MAX_VERSION, 0, 0,     0,     0,      2,  1, STR_PERMISSIVE,                            DifficultyNoiseChange),
+	 SDT_CONDVAR(Settings, difficulty.diff_level,                SLE_UINT8, 97, SL_MAX_VERSION, 0,NG,     0,     0,      3,  0, STR_NULL,                                  DifficultyReset),
 
-	SDT_BOOL(Patches, train_income_warn,             S, 0,  true,                    STR_CONFIG_PATCHES_WARN_INCOME_LESS,     NULL),
-	 SDT_VAR(Patches, order_review_system,SLE_UINT8, S,MS,     2,     0,       2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW,         NULL),
-	SDT_BOOL(Patches, never_expire_vehicles,         0,NN, false,                    STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES,NULL),
-	SDT_BOOL(Patches, lost_train_warn,               S, 0,  true,                    STR_CONFIG_PATCHES_WARN_LOST_TRAIN,      NULL),
-	SDT_BOOL(Patches, autorenew,                     S, 0, false,                    STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,    EngineRenewUpdate),
-	 SDT_VAR(Patches, autorenew_months,   SLE_INT16, S, 0,     6,   -12,      12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS,     EngineRenewMonthsUpdate),
-	 SDT_VAR(Patches, autorenew_money,     SLE_UINT, S,CR,100000,     0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY,      EngineRenewMoneyUpdate),
-	SDT_BOOL(Patches, always_build_infrastructure,   S, 0, false,                    STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
-	 SDT_VAR(Patches, max_trains,        SLE_UINT16, 0, 0,   500,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_TRAINS,           RedrawScreen),
-	 SDT_VAR(Patches, max_roadveh,       SLE_UINT16, 0, 0,   500,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_ROADVEH,          RedrawScreen),
-	 SDT_VAR(Patches, max_aircraft,      SLE_UINT16, 0, 0,   200,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_AIRCRAFT,         RedrawScreen),
-	 SDT_VAR(Patches, max_ships,         SLE_UINT16, 0, 0,   300,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_SHIPS,            RedrawScreen),
-	SDT_BOOL(Patches, servint_ispercent,             0, 0, false,                    STR_CONFIG_PATCHES_SERVINT_ISPERCENT,    CheckInterval),
-	 SDT_VAR(Patches, servint_trains,    SLE_UINT16, 0,D0,   150,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_TRAINS,       InValidateDetailsWindow),
-	 SDT_VAR(Patches, servint_roadveh,   SLE_UINT16, 0,D0,   150,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_ROADVEH,      InValidateDetailsWindow),
-	 SDT_VAR(Patches, servint_ships,     SLE_UINT16, 0,D0,   360,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_SHIPS,        InValidateDetailsWindow),
-	 SDT_VAR(Patches, servint_aircraft,  SLE_UINT16, 0,D0,   100,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_AIRCRAFT,     InValidateDetailsWindow),
-	SDT_BOOL(Patches, no_servicing_if_no_breakdowns, 0, 0, false,                    STR_CONFIG_PATCHES_NOSERVICE,            NULL),
-	SDT_BOOL(Patches, wagon_speed_limits,            0,NN,  true,                    STR_CONFIG_PATCHES_WAGONSPEEDLIMITS,     UpdateConsists),
-	SDT_CONDBOOL(Patches, disable_elrails, 38, SL_MAX_VERSION, 0, NN, false,         STR_CONFIG_PATCHES_DISABLE_ELRAILS,      SettingsDisableElrail),
-	SDT_CONDVAR(Patches, freight_trains, SLE_UINT8, 39, SL_MAX_VERSION, 0,NN, 1, 1, 255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS, NULL),
-	SDT_CONDBOOL(Patches, timetabling,              67, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_TIMETABLE_ALLOW,      NULL),
-	SDT_CONDVAR(Patches, plane_speed,    SLE_UINT8, 90, SL_MAX_VERSION, 0, 0, 4, 1,   4, 0, STR_CONFIG_PATCHES_PLANE_SPEED,   NULL),
-	SDT_CONDBOOL(Patches, dynamic_engines,          95, SL_MAX_VERSION, 0,NN, false, STR_CONFIG_PATCHES_DYNAMIC_ENGINES,      NULL),
+	/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
+ SDT_CONDOMANY(Settings, game_creation.town_name,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
+ SDT_CONDOMANY(Settings, game_creation.landscape,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0,   3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
+	 SDT_CONDVAR(Settings, game_creation.snow_line,              SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
+ SDT_CONDOMANY(Settings, vehicle.road_side,                    SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 1,   1, "left|right", STR_NULL, NULL, NULL),
 
-	/***************************************************************************/
-	/* Station section of the GUI-configure patches window */
-	SDT_BOOL(Patches, join_stations,           0, 0,  true,        STR_CONFIG_PATCHES_JOINSTATIONS,       NULL),
-	SDT_CONDBOOL(Patches, sg_full_load_any, 0, 92, 0, 0, true,     STR_NULL,                              NULL),
-	SDT_BOOL(Patches, improved_load,           0,NN, false,        STR_CONFIG_PATCHES_IMPROVEDLOAD,       NULL),
-	SDT_BOOL(Patches, selectgoods,             0, 0,  true,        STR_CONFIG_PATCHES_SELECTGOODS,        NULL),
-	SDT_BOOL(Patches, new_nonstop,             S, 0, false,        STR_CONFIG_PATCHES_NEW_NONSTOP,        NULL),
-	SDT_CONDBOOL(Patches, sg_new_nonstop, 0, 92, 0, 0, false,      STR_NULL,                              NULL),
-	SDT_BOOL(Patches, nonuniform_stations,     0,NN,  true,        STR_CONFIG_PATCHES_NONUNIFORM_STATIONS,NULL),
-	 SDT_VAR(Patches, station_spread,SLE_UINT8,0, 0, 12, 4, 64, 0, STR_CONFIG_PATCHES_STATION_SPREAD,     InvalidateStationBuildWindow),
-	SDT_BOOL(Patches, serviceathelipad,        0, 0,  true,        STR_CONFIG_PATCHES_SERVICEATHELIPAD,   NULL),
-	SDT_BOOL(Patches, modified_catchment,      0, 0,  true,        STR_CONFIG_PATCHES_CATCHMENT,          NULL),
-	SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0,  true, STR_CONFIG_PATCHES_GRADUAL_LOADING,    NULL),
-	SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL),
-	SDT_CONDBOOL(Patches, adjacent_stations,      62, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL),
+	    SDT_BOOL(Settings, construction.build_on_slopes,                                        0,NN,  true,                    STR_CONFIG_PATCHES_BUILDONSLOPES,          NULL),
+	SDT_CONDBOOL(Settings, construction.autoslope,                          75, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_AUTOSLOPE,              NULL),
+	    SDT_BOOL(Settings, construction.extra_dynamite,                                         0, 0, false,                    STR_CONFIG_PATCHES_EXTRADYNAMITE,          NULL),
+	    SDT_BOOL(Settings, construction.longbridges,                                            0,NN,  true,                    STR_CONFIG_PATCHES_LONGBRIDGES,            NULL),
+	    SDT_BOOL(Settings, construction.signal_side,                                            N,NN,  true,                    STR_CONFIG_PATCHES_SIGNALSIDE,             RedrawScreen),
+	    SDT_BOOL(Settings, station.always_small_airport,                                        0,NN, false,                    STR_CONFIG_PATCHES_SMALL_AIRPORTS,         NULL),
+	 SDT_CONDVAR(Settings, economy.town_layout,                  SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_NO_ROADS,NUM_TLS-1,1, STR_CONFIG_PATCHES_TOWN_LAYOUT,  CheckTownLayout),
 
-	/***************************************************************************/
-	/* Economy section of the GUI-configure patches window */
-	SDT_BOOL(Patches, inflation,                  0, 0,  true,            STR_CONFIG_PATCHES_INFLATION,        NULL),
-	 SDT_VAR(Patches, raw_industry_construction,SLE_UINT8,0,MS,0,0, 2, 0, STR_CONFIG_PATCHES_RAW_INDUSTRY_CONSTRUCTION_METHOD, InvalidateBuildIndustryWindow),
-	SDT_BOOL(Patches, multiple_industry_per_town, 0, 0, false,            STR_CONFIG_PATCHES_MULTIPINDTOWN,    NULL),
-	SDT_BOOL(Patches, same_industry_close,        0, 0, false,            STR_CONFIG_PATCHES_SAMEINDCLOSE,     NULL),
-	SDT_BOOL(Patches, bribe,                      0, 0,  true,            STR_CONFIG_PATCHES_BRIBE,            NULL),
-	SDT_CONDBOOL(Patches, exclusive_rights,           79, SL_MAX_VERSION, 0, 0, true,           STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE, NULL),
-	SDT_CONDBOOL(Patches, give_money,                 79, SL_MAX_VERSION, 0, 0, true,           STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY, NULL),
-	 SDT_VAR(Patches, snow_line_height,SLE_UINT8, 0, 0,     7,  2, 13, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT,  NULL),
-	 SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC,  2000, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL),
-	 SDT_VAR(Patches, starting_year,    SLE_INT32, 0,NC,  1950, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_STARTING_YEAR,NULL),
-	 SDT_VAR(Patches, ending_year,      SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR,  NULL),
-	SDT_BOOL(Patches, smooth_economy,             0, 0,  true,            STR_CONFIG_PATCHES_SMOOTH_ECONOMY,   NULL),
-	SDT_BOOL(Patches, allow_shares,               0, 0, false,            STR_CONFIG_PATCHES_ALLOW_SHARES,     NULL),
-	SDT_CONDVAR(Patches, town_growth_rate,  SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0,   4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH,          NULL),
-	SDT_CONDVAR(Patches, larger_towns,      SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS,         NULL),
-	SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0,  2, 1,  10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL),
-	SDT_CONDBOOL(Patches, mod_road_rebuild,            77, SL_MAX_VERSION, 0, 0, false,         STR_CONFIG_MODIFIED_ROAD_REBUILD,        NULL),
+	    SDT_BOOL(Settings, vehicle.realistic_acceleration,                                      0, 0, false,                    STR_CONFIG_PATCHES_REALISTICACCEL,         RealisticAccelerationChanged),
+	    SDT_BOOL(Settings, pf.forbid_90_deg,                                                    0, 0, false,                    STR_CONFIG_PATCHES_FORBID_90_DEG,          NULL),
+	    SDT_BOOL(Settings, vehicle.mammoth_trains,                                              0,NN,  true,                    STR_CONFIG_PATCHES_MAMMOTHTRAINS,          NULL),
+	    SDT_BOOL(Settings, order.gotodepot,                                                     0, 0,  true,                    STR_CONFIG_PATCHES_GOTODEPOT,              NULL),
+	    SDT_BOOL(Settings, pf.roadveh_queue,                                                    0, 0,  true,                    STR_CONFIG_PATCHES_ROADVEH_QUEUE,          NULL),
+
+	SDT_CONDBOOL(Settings, pf.new_pathfinding_all,                           0,             86, 0, 0, false,                    STR_NULL,                                  NULL),
+	SDT_CONDBOOL(Settings, pf.yapf.ship_use_yapf,                           28,             86, 0, 0, false,                    STR_NULL,                                  NULL),
+	SDT_CONDBOOL(Settings, pf.yapf.road_use_yapf,                           28,             86, 0, 0,  true,                    STR_NULL,                                  NULL),
+	SDT_CONDBOOL(Settings, pf.yapf.rail_use_yapf,                           28,             86, 0, 0,  true,                    STR_NULL,                                  NULL),
+
+	 SDT_CONDVAR(Settings, pf.pathfinder_for_trains,             SLE_UINT8, 87, SL_MAX_VERSION, 0, MS,    2,     0,       2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_TRAINS,  NULL),
+	 SDT_CONDVAR(Settings, pf.pathfinder_for_roadvehs,           SLE_UINT8, 87, SL_MAX_VERSION, 0, MS,    2,     0,       2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_ROADVEH, NULL),
+	 SDT_CONDVAR(Settings, pf.pathfinder_for_ships,              SLE_UINT8, 87, SL_MAX_VERSION, 0, MS,    0,     0,       2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_SHIPS,   NULL),
+
+	    SDT_BOOL(Settings, vehicle.never_expire_vehicles,                                       0,NN, false,                    STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES,  NULL),
+	     SDT_VAR(Settings, vehicle.max_trains,                  SLE_UINT16,                     0, 0,   500,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_TRAINS,             RedrawScreen),
+	     SDT_VAR(Settings, vehicle.max_roadveh,                 SLE_UINT16,                     0, 0,   500,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_ROADVEH,            RedrawScreen),
+	     SDT_VAR(Settings, vehicle.max_aircraft,                SLE_UINT16,                     0, 0,   200,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_AIRCRAFT,           RedrawScreen),
+	     SDT_VAR(Settings, vehicle.max_ships,                   SLE_UINT16,                     0, 0,   300,     0,    5000, 0, STR_CONFIG_PATCHES_MAX_SHIPS,              RedrawScreen),
+	    SDT_BOOL(Settings, vehicle.servint_ispercent,                                           0, 0, false,                    STR_CONFIG_PATCHES_SERVINT_ISPERCENT,      CheckInterval),
+	     SDT_VAR(Settings, vehicle.servint_trains,              SLE_UINT16,                     0,D0,   150,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_TRAINS,         InValidateDetailsWindow),
+	     SDT_VAR(Settings, vehicle.servint_roadveh,             SLE_UINT16,                     0,D0,   150,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_ROADVEH,        InValidateDetailsWindow),
+	     SDT_VAR(Settings, vehicle.servint_ships,               SLE_UINT16,                     0,D0,   360,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_SHIPS,          InValidateDetailsWindow),
+	     SDT_VAR(Settings, vehicle.servint_aircraft,            SLE_UINT16,                     0,D0,   100,     5,     800, 0, STR_CONFIG_PATCHES_SERVINT_AIRCRAFT,       InValidateDetailsWindow),
+	    SDT_BOOL(Settings, order.no_servicing_if_no_breakdowns,                                 0, 0, false,                    STR_CONFIG_PATCHES_NOSERVICE,              NULL),
+	    SDT_BOOL(Settings, vehicle.wagon_speed_limits,                                          0,NN,  true,                    STR_CONFIG_PATCHES_WAGONSPEEDLIMITS,       UpdateConsists),
+	SDT_CONDBOOL(Settings, vehicle.disable_elrails,                         38, SL_MAX_VERSION, 0,NN, false,                    STR_CONFIG_PATCHES_DISABLE_ELRAILS,        SettingsDisableElrail),
+	 SDT_CONDVAR(Settings, vehicle.freight_trains,               SLE_UINT8, 39, SL_MAX_VERSION, 0,NN,     1,     1,     255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS,         NULL),
+	SDT_CONDBOOL(Settings, order.timetabling,                               67, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_TIMETABLE_ALLOW,        NULL),
+	 SDT_CONDVAR(Settings, vehicle.plane_speed,                  SLE_UINT8, 90, SL_MAX_VERSION, 0, 0,     4,     1,       4, 0, STR_CONFIG_PATCHES_PLANE_SPEED,            NULL),
+	SDT_CONDBOOL(Settings, vehicle.dynamic_engines,                         95, SL_MAX_VERSION, 0,NN, false,                    STR_CONFIG_PATCHES_DYNAMIC_ENGINES,        NULL),
+
+	    SDT_BOOL(Settings, station.join_stations,                                               0, 0,  true,                    STR_CONFIG_PATCHES_JOINSTATIONS,           NULL),
+	SDT_CONDBOOL(Settings, gui.sg_full_load_any,                             0,             92, 0, 0 , true,                    STR_NULL,                                  NULL),
+	    SDT_BOOL(Settings, order.improved_load,                                                 0,NN,  true,                    STR_CONFIG_PATCHES_IMPROVEDLOAD,           NULL),
+	    SDT_BOOL(Settings, order.selectgoods,                                                   0, 0,  true,                    STR_CONFIG_PATCHES_SELECTGOODS,            NULL),
+	SDT_CONDBOOL(Settings, gui.sg_new_nonstop,                               0,             92, 0, 0, false,                    STR_NULL,                                  NULL),
+	    SDT_BOOL(Settings, station.nonuniform_stations,                                         0,NN,  true,                    STR_CONFIG_PATCHES_NONUNIFORM_STATIONS,    NULL),
+	     SDT_VAR(Settings, station.station_spread,               SLE_UINT8,                     0, 0,    12,     4,      64, 0, STR_CONFIG_PATCHES_STATION_SPREAD,         InvalidateStationBuildWindow),
+	    SDT_BOOL(Settings, order.serviceathelipad,                                              0, 0,  true,                    STR_CONFIG_PATCHES_SERVICEATHELIPAD,       NULL),
+	    SDT_BOOL(Settings, station.modified_catchment,                                          0, 0,  true,                    STR_CONFIG_PATCHES_CATCHMENT,              NULL),
+	SDT_CONDBOOL(Settings, order.gradual_loading,                           40, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_GRADUAL_LOADING,        NULL),
+	SDT_CONDBOOL(Settings, construction.road_stop_on_town_road,             47, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD,      NULL),
+	SDT_CONDBOOL(Settings, station.adjacent_stations,                       62, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_ADJACENT_STATIONS,      NULL),
+	SDT_CONDBOOL(Settings, economy.station_noise_level,                     96, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_PATCHES_NOISE_LEVEL,            InvalidateTownViewWindow),
+
+	    SDT_BOOL(Settings, economy.inflation,                                                   0, 0,  true,                    STR_CONFIG_PATCHES_INFLATION,              NULL),
+	     SDT_VAR(Settings, construction.raw_industry_construction, SLE_UINT8,                   0,MS,     0,     0,       2, 0, STR_CONFIG_PATCHES_RAW_INDUSTRY_CONSTRUCTION_METHOD, InvalidateBuildIndustryWindow),
+	    SDT_BOOL(Settings, economy.multiple_industry_per_town,                                  0, 0, false,                    STR_CONFIG_PATCHES_MULTIPINDTOWN,          NULL),
+	    SDT_BOOL(Settings, economy.same_industry_close,                                         0, 0, false,                    STR_CONFIG_PATCHES_SAMEINDCLOSE,           NULL),
+	    SDT_BOOL(Settings, economy.bribe,                                                       0, 0,  true,                    STR_CONFIG_PATCHES_BRIBE,                  NULL),
+	SDT_CONDBOOL(Settings, economy.exclusive_rights,                        79, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE,        NULL),
+	SDT_CONDBOOL(Settings, economy.give_money,                              79, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY,       NULL),
+	     SDT_VAR(Settings, game_creation.snow_line_height,       SLE_UINT8,                     0, 0,     7,     2,      13, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT,        NULL),
+	     SDT_VAR(Settings, gui.colored_news_year,                SLE_INT32,                     0,NC,  2000,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,      NULL),
+	     SDT_VAR(Settings, game_creation.starting_year,          SLE_INT32,                     0,NC,  1950,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_STARTING_YEAR,          NULL),
+	     SDT_VAR(Settings, gui.ending_year,                      SLE_INT32,                    0,NC|NO,2051,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_ENDING_YEAR,            NULL),
+	    SDT_BOOL(Settings, economy.smooth_economy,                                              0, 0,  true,                    STR_CONFIG_PATCHES_SMOOTH_ECONOMY,         NULL),
+	    SDT_BOOL(Settings, economy.allow_shares,                                                0, 0, false,                    STR_CONFIG_PATCHES_ALLOW_SHARES,           NULL),
+	 SDT_CONDVAR(Settings, economy.town_growth_rate,             SLE_UINT8, 54, SL_MAX_VERSION, 0, MS,    2,     0,       4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH,            NULL),
+	 SDT_CONDVAR(Settings, economy.larger_towns,                 SLE_UINT8, 54, SL_MAX_VERSION, 0, D0,    4,     0,     255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS,           NULL),
+	 SDT_CONDVAR(Settings, economy.initial_city_size,            SLE_UINT8, 56, SL_MAX_VERSION, 0, 0,     2,     1,      10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER,   NULL),
+	SDT_CONDBOOL(Settings, economy.mod_road_rebuild,                        77, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_MODIFIED_ROAD_REBUILD,          NULL),
+
+	    SDT_BOOL(Settings, ai.ainew_active,                                                     0, 0, false,                    STR_CONFIG_PATCHES_AINEW_ACTIVE,           AiNew_PatchActive_Warning),
+	    SDT_BOOL(Settings, ai.ai_in_multiplayer,                                                0, 0, false,                    STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER,      Ai_In_Multiplayer_Warning),
+	    SDT_BOOL(Settings, ai.ai_disable_veh_train,                                             0, 0, false,                    STR_CONFIG_PATCHES_AI_BUILDS_TRAINS,       NULL),
+	    SDT_BOOL(Settings, ai.ai_disable_veh_roadveh,                                           0, 0, false,                    STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH,      NULL),
+	    SDT_BOOL(Settings, ai.ai_disable_veh_aircraft,                                          0, 0, false,                    STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT,     NULL),
+	    SDT_BOOL(Settings, ai.ai_disable_veh_ship,                                              0, 0, false,                    STR_CONFIG_PATCHES_AI_BUILDS_SHIPS,        NULL),
+
+	     SDT_VAR(Settings, vehicle.extend_vehicle_life,          SLE_UINT8,                     0, 0,     0,     0,     100, 0, STR_NULL,                                  NULL),
+	     SDT_VAR(Settings, economy.dist_local_authority,         SLE_UINT8,                     0, 0,    20,     5,      60, 0, STR_NULL,                                  NULL),
+	     SDT_VAR(Settings, pf.wait_oneway_signal,                SLE_UINT8,                     0, 0,    15,     2,     100, 0, STR_NULL,                                  NULL),
+	     SDT_VAR(Settings, pf.wait_twoway_signal,                SLE_UINT8,                     0, 0,    41,     2,     100, 0, STR_NULL,                                  NULL),
+	SDT_CONDLISTO(Settings, economy.town_noise_population, 3,   SLE_UINT16, 96, SL_MAX_VERSION, 0,D0, "800,2000,4000",          STR_NULL,                                  NULL, CheckNoiseToleranceLevel),
+
+	     SDT_VAR(Settings, pf.opf.pf_maxlength,                          SLE_UINT16,                     0, 0,  4096,                    64,   65535, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.opf.pf_maxdepth,                            SLE_UINT8,                     0, 0,    48,                     4,     255, 0, STR_NULL,         NULL),
+
+	     SDT_VAR(Settings, pf.npf.npf_max_search_nodes,                    SLE_UINT,                     0, 0, 10000,                   500,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_firstred_penalty,               SLE_UINT,                     0, 0, ( 10 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_firstred_exit_penalty,          SLE_UINT,                     0, 0, (100 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_lastred_penalty,                SLE_UINT,                     0, 0, ( 10 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_station_penalty,                SLE_UINT,                     0, 0, (  1 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_slope_penalty,                  SLE_UINT,                     0, 0, (  1 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_curve_penalty,                  SLE_UINT,                     0, 0, 1,                         0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_rail_depot_reverse_penalty,          SLE_UINT,                     0, 0, ( 50 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_buoy_penalty,                        SLE_UINT,                     0, 0, (  2 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_water_curve_penalty,                 SLE_UINT,                     0, 0, (NPF_TILE_LENGTH / 4),     0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_road_curve_penalty,                  SLE_UINT,                     0, 0, 1,                         0,  100000, 0, STR_NULL,         NULL),
+	     SDT_VAR(Settings, pf.npf.npf_crossing_penalty,                    SLE_UINT,                     0, 0, (  3 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.npf.npf_road_drive_through_penalty,          SLE_UINT, 47, SL_MAX_VERSION, 0, 0, (  8 * NPF_TILE_LENGTH),   0,  100000, 0, STR_NULL,         NULL),
+
+
+	SDT_CONDBOOL(Settings, pf.yapf.disable_node_optimization,                        28, SL_MAX_VERSION, 0, 0, false,                                    STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.max_search_nodes,                       SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000,                   500, 1000000, 0, STR_NULL,         NULL),
+	SDT_CONDBOOL(Settings, pf.yapf.rail_firstred_twoway_eol,                         28, SL_MAX_VERSION, 0, 0,  true,                                    STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_firstred_penalty,                  SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_firstred_exit_penalty,             SLE_UINT, 28, SL_MAX_VERSION, 0, 0,   100 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_lastred_penalty,                   SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_lastred_exit_penalty,              SLE_UINT, 28, SL_MAX_VERSION, 0, 0,   100 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_station_penalty,                   SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    30 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_slope_penalty,                     SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     2 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_curve45_penalty,                   SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     1 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_curve90_penalty,                   SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     6 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_depot_reverse_penalty,             SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    50 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_crossing_penalty,                  SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     3 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_max_signals,            SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10,                     1,     100, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p0,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,   500,              -1000000, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p1,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,  -100,              -1000000, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p2,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,     5,              -1000000, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_longer_platform_penalty,           SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     8 * YAPF_TILE_LENGTH,  0,   20000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_longer_platform_per_tile_penalty,  SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     0 * YAPF_TILE_LENGTH,  0,   20000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_shorter_platform_penalty,          SLE_UINT, 33, SL_MAX_VERSION, 0, 0,    40 * YAPF_TILE_LENGTH,  0,   20000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     0 * YAPF_TILE_LENGTH,  0,   20000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.road_slope_penalty,                     SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     2 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.road_curve_penalty,                     SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     1 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.road_crossing_penalty,                  SLE_UINT, 33, SL_MAX_VERSION, 0, 0,     3 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(Settings, pf.yapf.road_stop_penalty,                      SLE_UINT, 47, SL_MAX_VERSION, 0, 0,     8 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+
+	 SDT_CONDVAR(Settings, game_creation.land_generator,                  SLE_UINT8, 30, SL_MAX_VERSION, 0,MS,     1,                     0,       1, 0, STR_CONFIG_PATCHES_LAND_GENERATOR,        NULL),
+	 SDT_CONDVAR(Settings, game_creation.oil_refinery_limit,              SLE_UINT8, 30, SL_MAX_VERSION, 0, 0,    32,                    12,      48, 0, STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE, NULL),
+	 SDT_CONDVAR(Settings, game_creation.tgen_smoothness,                 SLE_UINT8, 30, SL_MAX_VERSION, 0,MS,     1,                     0,       3, 0, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN,  NULL),
+	 SDT_CONDVAR(Settings, game_creation.generation_seed,                SLE_UINT32, 30, SL_MAX_VERSION, 0, 0,      GENERATE_NEW_SEED, 0, UINT32_MAX, 0, STR_NULL,                                 NULL),
+	 SDT_CONDVAR(Settings, game_creation.tree_placer,                     SLE_UINT8, 30, SL_MAX_VERSION, 0,MS,     2,                     0,       2, 0, STR_CONFIG_PATCHES_TREE_PLACER,           NULL),
+	     SDT_VAR(Settings, game_creation.heightmap_rotation,              SLE_UINT8,                     S,MS,     0,                     0,       1, 0, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION,    NULL),
+	     SDT_VAR(Settings, game_creation.se_flat_world_height,            SLE_UINT8,                     S, 0,     0,                     0,      15, 0, STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT,  NULL),
+
+ SDT_CONDOMANY(Settings, gui.currency,                                  SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL),
+ SDT_CONDOMANY(Settings, gui.units,                                     SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL),
 
 	/***************************************************************************/
-	/* AI section of the GUI-configure patches window */
-	SDT_BOOL(Patches, ainew_active,           0, 0, false, STR_CONFIG_PATCHES_AINEW_ACTIVE,      AiNew_PatchActive_Warning),
-	SDT_BOOL(Patches, ai_in_multiplayer,      0, 0, false, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, Ai_In_Multiplayer_Warning),
-	SDT_BOOL(Patches, ai_disable_veh_train,   0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_TRAINS,  NULL),
-	SDT_BOOL(Patches, ai_disable_veh_roadveh, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH, NULL),
-	SDT_BOOL(Patches, ai_disable_veh_aircraft,0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT,NULL),
-	SDT_BOOL(Patches, ai_disable_veh_ship,    0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_SHIPS,   NULL),
-
-	/***************************************************************************/
-	/* Patches without any GUI representation */
-	SDT_BOOL(Patches, keep_all_autosave,              S, 0, false,         STR_NULL, NULL),
-	SDT_BOOL(Patches, autosave_on_exit,               S, 0, false,         STR_NULL, NULL),
-	 SDT_VAR(Patches, max_num_autosaves,   SLE_UINT8, S, 0, 16, 0, 255, 0, STR_NULL, NULL),
-	SDT_BOOL(Patches, bridge_pillars,                 S, 0,  true,         STR_NULL, NULL),
-	 SDT_VAR(Patches, extend_vehicle_life, SLE_UINT8, 0, 0,  0, 0, 100, 0, STR_NULL, NULL),
-	SDT_BOOL(Patches, auto_euro,                      S, 0,  true,         STR_NULL, NULL),
-	 SDT_VAR(Patches, dist_local_authority,SLE_UINT8, 0, 0, 20, 5,  60, 0, STR_NULL, NULL),
-	 SDT_VAR(Patches, wait_oneway_signal,  SLE_UINT8, 0, 0, 15, 2, 100, 0, STR_NULL, NULL),
-	 SDT_VAR(Patches, wait_twoway_signal,  SLE_UINT8, 0, 0, 41, 2, 100, 0, STR_NULL, NULL),
-
-	/***************************************************************************/
-	/* New Pathfinding patch settings */
-	SDT_VAR(Patches, pf_maxlength,      SLE_UINT16, 0, 0,  4096,  64,  65535, 0, STR_NULL, NULL),
-	SDT_VAR(Patches, pf_maxdepth,        SLE_UINT8, 0, 0,    48,   4,    255, 0, STR_NULL, NULL),
-	/* The maximum number of nodes to search */
-	SDT_VAR(Patches, npf_max_search_nodes,SLE_UINT, 0, 0, 10000, 500, 100000, 0, STR_NULL, NULL),
+	/* Unsaved patch variables. */
+ SDT_OMANY(Settings, gui.autosave,               SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL,               NULL),
+	SDT_BOOL(Settings, gui.vehicle_speed,                     S, 0,  true,                        STR_CONFIG_PATCHES_VEHICLESPEED,                NULL),
+	SDT_BOOL(Settings, gui.status_long_date,                  S, 0,  true,                        STR_CONFIG_PATCHES_LONGDATE,                    NULL),
+	SDT_BOOL(Settings, gui.show_finances,                     S, 0,  true,                        STR_CONFIG_PATCHES_SHOWFINANCES,                NULL),
+	SDT_BOOL(Settings, gui.autoscroll,                        S, 0, false,                        STR_CONFIG_PATCHES_AUTOSCROLL,                  NULL),
+	SDT_BOOL(Settings, gui.reverse_scroll,                    S, 0, false,                        STR_CONFIG_PATCHES_REVERSE_SCROLLING,           NULL),
+	SDT_BOOL(Settings, gui.smooth_scroll,                     S, 0, false,                        STR_CONFIG_PATCHES_SMOOTH_SCROLLING,            NULL),
+	SDT_BOOL(Settings, gui.measure_tooltip,                   S, 0, false,                        STR_CONFIG_PATCHES_MEASURE_TOOLTIP,             NULL),
+	 SDT_VAR(Settings, gui.errmsg_duration,        SLE_UINT8, S, 0,     5,        0,       20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION,             NULL),
+	 SDT_VAR(Settings, gui.toolbar_pos,            SLE_UINT8, S,MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS,                 v_PositionMainToolbar),
+	 SDT_VAR(Settings, gui.window_snap_radius,     SLE_UINT8, S,D0,    10,        1,       32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS,                 NULL),
+	SDT_BOOL(Settings, gui.population_in_label,               S, 0,  true,                        STR_CONFIG_PATCHES_POPULATION_IN_LABEL,         PopulationInLabelActive),
+	SDT_BOOL(Settings, gui.link_terraform_toolbar,            S, 0, false,                        STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,      NULL),
+	 SDT_VAR(Settings, gui.liveries,               SLE_UINT8, S,MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_LIVERIES,                    RedrawScreen),
+	SDT_BOOL(Settings, gui.prefer_teamchat,                   S, 0, false,                        STR_CONFIG_PATCHES_PREFER_TEAMCHAT,             NULL),
+	 SDT_VAR(Settings, gui.scrollwheel_scrolling,  SLE_UINT8, S,MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING,       NULL),
+	 SDT_VAR(Settings, gui.scrollwheel_multiplier, SLE_UINT8, S, 0,     5,        1,       15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,      NULL),
+	SDT_BOOL(Settings, gui.pause_on_newgame,                  S, 0, false,                        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,           NULL),
+	 SDT_VAR(Settings, gui.advanced_vehicle_list,  SLE_UINT8, S,MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,      NULL),
+	SDT_BOOL(Settings, gui.timetable_in_ticks,                S, 0, false,                        STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS,          NULL),
+	 SDT_VAR(Settings, gui.loading_indicators,     SLE_UINT8, S,MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS,          RedrawScreen),
+	 SDT_VAR(Settings, gui.default_rail_type,      SLE_UINT8, S,MS,     4,        0,        6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE,           NULL),
+	SDT_BOOL(Settings, gui.enable_signal_gui,                 S, 0, false,                        STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI,           CloseSignalGUI),
+	 SDT_VAR(Settings, gui.drag_signals_density,   SLE_UINT8, S, 0,     4,        1,       20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,        DragSignalsDensityChanged),
+	 SDT_VAR(Settings, gui.semaphore_build_before, SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
+	SDT_BOOL(Settings, gui.train_income_warn,                 S, 0,  true,                        STR_CONFIG_PATCHES_WARN_INCOME_LESS,            NULL),
+	 SDT_VAR(Settings, gui.order_review_system,    SLE_UINT8, S,MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW,                NULL),
+	SDT_BOOL(Settings, gui.lost_train_warn,                   S, 0,  true,                        STR_CONFIG_PATCHES_WARN_LOST_TRAIN,             NULL),
+	SDT_BOOL(Settings, gui.autorenew,                         S, 0, false,                        STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,           EngineRenewUpdate),
+	 SDT_VAR(Settings, gui.autorenew_months,       SLE_INT16, S, 0,     6,      -12,       12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS,            EngineRenewMonthsUpdate),
+	 SDT_VAR(Settings, gui.autorenew_money,         SLE_UINT, S,CR,100000,        0,  2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY,             EngineRenewMoneyUpdate),
+	SDT_BOOL(Settings, gui.always_build_infrastructure,       S, 0, false,                        STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
+	SDT_BOOL(Settings, gui.new_nonstop,                       S, 0, false,                        STR_CONFIG_PATCHES_NEW_NONSTOP,                 NULL),
+	SDT_BOOL(Settings, gui.keep_all_autosave,                 S, 0, false,                        STR_NULL,                                       NULL),
+	SDT_BOOL(Settings, gui.autosave_on_exit,                  S, 0, false,                        STR_NULL,                                       NULL),
+	 SDT_VAR(Settings, gui.max_num_autosaves,      SLE_UINT8, S, 0,    16,        0,      255, 0, STR_NULL,                                       NULL),
+	SDT_BOOL(Settings, gui.bridge_pillars,                    S, 0,  true,                        STR_NULL,                                       NULL),
+	SDT_BOOL(Settings, gui.auto_euro,                         S, 0,  true,                        STR_NULL,                                       NULL),
 
-	/* When a red signal is encountered, a small detour can be made around
-	 * it. This specifically occurs when a track is doubled, in which case
-	 * the detour is typically 2 tiles. It is also often used at station
-	 * entrances, when there is a choice of multiple platforms. If we take
-	 * a typical 4 platform station, the detour is 4 tiles. To properly
-	 * support larger stations we increase this value.
-	 * We want to prevent that trains that want to leave at one side of a
-	 * station, leave through the other side, turn around, enter the
-	 * station on another platform and exit the station on the right side
-	 * again, just because the sign at the right side was red. If we take
-	 * a typical 5 length station, this detour is 10 or 11 tiles (not
-	 * sure), so we set the default penalty at 10 (the station tile
-	 * penalty will further prevent this.
-	 * We give presignal exits (and combo's) a different (larger) penalty, because
-	 * we really don't want trains waiting in front of a presignal exit. */
-	SDT_VAR(Patches, npf_rail_firstred_penalty,     SLE_UINT, 0, 0, (10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
-	SDT_VAR(Patches, npf_rail_firstred_exit_penalty,SLE_UINT, 0, 0, (100 * NPF_TILE_LENGTH),0, 100000, 0, STR_NULL, NULL),
-	/* This penalty is for when the last signal before the target is red.
-	 * This is useful for train stations, where there are multiple
-	 * platforms to choose from, which lie in different signal blocks.
-	 * Every target in a occupied signal block (ie an occupied platform)
-	 * will get this penalty. */
-	SDT_VAR(Patches, npf_rail_lastred_penalty, SLE_UINT, 0, 0, (10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
-	/* When a train plans a route over a station tile, this penalty is
-	 * applied. We want that trains plan a route around a typical, 4x5
-	 * station, which means two tiles to the right, and two tiles back to
-	 * the left around it, or 5 tiles of station through it. If we assign
-	 * a penalty of 1 tile for every station tile passed, the route will
-	 * be around it. */
-	SDT_VAR(Patches, npf_rail_station_penalty, SLE_UINT, 0, 0, (1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
-	SDT_VAR(Patches, npf_rail_slope_penalty,   SLE_UINT, 0, 0, (1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
-	/* This penalty is applied when a train makes a turn. Its value of 1 makes
-	 * sure that it has a minimal impact on the pathfinding, only when two
-	 * paths have equal length it will make a difference */
-	SDT_VAR(Patches, npf_rail_curve_penalty,        SLE_UINT, 0, 0, 1,                      0, 100000, 0, STR_NULL, NULL),
-	/* Ths penalty is applied when a vehicle reverses inside a depot (doesn't
-	 * apply to ships, as they can just come out the other end). XXX: Is this a
-	 * good value? */
-	SDT_VAR(Patches, npf_rail_depot_reverse_penalty,SLE_UINT, 0, 0, (NPF_TILE_LENGTH * 50), 0, 100000, 0, STR_NULL, NULL),
-	SDT_VAR(Patches, npf_buoy_penalty,              SLE_UINT, 0, 0, (2 * NPF_TILE_LENGTH),  0, 100000, 0, STR_NULL, NULL),
-	/* This penalty is applied when a ship makes a turn. It is bigger than the
-	 * rail curve penalty, since ships (realisticly) have more trouble with
-	 * making turns */
-	SDT_VAR(Patches, npf_water_curve_penalty,       SLE_UINT, 0, 0, (NPF_TILE_LENGTH / 4),  0, 100000, 0, STR_NULL, NULL),
-	/* This is the penalty for road, same as for rail. */
-	SDT_VAR(Patches, npf_road_curve_penalty,        SLE_UINT, 0, 0, 1,                      0, 100000, 0, STR_NULL, NULL),
-	/* This is the penalty for level crossings, for both road and rail vehicles */
-	SDT_VAR(Patches, npf_crossing_penalty,          SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH),  0, 100000, 0, STR_NULL, NULL),
-	/* This is the penalty for drive-through road, stops. */
-	SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0,  8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
-
-
-	/* The maximum number of nodes to search */
-	SDT_CONDBOOL(Patches, yapf.disable_node_optimization  ,           28, SL_MAX_VERSION, 0, 0, false                   ,                       STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.max_search_nodes           , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000                   ,      500, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDBOOL(Patches, yapf.rail_firstred_twoway_eol   ,           28, SL_MAX_VERSION, 0, 0,  true                   ,                       STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_firstred_penalty      , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_firstred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,   100 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_lastred_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_lastred_exit_penalty  , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,   100 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_station_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    30 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_slope_penalty         , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     2 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_curve45_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     1 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_curve90_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     6 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	/* This penalty is applied when a train reverses inside a depot */
-	SDT_CONDVAR (Patches, yapf.rail_depot_reverse_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    50 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	/* This is the penalty for level crossings (for trains only) */
-	SDT_CONDVAR (Patches, yapf.rail_crossing_penalty      , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     3 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	/* look-ahead how many signals are checked */
-	SDT_CONDVAR (Patches, yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10                   ,        1,     100, 0, STR_NULL, NULL),
-	/* look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0 */
-	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,   500                   , -1000000, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,  -100                   , -1000000, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,     5                   , -1000000, 1000000, 0, STR_NULL, NULL),
-	/* penalties for too long or too short station platforms */
-	SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty,           SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  8 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty,  SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  0 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty,          SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  0 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
-	/* road vehicles - penalties */
-	SDT_CONDVAR (Patches, yapf.road_slope_penalty                    , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.road_curve_penalty                    , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.road_crossing_penalty                 , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
-	SDT_CONDVAR (Patches, yapf.road_stop_penalty                     , SLE_UINT, 47, SL_MAX_VERSION, 0, 0,  8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
-
-	/***************************************************************************/
-	/* Terrain genation related patch options */
-	SDT_CONDVAR(Patches,      land_generator,           SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   1,                   0,    1,               0, STR_CONFIG_PATCHES_LAND_GENERATOR,           NULL),
-	SDT_CONDVAR(Patches,      oil_refinery_limit,       SLE_UINT8,  30, SL_MAX_VERSION, 0, 0,   32,                  12,   48,               0, STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE,    NULL),
-	SDT_CONDVAR(Patches,      tgen_smoothness,          SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   1,                   0,    3,               0, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN,     NULL),
-	SDT_CONDVAR(Patches,      generation_seed,          SLE_UINT32, 30, SL_MAX_VERSION, 0, 0,    GENERATE_NEW_SEED,   0, MAX_UVALUE(uint32), 0, STR_NULL,                                    NULL),
-	SDT_CONDVAR(Patches,      tree_placer,              SLE_UINT8,  30, SL_MAX_VERSION, 0, MS,   2,                   0,    2,               0, STR_CONFIG_PATCHES_TREE_PLACER,              NULL),
-	SDT_VAR    (Patches,      heightmap_rotation,       SLE_UINT8,                      S, MS,   0,                   0,    1,               0, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION,       NULL),
-	SDT_VAR    (Patches,      se_flat_world_height,     SLE_UINT8,                      S, 0,    0,                   0,   15,               0, STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT,     NULL),
+	 SDT_VAR(Settings, game_creation.map_x,        SLE_UINT8, S, 0,     8,        6,       11, 0, STR_CONFIG_PATCHES_MAP_X,                       NULL),
+	 SDT_VAR(Settings, game_creation.map_y,        SLE_UINT8, S, 0,     8,        6,       11, 0, STR_CONFIG_PATCHES_MAP_Y,                       NULL),
 
 	/*
 	 * Since the network code (CmdChangePatchSetting and friends) use the index in this array to decide
@@ -1643,7 +1767,7 @@
 
 #ifdef __APPLE__
 	/* We might need to emulate a right mouse button on mac */
-	SDT_VAR(Patches,right_mouse_btn_emulation,SLE_UINT8,S,MS,0, 0, 2, 0, STR_CONFIG_PATCHES_RIGHT_MOUSE_BTN_EMU,   NULL),
+	     SDT_VAR(Settings, gui.right_mouse_btn_emulation, SLE_UINT8, S, MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_RIGHT_MOUSE_BTN_EMU, NULL),
 #endif
 
 	SDT_END()
@@ -1669,6 +1793,31 @@
 #undef NO
 #undef CR
 
+static void PrepareOldDiffCustom()
+{
+	memset(_old_diff_custom, 0, sizeof(_old_diff_custom));
+}
+
+static void HandleOldDiffCustom()
+{
+	uint options_to_load = GAME_DIFFICULTY_NUM - (CheckSavegameVersion(4) ? 1 : 0);
+
+	/* If we did read to old_diff_custom, then at least one value must be non 0. */
+	bool old_diff_custom_used = false;
+	for (uint i = 0; i < options_to_load && !old_diff_custom_used; i++) {
+		old_diff_custom_used = (_old_diff_custom[i] != 0);
+	}
+
+	if (!old_diff_custom_used) return;
+
+	for (uint i = 0; i < options_to_load; i++) {
+		const SettingDesc *sd = &_patch_settings[i];
+		void *var = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save);
+		Write_ValidateSetting(var, sd, (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i]));
+	}
+}
+
+
 static void NewsDisplayLoadConfig(IniFile *ini, const char *grpname)
 {
 	IniGroup *group = ini_getgroup(ini, grpname);
@@ -1834,8 +1983,11 @@
 	proc(ini, (const SettingDesc*)_win32_settings,   "win32", NULL);
 #endif /* WIN32 */
 
-	proc(ini, _gameopt_settings, "gameopt",  &_opt_newgame);
-	proc(ini, _patch_settings,   "patches",  &_patches_newgame);
+	PrepareOldDiffCustom();
+	proc(ini, _gameopt_settings, "gameopt",  &_settings_newgame);
+	HandleOldDiffCustom();
+
+	proc(ini, _patch_settings,   "patches",  &_settings_newgame);
 	proc(ini, _currency_settings,"currency", &_custom_currency);
 
 #ifdef ENABLE_NETWORK
@@ -1845,8 +1997,6 @@
 #endif /* ENABLE_NETWORK */
 }
 
-extern void CheckDifficultyLevels();
-
 /** Load the values from the configuration files */
 void LoadFromConfig()
 {
@@ -1864,6 +2014,12 @@
 void SaveToConfig()
 {
 	IniFile *ini = ini_load(_config_file);
+
+	/* Remove some obsolete groups. These have all been loaded into other groups. */
+	ini_removegroup(ini, "patches");
+	ini_removegroup(ini, "yapf");
+	ini_removegroup(ini, "gameopt");
+
 	HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list);
 	GRFSaveConfig(ini, "newgrf", _grfconfig_newgame);
 	GRFSaveConfig(ini, "newgrf-static", _grfconfig_static);
@@ -1896,10 +2052,11 @@
 
 	if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return CMD_ERROR;
 	if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return CMD_ERROR;
+	if ((sd->desc.flags & SGF_NEWGAME_ONLY) && _game_mode != GM_MENU) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
-		Patches *patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches;
-		void *var = GetVariableAddress(patches_ptr, &sd->save);
+		Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
+		void *var = GetVariableAddress(s, &sd->save);
 		Write_ValidateSetting(var, sd, (int32)p2);
 		if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
 
@@ -1916,7 +2073,7 @@
  * This only affects patch-members that are not needed to be the same on all
  * clients in a network game.
  * @param value new value of the patch */
-bool SetPatchValue(uint index, const Patches *object, int32 value)
+bool SetPatchValue(uint index, const Settings *object, int32 value)
 {
 	const SettingDesc *sd = &_patch_settings[index];
 	/* If an item is player-based, we do not send it over the network
@@ -1928,7 +2085,7 @@
 		Write_ValidateSetting(var, sd, value);
 
 		if (_game_mode != GM_MENU) {
-			void *var2 = GetVariableAddress(&_patches_newgame, &sd->save);
+			void *var2 = GetVariableAddress(&_settings_newgame, &sd->save);
 			Write_ValidateSetting(var2, sd, value);
 		}
 		if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
@@ -1947,11 +2104,22 @@
 {
 	const SettingDesc *sd;
 
+	/* First check all full names */
 	for (*i = 0, sd = _patch_settings; sd->save.cmd != SL_END; sd++, (*i)++) {
 		if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
 		if (strcmp(sd->desc.name, name) == 0) return sd;
 	}
 
+	/* Then check the shortcut variant of the name. */
+	for (*i = 0, sd = _patch_settings; sd->save.cmd != SL_END; sd++, (*i)++) {
+		if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
+		const char *short_name = strchr(sd->desc.name, '.');
+		if (short_name != NULL) {
+			short_name++;
+			if (strcmp(short_name, name) == 0) return sd;
+		}
+	}
+
 	return NULL;
 }
 
@@ -1962,18 +2130,17 @@
 	bool success;
 	uint index;
 	const SettingDesc *sd = GetPatchFromName(name, &index);
-	const Patches *patches_ptr;
 	void *ptr;
 
 	if (sd == NULL) {
-		IConsolePrintF(_icolour_warn, "'%s' is an unknown patch setting.", name);
+		IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name);
 		return true;
 	}
 
-	patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches;
-	ptr = GetVariableAddress(patches_ptr, &sd->save);
+	Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
+	ptr = GetVariableAddress(s, &sd->save);
 
-	success = SetPatchValue(index, patches_ptr, value);
+	success = SetPatchValue(index, s, value);
 	return success;
 }
 
@@ -1985,11 +2152,11 @@
 	const void *ptr;
 
 	if (sd == NULL) {
-		IConsolePrintF(_icolour_warn, "'%s' is an unknown patch setting.", name);
+		IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name);
 		return;
 	}
 
-	ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save);
+	ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save);
 
 	if (sd->desc.cmd == SDT_BOOLX) {
 		snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off");
@@ -1997,27 +2164,27 @@
 		snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv));
 	}
 
-	IConsolePrintF(_icolour_warn, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
+	IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
 		name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
 }
 
 void IConsoleListPatches()
 {
-	IConsolePrintF(_icolour_warn, "All patches with their current value:");
+	IConsolePrintF(CC_WARNING, "All patches with their current value:");
 
 	for (const SettingDesc *sd = _patch_settings; sd->save.cmd != SL_END; sd++) {
 		char value[80];
-		const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save);
+		const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save);
 
 		if (sd->desc.cmd == SDT_BOOLX) {
 			snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off");
 		} else {
 			snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv));
 		}
-		IConsolePrintF(_icolour_def, "%s = %s", sd->desc.name, value);
+		IConsolePrintF(CC_DEFAULT, "%s = %s", sd->desc.name, value);
 	}
 
-	IConsolePrintF(_icolour_warn, "Use 'patch' command to change a value");
+	IConsolePrintF(CC_WARNING, "Use 'patch' command to change a value");
 }
 
 /** Save and load handler for patches/settings
@@ -2028,7 +2195,7 @@
 {
 	for (; osd->save.cmd != SL_END; osd++) {
 		const SaveLoad *sld = &osd->save;
-		void *ptr = GetVariableAddress(object, sld);
+		void *ptr = GetVariableAddress(sld->global ? NULL : object, sld);
 
 		if (!SlObjectMember(ptr, sld)) continue;
 	}
@@ -2078,13 +2245,9 @@
 	/* Copy over default setting since some might not get loaded in
 	 * a networking environment. This ensures for example that the local
 	 * autosave-frequency stays when joining a network-server */
-	_opt = _opt_newgame;
-	LoadSettings(_gameopt_settings, &_opt);
-}
-
-static void Save_OPTS()
-{
-	SaveSettings(_gameopt_settings, &_opt);
+	PrepareOldDiffCustom();
+	LoadSettings(_gameopt_settings, &_settings);
+	HandleOldDiffCustom();
 }
 
 static void Load_PATS()
@@ -2092,35 +2255,28 @@
 	/* Copy over default setting since some might not get loaded in
 	 * a networking environment. This ensures for example that the local
 	 * signal_side stays when joining a network-server */
-	_patches = _patches_newgame;
-	LoadSettings(_patch_settings, &_patches);
+	LoadSettings(_patch_settings, &_settings);
 }
 
 static void Save_PATS()
 {
-	SaveSettings(_patch_settings, &_patches);
+	SaveSettings(_patch_settings, &_settings);
 }
 
 void CheckConfig()
 {
-	// Increase old default values for pf_maxdepth and pf_maxlength
-	// to support big networks.
-	if (_patches_newgame.pf_maxdepth == 16 && _patches_newgame.pf_maxlength == 512) {
-		_patches_newgame.pf_maxdepth = 48;
-		_patches_newgame.pf_maxlength = 4096;
+	/*
+	 * Increase old default values for pf_maxdepth and pf_maxlength
+	 * to support big networks.
+	 */
+	if (_settings_newgame.pf.opf.pf_maxdepth == 16 && _settings_newgame.pf.opf.pf_maxlength == 512) {
+		_settings_newgame.pf.opf.pf_maxdepth = 48;
+		_settings_newgame.pf.opf.pf_maxlength = 4096;
 	}
 }
 
-void UpdatePatches()
-{
-	/* Since old(er) savegames don't have any patches saved, we initialise
-	 * them with the default values just as it was in the old days.
-	 * Also new games need this copying-over */
-	_patches = _patches_newgame; /* backwards compatibility */
-}
-
 extern const ChunkHandler _setting_chunk_handlers[] = {
-	{ 'OPTS', Save_OPTS, Load_OPTS, CH_RIFF},
+	{ 'OPTS', NULL,      Load_OPTS, CH_RIFF},
 	{ 'PATS', Save_PATS, Load_PATS, CH_RIFF | CH_LAST},
 };
 
--- a/src/settings_func.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/settings_func.h	Tue May 27 00:50:55 2008 +0000
@@ -12,6 +12,5 @@
 void LoadFromConfig();
 void SaveToConfig();
 void CheckConfig();
-void UpdatePatches();
 
 #endif /* SETTINGS_FUNC_H */
--- a/src/settings_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/settings_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -20,7 +20,6 @@
 #include "strings_func.h"
 #include "functions.h"
 #include "window_func.h"
-#include "vehicle_base.h"
 #include "core/alloc_func.hpp"
 #include "string_func.h"
 #include "gfx_func.h"
@@ -102,17 +101,6 @@
 	return i;
 }
 
-static inline bool RoadVehiclesAreBuilt()
-{
-	const Vehicle* v;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_ROAD) return true;
-	}
-	return false;
-}
-
-
 enum GameOptionsWidgets {
 	GAMEOPT_CURRENCY_BTN    =  4,
 	GAMEOPT_DISTANCE_BTN    =  6,
@@ -151,199 +139,181 @@
 	ShowDropDownList(w, list, sel, GAMEOPT_TOWNNAME_BTN);
 }
 
-/**
- * Update/redraw the languages dropdown
- * @param w   the window the dropdown belongs to
- */
-static void ShowLangDropdown(Window *w)
-{
-	typedef std::map<StringID, int, StringIDCompare> LangList;
-
-	/* Sort language names */
-	LangList langs;
-	for (int i = 0; i < _dynlang.num; i++) langs[SPECSTR_LANGUAGE_START + i] = i;
-
-	DropDownList *list = new DropDownList();
-	for (LangList::iterator it = langs.begin(); it != langs.end(); it++) {
-		list->push_back(new DropDownListStringItem((*it).first, (*it).second, false));
-	}
-
-	ShowDropDownList(w, list, _dynlang.curr, GAMEOPT_LANG_BTN);
-}
-
 static void ShowCustCurrency();
 
-static void GameOptionsWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			int i;
-			StringID str = STR_02BE_DEFAULT;
-
-			w->SetWidgetDisabledState(GAMEOPT_VEHICLENAME_SAVE, !(_vehicle_design_names & 1));
-			if (!w->IsWidgetDisabled(GAMEOPT_VEHICLENAME_SAVE)) str = STR_02BF_CUSTOM;
-			SetDParam(0, str);
-			SetDParam(1, _currency_specs[_opt_ptr->currency].name);
-			SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units);
-			SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side);
-			SetDParam(4, TownName(_opt_ptr->town_name));
-			SetDParam(5, _autosave_dropdown[_opt_ptr->autosave]);
-			SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr);
-			i = GetCurRes();
-			SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i);
-			SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format);
-			w->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen);
-
-			w->DrawWidgets();
-			DrawString(20, 175, STR_OPTIONS_FULLSCREEN, TC_FROMSTRING); // fullscreen
-		} break;
-
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case GAMEOPT_CURRENCY_BTN: /* Setup currencies dropdown */
-					ShowDropDownMenu(w, BuildCurrencyDropdown(), _opt_ptr->currency, GAMEOPT_CURRENCY_BTN, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);
-					break;
-
-				case GAMEOPT_DISTANCE_BTN: /* Setup distance unit dropdown */
-					ShowDropDownMenu(w, _units_dropdown, _opt_ptr->units, GAMEOPT_DISTANCE_BTN, 0, 0);
-					break;
-
-				case GAMEOPT_ROADSIDE_BTN: { /* Setup road-side dropdown */
-					int i = 0;
-
-					/* You can only change the drive side if you are in the menu or ingame with
-					 * no vehicles present. In a networking game only the server can change it */
-					if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server))
-						i = (-1) ^ (1 << _opt_ptr->road_side); // disable the other value
-
-					ShowDropDownMenu(w, _driveside_dropdown, _opt_ptr->road_side, GAMEOPT_ROADSIDE_BTN, i, 0);
-				} break;
-
-				case GAMEOPT_TOWNNAME_BTN: /* Setup townname dropdown */
-					ShowTownnameDropdown(w, _opt_ptr->town_name);
-					break;
-
-				case GAMEOPT_AUTOSAVE_BTN: /* Setup autosave dropdown */
-					ShowDropDownMenu(w, _autosave_dropdown, _opt_ptr->autosave, GAMEOPT_AUTOSAVE_BTN, 0, 0);
-					break;
-
-				case GAMEOPT_VEHICLENAME_BTN: /* Setup customized vehicle-names dropdown */
-					ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names & 1) ? 1 : 0, GAMEOPT_VEHICLENAME_BTN, (_vehicle_design_names & 2) ? 0 : 2, 0);
-					break;
-
-				case GAMEOPT_VEHICLENAME_SAVE: /* Save customized vehicle-names to disk */
-					break;  // not implemented
-
-				case GAMEOPT_LANG_BTN: /* Setup interface language dropdown */
-					ShowLangDropdown(w);
-					break;
-
-				case GAMEOPT_RESOLUTION_BTN: /* Setup resolution dropdown */
-					ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), GAMEOPT_RESOLUTION_BTN, 0, 0);
-					break;
+struct GameOptionsWindow : Window {
+	Settings *opt;
 
-				case GAMEOPT_FULLSCREEN: /* Click fullscreen on/off */
-					/* try to toggle full-screen on/off */
-					if (!ToggleFullScreen(!_fullscreen)) {
-						ShowErrorMessage(INVALID_STRING_ID, STR_FULLSCREEN_FAILED, 0, 0);
-					}
-					w->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen);
-					w->SetDirty();
-					break;
-
-				case GAMEOPT_SCREENSHOT_BTN: /* Setup screenshot format dropdown */
-					ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, GAMEOPT_SCREENSHOT_BTN, 0, 0);
-					break;
-			}
-			break;
-
-		case WE_DROPDOWN_SELECT:
-			switch (e->we.dropdown.button) {
-				case GAMEOPT_VEHICLENAME_BTN: /* Vehicle design names */
-					if (e->we.dropdown.index == 0) {
-						DeleteCustomEngineNames();
-						MarkWholeScreenDirty();
-					} else if (!(_vehicle_design_names & 1)) {
-						LoadCustomEngineNames();
-						MarkWholeScreenDirty();
-					}
-					break;
-
-				case GAMEOPT_CURRENCY_BTN: /* Currency */
-					if (e->we.dropdown.index == CUSTOM_CURRENCY_ID) ShowCustCurrency();
-					_opt_ptr->currency = e->we.dropdown.index;
-					MarkWholeScreenDirty();
-					break;
-
-				case GAMEOPT_DISTANCE_BTN: /* Measuring units */
-					_opt_ptr->units = e->we.dropdown.index;
-					MarkWholeScreenDirty();
-					break;
-
-				case GAMEOPT_ROADSIDE_BTN: /* Road side */
-					if (_opt_ptr->road_side != e->we.dropdown.index) { // only change if setting changed
-						DoCommandP(0, e->we.dropdown.index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
-						MarkWholeScreenDirty();
-					}
-					break;
-
-				case GAMEOPT_TOWNNAME_BTN: /* Town names */
-					if (_game_mode == GM_MENU) {
-						_opt_ptr->town_name = e->we.dropdown.index;
-						InvalidateWindow(WC_GAME_OPTIONS, 0);
-					}
-					break;
-
-				case GAMEOPT_AUTOSAVE_BTN: /* Autosave options */
-					_opt.autosave = _opt_newgame.autosave = e->we.dropdown.index;
-					w->SetDirty();
-					break;
-
-				case GAMEOPT_LANG_BTN: /* Change interface language */
-					ReadLanguagePack(e->we.dropdown.index);
-					CheckForMissingGlyphsInLoadedLanguagePack();
-					UpdateAllStationVirtCoord();
-					UpdateAllWaypointSigns();
-					MarkWholeScreenDirty();
-					break;
-
-				case GAMEOPT_RESOLUTION_BTN: /* Change resolution */
-					if (e->we.dropdown.index < _num_resolutions && ChangeResInGame(_resolutions[e->we.dropdown.index][0], _resolutions[e->we.dropdown.index][1]))
-						w->SetDirty();
-					break;
-
-				case GAMEOPT_SCREENSHOT_BTN: /* Change screenshot format */
-					SetScreenshotFormat(e->we.dropdown.index);
-					w->SetDirty();
-					break;
-			}
-			break;
-
-		case WE_DESTROY:
-			DeleteWindowById(WC_CUSTOM_CURRENCY, 0);
-			break;
+	GameOptionsWindow(const WindowDesc *desc) : Window(desc)
+	{
+		this->opt = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
+		this->FindWindowPlacementAndResize(desc);
 	}
 
-}
+	~GameOptionsWindow()
+	{
+		DeleteWindowById(WC_CUSTOM_CURRENCY, 0);
+	}
 
-/** Change the side of the road vehicles drive on (server only).
- * @param tile unused
- * @param flags operation to perform
- * @param p1 the side of the road; 0 = left side and 1 = right side
- * @param p2 unused
- */
-CommandCost CmdSetRoadDriveSide(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
-{
-	/* Check boundaries and you can only change this if NO vehicles have been built yet,
-	 * except in the intro-menu where of course it's always possible to do so. */
-	if (p1 > 1 || (_game_mode != GM_MENU && RoadVehiclesAreBuilt())) return CMD_ERROR;
+	virtual void OnPaint()
+	{
+		StringID str = STR_02BE_DEFAULT;
 
-	if (flags & DC_EXEC) {
-		_opt_ptr->road_side = p1;
-		InvalidateWindow(WC_GAME_OPTIONS, 0);
+		this->SetWidgetDisabledState(GAMEOPT_VEHICLENAME_SAVE, !(_vehicle_design_names & 1));
+		if (!this->IsWidgetDisabled(GAMEOPT_VEHICLENAME_SAVE)) str = STR_02BF_CUSTOM;
+		SetDParam(0, str);
+		SetDParam(1, _currency_specs[this->opt->gui.currency].name);
+		SetDParam(2, STR_UNITS_IMPERIAL + this->opt->gui.units);
+		SetDParam(3, STR_02E9_DRIVE_ON_LEFT + this->opt->vehicle.road_side);
+		SetDParam(4, TownName(this->opt->game_creation.town_name));
+		SetDParam(5, _autosave_dropdown[this->opt->gui.autosave]);
+		SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr);
+		int i = GetCurRes();
+		SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i);
+		SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format);
+		this->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen);
+
+		this->DrawWidgets();
+		DrawString(20, 175, STR_OPTIONS_FULLSCREEN, TC_FROMSTRING); // fullscreen
 	}
-	return CommandCost();
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case GAMEOPT_CURRENCY_BTN: // Setup currencies dropdown
+				ShowDropDownMenu(this, BuildCurrencyDropdown(), this->opt->gui.currency, GAMEOPT_CURRENCY_BTN, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);
+				break;
+
+			case GAMEOPT_DISTANCE_BTN: // Setup distance unit dropdown
+				ShowDropDownMenu(this, _units_dropdown, this->opt->gui.units, GAMEOPT_DISTANCE_BTN, 0, 0);
+				break;
+
+			case GAMEOPT_ROADSIDE_BTN: { // Setup road-side dropdown
+				int i = 0;
+				extern bool RoadVehiclesAreBuilt();
+
+				/* You can only change the drive side if you are in the menu or ingame with
+				 * no vehicles present. In a networking game only the server can change it */
+				if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
+					i = (-1) ^ (1 << this->opt->vehicle.road_side); // disable the other value
+				}
+
+				ShowDropDownMenu(this, _driveside_dropdown, this->opt->vehicle.road_side, GAMEOPT_ROADSIDE_BTN, i, 0);
+			} break;
+
+			case GAMEOPT_TOWNNAME_BTN: // Setup townname dropdown
+				ShowTownnameDropdown(this, this->opt->game_creation.town_name);
+				break;
+
+			case GAMEOPT_AUTOSAVE_BTN: // Setup autosave dropdown
+				ShowDropDownMenu(this, _autosave_dropdown, this->opt->gui.autosave, GAMEOPT_AUTOSAVE_BTN, 0, 0);
+				break;
+
+			case GAMEOPT_VEHICLENAME_BTN: // Setup customized vehicle-names dropdown
+				ShowDropDownMenu(this, _designnames_dropdown, (_vehicle_design_names & 1) ? 1 : 0, GAMEOPT_VEHICLENAME_BTN, (_vehicle_design_names & 2) ? 0 : 2, 0);
+				break;
+
+			case GAMEOPT_VEHICLENAME_SAVE: // Save customized vehicle-names to disk
+				break;  // not implemented
+
+			case GAMEOPT_LANG_BTN: { // Setup interface language dropdown
+				typedef std::map<StringID, int, StringIDCompare> LangList;
+
+				/* Sort language names */
+				LangList langs;
+				for (int i = 0; i < _dynlang.num; i++) langs[SPECSTR_LANGUAGE_START + i] = i;
+
+				DropDownList *list = new DropDownList();
+				for (LangList::iterator it = langs.begin(); it != langs.end(); it++) {
+					list->push_back(new DropDownListStringItem((*it).first, (*it).second, false));
+				}
+
+				ShowDropDownList(this, list, _dynlang.curr, GAMEOPT_LANG_BTN);
+			} break;
+
+			case GAMEOPT_RESOLUTION_BTN: // Setup resolution dropdown
+				ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), GAMEOPT_RESOLUTION_BTN, 0, 0);
+				break;
+
+			case GAMEOPT_FULLSCREEN: // Click fullscreen on/off
+				/* try to toggle full-screen on/off */
+				if (!ToggleFullScreen(!_fullscreen)) {
+					ShowErrorMessage(INVALID_STRING_ID, STR_FULLSCREEN_FAILED, 0, 0);
+				}
+				this->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen);
+				this->SetDirty();
+				break;
+
+			case GAMEOPT_SCREENSHOT_BTN: // Setup screenshot format dropdown
+				ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, GAMEOPT_SCREENSHOT_BTN, 0, 0);
+				break;
+		}
+	}
+
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		switch (widget) {
+			case GAMEOPT_VEHICLENAME_BTN: // Vehicle design names
+				if (index == 0) {
+					DeleteCustomEngineNames();
+					MarkWholeScreenDirty();
+				} else if (!(_vehicle_design_names & 1)) {
+					LoadCustomEngineNames();
+					MarkWholeScreenDirty();
+				}
+				break;
+
+			case GAMEOPT_CURRENCY_BTN: /* Currency */
+				if (index == CUSTOM_CURRENCY_ID) ShowCustCurrency();
+				this->opt->gui.currency = index;
+				MarkWholeScreenDirty();
+				break;
+
+			case GAMEOPT_DISTANCE_BTN: // Measuring units
+				this->opt->gui.units = index;
+				MarkWholeScreenDirty();
+				break;
+
+			case GAMEOPT_ROADSIDE_BTN: // Road side
+				if (this->opt->vehicle.road_side != index) { // only change if setting changed
+					DoCommandP(0, index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
+					MarkWholeScreenDirty();
+				}
+				break;
+
+			case GAMEOPT_TOWNNAME_BTN: // Town names
+				if (_game_mode == GM_MENU) {
+					this->opt->game_creation.town_name = index;
+					InvalidateWindow(WC_GAME_OPTIONS, 0);
+				}
+				break;
+
+			case GAMEOPT_AUTOSAVE_BTN: // Autosave options
+				_settings.gui.autosave = _settings_newgame.gui.autosave = index;
+				this->SetDirty();
+				break;
+
+			case GAMEOPT_LANG_BTN: // Change interface language
+				ReadLanguagePack(index);
+				CheckForMissingGlyphsInLoadedLanguagePack();
+				UpdateAllStationVirtCoord();
+				UpdateAllWaypointSigns();
+				MarkWholeScreenDirty();
+				break;
+
+			case GAMEOPT_RESOLUTION_BTN: // Change resolution
+				if (index < _num_resolutions && ChangeResInGame(_resolutions[index][0], _resolutions[index][1])) {
+					this->SetDirty();
+				}
+				break;
+
+			case GAMEOPT_SCREENSHOT_BTN: // Change screenshot format
+				SetScreenshotFormat(index);
+				this->SetDirty();
+				break;
+		}
+	}
+};
 
 static const Widget _game_options_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
@@ -382,98 +352,13 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_game_options_widgets,
-	GameOptionsWndProc
 };
 
 
 void ShowGameOptions()
 {
 	DeleteWindowById(WC_GAME_OPTIONS, 0);
-	new Window(&_game_options_desc);
-}
-
-struct GameSettingData {
-	int16 min;
-	int16 max;
-	int16 step;
-	StringID str;
-};
-
-static const GameSettingData _game_setting_info[] = {
-	{  0,   7,  1, STR_NULL},
-	{  0,   3,  1, STR_6830_IMMEDIATE},
-	{  0,   3,  1, STR_NUM_VERY_LOW},
-	{  0,   4,  1, STR_NONE},
-	{100, 500, 50, STR_NULL},
-	{  2,   4,  1, STR_NULL},
-	{  0,   2,  1, STR_6820_LOW},
-	{  0,   4,  1, STR_681B_VERY_SLOW},
-	{  0,   2,  1, STR_6820_LOW},
-	{  0,   2,  1, STR_6823_NONE},
-	{  0,   3,  1, STR_6826_X1_5},
-	{  0,   2,  1, STR_6820_LOW},
-	{  0,   3,  1, STR_682A_VERY_FLAT},
-	{  0,   3,  1, STR_VERY_LOW},
-	{  0,   1,  1, STR_682E_STEADY},
-	{  0,   1,  1, STR_6834_AT_END_OF_LINE_AND_AT_STATIONS},
-	{  0,   1,  1, STR_6836_OFF},
-	{  0,   2,  1, STR_PERMISSIVE},
-};
-
-/*
- * A: competitors
- * B: start time in months / 3
- * C: town count (3 = high, 0 = very low)
- * D: industry count (4 = high, 0 = none)
- * E: inital loan / 1000 (in GBP)
- * F: interest rate
- * G: running costs (0 = low, 2 = high)
- * H: construction speed of competitors (0 = very slow, 4 = very fast)
- * I: intelligence (0-2)
- * J: breakdowns (0 = off, 2 = normal)
- * K: subsidy multiplier (0 = 1.5, 3 = 4.0)
- * L: construction cost (0-2)
- * M: terrain type (0 = very flat, 3 = mountainous)
- * N: amount of water (0 = very low, 3 = high)
- * O: economy (0 = steady, 1 = fluctuating)
- * P: Train reversing (0 = end of line + stations, 1 = end of line)
- * Q: disasters
- * R: area restructuring (0 = permissive, 2 = hostile)
- */
-static const GDType _default_game_diff[3][GAME_DIFFICULTY_NUM] = { /*
-	 A, B, C, D,   E, F, G, H, I, J, K, L, M, N, O, P, Q, R*/
-	{2, 2, 2, 4, 300, 2, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0}, ///< easy
-	{4, 1, 2, 3, 150, 3, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1}, ///< medium
-	{7, 0, 3, 3, 100, 4, 1, 3, 2, 2, 0, 2, 3, 2, 1, 1, 1, 2}, ///< hard
-};
-
-void SetDifficultyLevel(int mode, GameOptions *gm_opt)
-{
-	int i;
-	assert(mode <= 3);
-
-	gm_opt->diff_level = mode;
-	if (mode != 3) { // not custom
-		for (i = 0; i != GAME_DIFFICULTY_NUM; i++)
-			((GDType*)&gm_opt->diff)[i] = _default_game_diff[mode][i];
-	}
-}
-
-/**
- * Checks the difficulty levels read from the configuration and
- * forces them to be correct when invalid.
- */
-void CheckDifficultyLevels()
-{
-	if (_opt_newgame.diff_level != 3) {
-		SetDifficultyLevel(_opt_newgame.diff_level, &_opt_newgame);
-	} else {
-		for (uint i = 0; i < GAME_DIFFICULTY_NUM; i++) {
-			GDType *diff = ((GDType*)&_opt_newgame.diff) + i;
-			*diff = Clamp(*diff, _game_setting_info[i].min, _game_setting_info[i].max);
-			*diff -= *diff % _game_setting_info[i].step;
-		}
-	}
+	new GameOptionsWindow(&_game_options_desc);
 }
 
 extern void StartupEconomy();
@@ -501,23 +386,23 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_game_difficulty_widgets,
-	NULL
 };
 
+void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
+
 struct GameDifficultyWindow : public Window {
 private:
+	static const uint GAME_DIFFICULTY_NUM = 18;
 	bool clicked_increase;
 	uint8 clicked_button;
 	uint8 timeout;
 
 	/* Temporary holding place of values in the difficulty window until 'Save' is clicked */
-	GameOptions opt_mod_temp;
+	Settings opt_mod_temp;
 
 	enum {
 		GAMEDIFF_WND_TOP_OFFSET = 45,
 		GAMEDIFF_WND_ROWSIZE    = 9,
-		// 0x383E = (1 << 13) | (1 << 12) | (1 << 11) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1)
-		DIFF_INGAME_DISABLED_BUTTONS = 0x383E,
 		NO_SETTINGS_BUTTON = 0xFF,
 	};
 
@@ -542,7 +427,7 @@
 	{
 		/* Copy current settings (ingame or in intro) to temporary holding place
 		 * change that when setting stuff, copy back on clicking 'OK' */
-		this->opt_mod_temp = *_opt_ptr;
+		this->opt_mod_temp = (_game_mode == GM_MENU) ? _settings_newgame : _settings;
 		this->clicked_increase = false;
 		this->clicked_button = NO_SETTINGS_BUTTON;
 		this->timeout = 0;
@@ -559,7 +444,7 @@
 			WIDGET_LIST_END);
 		this->SetWidgetDisabledState(GDW_HIGHSCORE, _game_mode == GM_EDITOR || _networking); // highscore chart in multiplayer
 		this->SetWidgetDisabledState(GDW_ACCEPT, _networking && !_network_server); // Save-button in multiplayer (and if client)
-		this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level);
+		this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 		this->FindWindowPlacementAndResize(&_game_difficulty_desc);
 	}
 
@@ -567,29 +452,20 @@
 	{
 		this->DrawWidgets();
 
-		/* XXX - Disabled buttons in normal gameplay or during muliplayer as non server.
-		 *       Bitshifted for each button to see if that bit is set. If it is set, the
-		 *       button is disabled */
-		uint32 disabled = 0;
-		if (_networking && !_network_server) {
-			disabled = MAX_UVALUE(uint32); // Disable all
-		} else if (_game_mode == GM_NORMAL) {
-			disabled = DIFF_INGAME_DISABLED_BUTTONS;
-		}
-
-		int value;
+		uint i;
+		const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i);
 		int y = GAMEDIFF_WND_TOP_OFFSET;
-		for (uint i = 0; i != GAME_DIFFICULTY_NUM; i++) {
-			const GameSettingData *gsd = &_game_setting_info[i];
-			value = ((GDType*)&this->opt_mod_temp.diff)[i];
+		for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) {
+			const SettingDescBase *sdb = &sd->desc;
+			int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
+			bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
 
 			DrawArrowButtons(5, y, 3,
 					(this->clicked_button == i) ? 1 + !!this->clicked_increase : 0,
-					!(HasBit(disabled, i) || gsd->min == value),
-					!(HasBit(disabled, i) || gsd->max == value));
+					editable && sdb->min != value,
+					editable && sdb->max != value);
 
-			value += _game_setting_info[i].str;
-			if (i == 4) value *= 1000; // XXX - handle currency option
+			value += sdb->str;
 			SetDParam(0, value);
 			DrawString(30, y, STR_6805_MAXIMUM_NO_COMPETITORS + i, TC_FROMSTRING);
 
@@ -614,30 +490,33 @@
 				const uint8 btn = y / (GAMEDIFF_WND_ROWSIZE + 2);
 				if (btn >= GAME_DIFFICULTY_NUM || y % (GAMEDIFF_WND_ROWSIZE + 2) >= 9) return;
 
+				uint i;
+				const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i) + btn;
+				const SettingDescBase *sdb = &sd->desc;
+
 				/* Clicked disabled button? */
-				if (_game_mode == GM_NORMAL && HasBit((int)DIFF_INGAME_DISABLED_BUTTONS, btn)) return;
+				bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0);
+				if (!editable) return;
 
 				this->timeout = 5;
+				int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
 
-				int16 val = ((GDType*)&this->opt_mod_temp.diff)[btn];
-
-				const GameSettingData *info = &_game_setting_info[btn]; // get information about the difficulty setting
 				if (x >= 10) {
 					/* Increase button clicked */
-					val = min(val + info->step, info->max);
+					val = min(val + sdb->interval, sdb->max);
 					this->clicked_increase = true;
 				} else {
 					/* Decrease button clicked */
-					val -= info->step;
-					val = max(val,  info->min);
+					val -= sdb->interval;
+					val = max(val, sdb->min);
 					this->clicked_increase = false;
 				}
 				this->clicked_button = btn;
 
 				/* save value in temporary variable */
-				((GDType*)&this->opt_mod_temp.diff)[btn] = val;
-				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level);
-				SetDifficultyLevel(3, &this->opt_mod_temp); // set difficulty level to custom
+				WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val);
+				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
+				SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom
 				this->LowerWidget(GDW_LVL_CUSTOM);
 				this->SetDirty();
 			} break;
@@ -647,25 +526,32 @@
 			case GDW_LVL_HARD:
 			case GDW_LVL_CUSTOM:
 				/* temporarily change difficulty level */
-				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level);
-				SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp);
-				this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level);
+				this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
+				SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp.difficulty);
+				this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level);
 				this->SetDirty();
 				break;
 
 			case GDW_HIGHSCORE: // Highscore Table
-				ShowHighscoreTable(this->opt_mod_temp.diff_level, -1);
+				ShowHighscoreTable(this->opt_mod_temp.difficulty.diff_level, -1);
 				break;
 
 			case GDW_ACCEPT: { // Save button - save changes
-				GDType btn, val;
-				for (btn = 0; btn != GAME_DIFFICULTY_NUM; btn++) {
-					val = ((GDType*)&this->opt_mod_temp.diff)[btn];
+				Settings *opt_ptr = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
+
+				uint i;
+				const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i);
+				for (uint btn = 0; btn != GAME_DIFFICULTY_NUM; btn++, sd++) {
+					int32 new_val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv);
+					int32 cur_val = (int32)ReadValue(GetVariableAddress(opt_ptr, &sd->save), sd->save.conv);
 					/* if setting has changed, change it */
-					if (val != ((GDType*)&_opt_ptr->diff)[btn])
-						DoCommandP(0, btn, val, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+					if (new_val != cur_val) {
+						DoCommandP(0, i + btn, new_val, NULL, CMD_CHANGE_PATCH_SETTING);
+					}
 				}
-				DoCommandP(0, UINT_MAX, this->opt_mod_temp.diff_level, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
+
+				GetPatchFromName("difficulty.diff_level", &i);
+				DoCommandP(0, i, this->opt_mod_temp.difficulty.diff_level, NULL, CMD_CHANGE_PATCH_SETTING);
 				delete this;
 				/* If we are in the editor, we should reload the economy.
 				 * This way when you load a game, the max loan and interest rate
@@ -697,124 +583,125 @@
 }
 
 static const char *_patches_ui[] = {
-	"vehicle_speed",
-	"status_long_date",
-	"show_finances",
-	"autoscroll",
-	"reverse_scroll",
-	"smooth_scroll",
-	"errmsg_duration",
-	"toolbar_pos",
-	"measure_tooltip",
-	"window_snap_radius",
-	"population_in_label",
-	"link_terraform_toolbar",
-	"liveries",
-	"prefer_teamchat",
+	"gui.vehicle_speed",
+	"gui.status_long_date",
+	"gui.show_finances",
+	"gui.autoscroll",
+	"gui.reverse_scroll",
+	"gui.smooth_scroll",
+	"gui.errmsg_duration",
+	"gui.toolbar_pos",
+	"gui.measure_tooltip",
+	"gui.window_snap_radius",
+	"gui.population_in_label",
+	"gui.link_terraform_toolbar",
+	"gui.liveries",
+	"gui.prefer_teamchat",
 	/* While the horizontal scrollwheel scrolling is written as general code, only
 	 *  the cocoa (OSX) driver generates input for it.
 	 *  Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
-	"scrollwheel_scrolling",
-	"scrollwheel_multiplier",
+	"gui.scrollwheel_scrolling",
+	"gui.scrollwheel_multiplier",
 #ifdef __APPLE__
 	/* We might need to emulate a right mouse button on mac */
-	"right_mouse_btn_emulation",
+	"gui.right_mouse_btn_emulation",
 #endif
-	"pause_on_newgame",
-	"advanced_vehicle_list",
-	"loading_indicators",
-	"timetable_in_ticks",
-	"default_rail_type",
-	"always_build_infrastructure",
+	"gui.pause_on_newgame",
+	"gui.advanced_vehicle_list",
+	"gui.loading_indicators",
+	"gui.timetable_in_ticks",
+	"gui.default_rail_type",
+	"gui.always_build_infrastructure",
 };
 
 static const char *_patches_construction[] = {
-	"build_on_slopes",
-	"autoslope",
-	"extra_dynamite",
-	"longbridges",
-	"signal_side",
-	"always_small_airport",
-	"enable_signal_gui",
-	"drag_signals_density",
-	"oil_refinery_limit",
-	"semaphore_build_before",
+	"construction.build_on_slopes",
+	"construction.autoslope",
+	"construction.extra_dynamite",
+	"construction.longbridges",
+	"construction.signal_side",
+	"station.always_small_airport",
+	"gui.enable_signal_gui",
+	"gui.drag_signals_density",
+	"game_creation.oil_refinery_limit",
+	"gui.semaphore_build_before",
 };
 
 static const char *_patches_stations[] = {
-	"join_stations",
-	"improved_load",
-	"selectgoods",
-	"new_nonstop",
-	"nonuniform_stations",
-	"station_spread",
-	"serviceathelipad",
-	"modified_catchment",
-	"gradual_loading",
-	"road_stop_on_town_road",
-	"adjacent_stations",
+	"station.join_stations",
+	"order.improved_load",
+	"order.selectgoods",
+	"gui.new_nonstop",
+	"station.nonuniform_stations",
+	"station.station_spread",
+	"order.serviceathelipad",
+	"station.modified_catchment",
+	"order.gradual_loading",
+	"construction.road_stop_on_town_road",
+	"station.adjacent_stations",
+	"economy.station_noise_level",
 };
 
 static const char *_patches_economy[] = {
-	"inflation",
-	"raw_industry_construction",
-	"multiple_industry_per_town",
-	"same_industry_close",
-	"bribe",
-	"exclusive_rights",
-	"give_money",
-	"colored_news_year",
-	"ending_year",
-	"smooth_economy",
-	"allow_shares",
-	"town_layout",
-	"mod_road_rebuild",
-	"town_growth_rate",
-	"larger_towns",
-	"initial_city_size",
+	"economy.inflation",
+	"construction.raw_industry_construction",
+	"economy.multiple_industry_per_town",
+	"economy.same_industry_close",
+	"economy.bribe",
+	"economy.exclusive_rights",
+	"economy.give_money",
+	"gui.colored_news_year",
+	"gui.ending_year",
+	"economy.smooth_economy",
+	"economy.allow_shares",
+	"economy.town_layout",
+	"economy.mod_road_rebuild",
+	"economy.town_growth_rate",
+	"economy.larger_towns",
+	"economy.initial_city_size",
 };
 
 static const char *_patches_ai[] = {
-	"ainew_active",
-	"ai_in_multiplayer",
-	"ai_disable_veh_train",
-	"ai_disable_veh_roadveh",
-	"ai_disable_veh_aircraft",
-	"ai_disable_veh_ship",
+	"ai.ainew_active",
+	"ai.ai_in_multiplayer",
+	"ai.ai_disable_veh_train",
+	"ai.ai_disable_veh_roadveh",
+	"ai.ai_disable_veh_aircraft",
+	"ai.ai_disable_veh_ship",
 };
 
 static const char *_patches_vehicles[] = {
-	"realistic_acceleration",
-	"forbid_90_deg",
-	"mammoth_trains",
-	"gotodepot",
-	"roadveh_queue",
-	"pathfinder_for_trains",
-	"pathfinder_for_roadvehs",
-	"pathfinder_for_ships",
-	"train_income_warn",
-	"order_review_system",
-	"never_expire_vehicles",
-	"lost_train_warn",
-	"autorenew",
-	"autorenew_months",
-	"autorenew_money",
-	"max_trains",
-	"max_roadveh",
-	"max_aircraft",
-	"max_ships",
-	"servint_ispercent",
-	"servint_trains",
-	"servint_roadveh",
-	"servint_ships",
-	"servint_aircraft",
-	"no_servicing_if_no_breakdowns",
-	"wagon_speed_limits",
-	"disable_elrails",
-	"freight_trains",
-	"plane_speed",
-	"timetabling",
-	"dynamic_engines",
+	"vehicle.realistic_acceleration",
+	"pf.forbid_90_deg",
+	"vehicle.mammoth_trains",
+	"order.gotodepot",
+	"pf.roadveh_queue",
+	"pf.pathfinder_for_trains",
+	"pf.pathfinder_for_roadvehs",
+	"pf.pathfinder_for_ships",
+	"gui.train_income_warn",
+	"gui.order_review_system",
+	"vehicle.never_expire_vehicles",
+	"gui.lost_train_warn",
+	"gui.autorenew",
+	"gui.autorenew_months",
+	"gui.autorenew_money",
+	"vehicle.max_trains",
+	"vehicle.max_roadveh",
+	"vehicle.max_aircraft",
+	"vehicle.max_ships",
+	"vehicle.servint_ispercent",
+	"vehicle.servint_trains",
+	"vehicle.servint_roadveh",
+	"vehicle.servint_ships",
+	"vehicle.servint_aircraft",
+	"order.no_servicing_if_no_breakdowns",
+	"vehicle.wagon_speed_limits",
+	"vehicle.disable_elrails",
+	"vehicle.freight_trains",
+	"vehicle.plane_speed",
+	"order.timetabling",
+	"vehicle.dynamic_engines",
 };
 
 struct PatchEntry {
@@ -851,7 +738,7 @@
 };
 
 struct PatchesSelectionWindow : Window {
-	static Patches *patches_ptr;
+	static Settings *patches_ptr;
 	static int patches_max;
 
 	int page;
@@ -862,7 +749,7 @@
 	{
 		static bool first_time = true;
 
-		patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches;
+		patches_ptr = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings;
 
 		/* Build up the dynamic settings-array only once per OpenTTD session */
 		if (first_time) {
@@ -1074,7 +961,7 @@
 	}
 };
 
-Patches *PatchesSelectionWindow::patches_ptr = NULL;
+Settings *PatchesSelectionWindow::patches_ptr = NULL;
 int PatchesSelectionWindow::patches_max = 0;
 
 static const Widget _patches_selection_widgets[] = {
@@ -1097,7 +984,6 @@
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_patches_selection_widgets,
-	NULL,
 };
 
 void ShowPatchesSelection()
@@ -1328,7 +1214,6 @@
 	WC_CUSTOM_CURRENCY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_cust_currency_widgets,
-	NULL,
 };
 
 static void ShowCustCurrency()
--- a/src/settings_internal.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/settings_internal.h	Tue May 27 00:50:55 2008 +0000
@@ -39,8 +39,8 @@
 	SGF_NETWORK_ONLY = 1 << 3, ///< this setting only applies to network games
 	SGF_CURRENCY     = 1 << 4, ///< the number represents money, so when reading value multiply by exchange rate
 	SGF_NO_NETWORK   = 1 << 5, ///< this setting does not apply to network games; it may not be changed during the game
-	SGF_END          = 1 << 6,
-	/* 3 more possible flags */
+	SGF_NEWGAME_ONLY = 1 << 6, ///< this setting cannot be changed in inside a game
+	SGF_END          = 1 << 7,
 };
 
 DECLARE_ENUM_AS_BIT_SET(SettingGuiFlagLong);
@@ -84,6 +84,6 @@
 };
 
 const SettingDesc *GetPatchFromName(const char *name, uint *i);
-bool SetPatchValue(uint index, const Patches *object, int32 value);
+bool SetPatchValue(uint index, const Settings *object, int32 value);
 
 #endif /* SETTINGS_H */
--- a/src/settings_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/settings_type.h	Tue May 27 00:50:55 2008 +0000
@@ -5,241 +5,283 @@
 #ifndef SETTINGS_TYPE_H
 #define SETTINGS_TYPE_H
 
-#include "yapf/yapf_settings.h"
 #include "date_type.h"
 #include "town_type.h"
 #include "transport_type.h"
 
-#define GAME_DIFFICULTY_NUM 18
-
-/** Specific type for Game Difficulty to ease changing the type */
-typedef uint16 GDType;
-struct GameDifficulty {
-	GDType max_no_competitors;
-	GDType competitor_start_time;
-	GDType number_towns;
-	GDType number_industries;
-	GDType max_loan;
-	GDType initial_interest;
-	GDType vehicle_costs;
-	GDType competitor_speed;
-	GDType competitor_intelligence; ///< no longer in use
-	GDType vehicle_breakdowns;
-	GDType subsidy_multiplier;
-	GDType construction_cost;
-	GDType terrain_type;
-	GDType quantity_sea_lakes;
-	GDType economy;
-	GDType line_reverse_mode;
-	GDType disasters;
-	GDType town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff
-};
-
-struct GameOptions {
-	GameDifficulty diff;
-	byte diff_level;
-	byte currency;
-	byte units;
-	byte town_name;
-	byte landscape;
-	byte snow_line;
-	byte autosave;
-	byte road_side;
+/** Settings related to the difficulty of the game */
+struct DifficultySettings {
+	byte   max_no_competitors;               ///< the number of competitors (AIs)
+	byte   competitor_start_time;            ///< how long to wait for the first competitors (AIs)
+	byte   number_towns;                     ///< the amount of towns
+	byte   number_industries;                ///< the amount of industries
+	uint32 max_loan;                         ///< the maximum initial loan
+	byte   initial_interest;                 ///< amount of interest (to pay over the loan)
+	byte   vehicle_costs;                    ///< amount of money spent on vehicle running cost
+	byte   competitor_speed;                 ///< the speed at which the AI builds
+	byte   competitor_intelligence;          ///< the competior's (AI) intelligence
+	byte   vehicle_breakdowns;               ///< likelihood of vehicles breaking down
+	byte   subsidy_multiplier;               ///< amount of subsidy
+	byte   construction_cost;                ///< how expensive is building
+	byte   terrain_type;                     ///< the mountainousness of the landscape
+	byte   quantity_sea_lakes;               ///< the amount of seas/lakes
+	byte   economy;                          ///< how volatile is the economy
+	byte   line_reverse_mode;                ///< reversing at stations or not
+	byte   disasters;                        ///< are disasters enabled
+	byte   town_council_tolerance;           ///< minimum required town ratings to be allowed to demolish stuff
+	byte   diff_level;                       ///< the difficulty level
 };
 
-/* These are the options for the current game
- * either ingame, or loaded. Also used for networking games */
-extern GameOptions _opt;
-
-/* These are the default options for a new game */
-extern GameOptions _opt_newgame;
-
-/* Pointer to one of the two _opt OR _opt_newgame structs */
-extern GameOptions *_opt_ptr;
-
-struct Patches {
-	bool modified_catchment;            ///< different-size catchment areas
-	bool vehicle_speed;                 ///< show vehicle speed
-	bool build_on_slopes;               ///< allow building on slopes
-	bool mammoth_trains;                ///< allow very long trains
-	bool join_stations;                 ///< allow joining of train stations
-	bool sg_full_load_any;              ///< new full load calculation, any cargo must be full read from pre v93 savegames
-	bool improved_load;                 ///< improved loading algorithm
-	bool gradual_loading;               ///< load vehicles gradually
-	byte station_spread;                ///< amount a station may spread
-	bool inflation;                     ///< disable inflation
-	bool selectgoods;                   ///< only send the goods to station if a train has been there
-	bool longbridges;                   ///< allow 100 tile long bridges
-	bool gotodepot;                     ///< allow goto depot in orders
-	uint8 raw_industry_construction;    ///< Type of (raw) industry construction (none, "normal", prospecting)
-	bool multiple_industry_per_town;    ///< allow many industries of the same type per town
-	bool same_industry_close;           ///< allow same type industries to be built close to each other
-	bool lost_train_warn;               ///< if a train can't find its destination, show a warning
-	uint8 order_review_system;
-	bool train_income_warn;             ///< if train is generating little income, show a warning
-	bool status_long_date;              ///< always show long date in status bar
-	bool signal_side;                   ///< show signals on right side
-	bool show_finances;                 ///< show finances at end of year
-	bool sg_new_nonstop;                ///< ttdpatch compatible nonstop handling read from pre v93 savegames
-	bool new_nonstop;                   ///< ttdpatch compatible nonstop handling
-	bool roadveh_queue;                 ///< buggy road vehicle queueing
-	bool autoscroll;                    ///< scroll when moving mouse to the edge.
-	byte errmsg_duration;               ///< duration of error message
-	byte land_generator;                ///< the landscape generator
-	byte oil_refinery_limit;            ///< distance oil refineries allowed from map edge
-	byte snow_line_height;              ///< a number 0-15 that configured snow line height
-	byte tgen_smoothness;               ///< how rough is the terrain from 0-3
-	uint32 generation_seed;             ///< noise seed for world generation
-	byte tree_placer;                   ///< the tree placer algorithm
-	byte heightmap_rotation;            ///< rotation director for the heightmap
-	byte se_flat_world_height;          ///< land height a flat world gets in SE
-	bool bribe;                         ///< enable bribing the local authority
-	bool nonuniform_stations;           ///< allow nonuniform train stations
-	bool adjacent_stations;             ///< allow stations to be built directly adjacent to other stations
-	bool always_small_airport;          ///< always allow small airports
-	bool realistic_acceleration;        ///< realistic acceleration for trains
-	bool wagon_speed_limits;            ///< enable wagon speed limits
-	bool forbid_90_deg;                 ///< forbid trains to make 90 deg turns
-	bool no_servicing_if_no_breakdowns; ///< dont send vehicles to depot when breakdowns are disabled
-	bool link_terraform_toolbar;        ///< display terraform toolbar when displaying rail, road, water and airport toolbars
-	bool reverse_scroll;                ///< Right-Click-Scrolling scrolls in the opposite direction
-	bool smooth_scroll;                 ///< Smooth scroll viewports
-	bool disable_elrails;               ///< when true, the elrails are disabled
-	bool measure_tooltip;               ///< Show a permanent tooltip when dragging tools
-	byte liveries;                      ///< Options for displaying company liveries, 0=none, 1=self, 2=all
-	bool prefer_teamchat;               ///< Choose the chat message target with <ENTER>, true=all players, false=your team
-	uint8 advanced_vehicle_list;        ///< Use the "advanced" vehicle list
-	uint8 loading_indicators;           ///< Show loading indicators
-	uint8 default_rail_type;            ///< The default rail type for the rail GUI
+/** Settings related to the GUI and other stuff that is not saved in the savegame. */
+struct GUISettings {
+	bool   vehicle_speed;                    ///< show vehicle speed
+	bool   sg_full_load_any;                 ///< new full load calculation, any cargo must be full read from pre v93 savegames
+	bool   lost_train_warn;                  ///< if a train can't find its destination, show a warning
+	uint8  order_review_system;              ///< perform order reviews on vehicles
+	bool   train_income_warn;                ///< if train is generating little income, show a warning
+	bool   status_long_date;                 ///< always show long date in status bar
+	bool   show_finances;                    ///< show finances at end of year
+	bool   sg_new_nonstop;                   ///< ttdpatch compatible nonstop handling read from pre v93 savegames
+	bool   new_nonstop;                      ///< ttdpatch compatible nonstop handling
+	bool   autoscroll;                       ///< scroll when moving mouse to the edge
+	byte   errmsg_duration;                  ///< duration of error message
+	bool   link_terraform_toolbar;           ///< display terraform toolbar when displaying rail, road, water and airport toolbars
+	bool   reverse_scroll;                   ///< right-Click-Scrolling scrolls in the opposite direction
+	bool   smooth_scroll;                    ///< smooth scroll viewports
+	bool   measure_tooltip;                  ///< show a permanent tooltip when dragging tools
+	byte   liveries;                         ///< options for displaying company liveries, 0=none, 1=self, 2=all
+	bool   prefer_teamchat;                  ///< choose the chat message target with <ENTER>, true=all players, false=your team
+	uint8  advanced_vehicle_list;            ///< use the "advanced" vehicle list
+	uint8  loading_indicators;               ///< show loading indicators
+	uint8  default_rail_type;                ///< the default rail type for the rail GUI
+	uint8  toolbar_pos;                      ///< position of toolbars, 0=left, 1=center, 2=right
+	uint8  window_snap_radius;               ///< windows snap at each other if closer than this
+	bool   always_build_infrastructure;      ///< always allow building of infrastructure, even when you do not have the vehicles for it
+	byte   autosave;                         ///< how often should we do autosaves?
+	bool   keep_all_autosave;                ///< name the autosave in a different way
+	bool   autosave_on_exit;                 ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?"
+	byte   max_num_autosaves;                ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1)
+	bool   population_in_label;              ///< show the population of a town in his label?
+	uint8  right_mouse_btn_emulation;        ///< should we emulate right mouse clicking?
+	uint8  scrollwheel_scrolling;            ///< scrolling using the scroll wheel?
+	uint8  scrollwheel_multiplier;           ///< how much 'wheel' per incoming event from the OS?
+	bool   pause_on_newgame;                 ///< whether to start new games paused or not
+	bool   enable_signal_gui;                ///< show the signal GUI when the signal button is pressed
+	Year   ending_year;                      ///< end of the game (just show highscore)
+	Year   colored_news_year;                ///< when does newspaper become colored?
+	bool   timetable_in_ticks;               ///< whether to show the timetable in ticks rather than days
+	bool   bridge_pillars;                   ///< show bridge pillars for high bridges
+	bool   auto_euro;                        ///< automatically switch to euro in 2002
+	byte   drag_signals_density;             ///< many signals density
+	Year   semaphore_build_before;           ///< build semaphore signals automatically before this year
+	bool   autorenew;                        ///< should autorenew be enabled for new companies?
+	int16  autorenew_months;                 ///< how many months from EOL of vehicles should autorenew trigger for new companies?
+	int32  autorenew_money;                  ///< how much money before autorenewing for new companies?
+	byte   currency;                         ///< currency we currently use
+	byte   units;                            ///< unit system we show everything
+};
 
-	uint8 toolbar_pos;                  ///< position of toolbars, 0=left, 1=center, 2=right
-	uint8 window_snap_radius;           ///< Windows snap at each other if closer than this
-
-	bool always_build_infrastructure;   ///< Always allow building of infrastructure, even when you do not have the vehicles for it
-	UnitID max_trains;                  ///< max trains in game per player (these are 16bit because the unitnumber field can't hold more)
-	UnitID max_roadveh;                 ///< max trucks in game per player
-	UnitID max_aircraft;                ///< max planes in game per player
-	UnitID max_ships;                   ///< max ships in game per player
-
-	bool servint_ispercent;             ///< service intervals are in percents
-	uint16 servint_trains;              ///< service interval for trains
-	uint16 servint_roadveh;             ///< service interval for road vehicles
-	uint16 servint_aircraft;            ///< service interval for aircraft
-	uint16 servint_ships;               ///< service interval for ships
-
-	uint8 pathfinder_for_trains;        ///< the pathfinder to use for trains
-	uint8 pathfinder_for_roadvehs;      ///< the pathfinder to use for roadvehicles
-	uint8 pathfinder_for_ships;         ///< the pathfinder to use for ships
-
-	uint8 plane_speed;                  ///< divisor for speed of aircraft
-
-	bool autorenew;
-	int16 autorenew_months;
-	int32 autorenew_money;
-
-	byte pf_maxdepth;                      ///< maximum recursion depth when searching for a train route for new pathfinder
-	uint16 pf_maxlength;                   ///< maximum length when searching for a train route for new pathfinder
-
-	bool bridge_pillars;                   ///< show bridge pillars for high bridges
+/** Settings related to the creation of games. */
+struct GameCreationSettings {
+	uint32 generation_seed;                  ///< noise seed for world generation
+	Year   starting_year;                    ///< starting date
+	uint8  map_x;                            ///< X size of map
+	uint8  map_y;                            ///< Y size of map
+	byte   land_generator;                   ///< the landscape generator
+	byte   oil_refinery_limit;               ///< distance oil refineries allowed from map edge
+	byte   snow_line_height;                 ///< a number 0-15 that configured snow line height
+	byte   tgen_smoothness;                  ///< how rough is the terrain from 0-3
+	byte   tree_placer;                      ///< the tree placer algorithm
+	byte   heightmap_rotation;               ///< rotation director for the heightmap
+	byte   se_flat_world_height;             ///< land height a flat world gets in SE
+	byte   town_name;                        ///< the town name generator used for town names
+	byte   landscape;                        ///< the landscape we're currently in
+	byte   snow_line;                        ///< the snowline level in this game
+};
 
-	bool ai_disable_veh_train;             ///< disable types for AI
-	bool ai_disable_veh_roadveh;           ///< disable types for AI
-	bool ai_disable_veh_aircraft;          ///< disable types for AI
-	bool ai_disable_veh_ship;              ///< disable types for AI
-	Year starting_year;                    ///< starting date
-	Year ending_year;                      ///< end of the game (just show highscore)
-	Year colored_news_year;                ///< when does newspaper become colored?
-
-	bool keep_all_autosave;                ///< name the autosave in a different way.
-	bool autosave_on_exit;                 ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?"
-	byte max_num_autosaves;                ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1)
-	bool extra_dynamite;                   ///< extra dynamite
-	bool road_stop_on_town_road;           ///< allow building of drive-through road stops on town owned roads
-
-	bool never_expire_vehicles;            ///< never expire vehicles
-	byte extend_vehicle_life;              ///< extend vehicle life by this many years
+/** Settings related to construction in-game */
+struct ConstructionSettings {
+	bool   build_on_slopes;                  ///< allow building on slopes
+	bool   autoslope;                        ///< allow terraforming under things
+	bool   longbridges;                      ///< allow 100 tile long bridges
+	bool   signal_side;                      ///< show signals on right side
+	bool   extra_dynamite;                   ///< extra dynamite
+	bool   road_stop_on_town_road;           ///< allow building of drive-through road stops on town owned roads
+	uint8  raw_industry_construction;        ///< type of (raw) industry construction (none, "normal", prospecting)
+};
 
-	bool auto_euro;                        ///< automatically switch to euro in 2002
-	bool serviceathelipad;                 ///< service helicopters at helipads automatically (no need to send to depot)
-	bool smooth_economy;                   ///< smooth economy
-	bool allow_shares;                     ///< allow the buying/selling of shares
-	byte dist_local_authority;             ///< distance for town local authority, default 20
-
-	byte wait_oneway_signal;               ///< waitingtime in days before a oneway signal
-	byte wait_twoway_signal;               ///< waitingtime in days before a twoway signal
+/** Settings related to the AI. */
+struct AISettings {
+	bool   ainew_active;                     ///< is the new AI active?
+	bool   ai_in_multiplayer;                ///< so we allow AIs in multiplayer
+	bool   ai_disable_veh_train;             ///< disable types for AI
+	bool   ai_disable_veh_roadveh;           ///< disable types for AI
+	bool   ai_disable_veh_aircraft;          ///< disable types for AI
+	bool   ai_disable_veh_ship;              ///< disable types for AI
+};
 
-	uint8 map_x;                           ///< Size of map
-	uint8 map_y;
+/** Settings related to the old pathfinder. */
+struct OPFSettings {
+	uint16 pf_maxlength;                     ///< maximum length when searching for a train route for new pathfinder
+	byte   pf_maxdepth;                      ///< maximum recursion depth when searching for a train route for new pathfinder
+};
 
-	byte drag_signals_density;             ///< many signals density
-	Year semaphore_build_before;           ///< Build semaphore signals automatically before this year
-	bool ainew_active;                     ///< Is the new AI active?
-	bool ai_in_multiplayer;                ///< Do we allow AIs in multiplayer
-
-	/*
-	 * New Path Finding
-	 */
-	bool new_pathfinding_all;              ///< Use the newest pathfinding algorithm for all
-
+/** Settings related to the new pathfinder. */
+struct NPFSettings {
 	/**
 	 * The maximum amount of search nodes a single NPF run should take. This
 	 * limit should make sure performance stays at acceptable levels at the cost
-	 * of not being perfect anymore. This will probably be fixed in a more
-	 * sophisticated way sometime soon
+	 * of not being perfect anymore.
 	 */
 	uint32 npf_max_search_nodes;
 
-	uint32 npf_rail_firstred_penalty;      ///< The penalty for when the first signal is red (and it is not an exit or combo signal)
-	uint32 npf_rail_firstred_exit_penalty; ///< The penalty for when the first signal is red (and it is an exit or combo signal)
-	uint32 npf_rail_lastred_penalty;       ///< The penalty for when the last signal is red
-	uint32 npf_rail_station_penalty;       ///< The penalty for station tiles
-	uint32 npf_rail_slope_penalty;         ///< The penalty for sloping upwards
-	uint32 npf_rail_curve_penalty;         ///< The penalty for curves
-	uint32 npf_rail_depot_reverse_penalty; ///< The penalty for reversing in depots
-	uint32 npf_buoy_penalty;               ///< The penalty for going over (through) a buoy
-	uint32 npf_water_curve_penalty;        ///< The penalty for curves
-	uint32 npf_road_curve_penalty;         ///< The penalty for curves
-	uint32 npf_crossing_penalty;           ///< The penalty for level crossings
-	uint32 npf_road_drive_through_penalty; ///< The penalty for going through a drive-through road stop
-
-	bool population_in_label;              ///< Show the population of a town in his label?
-
-	uint8 freight_trains;                  ///< Value to multiply the weight of cargo by
-
-	/** YAPF settings */
-	YapfSettings  yapf;
-
-	uint8 right_mouse_btn_emulation;
-
-	uint8 scrollwheel_scrolling;
-	uint8 scrollwheel_multiplier;
-
-	uint8 town_growth_rate;      ///< Town growth rate
-	uint8 larger_towns;          ///< The number of cities to build. These start off larger and grow twice as fast
-	uint8 initial_city_size;     ///< Multiplier for the initial size of the cities compared to towns
-
-	bool pause_on_newgame;       ///< Whether to start new games paused or not.
-
-	TownLayoutByte town_layout;  ///< Select town layout
-
-	bool timetabling;            ///< Whether to allow timetabling.
-	bool timetable_in_ticks;     ///< Whether to show the timetable in ticks rather than days.
-
-	bool autoslope;              ///< Allow terraforming under things.
-
-	bool mod_road_rebuild;       ///< Roadworks remove unneccesary RoadBits
-
-	bool exclusive_rights;       ///< allow buying exclusive rights
-	bool give_money;             ///< allow giving other players money
-
-	bool enable_signal_gui;      ///< Show the signal GUI when the signal button is pressed
-
-	bool dynamic_engines;    ///< Enable dynamic allocation of engine data
+	uint32 npf_rail_firstred_penalty;        ///< the penalty for when the first signal is red (and it is not an exit or combo signal)
+	uint32 npf_rail_firstred_exit_penalty;   ///< the penalty for when the first signal is red (and it is an exit or combo signal)
+	uint32 npf_rail_lastred_penalty;         ///< the penalty for when the last signal is red
+	uint32 npf_rail_station_penalty;         ///< the penalty for station tiles
+	uint32 npf_rail_slope_penalty;           ///< the penalty for sloping upwards
+	uint32 npf_rail_curve_penalty;           ///< the penalty for curves
+	uint32 npf_rail_depot_reverse_penalty;   ///< the penalty for reversing in depots
+	uint32 npf_buoy_penalty;                 ///< the penalty for going over (through) a buoy
+	uint32 npf_water_curve_penalty;          ///< the penalty for curves
+	uint32 npf_road_curve_penalty;           ///< the penalty for curves
+	uint32 npf_crossing_penalty;             ///< the penalty for level crossings
+	uint32 npf_road_drive_through_penalty;   ///< the penalty for going through a drive-through road stop
 };
 
-extern Patches _patches;
+/** Settings related to the yet another pathfinder. */
+struct YAPFSettings {
+	bool   disable_node_optimization;        ///< whether to use exit-dir instead of trackdir in node key
+	uint32 max_search_nodes;                 ///< stop path-finding when this number of nodes visited
+	bool   ship_use_yapf;                    ///< use YAPF for ships
+	bool   road_use_yapf;                    ///< use YAPF for road
+	bool   rail_use_yapf;                    ///< use YAPF for rail
+	uint32 road_slope_penalty;               ///< penalty for up-hill slope
+	uint32 road_curve_penalty;               ///< penalty for curves
+	uint32 road_crossing_penalty;            ///< penalty for level crossing
+	uint32 road_stop_penalty;                ///< penalty for going through a drive-through road stop
+	bool   rail_firstred_twoway_eol;         ///< treat first red two-way signal as dead end
+	uint32 rail_firstred_penalty;            ///< penalty for first red signal
+	uint32 rail_firstred_exit_penalty;       ///< penalty for first red exit signal
+	uint32 rail_lastred_penalty;             ///< penalty for last red signal
+	uint32 rail_lastred_exit_penalty;        ///< penalty for last red exit signal
+	uint32 rail_station_penalty;             ///< penalty for non-target station tile
+	uint32 rail_slope_penalty;               ///< penalty for up-hill slope
+	uint32 rail_curve45_penalty;             ///< penalty for curve
+	uint32 rail_curve90_penalty;             ///< penalty for 90-deg curve
+	uint32 rail_depot_reverse_penalty;       ///< penalty for reversing in the depot
+	uint32 rail_crossing_penalty;            ///< penalty for level crossing
+	uint32 rail_look_ahead_max_signals;      ///< max. number of signals taken into consideration in look-ahead load balancer
+	int32  rail_look_ahead_signal_p0;        ///< constant in polynomial penalty function
+	int32  rail_look_ahead_signal_p1;        ///< constant in polynomial penalty function
+	int32  rail_look_ahead_signal_p2;        ///< constant in polynomial penalty function
 
-/** The patch values that are used for new games and/or modified in config file */
-extern Patches _patches_newgame;
+	uint32 rail_longer_platform_penalty;           ///< penalty for longer  station platform than train
+	uint32 rail_longer_platform_per_tile_penalty;  ///< penalty for longer  station platform than train (per tile)
+	uint32 rail_shorter_platform_penalty;          ///< penalty for shorter station platform than train
+	uint32 rail_shorter_platform_per_tile_penalty; ///< penalty for shorter station platform than train (per tile)
+};
+
+/** Settings related to all pathfinders. */
+struct PathfinderSettings {
+	uint8  pathfinder_for_trains;            ///< the pathfinder to use for trains
+	uint8  pathfinder_for_roadvehs;          ///< the pathfinder to use for roadvehicles
+	uint8  pathfinder_for_ships;             ///< the pathfinder to use for ships
+	bool   new_pathfinding_all;              ///< use the newest pathfinding algorithm for all
+
+	bool   roadveh_queue;                    ///< buggy road vehicle queueing
+	bool   forbid_90_deg;                    ///< forbid trains to make 90 deg turns
+
+	byte   wait_oneway_signal;               ///< waitingtime in days before a oneway signal
+	byte   wait_twoway_signal;               ///< waitingtime in days before a twoway signal
+
+	OPFSettings  opf;                        ///< pathfinder settings for the old pathfinder
+	NPFSettings  npf;                        ///< pathfinder settings for the new pathfinder
+	YAPFSettings yapf;                       ///< pathfinder settings for the yet another pathfinder
+};
+
+/** Settings related to orders. */
+struct OrderSettings {
+	bool   improved_load;                    ///< improved loading algorithm
+	bool   gradual_loading;                  ///< load vehicles gradually
+	bool   selectgoods;                      ///< only send the goods to station if a train has been there
+	bool   gotodepot;                        ///< allow goto depot in orders
+	bool   no_servicing_if_no_breakdowns;    ///< dont send vehicles to depot when breakdowns are disabled
+	bool   timetabling;                      ///< whether to allow timetabling
+	bool   serviceathelipad;                 ///< service helicopters at helipads automatically (no need to send to depot)
+};
+
+/** Settings related to vehicles. */
+struct VehicleSettings {
+	bool   mammoth_trains;                   ///< allow very long trains
+	bool   realistic_acceleration;           ///< realistic acceleration for trains
+	bool   wagon_speed_limits;               ///< enable wagon speed limits
+	bool   disable_elrails;                  ///< when true, the elrails are disabled
+	UnitID max_trains;                       ///< max trains in game per player
+	UnitID max_roadveh;                      ///< max trucks in game per player
+	UnitID max_aircraft;                     ///< max planes in game per player
+	UnitID max_ships;                        ///< max ships in game per player
+	bool   servint_ispercent;                ///< service intervals are in percents
+	uint16 servint_trains;                   ///< service interval for trains
+	uint16 servint_roadveh;                  ///< service interval for road vehicles
+	uint16 servint_aircraft;                 ///< service interval for aircraft
+	uint16 servint_ships;                    ///< service interval for ships
+	uint8  plane_speed;                      ///< divisor for speed of aircraft
+	uint8  freight_trains;                   ///< value to multiply the weight of cargo by
+	bool   dynamic_engines;                  ///< enable dynamic allocation of engine data
+	bool   never_expire_vehicles;            ///< never expire vehicles
+	byte   extend_vehicle_life;              ///< extend vehicle life by this many years
+	byte   road_side;                        ///< the side of the road vehicles drive on
+};
+
+/** Settings related to the economy. */
+struct EconomySettings {
+	bool   inflation;                        ///< disable inflation
+	bool   bribe;                            ///< enable bribing the local authority
+	bool   smooth_economy;                   ///< smooth economy
+	bool   allow_shares;                     ///< allow the buying/selling of shares
+	byte   dist_local_authority;             ///< distance for town local authority, default 20
+	bool   exclusive_rights;                 ///< allow buying exclusive rights
+	bool   give_money;                       ///< allow giving other players money
+	bool   mod_road_rebuild;                 ///< roadworks remove unneccesary RoadBits
+	bool   multiple_industry_per_town;       ///< allow many industries of the same type per town
+	bool   same_industry_close;              ///< allow same type industries to be built close to each other
+	uint8  town_growth_rate;                 ///< town growth rate
+	uint8  larger_towns;                     ///< the number of cities to build. These start off larger and grow twice as fast
+	uint8  initial_city_size;                ///< multiplier for the initial size of the cities compared to towns
+	TownLayoutByte town_layout;              ///< select town layout
+	bool   station_noise_level;              ///< build new airports when the town noise level is still within accepted limits
+	uint16 town_noise_population[3];         ///< population to base decision on noise evaluation (@see town_council_tolerance)
+};
+
+/** Settings related to stations. */
+struct StationSettings {
+	bool   modified_catchment;               ///< different-size catchment areas
+	bool   join_stations;                    ///< allow joining of train stations
+	bool   nonuniform_stations;              ///< allow nonuniform train stations
+	bool   adjacent_stations;                ///< allow stations to be built directly adjacent to other stations
+	bool   always_small_airport;             ///< always allow small airports
+	byte   station_spread;                   ///< amount a station may spread
+};
+
+/** All settings together. */
+struct Settings {
+	DifficultySettings   difficulty;         ///< settings related to the difficulty
+	GUISettings          gui;                ///< settings related to the GUI
+	GameCreationSettings game_creation;      ///< settings used during the creation of a game (map)
+	ConstructionSettings construction;       ///< construction of things in-game
+	AISettings           ai;                 ///< what may the AI do?
+	PathfinderSettings   pf;                 ///< settings for all pathfinders
+	OrderSettings        order;              ///< settings related to orders
+	VehicleSettings      vehicle;            ///< options for vehicles
+	EconomySettings      economy;            ///< settings to change the economy
+	StationSettings      station;            ///< settings related to station management
+};
+
+/** The current settings. */
+extern Settings _settings;
+
+/** The settings values that are used for new games and/or modified in config file */
+extern Settings _settings_newgame;
 
 #endif /* SETTINGS_TYPE_H */
--- a/src/ship_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/ship_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -106,7 +106,7 @@
 
 static const Depot* FindClosestShipDepot(const Vehicle* v)
 {
-	if (_patches.pathfinder_for_ships == VPF_NPF) { /* NPF is used */
+	if (_settings.pf.pathfinder_for_ships == VPF_NPF) { /* NPF is used */
 		Trackdir trackdir = GetVehicleTrackdir(v);
 		NPFFoundTargetData ftd = NPFRouteToDepotTrialError(v->tile, trackdir, false, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES);
 
@@ -137,7 +137,7 @@
 
 static void CheckIfShipNeedsService(Vehicle *v)
 {
-	if (_patches.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
+	if (_settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
 	if (v->IsInDepot()) {
 		VehicleServiceInDepot(v);
 		return;
@@ -196,7 +196,7 @@
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
 		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
-			SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ?
+			SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ?
 				SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
 		}
 
@@ -320,7 +320,7 @@
 	/*updates statusbar only if speed have changed to save CPU time */
 	if (spd != v->cur_speed) {
 		v->cur_speed = spd;
-		if (_patches.vehicle_speed)
+		if (_settings.gui.vehicle_speed)
 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 	}
 
@@ -459,7 +459,7 @@
 {
 	assert(IsValidDiagDirection(enterdir));
 
-	switch (_patches.pathfinder_for_ships) {
+	switch (_settings.pf.pathfinder_for_ships) {
 		case VPF_YAPF: { /* YAPF */
 			Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
 			if (trackdir != INVALID_TRACKDIR) return TrackdirToTrack(trackdir);
@@ -756,7 +756,7 @@
 
 	unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_SHIP);
 
-	if (!Vehicle::AllocateList(NULL, 1) || unit_num > _patches.max_ships)
+	if (!Vehicle::AllocateList(NULL, 1) || unit_num > _settings.vehicle.max_ships)
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 	if (flags & DC_EXEC) {
@@ -800,7 +800,7 @@
 		v->name = NULL;
 		v->u.ship.state = TRACK_BIT_DEPOT;
 
-		v->service_interval = _patches.servint_ships;
+		v->service_interval = _settings.vehicle.servint_ships;
 		v->date_of_last_service = _date;
 		v->build_year = _cur_year;
 		v->cur_image = 0x0E5E;
@@ -814,7 +814,7 @@
 		VehiclePositionChanged(v);
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 		InvalidateWindow(WC_COMPANY, v->owner);
 		if (IsLocalPlayer())
 			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Ship window
@@ -851,7 +851,7 @@
 
 	if (flags & DC_EXEC) {
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 		InvalidateWindow(WC_COMPANY, v->owner);
 		DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 		DeleteDepotHighlightOfVehicle(v);
@@ -997,7 +997,7 @@
 		v->cargo_subtype = new_subtype;
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 	}
 
 	return cost;
--- a/src/signal.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/signal.cpp	Tue May 27 00:50:55 2008 +0000
@@ -465,7 +465,7 @@
  * Updates blocks in _globset buffer
  *
  * @param owner player whose signals we are updating
- * @return false iff presignal entry would be green (needed for trains leaving depot)
+ * @return state of the first block from _globset
  * @pre IsValidPlayer(owner)
  */
 static SigSegState UpdateSignalsInBuffer(Owner owner)
@@ -630,7 +630,7 @@
  * @param tile tile where we start
  * @param side side of tile
  * @param owner owner whose signals we will update
- * @return false iff train can leave depot
+ * @return the state of the signal segment
  */
 SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
 {
--- a/src/signs_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/signs_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -66,54 +66,63 @@
 	DEBUG(misc, 3, "Resorting global signs list");
 }
 
-static void SignListWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			if (_sign_sort_dirty) GlobalSortSignList();
-
-			SetVScrollCount(w, _num_sign_sort);
-
-			SetDParam(0, w->vscroll.count);
-			w->DrawWidgets();
-
-			/* 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 (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);
+struct SignListWindow : Window {
+	SignListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->vscroll.cap = 12;
+		this->resize.step_height = 10;
+		this->resize.height = this->height - 10 * 7; // minimum if 5 in the list
 
-				SetDParam(0, si->index);
-				DrawString(22, y, STR_SIGN_NAME, TC_YELLOW);
-				y += 10;
-			}
-		} break;
-
-		case WE_CLICK:
-			if (e->we.click.widget == 3) {
-				uint32 id_v = (e->we.click.pt.y - 15) / 10;
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-				if (id_v >= w->vscroll.cap) return;
-				id_v += w->vscroll.pos;
-				if (id_v >= w->vscroll.count) return;
+	virtual void OnPaint()
+	{
+		if (_sign_sort_dirty) GlobalSortSignList();
 
-				const Sign *si = _sign_sort[id_v];
-				ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
-			}
-			break;
+		SetVScrollCount(this, _num_sign_sort);
 
-		case WE_RESIZE:
-			w->vscroll.cap += e->we.sizing.diff.y / 10;
-			break;
+		SetDParam(0, this->vscroll.count);
+		this->DrawWidgets();
+
+		/* No signs? */
+		int y = 16; // offset from top of widget
+		if (this->vscroll.count == 0) {
+			DrawString(2, y, STR_304A_NONE, TC_FROMSTRING);
+			return;
+		}
+
+		/* Start drawing the signs */
+		for (uint16 i = this->vscroll.pos; i < this->vscroll.cap + this->vscroll.pos && i < this->vscroll.count; i++) {
+			const Sign *si = _sign_sort[i];
+
+			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;
+		}
 	}
-}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget == 3) {
+			uint32 id_v = (pt.y - 15) / 10;
+
+			if (id_v >= this->vscroll.cap) return;
+			id_v += this->vscroll.pos;
+			if (id_v >= this->vscroll.count) return;
+
+			const Sign *si = _sign_sort[id_v];
+			ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
+		}
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->vscroll.cap += delta.y / 10;
+	}
+};
 
 static const Widget _sign_list_widget[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
@@ -130,18 +139,12 @@
 	WC_SIGN_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_sign_list_widget,
-	SignListWndProc
 };
 
 
 void ShowSignList()
 {
-	Window *w = AllocateWindowDescFront<Window>(&_sign_list_desc, 0);
-	if (w != NULL) {
-		w->vscroll.cap = 12;
-		w->resize.step_height = 10;
-		w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
-	}
+	AllocateWindowDescFront<SignListWindow>(&_sign_list_desc, 0);
 }
 
 static void RenameSign(SignID index, const char *text)
@@ -170,6 +173,7 @@
 		this->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
 
 		UpdateSignEditWindow(si);
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	~SignWindow()
@@ -255,10 +259,10 @@
 		}
 	}
 
-	virtual bool OnKeyPress(uint16 key, uint16 keycode)
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 	{
-		bool cont = true;
-		switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, cont)) {
+		EventState state = ES_NOT_HANDLED;
+		switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, state)) {
 			case 1: // Enter pressed, confirms change
 				RenameSign(this->cur_sign, this->text.buf);
 				/* FALL THROUGH */
@@ -267,7 +271,7 @@
 				delete this;
 				break;
 		}
-		return cont;
+		return state;
 	}
 
 	virtual void OnMouseLoop()
@@ -295,7 +299,6 @@
 	WC_QUERY_STRING, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_query_sign_edit_widgets,
-	NULL
 };
 
 void ShowRenameSignWindow(const Sign *si)
--- a/src/smallmap_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/smallmap_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -459,7 +459,7 @@
 
 		case MP_TREES:
 			if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) {
-				bits = (_opt.landscape == LT_ARCTIC) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2);
+				bits = (_settings.game_creation.landscape == LT_ARCTIC) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2);
 			} else {
 				bits = MKCOLOR(0x54575754);
 			}
@@ -490,6 +490,10 @@
 		case MP_INDUSTRY: o = OWNER_END;          break;
 		case MP_HOUSE:    o = OWNER_TOWN;         break;
 		default:          o = GetTileOwner(tile); break;
+		/* FIXME: For MP_ROAD there are multiple owners.
+		 * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
+		 * even if there are no ROADTYPE_ROAD bits on the tile.
+		 */
 	}
 
 	return _owner_colors[o];
@@ -1078,7 +1082,6 @@
 	WC_SMALLMAP, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_smallmap_widgets,
-	NULL
 };
 
 void ShowSmallMap()
@@ -1224,7 +1227,6 @@
 	WC_EXTRA_VIEW_PORT, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_extra_view_port_widgets,
-	NULL
 };
 
 void ShowExtraViewPortWindow(TileIndex tile)
--- a/src/sortlist_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/sortlist_type.h	Tue May 27 00:50:55 2008 +0000
@@ -5,12 +5,16 @@
 #ifndef SORTLIST_TYPE_H
 #define SORTLIST_TYPE_H
 
+#include "misc/smallvec.h"
+#include "date_type.h"
+
 enum SortListFlags {
-	VL_NONE    = 0,      ///< no sort
-	VL_DESC    = 1 << 0, ///< sort descending or ascending
-	VL_RESORT  = 1 << 1, ///< instruct the code to resort the list in the next loop
-	VL_REBUILD = 1 << 2, ///< create sort-listing to use for qsort and friends
-	VL_END     = 1 << 3,
+	VL_NONE       = 0,      ///< no sort
+	VL_DESC       = 1 << 0, ///< sort descending or ascending
+	VL_RESORT     = 1 << 1, ///< instruct the code to resort the list in the next loop
+	VL_REBUILD    = 1 << 2, ///< rebuild the sort list
+	VL_FIRST_SORT = 1 << 3, ///< sort with qsort first
+	VL_END        = 1 << 4,
 };
 DECLARE_ENUM_AS_BIT_SET(SortListFlags);
 
@@ -20,12 +24,269 @@
 };
 
 template <typename T>
-struct GUIList {
-	T* sort_list;        ///< The items to sort.
-	SortListFlags flags; ///< used to control sorting/resorting/etc.
-	uint16 list_length;  ///< length of the list being sorted
-	uint16 resort_timer; ///< resort list after a given amount of ticks if set
-	byte sort_type;      ///< what criteria to sort on
+class GUIList : public SmallVector<T, 32> {
+public:
+	typedef int CDECL SortFunction(const T*, const T*);
+
+public: // Temporary: public for conversion only
+	SortFunction* const *func_list; ///< The sort criteria functions
+	SortListFlags flags;            ///< used to control sorting/resorting/etc.
+	uint8 sort_type;                ///< what criteria to sort on
+	uint16 resort_timer;            ///< resort list after a given amount of ticks if set
+
+	/**
+	 * Check if the list is sortable
+	 *
+	 * @return true if we can sort the list
+	 */
+	bool IsSortable() const
+	{
+		return (this->data != NULL && this->items >= 2);
+	}
+
+	/**
+	 * Reset the resort timer
+	 */
+	void ResetResortTimer()
+	{
+		/* Resort every 10 days */
+		this->resort_timer = DAY_TICKS * 10;
+	}
+
+	/**
+	 * Reverse the list
+	 */
+	void Reverse()
+	{
+		assert(this->IsSortable());
+
+		T *a = this->data;
+		T *b = a + (this->items - 1);
+
+		do {
+			Swap(*a, *b);
+		} while (++a < --b);
+	}
+
+public:
+	GUIList() :
+		func_list(NULL),
+		flags(VL_FIRST_SORT),
+		sort_type(0),
+		resort_timer(1)
+	{};
+
+	/**
+	 * Get the sorttype of the list
+	 *
+	 * @return The current sorttype
+	 */
+	uint8 SortType() const
+	{
+		return this->sort_type;
+	}
+
+	/**
+	 * Set the sorttype of the list
+	 *
+	 * @param n_type the new sort type
+	 */
+	void SetSortType(uint8 n_type)
+	{
+		if (this->sort_type != n_type) {
+			SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
+			this->sort_type = n_type;
+		}
+	}
+
+	/**
+	 * Export current sort conditions
+	 *
+	 * @return the current sort conditions
+	 */
+	Listing GetListing() const
+	{
+		Listing l;
+		l.order = HASBITS(this->flags, VL_DESC);
+		l.criteria = this->sort_type;
+
+		return l;
+	}
+
+	/**
+	 * Import sort conditions
+	 *
+	 * @param l The sport conditions we want to use
+	 */
+	void SetListing(Listing l)
+	{
+		if (l.order) {
+			SETBITS(this->flags, VL_DESC);
+		} else {
+			CLRBITS(this->flags, VL_DESC);
+		}
+		this->sort_type = l.criteria;
+
+		SETBITS(this->flags, VL_FIRST_SORT);
+	}
+
+	/**
+	 * Check if a resort is needed next loop
+	 *  If used the resort timer will decrease every call
+	 *  till 0. If 0 reached the resort bit will be set and
+	 *  the timer will be reset.
+	 *
+	 * @return true if resort bit is set for next loop
+	 */
+	bool NeedResort()
+	{
+		if (--this->resort_timer == 0) {
+			SETBITS(this->flags, VL_RESORT);
+			this->ResetResortTimer();
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Force a resort next Sort call
+	 *  Reset the resort timer if used too.
+	 */
+	void ForceResort()
+	{
+		SETBITS(this->flags, VL_RESORT);
+	}
+
+	/**
+	 * Check if the sort order is descending
+	 *
+	 * @return true if the sort order is descending
+	 */
+	bool IsDescSortOrder() const
+	{
+		return HASBITS(this->flags, VL_DESC);
+	}
+
+	/**
+	 * Toogle the sort order
+	 *  Since that is the worst condition for the sort function
+	 *  reverse the list here.
+	 */
+	FORCEINLINE void ToggleSortOrder()
+	{
+		this->flags ^= VL_DESC;
+
+		if (this->IsSortable()) this->Reverse();
+	}
+
+	/**
+	 * GnomeSort algorithm
+	 *  This sorting uses a slightly modifyied Gnome search.
+	 *  The basic Gnome search trys to sort already sorted
+	 *  list parts. The modification skips these. For the first
+	 *  sorting we use qsort since it is faster for irregular
+	 *  sorted data.
+	 *
+	 * @param compare The function to compare two list items
+	 * */
+	FORCEINLINE void Sort(SortFunction *compare)
+	{
+		/* Do not sort if the resort bit is not set */
+		if (!HASBITS(this->flags, VL_RESORT)) return;
+
+		CLRBITS(this->flags, VL_RESORT);
+
+		this->ResetResortTimer();
+
+		/* Do not sort when the list is not sortable */
+		if (!this->IsSortable()) return;
+
+		const bool desc = HASBITS(this->flags, VL_DESC);
+
+		if (HASBITS(this->flags, VL_FIRST_SORT)) {
+			qsort(this->data, this->items, sizeof(T), (int (CDECL *)(const void *, const void *))compare);
+
+			if (desc) this->Reverse();
+			return;
+		}
+
+		T *a = this->data;
+		T *b = a + 1;
+
+		uint length = this->items;
+		uint offset = 0; // Jump variable
+
+		while (length > 1) {
+			const int diff = compare(a, b);
+			if ((!desc && diff <= 0) || (desc && diff >= 0)) {
+				if (offset != 0) {
+					/* Jump back to the last direction switch point */
+					a += offset;
+					b += offset;
+					offset = 0;
+					continue;
+				}
+				a++;
+				b++;
+				length--;
+			} else {
+				Swap(*a, *b);
+				if (a != this->data) {
+					offset++;
+					a--;
+					b--;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Hand the array of sort function pointers to the sort list
+	 *
+	 * @param n_funcs The pointer to the first sort func
+	 */
+	void SetSortFuncs(SortFunction* const* n_funcs)
+	{
+		this->func_list = n_funcs;
+	}
+
+	/**
+	 * Overload of Sort()
+	 * Overloaded to reduce external code
+	 */
+	void Sort()
+	{
+		assert(this->func_list != NULL);
+		this->Sort(this->func_list[this->sort_type]);
+	}
+
+	/**
+	 * Check if a rebuild is needed
+	 * @return true if a rebuild is needed
+	 */
+	bool NeedRebuild() const
+	{
+		return HASBITS(this->flags, VL_REBUILD);
+	}
+
+	/**
+	 * Force that a rebuild is needed
+	 */
+	void ForceRebuild()
+	{
+		SETBITS(this->flags, VL_REBUILD);
+	}
+
+	/**
+	 * Notify the sortlist that the rebuild is done
+	 *
+	 * @note This forces a resort
+	 */
+	void RebuildDone()
+	{
+		CLRBITS(this->flags, VL_REBUILD);
+		SETBITS(this->flags, VL_RESORT);
+	}
 };
 
 #endif /* SORTLIST_TYPE_H */
--- a/src/station.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/station.cpp	Tue May 27 00:50:55 2008 +0000
@@ -74,8 +74,7 @@
 	}
 
 	MarkDirty();
-	RebuildStationLists();
-	InvalidateWindowClasses(WC_STATION_LIST);
+	InvalidateWindowData(WC_STATION_LIST, this->owner, 0);
 
 	DeleteWindowById(WC_STATION_VIEW, index);
 
@@ -286,7 +285,7 @@
 		/* check new rect dimensions against preset max */
 		int w = new_rect.right - new_rect.left + 1;
 		int h = new_rect.bottom - new_rect.top + 1;
-		if (mode != ADD_FORCE && (w > _patches.station_spread || h > _patches.station_spread)) {
+		if (mode != ADD_FORCE && (w > _settings.station.station_spread || h > _settings.station.station_spread)) {
 			assert(mode != ADD_TRY);
 			_error_message = STR_306C_STATION_TOO_SPREAD_OUT;
 			return false;
--- a/src/station_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -358,7 +358,7 @@
 				CountMapSquareAround(tile, CMSATree) >= 8 ||
 				CountMapSquareAround(tile, CMSAForest) >= 2)
 			) {
-		return _opt.landscape == LT_TROPIC ? STR_SV_STNAME_FOREST : STR_SV_STNAME_WOODS;
+		return _settings.game_creation.landscape == LT_TROPIC ? STR_SV_STNAME_FOREST : STR_SV_STNAME_WOODS;
 	}
 
 	/* check elevation compared to town */
@@ -625,7 +625,7 @@
 			TileXY(rect.left, rect.bottom),
 			rect.right - rect.left   + 1,
 			rect.top   - rect.bottom + 1,
-			_patches.modified_catchment ? FindCatchmentRadius(st) : (uint)CA_UNMODIFIED
+			_settings.station.modified_catchment ? FindCatchmentRadius(st) : (uint)CA_UNMODIFIED
 		);
 	} else {
 		memset(accepts, 0, sizeof(accepts));
@@ -712,8 +712,7 @@
 {
 	if (st->facilities == 0) {
 		st->delete_ctr = 0;
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 	}
 	/* station remains but it probably lost some parts - station sign should stay in the station boundaries */
 	UpdateStationSignCoord(st);
@@ -763,7 +762,7 @@
 		 *     b) the build_on_slopes switch is disabled
 		 */
 		if (IsSteepSlope(tileh) ||
-				((_is_old_ai_player || !_patches.build_on_slopes) && tileh != SLOPE_FLAT)) {
+				((_is_old_ai_player || !_settings.construction.build_on_slopes) && tileh != SLOPE_FLAT)) {
 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 		}
 
@@ -840,7 +839,7 @@
 	uint w = fin[1];
 	uint h = fin[2];
 
-	if (_patches.nonuniform_stations) {
+	if (_settings.station.nonuniform_stations) {
 		/* determine new size of train station region.. */
 		int x = min(TileX(st->train_tile), TileX(tile));
 		int y = min(TileY(st->train_tile), TileY(tile));
@@ -884,7 +883,7 @@
 		}
 	}
 	/* make sure the final size is not too big. */
-	if (curw > _patches.station_spread || curh > _patches.station_spread) {
+	if (curw > _settings.station.station_spread || curh > _settings.station.station_spread) {
 		_error_message = STR_306C_STATION_TOO_SPREAD_OUT;
 		return false;
 	}
@@ -973,7 +972,7 @@
 		w_org = numtracks;
 	}
 
-	if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR;
+	if (h_org > _settings.station.station_spread || w_org > _settings.station.station_spread) return CMD_ERROR;
 
 	/* these values are those that will be stored in train_tile and station_platforms */
 	uint finalvalues[3];
@@ -986,14 +985,14 @@
 	/* If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug
 	 * for detail info, see:
 	 * https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 */
-	CommandCost ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
+	CommandCost ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _settings.station.nonuniform_stations ? &est : NULL);
 	if (CmdFailed(ret)) return ret;
 	CommandCost cost(EXPENSES_CONSTRUCTION, ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
 
 	Station *st = NULL;
 	bool check_surrounding = true;
 
-	if (_patches.adjacent_stations) {
+	if (_settings.station.adjacent_stations) {
 		if (est != INVALID_STATION) {
 			if (HasBit(p1, 24)) {
 				/* You can't build an adjacent station over the top of one that
@@ -1028,7 +1027,7 @@
 
 		if (st->train_tile != 0) {
 			/* check if we want to expanding an already existing station? */
-			if (_is_old_ai_player || !_patches.join_stations)
+			if (_is_old_ai_player || !_settings.station.join_stations)
 				return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD);
 			if (!CanExpandRailroadStation(st, finalvalues, axis))
 				return CMD_ERROR;
@@ -1083,7 +1082,7 @@
 		/* Now really clear the land below the station
 		 * It should never return CMD_ERROR.. but you never know ;)
 		 * (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags) */
-		ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
+		ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _settings.station.nonuniform_stations ? &est : NULL);
 		if (CmdFailed(ret)) return ret;
 
 		st->train_tile = finalvalues[0];
@@ -1140,8 +1139,7 @@
 		st->MarkTilesDirty(false);
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 	}
 
@@ -1253,7 +1251,7 @@
 		/* Do not allow removing from stations if non-uniform stations are not enabled
 		 * The check must be here to give correct error message
 		 */
-		if (!_patches.nonuniform_stations) return_cmd_error(STR_NONUNIFORM_STATIONS_DISALLOWED);
+		if (!_settings.station.nonuniform_stations) return_cmd_error(STR_NONUNIFORM_STATIONS_DISALLOWED);
 
 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
 		quantity++;
@@ -1298,7 +1296,7 @@
 static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
 {
 	/* if there is flooding and non-uniform stations are enabled, remove platforms tile by tile */
-	if (_current_player == OWNER_WATER && _patches.nonuniform_stations) {
+	if (_current_player == OWNER_WATER && _settings.station.nonuniform_stations) {
 		return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAILROAD_STATION);
 	}
 
@@ -1391,7 +1389,7 @@
 	bool type = HasBit(p2, 0);
 	bool is_drive_through = HasBit(p2, 1);
 	bool build_over_road  = is_drive_through && IsNormalRoadTile(tile);
-	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
+	bool town_owned_road  = false;
 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
 
 	if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
@@ -1410,14 +1408,17 @@
 
 	/* Not allowed to build over this road */
 	if (build_over_road) {
-		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
-
 		RoadTypes cur_rts = GetRoadTypes(tile);
 
 		/* there is a road, check if we can build road+tram stop over it */
 		if (HasBit(cur_rts, ROADTYPE_ROAD)) {
 			Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
-			if (road_owner != OWNER_TOWN && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR;
+			if (road_owner == OWNER_TOWN) {
+				town_owned_road = true;
+				if (!_settings.construction.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
+			} else {
+				if (road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR;
+			}
 		}
 
 		/* there is a tram, check if we can build road+tram stop over it */
@@ -1437,7 +1438,7 @@
 
 	Station *st = NULL;
 
-	if (!_patches.adjacent_stations || !HasBit(p2, 5)) {
+	if (!_settings.station.adjacent_stations || !HasBit(p2, 5)) {
 		st = GetStationAround(tile, 1, 1, INVALID_STATION);
 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 	}
@@ -1498,8 +1499,7 @@
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 	}
 	return cost;
@@ -1608,6 +1608,88 @@
 	return ret;
 }
 
+/** Recalculate the noise generated by the airports of each town */
+void UpdateAirportsNoise()
+{
+	Town *t;
+	const Station *st;
+
+	FOR_ALL_TOWNS(t) t->noise_reached = 0;
+
+	FOR_ALL_STATIONS(st) {
+		if (IsAirport(st->xy)) {
+			st->town->noise_reached += GetAirportNoiseLevelForTown(st->Airport(), st->town->xy, st->xy);
+		}
+	}
+}
+
+/** Get a possible noise reduction factor based on distance from town center.
+ * The further you get, the less noise you generate.
+ * So all those folks at city council can now happily slee...  work in their offices
+ * @param afc AirportFTAClass pointer of the class being proposed
+ * @param town_tile TileIndex of town's center, the one who will receive the airport's candidature
+ * @param tile TileIndex where the new airport might be built
+ * @return the noise that will be generated, according to distance
+ */
+uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile)
+{
+	struct TileIndexDistance {
+		TileIndex index;
+		uint distance;
+	};
+
+	uint distance;
+
+	/* 0 cannot be accounted, and 1 is the lowest that can be reduced from town.
+	 * So no need to go any further*/
+	if (afc->noise_level < 2) return afc->noise_level;
+
+	/* Find the airport-to-be's closest corner to the town */
+	if (afc->size_x == 1 && afc->size_y == 1) {
+		distance = DistanceManhattan(town_tile, tile);  // ont tile, one corner, it's THE corner
+	} else {
+		/* calculate manhattan distance to town of each side of the airport */
+		TileIndexDistance dist[4]; ///< Array that will contain all 4 corners in TileIndex and distance
+		uint min_tile = UINT_MAX;  ///< Sentinel value
+		uint min_indice = 4;
+
+		/* Based on the size of the airport, establish location of each corner*/
+		dist[0].index = tile; // north tile
+		dist[1].index = TileAddWrap(tile, afc->size_x - 1, afc->size_y - 1);  // south tile
+		dist[2].index = TileAddWrap(tile, afc->size_x - 1, 0);  // west tile
+		dist[3].index = TileAddWrap(tile, 0, afc->size_y - 1); //east tile
+
+		/* now, go and find the smallest one, thus the closest to town */
+		for (uint i = 0; i < 4; i++) {
+			dist[i].distance = DistanceManhattan(town_tile, dist[i].index);
+
+			if (dist[i].distance < min_tile) {
+				min_tile = dist[i].distance;  // here's a new candidate
+				min_indice = i;
+			}
+		}
+
+		distance = dist[min_indice].distance;
+	}
+
+	/* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance
+	 * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance.
+	 * Basically, it says that the less tolerant a town is, the bigger the distance before
+	 * an actual decrease can be granted */
+	uint8 town_tolerance_distance = 8 + (_settings.difficulty.town_council_tolerance * 4);
+
+	/* The airport is in the "inner" distance where there is no noise reduction */
+	if (distance < town_tolerance_distance) return afc->noise_level;
+
+	/* now, we want to have the distance segmented using the distance judged bareable by town
+	 * This will give us the coefficient of reduction the distance provides. */
+	uint noise_reduction = min(afc->noise_level, distance / town_tolerance_distance);
+
+	/* If the noise reduction equals the airport noise itself, don't give it for free. Use it all minus 1.
+	 * Otherwise, simply reduce the airport's level. */
+	return max(1U, noise_reduction == afc->noise_level ? afc->noise_level - 1 : afc->noise_level - noise_reduction);
+}
+
 /** Place an Airport.
  * @param tile tile where airport will be built
  * @param flags operation to perform
@@ -1639,24 +1721,38 @@
 	/* Check if the given station class is valid */
 	if (GB(p2, 8, 8) >= FSMPORTS_CLASS_MAX) return CMD_ERROR;
 
-	/* Check if local auth refuses a new airport */
-	uint num = 0;
-	FOR_ALL_STATIONS(st) {
-		if (st->town == t && st->facilities & FACIL_AIRPORT && st->Airport() != AirportFTAClass::oil_rig) num++;
+	/* Check if we can allocate a custom stationspec to this station */
+	const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8));
+	if (fsmportsspec == NULL) return CMD_ERROR;
+
+	/* Go get the final noise level, that is base noise minus factor from distance to town center */
+	uint newnoise_level = GetAirportNoiseLevelForTown(fsmportsspec->portFSM, t->xy, tile);
+
+	/* Check if local auth would allow a new airport */
+	bool authority_refused;
+
+	if (_settings.economy.station_noise_level) {
+		/* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
+		authority_refused = (t->noise_reached + newnoise_level) > t->MaxTownNoise();
+	} else {
+		uint num = 0;
+		const Station *st;
+		FOR_ALL_STATIONS(st) {
+			if (st->town == t && st->facilities & FACIL_AIRPORT && st->Airport() != AirportFTAClass::oil_rig) num++;
+		}
+		authority_refused = (num >= 2);
 	}
-	if (num >= 2) {
+
+	if (authority_refused) {
 		SetDParam(0, t->index);
 		return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES);
 	}
-	/* Check if we can allocate a custom stationspec to this station */
-	const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8));
-	if (fsmportsspec == NULL) return CMD_ERROR;
 
 	/* Perform NewStation checks */
 	byte w = fsmportsspec->size_x[layout_set];
 	byte h = fsmportsspec->size_y[layout_set];
 
-	if (w > _patches.station_spread || h > _patches.station_spread) {
+	if (w > _settings.station.station_spread || h > _settings.station.station_spread) {
 		_error_message = STR_306C_STATION_TOO_SPREAD_OUT;
 		return CMD_ERROR;
 	}
@@ -1666,7 +1762,7 @@
 		return CMD_ERROR;
 	}
 
-	if (!_patches.adjacent_stations || !HasBit(p1, 24)) {
+	if (!_settings.station.adjacent_stations || !HasBit(p1, 24)) {
 		st = GetStationAround(tile, w, h, INVALID_STATION);
 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 	} else {
@@ -1742,6 +1838,9 @@
 	cost.AddCost(_price.build_airport * w * h);
 
 	if (flags & DC_EXEC) {
+		/* Always add the noise, so there will be no need to recalculate when option toggles */
+		st->town->noise_reached += newnoise_level;
+
 		st->airport_tile = tile;
 		st->AddFacility(FACIL_AIRPORT, tile);
 		st->airport_flags.ResetAll();
@@ -1773,7 +1872,7 @@
 		BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
 			partial_snow_desert = 0x00;
 			byte layout = *layout_ptr++;
-			if ((GetTropicZone(tile_cur) == TROPICZONE_DESERT) || ((GetTileZ(tile_cur) >= GetSnowLine() && _opt.landscape == LT_ARCTIC)))
+			if ((GetTropicZone(tile_cur) == TROPICZONE_DESERT) || ((GetTileZ(tile_cur) >= GetSnowLine() && _settings.game_creation.landscape == LT_ARCTIC)))
 				partial_snow_desert = 1;
 			MakeAirport(tile_cur, st->owner, st->index, layout);
 			if (layout != 255)
@@ -1786,9 +1885,12 @@
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
+
+		if (_settings.economy.station_noise_level) {
+			InvalidateWindow(WC_TOWN_VIEW, st->town->index);
+		}
 	}
 
 	return cost;
@@ -1849,12 +1951,22 @@
 			);
 		}
 
+		/* Go get the final noise level, that is base noise minus factor from distance to town center.
+		 * And as for construction, always remove it, even if the patch is not set, in order to avoid the
+		 * need of recalculation */
+		st->town->noise_reached -= GetAirportNoiseLevelForTown(st->Airport(), st->town->xy, tile);
+
 		st->rect.AfterRemoveRect(st, tile, w, h);
 
 		st->airport_tile = 0;
 		st->facilities &= ~FACIL_AIRPORT;
 
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
+
+		if (_settings.economy.station_noise_level) {
+			InvalidateWindow(WC_TOWN_VIEW, st->town->index);
+		}
+
 		UpdateStationVirtCoordDirty(st);
 		DeleteStationIfEmpty(st);
 	}
@@ -1901,8 +2013,7 @@
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 	}
 
@@ -2015,7 +2126,7 @@
 	/* middle */
 	Station *st = NULL;
 
-	if (!_patches.adjacent_stations || !HasBit(p1, 0)) {
+	if (!_settings.station.adjacent_stations || !HasBit(p1, 0)) {
 		st = GetStationAround(
 				tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
 				_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
@@ -2060,8 +2171,7 @@
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
-		RebuildStationLists();
-		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 	}
 
@@ -2311,7 +2421,12 @@
 
 static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
 {
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
+	if (IsDriveThroughStopTile(tile) && HasTileRoadType(tile, ROADTYPE_ROAD) && GetStopBuiltOnTownRoad(tile)) {
+		/* Display a second owner */
+		td->owner_type[1] = STR_ROAD_OWNER;
+		td->owner[1] = OWNER_TOWN;
+	}
 	td->build_date = GetStationByTile(tile)->build_date;
 
 	StringID str;
@@ -2756,7 +2871,7 @@
 		st->name = strdup(_cmd_text);
 
 		UpdateStationVirtCoord(st);
-		ResortStationLists();
+		InvalidateWindowData(WC_STATION_LIST, st->owner, 1);
 		MarkWholeScreenDirty();
 	}
 
@@ -2779,7 +2894,7 @@
 	int w_prod; // width and height of the "producer" of the cargo
 	int h_prod;
 	int max_rad;
-	if (_patches.modified_catchment) {
+	if (_settings.station.modified_catchment) {
 		w_prod = w;
 		h_prod = h;
 		w += 2 * MAX_CATCHMENT;
@@ -2802,7 +2917,7 @@
 		if (st->IsBuoy()) continue; // bouys don't accept cargo
 
 
-		if (_patches.modified_catchment) {
+		if (_settings.station.modified_catchment) {
 			/* min and max coordinates of the producer relative */
 			const int x_min_prod = max_rad + 1;
 			const int x_max_prod = max_rad + w_prod;
@@ -2856,7 +2971,7 @@
 
 		if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
 
-		if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
+		if (_settings.order.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
 
 		if (IsCargoInClass(type, CC_PASSENGERS)) {
 			if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
@@ -2981,8 +3096,7 @@
 
 		SetTileOwner(tile, new_player);
 		if (!IsBuoy(tile)) st->owner = new_player; // do not set st->owner for buoys
-		RebuildStationLists();
-		InvalidateWindowClasses(WC_STATION_LIST);
+		InvalidateWindowClassesData(WC_STATION_LIST, 0);
 	} else {
 		if (IsDriveThroughStopTile(tile)) {
 			/* Remove the drive-through road stop */
@@ -3005,16 +3119,15 @@
  * Road stops built on town-owned roads check the conditions
  * that would allow clearing of the original road.
  * @param tile road stop tile to check
+ * @param flags command flags
  * @return true if the road can be cleared
  */
-static bool CanRemoveRoadWithStop(TileIndex tile)
+static bool CanRemoveRoadWithStop(TileIndex tile, uint32 flags)
 {
 	/* The road can always be cleared if it was not a town-owned road */
 	if (!GetStopBuiltOnTownRoad(tile)) return true;
 
-	bool edge_road;
-	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, &edge_road, ROADTYPE_ROAD) &&
-				CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM);
+	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags);
 }
 
 static CommandCost ClearTile_Station(TileIndex tile, byte flags)
@@ -3039,11 +3152,11 @@
 		case STATION_RAIL:    return RemoveRailroadStation(st, tile, flags);
 		case STATION_AIRPORT: return RemoveAirport(st, flags);
 		case STATION_TRUCK:
-			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile))
+			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
 				return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION);
 			return RemoveRoadStop(st, flags, tile);
 		case STATION_BUS:
-			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile))
+			if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
 				return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION);
 			return RemoveRoadStop(st, flags, tile);
 		case STATION_BUOY:    return RemoveBuoy(st, flags);
@@ -3095,7 +3208,7 @@
 
 static CommandCost TerraformTile_Station(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
-	if (_patches.build_on_slopes && AutoslopeEnabled()) {
+	if (_settings.construction.build_on_slopes && AutoslopeEnabled()) {
 		/* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here.
 		 *       TTDP does not call it.
 		 */
--- a/src/station_func.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_func.h	Tue May 27 00:50:55 2008 +0000
@@ -47,5 +47,6 @@
 /* Check if a rail station tile is electrifiable. */
 bool IsStationTileElectrifiable(TileIndex tile);
 
+void UpdateAirportsNoise();
 
 #endif /* STATION_FUNC_H */
--- a/src/station_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -168,39 +168,6 @@
 typedef GUIList<const Station*> GUIStationList;
 
 /**
- * Set the station sort flag for all station-list windows.
- * @param sl_flag Sort list flag to set for all station-list windows
- */
-static void SetStationListsFlag(SortListFlags sl_flag)
-{
-	Window *const *wz;
-
-	FOR_ALL_WINDOWS(wz) {
-		Window *w = *wz;
-		if (w->window_class == WC_STATION_LIST) {
-			dynamic_cast<GUIStationList*>(w)->flags |= sl_flag;
-			w->SetDirty();
-		}
-	}
-}
-
-/**
- * Set the 'VL_REBUILD' flag for all station lists
- */
-void RebuildStationLists()
-{
-	SetStationListsFlag(VL_REBUILD);
-}
-
-/**
- * Set the 'VL_RESORT' flag for all station lists
- */
-void ResortStationLists()
-{
-	SetStationListsFlag(VL_RESORT);
-}
-
-/**
  * Rebuild station list if the VL_REBUILD flag is set
  *
  * @param sl pointer to plstations_d (station list and flags)
@@ -211,16 +178,13 @@
  */
 static void BuildStationsList(GUIStationList *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty)
 {
-	uint n = 0;
-	const Station *st;
-
 	if (!(sl->flags & VL_REBUILD)) return;
 
-	/* Create array for sorting */
-	const Station **station_sort = MallocT<const Station*>(GetMaxStationIndex() + 1);
+	sl->Clear();
 
 	DEBUG(misc, 3, "Building station list for player %d", owner);
 
+	const Station *st;
 	FOR_ALL_STATIONS(st) {
 		if (st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy() && HasStationInUse(st->index, owner))) {
 			if (facilities & st->facilities) { //only stations with selected facilities
@@ -229,28 +193,23 @@
 					if (!st->goods[j].cargo.Empty()) {
 						num_waiting_cargo++; //count number of waiting cargo
 						if (HasBit(cargo_filter, j)) {
-							station_sort[n++] = st;
+							*sl->Append() = st;
 							break;
 						}
 					}
 				}
 				/* stations without waiting cargo */
 				if (num_waiting_cargo == 0 && include_empty) {
-					station_sort[n++] = st;
+					*sl->Append() = st;
 				}
 			}
 		}
 	}
 
-	free((void*)sl->sort_list);
-	sl->sort_list = MallocT<const Station*>(n);
-	sl->list_length = n;
-
-	for (uint i = 0; i < n; ++i) sl->sort_list[i] = station_sort[i];
+	sl->Compact();
 
 	sl->flags &= ~VL_REBUILD;
 	sl->flags |= VL_RESORT;
-	free((void*)station_sort);
 }
 
 
@@ -272,7 +231,7 @@
 
 	_internal_sort_order = sl->flags & VL_DESC;
 	_last_station = NULL; // used for "cache" in namesorting
-	qsort((void*)sl->sort_list, sl->list_length, sizeof(sl->sort_list[0]), _station_sorter[sl->sort_type]);
+	qsort((void*)sl->Begin(), sl->Length(), sizeof(sl->Begin()), _station_sorter[sl->sort_type]);
 
 	sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
 	sl->flags &= ~VL_RESORT;
@@ -344,13 +303,14 @@
 		this->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty);
 		this->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty);
 
-		this->sort_list = NULL;
 		this->flags = VL_REBUILD;
 		this->sort_type = station_sort.criteria;
 		if (station_sort.order) this->flags |= VL_DESC;
 
 		/* set up resort timer */
 		this->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
@@ -360,7 +320,7 @@
 		BuildStationsList(this, owner, facilities, _cargo_filter, include_empty);
 		SortStationsList(this);
 
-		SetVScrollCount(this, this->list_length);
+		SetVScrollCount(this, this->Length());
 
 		/* draw widgets, with player's name in the caption */
 		SetDParam(0, owner);
@@ -406,11 +366,11 @@
 			return;
 		}
 
-		int max = min(this->vscroll.pos + this->vscroll.cap, this->list_length);
+		int max = min(this->vscroll.pos + this->vscroll.cap, this->Length());
 		y = 40; // start of the list-widget
 
 		for (int i = this->vscroll.pos; i < max; ++i) { // do until max number of stations of owner
-			const Station *st = this->sort_list[i];
+			const Station *st = *this->Get(i);
 			int x;
 
 			assert(st->xy != 0);
@@ -444,9 +404,9 @@
 
 				id_v += this->vscroll.pos;
 
-				if (id_v >= this->list_length) return; // click out of list bound
+				if (id_v >= this->Length()) return; // click out of list bound
 
-				const Station *st = this->sort_list[id_v];
+				const Station *st = *this->Get(id_v);
 				/* do not check HasStationInUse - it is slow and may be invalid */
 				assert(st->owner == (PlayerID)this->window_number || (st->owner == OWNER_NONE && !st->IsBuoy()));
 
@@ -605,6 +565,11 @@
 	{
 		this->vscroll.cap += delta.y / 10;
 	}
+
+	virtual void OnInvalidateData(int data)
+	{
+		this->flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+	}
 };
 
 Listing PlayerStationsWindow::station_sort = {0, 0};
@@ -643,7 +608,6 @@
 	WC_STATION_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_player_stations_widgets,
-	NULL
 };
 
 /**
@@ -1015,7 +979,6 @@
 	WC_STATION_VIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_station_view_widgets,
-	NULL
 };
 
 /**
--- a/src/station_gui.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -48,10 +48,6 @@
 	SVW_RESIZE,          ///< Resize button
 };
 
-/* sorter stuff */
-void RebuildStationLists();
-void ResortStationLists();
-
 enum StationCoverageType {
 	SCT_PASSENGERS_ONLY,
 	SCT_NON_PASSENGERS_ONLY,
--- a/src/station_map.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_map.h	Tue May 27 00:50:55 2008 +0000
@@ -134,6 +134,12 @@
 	return HasBit(_m[t].m6, 2);
 }
 
+static inline void SetStopBuiltOnTownRoad(TileIndex t, bool on_town_road)
+{
+	assert(IsDriveThroughStopTile(t));
+	SB(_m[t].m6, 2, 1, on_town_road);
+}
+
 
 /**
  * Gets the direction the road stop entrance points towards.
--- a/src/station_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/station_type.h	Tue May 27 00:50:55 2008 +0000
@@ -57,7 +57,7 @@
 	CA_TRAIN           =  4,
 	CA_DOCK            =  5,
 
-	CA_UNMODIFIED      =  4, ///< Used when _patches.modified_catchment is false
+	CA_UNMODIFIED      =  4, ///< Used when _settings.station.modified_catchment is false
 
 	MAX_CATCHMENT      = 10, ///< Airports have a catchment up to this number.
 };
--- a/src/statusbar_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/statusbar_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -82,7 +82,7 @@
 
 		this->DrawWidgets();
 		SetDParam(0, _date);
-		DrawStringCentered(70, 1, (_pause_game || _patches.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING);
+		DrawStringCentered(70, 1, (_pause_game || _settings.gui.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING);
 
 		if (p != NULL) {
 			/* Draw player money */
@@ -168,7 +168,6 @@
 	WC_STATUS_BAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_main_status_widgets,
-	NULL
 };
 
 /**
--- a/src/strings.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/strings.cpp	Tue May 27 00:50:55 2008 +0000
@@ -546,7 +546,7 @@
  */
 uint ConvertSpeedToDisplaySpeed(uint speed)
 {
- return (speed * units[_opt_ptr->units].s_m) >> units[_opt_ptr->units].s_s;
+ return (speed * units[_settings.gui.units].s_m) >> units[_settings.gui.units].s_s;
 }
 
 /**
@@ -556,7 +556,7 @@
  */
 uint ConvertDisplaySpeedToSpeed(uint speed)
 {
-	return ((speed << units[_opt_ptr->units].s_s) + units[_opt_ptr->units].s_m / 2) / units[_opt_ptr->units].s_m;
+	return ((speed << units[_settings.gui.units].s_s) + units[_settings.gui.units].s_m / 2) / units[_settings.gui.units].s_m;
 }
 
 static char* FormatString(char* buff, const char* str, const int64* argv, uint casei, const char* last)
@@ -602,9 +602,9 @@
 
 			case SCC_VELOCITY: {// {VELOCITY}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
+				assert(_settings.gui.units < lengthof(units));
 				args[0] = ConvertSpeedToDisplaySpeed(GetInt32(&argv));
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].velocity), args, modifier >> 24, last);
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].velocity), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
@@ -625,18 +625,18 @@
 				switch (cargo_str) {
 					case STR_TONS: {
 						int64 args[1];
-						assert(_opt_ptr->units < lengthof(units));
-						args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
-						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last);
+						assert(_settings.gui.units < lengthof(units));
+						args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s;
+						buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_weight), args, modifier >> 24, last);
 						modifier = 0;
 						break;
 					}
 
 					case STR_LITERS: {
 						int64 args[1];
-						assert(_opt_ptr->units < lengthof(units));
-						args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
-						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last);
+						assert(_settings.gui.units < lengthof(units));
+						args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s;
+						buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_volume), args, modifier >> 24, last);
 						modifier = 0;
 						break;
 					}
@@ -718,9 +718,9 @@
 
 			case SCC_VOLUME: { // {VOLUME}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_volume), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
@@ -763,45 +763,45 @@
 
 			case SCC_POWER: { // {POWER}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].p_m >> units[_opt_ptr->units].p_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].power), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].p_m >> units[_settings.gui.units].p_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].power), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
 
 			case SCC_VOLUME_SHORT: { // {VOLUME_S}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_volume), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].s_volume), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
 
 			case SCC_WEIGHT: { // {WEIGHT}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_weight), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
 
 			case SCC_WEIGHT_SHORT: { // {WEIGHT_S}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_weight), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].s_weight), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
 
 			case SCC_FORCE: { // {FORCE}
 				int64 args[1];
-				assert(_opt_ptr->units < lengthof(units));
-				args[0] = GetInt32(&argv) * units[_opt_ptr->units].f_m >> units[_opt_ptr->units].f_s;
-				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].force), args, modifier >> 24, last);
+				assert(_settings.gui.units < lengthof(units));
+				args[0] = GetInt32(&argv) * units[_settings.gui.units].f_m >> units[_settings.gui.units].f_s;
+				buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].force), args, modifier >> 24, last);
 				modifier = 0;
 				break;
 			}
@@ -1137,7 +1137,7 @@
 	const char* const* base;
 	uint num;
 
-	if (_opt_ptr->landscape == LT_TOYLAND) {
+	if (_settings.game_creation.landscape == LT_TOYLAND) {
 		base = _silly_surname_list;
 		num  = lengthof(_silly_surname_list);
 	} else {
@@ -1167,7 +1167,7 @@
 		buff = strecpy(buff, initial, last);
 	}
 
-	if (_opt_ptr->landscape == LT_TOYLAND) {
+	if (_settings.game_creation.landscape == LT_TOYLAND) {
 		base = _silly_surname_list;
 		num  = lengthof(_silly_surname_list);
 	} else {
--- a/src/subsidy_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/subsidy_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -19,161 +19,153 @@
 
 #include "table/strings.h"
 
-static void HandleSubsidyClick(int y)
-{
-	const Subsidy *s;
-	uint num;
-	int offs;
-	TileIndex xy;
+struct SubsidyListWindow : Window {
+	SubsidyListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-	if (y < 0) return;
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget != 3) return;
 
-	num = 0;
-	for (s = _subsidies; s != endof(_subsidies); s++) {
-		if (s->cargo_type != CT_INVALID && s->age < 12) {
+		int y = pt.y - 25;
+
+		if (y < 0) return;
+
+		uint num = 0;
+		for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
+			if (s->cargo_type != CT_INVALID && s->age < 12) {
+				y -= 10;
+				if (y < 0) this->HandleClick(s);
+				num++;
+			}
+		}
+
+		if (num == 0) {
 			y -= 10;
-			if (y < 0) goto handle_click;
-			num++;
+			if (y < 0) return;
+		}
+
+		y -= 11;
+		if (y < 0) return;
+
+		for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
+			if (s->cargo_type != CT_INVALID && s->age >= 12) {
+				y -= 10;
+				if (y < 0) this->HandleClick(s);
+			}
 		}
 	}
 
-	if (num == 0) {
-		y -= 10;
-		if (y < 0) return;
-	}
-
-	y -= 11;
-	if (y < 0) return;
-
-	for (s = _subsidies; s != endof(_subsidies); s++) {
-		if (s->cargo_type != CT_INVALID && s->age >= 12) {
-			y -= 10;
-			if (y < 0) goto handle_click;
-		}
-	}
-	return;
+	void HandleClick(const Subsidy *s)
+	{
+		TownEffect te = GetCargo(s->cargo_type)->town_effect;
+		TileIndex xy;
 
-handle_click:
-
-	TownEffect te = GetCargo(s->cargo_type)->town_effect;
-
-	/* determine from coordinate for subsidy and try to scroll to it */
-	offs = s->from;
-	if (s->age >= 12) {
-		xy = GetStation(offs)->xy;
-	} else if (te == TE_PASSENGERS || te == TE_MAIL) {
-		xy = GetTown(offs)->xy;
-	} else {
-		xy = GetIndustry(offs)->xy;
-	}
-
-	if (_ctrl_pressed || !ScrollMainWindowToTile(xy)) {
-		if (_ctrl_pressed) ShowExtraViewPortWindow(xy);
-
-		/* otherwise determine to coordinate for subsidy and scroll to it */
-		offs = s->to;
+		/* determine from coordinate for subsidy and try to scroll to it */
+		uint offs = s->from;
 		if (s->age >= 12) {
 			xy = GetStation(offs)->xy;
-		} else if (te == TE_PASSENGERS || te == TE_MAIL || te == TE_GOODS || te == TE_FOOD) {
+		} else if (te == TE_PASSENGERS || te == TE_MAIL) {
 			xy = GetTown(offs)->xy;
 		} else {
 			xy = GetIndustry(offs)->xy;
 		}
 
-		if (_ctrl_pressed) {
-			ShowExtraViewPortWindow(xy);
-		} else {
-			ScrollMainWindowToTile(xy);
-		}
-	}
-}
-
-static void DrawSubsidiesWindow(const Window *w)
-{
-	YearMonthDay ymd;
-	const Subsidy *s;
-	uint num;
-	int x;
-	int y;
-
-	w->DrawWidgets();
-
-	ConvertDateToYMD(_date, &ymd);
+		if (_ctrl_pressed || !ScrollMainWindowToTile(xy)) {
+			if (_ctrl_pressed) ShowExtraViewPortWindow(xy);
 
-	int width = w->width - 13;  // scroll bar = 11 + pixel each side
-	y = 15;
-	x = 1;
-
-	/* Section for drawing the offered subisidies */
-	DrawStringTruncated(x, y, STR_2026_SUBSIDIES_ON_OFFER_FOR, TC_FROMSTRING, width);
-	y += 10;
-	num = 0;
+			/* otherwise determine to coordinate for subsidy and scroll to it */
+			offs = s->to;
+			if (s->age >= 12) {
+				xy = GetStation(offs)->xy;
+			} else if (te == TE_PASSENGERS || te == TE_MAIL || te == TE_GOODS || te == TE_FOOD) {
+				xy = GetTown(offs)->xy;
+			} else {
+				xy = GetIndustry(offs)->xy;
+			}
 
-	for (s = _subsidies; s != endof(_subsidies); s++) {
-		if (s->cargo_type != CT_INVALID && s->age < 12) {
-			int x2;
-
-			/* Displays the two offered towns */
-			SetupSubsidyDecodeParam(s, 1);
-			x2 = DrawStringTruncated(x + 2, y, STR_2027_FROM_TO, TC_FROMSTRING, width);
-
-			/* Displays the deadline before voiding the proposal */
-			SetDParam(0, _date - ymd.day + 384 - s->age * 32);
-			DrawStringTruncated(x2, y, STR_2028_BY, TC_FROMSTRING, width - x2);
-			y += 10;
-			num++;
+			if (_ctrl_pressed) {
+				ShowExtraViewPortWindow(xy);
+			} else {
+				ScrollMainWindowToTile(xy);
+			}
 		}
 	}
 
-	if (num == 0) {
-		DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2);
-		y += 10;
-	}
-
-	/* Section for drawing the already granted subisidies */
-	DrawStringTruncated(x, y + 1, STR_202B_SERVICES_ALREADY_SUBSIDISED, TC_FROMSTRING, width);
-	y += 10;
-	num = 0;
-
-	for (s = _subsidies; s != endof(_subsidies); s++) {
-		if (s->cargo_type != CT_INVALID && s->age >= 12) {
-			int xt;
-
-			SetupSubsidyDecodeParam(s, 1);
-
-			PlayerID player = GetStation(s->to)->owner;
-			SetDParam(3, player);
-
-			/* Displays the two connected stations */
-			xt = DrawStringTruncated(x + 2, y, STR_202C_FROM_TO, TC_FROMSTRING, width - 2);
+	virtual void OnPaint()
+	{
+		YearMonthDay ymd;
+		const Subsidy *s;
 
-			/* Displays the date where the granted subsidy will end */
-			if ((xt > 3) && (width - xt) > 9 ) { // do not draw if previous drawing failed or if it will overlap on scrollbar
-				SetDParam(0, _date - ymd.day + 768 - s->age * 32);
-				DrawStringTruncated(xt, y, STR_202D_UNTIL, TC_FROMSTRING, width - xt);
-			}
-			y += 10;
-			num++;
-		}
-	}
-
-	if (num == 0) DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2);
-}
+		this->DrawWidgets();
 
-static void SubsidiesListWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: DrawSubsidiesWindow(w); break;
+		ConvertDateToYMD(_date, &ymd);
 
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case 3:
-					HandleSubsidyClick(e->we.click.pt.y - 25);
-					break;
+		int width = this->width - 13;  // scroll bar = 11 + pixel each side
+		int y = 15;
+		int x = 1;
+
+		/* Section for drawing the offered subisidies */
+		DrawStringTruncated(x, y, STR_2026_SUBSIDIES_ON_OFFER_FOR, TC_FROMSTRING, width);
+		y += 10;
+		uint num = 0;
+
+		for (s = _subsidies; s != endof(_subsidies); s++) {
+			if (s->cargo_type != CT_INVALID && s->age < 12) {
+				int x2;
+
+				/* Displays the two offered towns */
+				SetupSubsidyDecodeParam(s, 1);
+				x2 = DrawStringTruncated(x + 2, y, STR_2027_FROM_TO, TC_FROMSTRING, width - 2);
+
+				if (width - x2 > 10) {
+					/* Displays the deadline before voiding the proposal */
+					SetDParam(0, _date - ymd.day + 384 - s->age * 32);
+					DrawStringTruncated(x2, y, STR_2028_BY, TC_FROMSTRING, width - x2);
+				}
+
+				y += 10;
+				num++;
 			}
-		break;
+		}
+
+		if (num == 0) {
+			DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2);
+			y += 10;
+		}
+
+		/* Section for drawing the already granted subisidies */
+		DrawStringTruncated(x, y + 1, STR_202B_SERVICES_ALREADY_SUBSIDISED, TC_FROMSTRING, width);
+		y += 10;
+		num = 0;
+
+		for (s = _subsidies; s != endof(_subsidies); s++) {
+			if (s->cargo_type != CT_INVALID && s->age >= 12) {
+				int xt;
+
+				SetupSubsidyDecodeParam(s, 1);
+
+				PlayerID player = GetStation(s->to)->owner;
+				SetDParam(3, player);
+
+				/* Displays the two connected stations */
+				xt = DrawStringTruncated(x + 2, y, STR_202C_FROM_TO, TC_FROMSTRING, width - 2);
+
+				/* Displays the date where the granted subsidy will end */
+				if ((xt > 3) && (width - xt) > 9 ) { // do not draw if previous drawing failed or if it will overlap on scrollbar
+					SetDParam(0, _date - ymd.day + 768 - s->age * 32);
+					DrawStringTruncated(xt, y, STR_202D_UNTIL, TC_FROMSTRING, width - xt);
+				}
+				y += 10;
+				num++;
+			}
+		}
+
+		if (num == 0) DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2);
 	}
-}
+};
 
 static const Widget _subsidies_list_widgets[] = {
 {   WWT_CLOSEBOX, RESIZE_NONE,   13,   0,  10,   0,  13, STR_00C5,           STR_018B_CLOSE_WINDOW},
@@ -191,11 +183,10 @@
 	WC_SUBSIDIES_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_subsidies_list_widgets,
-	SubsidiesListWndProc
 };
 
 
 void ShowSubsidiesList()
 {
-	AllocateWindowDescFront<Window>(&_subsidies_list_desc, 0);
+	AllocateWindowDescFront<SubsidyListWindow>(&_subsidies_list_desc, 0);
 }
--- a/src/terraform_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/terraform_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -301,7 +301,10 @@
 				return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
 			}
 			/* Check tiletype-specific things, and add extra-cost */
+			const bool curr_gen = _generating_world;
+			if (_game_mode == GM_EDITOR) _generating_world = true; // used to create green terraformed land
 			CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags | DC_AUTO, z_min * TILE_HEIGHT, tileh);
+			_generating_world = curr_gen;
 			if (CmdFailed(cost)) {
 				_terraform_err_tile = tile;
 				return cost;
--- a/src/terraform_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/terraform_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -110,12 +110,9 @@
  * allows for additional implements that are more local. For example X_Y drag
  * of convertrail which belongs in rail_gui.cpp and not terraform_gui.cpp
  **/
-bool GUIPlaceProcDragXY(const WindowEvent *e)
+bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile)
 {
-	TileIndex start_tile = e->we.place.starttile;
-	TileIndex end_tile = e->we.place.tile;
-
-	switch (e->we.place.select_proc) {
+	switch (proc) {
 		case DDSP_DEMOLISH_AREA:
 			DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
 			break;
@@ -186,29 +183,45 @@
 	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
 }
 
+/** Enum referring to the widgets of the terraform toolbar */
+enum TerraformToolbarWidgets {
+	TTW_CLOSEBOX = 0,                     ///< Close window button
+	TTW_CAPTION,                          ///< Window caption
+	TTW_STICKY,                           ///< Sticky window button
+	TTW_SEPERATOR,                        ///< Thin seperator line between level land button and demolish button
+	TTW_BUTTONS_START,                    ///< Start of pushable buttons
+	TTW_LOWER_LAND = TTW_BUTTONS_START,   ///< Lower land button
+	TTW_RAISE_LAND,                       ///< Raise land button
+	TTW_LEVEL_LAND,                       ///< Level land button
+	TTW_DEMOLISH,                         ///< Demolish aka dynamite button
+	TTW_BUY_LAND,                         ///< Buy land button
+	TTW_PLANT_TREES,                      ///< Plant trees button (note: opens seperate window, no place-push-button)
+	TTW_PLACE_SIGN,                       ///< Place sign button
+};
+
 static void TerraformClick_Lower(Window *w)
 {
-	HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerLand);
+	HandlePlacePushButton(w, TTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerLand);
 }
 
 static void TerraformClick_Raise(Window *w)
 {
-	HandlePlacePushButton(w, 5, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseLand);
+	HandlePlacePushButton(w, TTW_RAISE_LAND, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseLand);
 }
 
 static void TerraformClick_Level(Window *w)
 {
-	HandlePlacePushButton(w, 6, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand);
+	HandlePlacePushButton(w, TTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand);
 }
 
 static void TerraformClick_Dynamite(Window *w)
 {
-	HandlePlacePushButton(w, 7, ANIMCURSOR_DEMOLISH , VHM_RECT, PlaceProc_DemolishArea);
+	HandlePlacePushButton(w, TTW_DEMOLISH, ANIMCURSOR_DEMOLISH , VHM_RECT, PlaceProc_DemolishArea);
 }
 
 static void TerraformClick_BuyLand(Window *w)
 {
-	HandlePlacePushButton(w, 8, SPR_CURSOR_BUY_LAND, VHM_RECT, PlaceProc_BuyLand);
+	HandlePlacePushButton(w, TTW_BUY_LAND, SPR_CURSOR_BUY_LAND, VHM_RECT, PlaceProc_BuyLand);
 }
 
 static void TerraformClick_Trees(Window *w)
@@ -219,7 +232,7 @@
 
 static void TerraformClick_PlaceSign(Window *w)
 {
-	HandlePlacePushButton(w, 10, SPR_CURSOR_SIGN, VHM_RECT, PlaceProc_Sign);
+	HandlePlacePushButton(w, TTW_PLACE_SIGN, SPR_CURSOR_SIGN, VHM_RECT, PlaceProc_Sign);
 }
 
 static OnButtonClick * const _terraform_button_proc[] = {
@@ -232,70 +245,81 @@
 	TerraformClick_PlaceSign,
 };
 
-static void TerraformToolbWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-	case WE_PAINT:
-		w->DrawWidgets();
-		break;
+struct TerraformToolbarWindow : Window {
+	TerraformToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-	case WE_CLICK:
-		if (e->we.click.widget >= 4) _terraform_button_proc[e->we.click.widget - 4](w);
-		break;
+	~TerraformToolbarWindow()
+	{
+	}
 
-	case WE_KEYPRESS: {
-		uint i;
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
 
-		for (i = 0; i != lengthof(_terraform_keycodes); i++) {
-			if (e->we.keypress.keycode == _terraform_keycodes[i]) {
-				e->we.keypress.cont = false;
-				_terraform_button_proc[i](w);
-				break;
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (widget >= TTW_BUTTONS_START) _terraform_button_proc[widget - TTW_BUTTONS_START](this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		for (uint i = 0; i != lengthof(_terraform_keycodes); i++) {
+			if (keycode == _terraform_keycodes[i]) {
+				_terraform_button_proc[i](this);
+				return ES_HANDLED;
 			}
 		}
-		break;
+		return ES_NOT_HANDLED;
 	}
 
-	case WE_PLACE_OBJ:
-		_place_proc(e->we.place.tile);
-		return;
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
 
-	case WE_PLACE_DRAG:
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-		break;
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
 
-	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1) {
-			switch (e->we.place.select_proc) {
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				default: NOT_REACHED();
 				case DDSP_DEMOLISH_AREA:
 				case DDSP_RAISE_AND_LEVEL_AREA:
 				case DDSP_LOWER_AND_LEVEL_AREA:
 				case DDSP_LEVEL_AREA:
-					GUIPlaceProcDragXY(e);
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
 					break;
 			}
 		}
-		break;
+	}
 
-	case WE_ABORT_PLACE_OBJ:
-		w->RaiseButtons();
-		break;
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
 	}
-}
+};
 
 static const Widget _terraform_widgets[] = {
-{ WWT_CLOSEBOX,   RESIZE_NONE,     7,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},
-{  WWT_CAPTION,   RESIZE_NONE,     7,  11, 145,   0,  13, STR_LANDSCAPING_TOOLBAR, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{WWT_STICKYBOX,   RESIZE_NONE,     7, 146, 157,   0,  13, STR_NULL,                STR_STICKY_BUTTON},
+{ WWT_CLOSEBOX,   RESIZE_NONE,     7,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},             // TTW_CLOSEBOX
+{  WWT_CAPTION,   RESIZE_NONE,     7,  11, 145,   0,  13, STR_LANDSCAPING_TOOLBAR, STR_018C_WINDOW_TITLE_DRAG_THIS},   // TTW_CAPTION
+{WWT_STICKYBOX,   RESIZE_NONE,     7, 146, 157,   0,  13, STR_NULL,                STR_STICKY_BUTTON},                 // TTW_STICKY
 
-{    WWT_PANEL,   RESIZE_NONE,     7,  66,  69,  14,  35, 0x0,                    STR_NULL},
-{   WWT_IMGBTN,   RESIZE_NONE,     7,   0,  21,  14,  35, SPR_IMG_TERRAFORM_DOWN,  STR_018E_LOWER_A_CORNER_OF_LAND},
-{   WWT_IMGBTN,   RESIZE_NONE,     7,  22,  43,  14,  35, SPR_IMG_TERRAFORM_UP,    STR_018F_RAISE_A_CORNER_OF_LAND},
-{   WWT_IMGBTN,   RESIZE_NONE,     7,  44,  65,  14,  35, SPR_IMG_LEVEL_LAND,      STR_LEVEL_LAND_TOOLTIP},
-{   WWT_IMGBTN,   RESIZE_NONE,     7,  70,  91,  14,  35, SPR_IMG_DYNAMITE,        STR_018D_DEMOLISH_BUILDINGS_ETC},
-{   WWT_IMGBTN,   RESIZE_NONE,     7,  92, 113,  14,  35, SPR_IMG_BUY_LAND,        STR_0329_PURCHASE_LAND_FOR_FUTURE},
-{   WWT_IMGBTN,   RESIZE_NONE,     7, 114, 135,  14,  35, SPR_IMG_PLANTTREES,      STR_0185_PLANT_TREES_PLACE_SIGNS},
-{   WWT_IMGBTN,   RESIZE_NONE,     7, 136, 157,  14,  35, SPR_IMG_SIGN,            STR_0289_PLACE_SIGN},
+{    WWT_PANEL,   RESIZE_NONE,     7,  66,  69,  14,  35, 0x0,                    STR_NULL},                           // TTW_SEPERATOR
+{   WWT_IMGBTN,   RESIZE_NONE,     7,   0,  21,  14,  35, SPR_IMG_TERRAFORM_DOWN,  STR_018E_LOWER_A_CORNER_OF_LAND},   // TTW_LOWER_LAND
+{   WWT_IMGBTN,   RESIZE_NONE,     7,  22,  43,  14,  35, SPR_IMG_TERRAFORM_UP,    STR_018F_RAISE_A_CORNER_OF_LAND},   // TTW_RAISE_LAND
+{   WWT_IMGBTN,   RESIZE_NONE,     7,  44,  65,  14,  35, SPR_IMG_LEVEL_LAND,      STR_LEVEL_LAND_TOOLTIP},            // TTW_LEVEL_LAND
+{   WWT_IMGBTN,   RESIZE_NONE,     7,  70,  91,  14,  35, SPR_IMG_DYNAMITE,        STR_018D_DEMOLISH_BUILDINGS_ETC},   // TTW_DEMOLISH
+{   WWT_IMGBTN,   RESIZE_NONE,     7,  92, 113,  14,  35, SPR_IMG_BUY_LAND,        STR_0329_PURCHASE_LAND_FOR_FUTURE}, // TTW_BUY_LAND
+{   WWT_IMGBTN,   RESIZE_NONE,     7, 114, 135,  14,  35, SPR_IMG_PLANTTREES,      STR_0185_PLANT_TREES_PLACE_SIGNS},  // TTW_PLANT_TREES
+{   WWT_IMGBTN,   RESIZE_NONE,     7, 136, 157,  14,  35, SPR_IMG_SIGN,            STR_0289_PLACE_SIGN},               // TTW_PLACE_SIGN
 
 {   WIDGETS_END},
 };
@@ -305,20 +329,19 @@
 	WC_SCEN_LAND_GEN, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_terraform_widgets,
-	TerraformToolbWndProc
 };
 
 void ShowTerraformToolbar(Window *link)
 {
 	if (!IsValidPlayer(_current_player)) return;
-	Window *w = AllocateWindowDescFront<Window>(&_terraform_desc, 0);
+	Window *w = AllocateWindowDescFront<TerraformToolbarWindow>(&_terraform_desc, 0);
 	if (w != NULL && link != NULL) {
 		/* Align the terraform toolbar under the main toolbar and put the linked
 		 * toolbar to left of it
 		 */
 		w->top = 22;
+		w->SetDirty();
 		link->left = w->left - link->width;
-
 		link->SetDirty();
 	}
 }
@@ -339,8 +362,6 @@
 	int sizex, sizey;
 	uint h;
 
-	_generating_world = true; // used to create green terraformed land
-
 	if (_terraform_size == 1) {
 		StringID msg =
 			mode ? STR_0808_CAN_T_RAISE_LAND_HERE : STR_0809_CAN_T_LOWER_LAND_HERE;
@@ -376,8 +397,6 @@
 			}
 		} END_TILE_LOOP(tile2, sizex, sizey, tile)
 	}
-
-	_generating_world = false;
 }
 
 static void PlaceProc_RaiseBigLand(TileIndex tile)
@@ -435,23 +454,23 @@
 }
 
 static const Widget _scen_edit_land_gen_widgets[] = {
-{  WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                  STR_018B_CLOSE_WINDOW},
-{   WWT_CAPTION,   RESIZE_NONE,     7,    11,   191,     0,    13, STR_0223_LAND_GENERATION,  STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_STICKYBOX,   RESIZE_NONE,     7,   192,   203,     0,    13, STR_NULL,                  STR_STICKY_BUTTON},
-{     WWT_PANEL,   RESIZE_NONE,     7,     0,   203,    14,   102, 0x0,                       STR_NULL},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,     2,    23,    16,    37, SPR_IMG_DYNAMITE,          STR_018D_DEMOLISH_BUILDINGS_ETC},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,    24,    45,    16,    37, SPR_IMG_TERRAFORM_DOWN,    STR_018E_LOWER_A_CORNER_OF_LAND},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,    46,    67,    16,    37, SPR_IMG_TERRAFORM_UP,      STR_018F_RAISE_A_CORNER_OF_LAND},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,    68,    89,    16,    37, SPR_IMG_LEVEL_LAND,        STR_LEVEL_LAND_TOOLTIP},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,    90,   111,    16,    37, SPR_IMG_BUILD_CANAL,       STR_CREATE_LAKE},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   112,   133,    16,    37, SPR_IMG_BUILD_RIVER,       STR_CREATE_RIVER},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   134,   156,    16,    37, SPR_IMG_ROCKS,             STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   157,   179,    16,    37, SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL}, // XXX - dynamic
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   180,   201,    16,    37, SPR_IMG_TRANSMITTER,       STR_028E_PLACE_TRANSMITTER},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   150,   161,    45,    56, SPR_ARROW_UP,              STR_0228_INCREASE_SIZE_OF_LAND_AREA},
-{    WWT_IMGBTN,   RESIZE_NONE,    14,   150,   161,    58,    69, SPR_ARROW_DOWN,            STR_0229_DECREASE_SIZE_OF_LAND_AREA},
-{   WWT_TEXTBTN,   RESIZE_NONE,    14,    24,   179,    76,    87, STR_SE_NEW_WORLD,          STR_022A_GENERATE_RANDOM_LAND},
-{   WWT_TEXTBTN,   RESIZE_NONE,    14,    24,   179,    89,   100, STR_022B_RESET_LANDSCAPE,  STR_RESET_LANDSCAPE_TOOLTIP},
+{  WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                  STR_018B_CLOSE_WINDOW},                   // ETTW_CLOSEBOX
+{   WWT_CAPTION,   RESIZE_NONE,     7,    11,   191,     0,    13, STR_0223_LAND_GENERATION,  STR_018C_WINDOW_TITLE_DRAG_THIS},         // ETTW_CAPTION
+{ WWT_STICKYBOX,   RESIZE_NONE,     7,   192,   203,     0,    13, STR_NULL,                  STR_STICKY_BUTTON},                       // ETTW_STICKY
+{     WWT_PANEL,   RESIZE_NONE,     7,     0,   203,    14,   102, 0x0,                       STR_NULL},                                // ETTW_BACKGROUND
+{    WWT_IMGBTN,   RESIZE_NONE,    14,     2,    23,    16,    37, SPR_IMG_DYNAMITE,          STR_018D_DEMOLISH_BUILDINGS_ETC},         // ETTW_DEMOLISH
+{    WWT_IMGBTN,   RESIZE_NONE,    14,    24,    45,    16,    37, SPR_IMG_TERRAFORM_DOWN,    STR_018E_LOWER_A_CORNER_OF_LAND},         // ETTW_LOWER_LAND
+{    WWT_IMGBTN,   RESIZE_NONE,    14,    46,    67,    16,    37, SPR_IMG_TERRAFORM_UP,      STR_018F_RAISE_A_CORNER_OF_LAND},         // ETTW_RAISE_LAND
+{    WWT_IMGBTN,   RESIZE_NONE,    14,    68,    89,    16,    37, SPR_IMG_LEVEL_LAND,        STR_LEVEL_LAND_TOOLTIP},                  // ETTW_LEVEL_LAND
+{    WWT_IMGBTN,   RESIZE_NONE,    14,    90,   111,    16,    37, SPR_IMG_BUILD_CANAL,       STR_CREATE_LAKE},                         // ETTW_BUILD_CANAL
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   112,   133,    16,    37, SPR_IMG_BUILD_RIVER,       STR_CREATE_RIVER},                        // ETTW_BUILD_RIVER
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   134,   156,    16,    37, SPR_IMG_ROCKS,             STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE}, // ETTW_PLACE_ROCKS
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   157,   179,    16,    37, SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL},                                // ETTW_PLACE_DESERT_LIGHTHOUSE XXX - dynamic
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   180,   201,    16,    37, SPR_IMG_TRANSMITTER,       STR_028E_PLACE_TRANSMITTER},              // ETTW_PLACE_TRANSMITTER
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   150,   161,    45,    56, SPR_ARROW_UP,              STR_0228_INCREASE_SIZE_OF_LAND_AREA},     // ETTW_INCREASE_SIZE
+{    WWT_IMGBTN,   RESIZE_NONE,    14,   150,   161,    58,    69, SPR_ARROW_DOWN,            STR_0229_DECREASE_SIZE_OF_LAND_AREA},     // ETTW_DECREASE_SIZE
+{   WWT_TEXTBTN,   RESIZE_NONE,    14,    24,   179,    76,    87, STR_SE_NEW_WORLD,          STR_022A_GENERATE_RANDOM_LAND},           // ETTW_NEW_SCENARIO
+{   WWT_TEXTBTN,   RESIZE_NONE,    14,    24,   179,    89,   100, STR_022B_RESET_LANDSCAPE,  STR_RESET_LANDSCAPE_TOOLTIP},             // ETTW_RESET_LANDSCAPE
 {   WIDGETS_END},
 };
 
@@ -466,53 +485,77 @@
 	{-28,  0}, {-24, -2}, {-20, -4}, {-16, -6}, {-12, -8}, { -8,-10}, { -4,-12}, {  0,-14}, {  4,-12}, {  8,-10}, { 12, -8}, { 16, -6}, { 20, -4}, { 24, -2}, { 28,  0},
 };
 
+/** Enum referring to the widgets of the editor terraform toolbar */
+enum EditorTerraformToolbarWidgets {
+	ETTW_START = 0,                        ///< Used for iterations
+	ETTW_CLOSEBOX = ETTW_START,            ///< Close window button
+	ETTW_CAPTION,                          ///< Window caption
+	ETTW_STICKY,                           ///< Sticky window button
+	ETTW_BACKGROUND,                       ///< Background of the lower part of the window
+	ETTW_BUTTONS_START,                    ///< Start of pushable buttons
+	ETTW_DEMOLISH = ETTW_BUTTONS_START,    ///< Demolish aka dynamite button
+	ETTW_LOWER_LAND,                       ///< Lower land button
+	ETTW_RAISE_LAND,                       ///< Raise land button
+	ETTW_LEVEL_LAND,                       ///< Level land button
+	ETTW_BUILD_CANAL,                      ///< Build canal button
+	ETTW_BUILD_RIVER,                      ///< Build river button
+	ETTW_PLACE_ROCKS,                      ///< Place rocks button
+	ETTW_PLACE_DESERT_LIGHTHOUSE,          ///< Place desert button (in tropical climate) / place lighthouse button (else)
+	ETTW_PLACE_TRANSMITTER,                ///< Place transmitter button
+	ETTW_BUTTONS_END,                      ///< End of pushable buttons
+	ETTW_INCREASE_SIZE = ETTW_BUTTONS_END, ///< Upwards arrow button to increase terraforming size
+	ETTW_DECREASE_SIZE,                    ///< Downwards arrow button to decrease terraforming size
+	ETTW_NEW_SCENARIO,                     ///< Button for generating a new scenario
+	ETTW_RESET_LANDSCAPE,                  ///< Button for removing all player-owned property
+};
+
 /**
  * @todo Merge with terraform_gui.cpp (move there) after I have cooled down at its braindeadness
  * and changed OnButtonClick to include the widget as well in the function declaration. Post 0.4.0 - Darkvater
  */
 static void EditorTerraformClick_Dynamite(Window *w)
 {
-	HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea);
+	HandlePlacePushButton(w, ETTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea);
 }
 
 static void EditorTerraformClick_LowerBigLand(Window *w)
 {
-	HandlePlacePushButton(w, 5, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerBigLand);
+	HandlePlacePushButton(w, ETTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerBigLand);
 }
 
 static void EditorTerraformClick_RaiseBigLand(Window *w)
 {
-	HandlePlacePushButton(w, 6, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseBigLand);
+	HandlePlacePushButton(w, ETTW_RAISE_LAND, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseBigLand);
 }
 
 static void EditorTerraformClick_LevelLand(Window *w)
 {
-	HandlePlacePushButton(w, 7, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand);
+	HandlePlacePushButton(w, ETTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand);
 }
 
 static void EditorTerraformClick_WaterArea(Window *w)
 {
-	HandlePlacePushButton(w, 8, SPR_CURSOR_CANAL, VHM_RECT, PlaceProc_WaterArea);
+	HandlePlacePushButton(w, ETTW_BUILD_CANAL, SPR_CURSOR_CANAL, VHM_RECT, PlaceProc_WaterArea);
 }
 
 static void EditorTerraformClick_RiverArea(Window *w)
 {
-	HandlePlacePushButton(w, 9, SPR_CURSOR_RIVER, VHM_RECT, PlaceProc_RiverArea);
+	HandlePlacePushButton(w, ETTW_BUILD_RIVER, SPR_CURSOR_RIVER, VHM_RECT, PlaceProc_RiverArea);
 }
 
 static void EditorTerraformClick_RockyArea(Window *w)
 {
-	HandlePlacePushButton(w, 10, SPR_CURSOR_ROCKY_AREA, VHM_RECT, PlaceProc_RockyArea);
+	HandlePlacePushButton(w, ETTW_PLACE_ROCKS, SPR_CURSOR_ROCKY_AREA, VHM_RECT, PlaceProc_RockyArea);
 }
 
 static void EditorTerraformClick_DesertLightHouse(Window *w)
 {
-	HandlePlacePushButton(w, 11, SPR_CURSOR_LIGHTHOUSE, VHM_RECT, (_opt.landscape == LT_TROPIC) ? PlaceProc_DesertArea : PlaceProc_LightHouse);
+	HandlePlacePushButton(w, ETTW_PLACE_DESERT_LIGHTHOUSE, SPR_CURSOR_LIGHTHOUSE, VHM_RECT, (_settings.game_creation.landscape == LT_TROPIC) ? PlaceProc_DesertArea : PlaceProc_LightHouse);
 }
 
 static void EditorTerraformClick_Transmitter(Window *w)
 {
-	HandlePlacePushButton(w, 12, SPR_CURSOR_TRANSMITTER, VHM_RECT, PlaceProc_Transmitter);
+	HandlePlacePushButton(w, ETTW_PLACE_TRANSMITTER, SPR_CURSOR_TRANSMITTER, VHM_RECT, PlaceProc_Transmitter);
 }
 
 static const uint16 _editor_terraform_keycodes[] = {
@@ -569,62 +612,64 @@
 	}
 }
 
-static void ScenEditLandGenWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_CREATE:
-			/* XXX - lighthouse button is widget 11!! Don't forget when changing */
-			w->widget[11].tooltips = (_opt.landscape == LT_TROPIC) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE;
-			break;
-
-		case WE_PAINT: {
-			w->DrawWidgets();
-
-			int n = _terraform_size * _terraform_size;
-			const int8 *coords = &_multi_terraform_coords[0][0];
-
-			assert(n != 0);
-			do {
-				DrawSprite(SPR_WHITE_POINT, PAL_NONE, 88 + coords[0], 55 + coords[1]);
-				coords += 2;
-			} while (--n);
+struct ScenarioEditorLandscapeGenerationWindow : Window {
+	ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->widget[ETTW_PLACE_DESERT_LIGHTHOUSE].tooltips = (_settings.game_creation.landscape == LT_TROPIC) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE;
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-			if (w->IsWidgetLowered(5) || w->IsWidgetLowered(6)) // change area-size if raise/lower corner is selected
-				SetTileSelectSize(_terraform_size, _terraform_size);
-
-		} break;
+	virtual void OnPaint() {
+		this->DrawWidgets();
 
-		case WE_KEYPRESS:
-			for (uint i = 0; i != lengthof(_editor_terraform_keycodes); i++) {
-				if (e->we.keypress.keycode == _editor_terraform_keycodes[i]) {
-					e->we.keypress.cont = false;
-					_editor_terraform_button_proc[i](w);
-					break;
-				}
+		int n = _terraform_size * _terraform_size;
+		const int8 *coords = &_multi_terraform_coords[0][0];
+
+		assert(n != 0);
+		do {
+			DrawSprite(SPR_WHITE_POINT, PAL_NONE, 88 + coords[0], 55 + coords[1]);
+			coords += 2;
+		} while (--n);
+
+		if (this->IsWidgetLowered(ETTW_LOWER_LAND) || this->IsWidgetLowered(ETTW_RAISE_LAND)) { // change area-size if raise/lower corner is selected
+			SetTileSelectSize(_terraform_size, _terraform_size);
+		}
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		for (uint i = 0; i != lengthof(_editor_terraform_keycodes); i++) {
+			if (keycode == _editor_terraform_keycodes[i]) {
+				_editor_terraform_button_proc[i](this);
+				return ES_HANDLED;
 			}
-			break;
+		}
+		return ES_NOT_HANDLED;
+	}
 
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
-					_editor_terraform_button_proc[e->we.click.widget - 4](w);
-					break;
-				case 13: case 14: { // Increase/Decrease terraform size
-					int size = (e->we.click.widget == 13) ? 1 : -1;
-					w->HandleButtonClick(e->we.click.widget);
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (IsInsideMM(widget, ETTW_BUTTONS_START, ETTW_BUTTONS_END)) {
+			_editor_terraform_button_proc[widget - ETTW_BUTTONS_START](this);
+		} else {
+			switch (widget) {
+				case ETTW_INCREASE_SIZE:
+				case ETTW_DECREASE_SIZE: { // Increase/Decrease terraform size
+					int size = (widget == ETTW_INCREASE_SIZE) ? 1 : -1;
+					this->HandleButtonClick(widget);
 					size += _terraform_size;
 
 					if (!IsInsideMM(size, 1, 8 + 1)) return;
 					_terraform_size = size;
 
 					SndPlayFx(SND_15_BEEP);
-					w->SetDirty();
+					this->SetDirty();
 				} break;
-				case 15: // gen random land
-					w->HandleButtonClick(15);
+				case ETTW_NEW_SCENARIO: // gen random land
+					this->HandleButtonClick(widget);
 					ShowCreateScenario();
 					break;
-				case 16: // Reset landscape
+				case ETTW_RESET_LANDSCAPE: // Reset landscape
 					ShowQuery(
 						STR_022C_RESET_LANDSCAPE,
 						STR_RESET_LANDSCAPE_CONFIRMATION_TEXT,
@@ -632,59 +677,64 @@
 						ResetLandscapeConfirmationCallback);
 					break;
 			}
-			break;
-
-		case WE_TIMEOUT:
-			for (uint i = 0; i < w->widget_count; i++) {
-				if (w->IsWidgetLowered(i)) {
-					w->RaiseWidget(i);
-					w->InvalidateWidget(i);
-				}
-				if (i == 3) i = 12;
-			}
-			break;
-
-		case WE_PLACE_OBJ:
-			_place_proc(e->we.place.tile);
-			break;
-
-		case WE_PLACE_DRAG:
-			VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
-			break;
+		}
+	}
 
-		case WE_PLACE_MOUSEUP:
-			if (e->we.place.pt.x != -1) {
-				switch (e->we.place.select_proc) {
-					case DDSP_CREATE_ROCKS:
-					case DDSP_CREATE_DESERT:
-					case DDSP_CREATE_WATER:
-					case DDSP_CREATE_RIVER:
-					case DDSP_RAISE_AND_LEVEL_AREA:
-					case DDSP_LOWER_AND_LEVEL_AREA:
-					case DDSP_LEVEL_AREA:
-					case DDSP_DEMOLISH_AREA:
-						GUIPlaceProcDragXY(e);
-						break;
-				}
+	virtual void OnTimeout()
+	{
+		for (uint i = ETTW_START; i < this->widget_count; i++) {
+			if (i == ETTW_BUTTONS_START) i = ETTW_BUTTONS_END; // skip the buttons
+			if (this->IsWidgetLowered(i)) {
+				this->RaiseWidget(i);
+				this->InvalidateWidget(i);
 			}
-			break;
+		}
+	}
 
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseButtons();
-			w->SetDirty();
-			break;
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
 	}
-}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				default: NOT_REACHED();
+				case DDSP_CREATE_ROCKS:
+				case DDSP_CREATE_DESERT:
+				case DDSP_CREATE_WATER:
+				case DDSP_CREATE_RIVER:
+				case DDSP_RAISE_AND_LEVEL_AREA:
+				case DDSP_LOWER_AND_LEVEL_AREA:
+				case DDSP_LEVEL_AREA:
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
+					break;
+			}
+		}
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
+		this->SetDirty();
+	}
+};
 
 static const WindowDesc _scen_edit_land_gen_desc = {
 	WDP_AUTO, WDP_AUTO, 204, 103, 204, 103,
 	WC_SCEN_LAND_GEN, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_scen_edit_land_gen_widgets,
-	ScenEditLandGenWndProc,
 };
 
 void ShowEditorTerraformToolbar()
 {
-	AllocateWindowDescFront<Window>(&_scen_edit_land_gen_desc, 0);
+	AllocateWindowDescFront<ScenarioEditorLandscapeGenerationWindow>(&_scen_edit_land_gen_desc, 0);
 }
--- a/src/textbuf_gui.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/textbuf_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -28,8 +28,10 @@
 void InitializeTextBuffer(Textbuf *tb, const char *buf, uint16 maxlength, uint16 maxwidth);
 void UpdateTextBufferSize(Textbuf *tb);
 
+typedef void QueryCallbackProc(Window*, bool);
+
 void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, Window *parent, CharSetFilter afilter);
-void ShowQuery(StringID caption, StringID message, Window *w, void (*callback)(Window*, bool));
+void ShowQuery(StringID caption, StringID message, Window *w, QueryCallbackProc *callback);
 
 /** The number of 'characters' on the on-screen keyboard. */
 static const uint OSK_KEYBOARD_ENTRIES = 50;
--- a/src/texteff.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/texteff.cpp	Tue May 27 00:50:55 2008 +0000
@@ -6,7 +6,7 @@
 #include "openttd.h"
 #include "landscape.h"
 #include "gfx_func.h"
-#include "console.h"
+#include "console_func.h"
 #include "variables.h"
 #include "blitter/factory.hpp"
 #include "texteff.hpp"
@@ -392,7 +392,7 @@
 						dpi->top  <= te->bottom &&
 						dpi->left + dpi->width  > te->x &&
 						dpi->top  + dpi->height > te->y) {
-					if (te->mode == TE_RISING || (_patches.loading_indicators && !IsTransparencySet(TO_LOADING))) {
+					if (te->mode == TE_RISING || (_settings.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) {
 						AddStringToDraw(te->x, te->y, te->string_id, te->params_1, te->params_2);
 					}
 				}
@@ -407,7 +407,7 @@
 						dpi->top  <= te->bottom * 2 - te->y &&
 						dpi->left + dpi->width  > te->x &&
 						dpi->top  + dpi->height > te->y) {
-					if (te->mode == TE_RISING || (_patches.loading_indicators && !IsTransparencySet(TO_LOADING))) {
+					if (te->mode == TE_RISING || (_settings.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) {
 						AddStringToDraw(te->x, te->y, (StringID)(te->string_id - 1), te->params_1, te->params_2);
 					}
 				}
--- a/src/tgp.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/tgp.cpp	Tue May 27 00:50:55 2008 +0000
@@ -10,7 +10,6 @@
 #include "variables.h"
 #include "void_map.h"
 #include "tgp.h"
-#include "console.h"
 #include "genworld.h"
 #include "core/alloc_func.hpp"
 #include "core/random_func.hpp"
@@ -212,10 +211,10 @@
 	{1500, 1000, 1200, 1000,  500,   32,    20,    0,    0,    0,    0,    0},
 };
 
-/** Desired water percentage (100% == 1024) - indexed by _opt.diff.quantity_sea_lakes */
+/** Desired water percentage (100% == 1024) - indexed by _settings.difficulty.quantity_sea_lakes */
 static const amplitude_t _water_percent[4] = {20, 80, 250, 400};
 
-/** Desired maximum height - indexed by _opt.diff.terrain_type */
+/** Desired maximum height - indexed by _settings.difficulty.terrain_type */
 static const int8 _max_height[4] = {
 	6,       ///< Very flat
 	9,       ///< Flat
@@ -343,7 +342,7 @@
 	do {
 		log_frequency = iteration_round - log_frequency_min;
 		if (log_frequency >= 0) {
-			amplitude = _amplitudes_by_smoothness_and_frequency[_patches.tgen_smoothness][log_frequency];
+			amplitude = _amplitudes_by_smoothness_and_frequency[_settings.game_creation.tgen_smoothness][log_frequency];
 		} else {
 			amplitude = 0;
 		}
@@ -403,7 +402,7 @@
 		/* Transform height into 0..1 space */
 		fheight = (double)(*h - h_min) / (double)(h_max - h_min);
 		/* Apply sine transform depending on landscape type */
-		switch(_opt.landscape) {
+		switch(_settings.game_creation.landscape) {
 			case LT_TOYLAND:
 			case LT_TEMPERATE:
 				/* Move and scale 0..1 into -1..+1 */
@@ -532,7 +531,7 @@
  */
 static void HeightMapCoastLines()
 {
-	int smallest_size = min(_patches.map_x, _patches.map_y);
+	int smallest_size = min(_settings.game_creation.map_x, _settings.game_creation.map_y);
 	const int margin = 4;
 	uint y, x;
 	double max_x;
@@ -662,9 +661,9 @@
  *  - height histogram redistribution by sine wave transform */
 static void HeightMapNormalize()
 {
-	const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes];
-	const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]);
-	const height_t roughness = 7 + 3 * _patches.tgen_smoothness;
+	const amplitude_t water_percent = _water_percent[_settings.difficulty.quantity_sea_lakes];
+	const height_t h_max_new = I2H(_max_height[_settings.difficulty.terrain_type]);
+	const height_t roughness = 7 + 3 * _settings.game_creation.tgen_smoothness;
 
 	HeightMapAdjustWaterLevel(water_percent, h_max_new);
 
@@ -693,7 +692,7 @@
  */
 static double int_noise(const long x, const long y, const int prime)
 {
-	long n = x + y * prime + _patches.generation_seed;
+	long n = x + y * prime + _settings.game_creation.generation_seed;
 
 	n = (n << 13) ^ n;
 
--- a/src/tile_cmd.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/tile_cmd.h	Tue May 27 00:50:55 2008 +0000
@@ -49,7 +49,8 @@
 
 struct TileDesc {
 	StringID str;
-	Owner owner;
+	Owner owner[4];
+	StringID owner_type[4];
 	Date build_date;
 	uint64 dparam[2];
 };
--- a/src/tilehighlight_func.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/tilehighlight_func.h	Tue May 27 00:50:55 2008 +0000
@@ -12,7 +12,7 @@
 
 typedef void PlaceProc(TileIndex tile);
 void PlaceProc_DemolishArea(TileIndex tile);
-bool GUIPlaceProcDragXY(const WindowEvent *e);
+bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile);
 
 bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, ViewportHighlightMode mode, PlaceProc *placeproc);
 void SetObjectToPlaceWnd(CursorID icon, SpriteID pal, ViewportHighlightMode mode, Window *w);
--- a/src/timetable_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/timetable_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -54,7 +54,7 @@
  */
 CommandCost CmdChangeTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	if (!_patches.timetabling) return CMD_ERROR;
+	if (!_settings.order.timetabling) return CMD_ERROR;
 
 	VehicleID veh = GB(p1, 0, 16);
 	if (!IsValidVehicleID(veh)) return CMD_ERROR;
@@ -90,7 +90,7 @@
  */
 CommandCost CmdSetVehicleOnTime(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	if (!_patches.timetabling) return CMD_ERROR;
+	if (!_settings.order.timetabling) return CMD_ERROR;
 
 	VehicleID veh = GB(p1, 0, 16);
 	if (!IsValidVehicleID(veh)) return CMD_ERROR;
@@ -116,7 +116,7 @@
  */
 CommandCost CmdAutofillTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	if (!_patches.timetabling) return CMD_ERROR;
+	if (!_settings.order.timetabling) return CMD_ERROR;
 
 	VehicleID veh = GB(p1, 0, 16);
 	if (!IsValidVehicleID(veh)) return CMD_ERROR;
@@ -157,7 +157,7 @@
 
 	v->current_order_time = 0;
 
-	if (!_patches.timetabling) return;
+	if (!_settings.order.timetabling) return;
 
 	/* Make sure the timetable only starts when the vehicle reaches the first
 	 * order, not when travelling from the depot to the first station. */
--- a/src/timetable_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/timetable_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -38,7 +38,7 @@
 
 void SetTimetableParams(int param1, int param2, uint32 time)
 {
-	if (_patches.timetable_in_ticks) {
+	if (_settings.gui.timetable_in_ticks) {
 		SetDParam(param1, STR_TIMETABLE_TICKS);
 		SetDParam(param2, time);
 	} else {
@@ -56,6 +56,8 @@
 		this->vscroll.cap = 8;
 		this->resize.step_height = 10;
 		this->sel_index = -1;
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	int GetOrderFromTimetableWndPt(int y, const Vehicle *v)
@@ -170,7 +172,7 @@
 		}
 		y += 10;
 
-		if (v->lateness_counter == 0 || (!_patches.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) {
+		if (v->lateness_counter == 0 || (!_settings.gui.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) {
 			DrawString(2, y, STR_TIMETABLE_STATUS_ON_TIME, TC_BLACK);
 		} else {
 			SetTimetableParams(0, 1, abs(v->lateness_counter));
@@ -220,7 +222,7 @@
 
 				if (order != NULL) {
 					uint time = (selected % 2 == 1) ? order->travel_time : order->wait_time;
-					if (!_patches.timetable_in_ticks) time /= DAY_TICKS;
+					if (!_settings.gui.timetable_in_ticks) time /= DAY_TICKS;
 
 					if (time != 0) {
 						SetDParam(0, time);
@@ -257,7 +259,7 @@
 		uint32 p1 = PackTimetableArgs(v, this->sel_index);
 
 		uint64 time = StrEmpty(str) ? 0 : strtoul(str, NULL, 10);
-		if (!_patches.timetable_in_ticks) time *= DAY_TICKS;
+		if (!_settings.gui.timetable_in_ticks) time *= DAY_TICKS;
 
 		uint32 p2 = minu(time, MAX_UVALUE(uint16));
 
@@ -298,7 +300,6 @@
 	WC_VEHICLE_TIMETABLE, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_timetable_widgets,
-	NULL
 };
 
 void ShowTimetableWindow(const Vehicle *v)
--- a/src/toolbar_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/toolbar_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -35,7 +35,7 @@
 #include "signs_func.h"
 #include "fios.h"
 #include "functions.h"
-#include "console.h"
+#include "console_gui.h"
 #include "news_gui.h"
 #include "tilehighlight_func.h"
 
@@ -542,8 +542,8 @@
 		w->HandleButtonClick(6);
 		w->SetDirty();
 
-		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
-		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
+		_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year - 1, MIN_YEAR, MAX_YEAR);
+		SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1));
 	}
 	_left_button_clicked = false;
 }
@@ -555,8 +555,8 @@
 		w->HandleButtonClick(7);
 		w->SetDirty();
 
-		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
-		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
+		_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + 1, MIN_YEAR, MAX_YEAR);
+		SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1));
 	}
 	_left_button_clicked = false;
 }
@@ -666,137 +666,155 @@
 	ToolbarHelpClick,
 };
 
-static void MainToolbarWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT:
-			/* Draw brown-red toolbar bg. */
-			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2);
-			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
-
-			/* If spectator, disable all construction buttons
-			* ie : Build road, rail, ships, airports and landscaping
-			* Since enabled state is the default, just disable when needed */
-			w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
-			/* disable company list drop downs, if there are no companies */
-			w->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END);
-
-			w->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN));
-			w->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
-
-			w->DrawWidgets();
-			break;
-
-		case WE_CLICK:
-			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) _toolbar_button_procs[e->we.click.widget](w);
-			break;
+struct MainToolbarWindow : Window {
+	MainToolbarWindow(const WindowDesc *desc) : Window(desc)
+	{
+		this->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button
+		this->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button
 
-		case WE_KEYPRESS:
-			switch (e->we.keypress.keycode) {
-				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
-				case WKC_F2: ShowGameOptions(); break;
-				case WKC_F3: MenuClickSaveLoad(0); break;
-				case WKC_F4: ShowSmallMap(); break;
-				case WKC_F5: ShowTownDirectory(); break;
-				case WKC_F6: ShowSubsidiesList(); break;
-				case WKC_F7: ShowPlayerStations(_local_player); break;
-				case WKC_F8: ShowPlayerFinances(_local_player); break;
-				case WKC_F9: ShowPlayerCompany(_local_player); break;
-				case WKC_F10: ShowOperatingProfitGraph(); break;
-				case WKC_F11: ShowCompanyLeagueTable(); break;
-				case WKC_F12: ShowBuildIndustryWindow(); break;
-				case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break;
-				case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break;
-				case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break;
-				case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break;
-				case WKC_NUM_PLUS: // Fall through
-				case WKC_EQUALS: // Fall through
-				case WKC_SHIFT | WKC_EQUALS: // Fall through
-				case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
-				case WKC_NUM_MINUS: // Fall through
-				case WKC_MINUS: // Fall through
-				case WKC_SHIFT | WKC_MINUS: // Fall through
-				case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
-				case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break;
-				case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break;
-				case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break;
-				case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
-				case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
-				case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break;
-				case WKC_CTRL  | 'S': MenuClickSmallScreenshot(); break;
-				case WKC_CTRL  | 'G': MenuClickWorldScreenshot(); break;
-				case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
-				case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail
-				case 'L': ShowTerraformToolbar(); break;
-				case 'M': ShowSmallMap(); break;
-				case 'V': ShowExtraViewPortWindow(); break;
-				default: return;
-			}
-			e->we.keypress.cont = false;
-			break;
+		CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
 
-		case WE_PLACE_OBJ:
-			_place_proc(e->we.place.tile);
-			break;
+		this->FindWindowPlacementAndResize(desc);
+		PositionMainToolbar(this);
+		DoZoomInOutWindow(ZOOM_NONE, this);
+	}
 
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseWidget(25);
-			w->SetDirty();
-			break;
+	virtual void OnPaint()
+	{
+		/* Draw brown-red toolbar bg. */
+		GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2);
+		GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
 
-		case WE_TICK:
-			if (w->IsWidgetLowered(0) != !!_pause_game) {
-				w->ToggleWidgetLoweredState(0);
-				w->InvalidateWidget(0);
+		/* If spectator, disable all construction buttons
+		* ie : Build road, rail, ships, airports and landscaping
+		* Since enabled state is the default, just disable when needed */
+		this->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
+		/* disable company list drop downs, if there are no companies */
+		this->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END);
+
+		this->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN));
+		this->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
+
+		this->DrawWidgets();
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		switch (keycode) {
+			case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break;
+			case WKC_F2: ShowGameOptions(); break;
+			case WKC_F3: MenuClickSaveLoad(0); break;
+			case WKC_F4: ShowSmallMap(); break;
+			case WKC_F5: ShowTownDirectory(); break;
+			case WKC_F6: ShowSubsidiesList(); break;
+			case WKC_F7: ShowPlayerStations(_local_player); break;
+			case WKC_F8: ShowPlayerFinances(_local_player); break;
+			case WKC_F9: ShowPlayerCompany(_local_player); break;
+			case WKC_F10: ShowOperatingProfitGraph(); break;
+			case WKC_F11: ShowCompanyLeagueTable(); break;
+			case WKC_F12: ShowBuildIndustryWindow(); break;
+			case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break;
+			case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break;
+			case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break;
+			case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break;
+			case WKC_NUM_PLUS: // Fall through
+			case WKC_EQUALS: // Fall through
+			case WKC_SHIFT | WKC_EQUALS: // Fall through
+			case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break;
+			case WKC_NUM_MINUS: // Fall through
+			case WKC_MINUS: // Fall through
+			case WKC_SHIFT | WKC_MINUS: // Fall through
+			case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break;
+			case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break;
+			case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break;
+			case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break;
+			case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
+			case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
+			case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break;
+			case WKC_CTRL  | 'S': MenuClickSmallScreenshot(); break;
+			case WKC_CTRL  | 'G': MenuClickWorldScreenshot(); break;
+			case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
+			case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail
+			case 'L': ShowTerraformToolbar(); break;
+			case 'M': ShowSmallMap(); break;
+			case 'V': ShowExtraViewPortWindow(); break;
+			default: return ES_NOT_HANDLED;
+		}
+		return ES_HANDLED;
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseWidget(25);
+		this->SetDirty();
+	}
+
+	virtual void OnTick()
+	{
+		if (this->IsWidgetLowered(0) != !!_pause_game) {
+			this->ToggleWidgetLoweredState(0);
+			this->InvalidateWidget(0);
+		}
+
+		if (this->IsWidgetLowered(1) != !!_fast_forward) {
+			this->ToggleWidgetLoweredState(1);
+			this->InvalidateWidget(1);
+		}
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		/* There are 27 buttons plus some spacings if the space allows it */
+		uint button_width;
+		uint spacing;
+		if (this->width >= 27 * 22) {
+			button_width = 22;
+			spacing = this->width - (27 * button_width);
+		} else {
+			button_width = this->width / 27;
+			spacing = 0;
+		}
+		uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
+
+		for (uint i = 0, x = 0, j = 0; i < 27; i++) {
+			if (extra_spacing_at[j] == i) {
+				j++;
+				uint add = spacing / (lengthof(extra_spacing_at) - j);
+				spacing -= add;
+				x += add;
 			}
 
-			if (w->IsWidgetLowered(1) != !!_fast_forward) {
-				w->ToggleWidgetLoweredState(1);
-				w->InvalidateWidget(1);
-			}
-			break;
-
-		case WE_RESIZE: {
-			/* There are 27 buttons plus some spacings if the space allows it */
-			uint button_width;
-			uint spacing;
-			if (w->width >= 27 * 22) {
-				button_width = 22;
-				spacing = w->width - (27 * button_width);
-			} else {
-				button_width = w->width / 27;
-				spacing = 0;
-			}
-			uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
+			this->widget[i].left = x;
+			x += (spacing != 0) ? button_width : (this->width - x) / (27 - i);
+			this->widget[i].right = x - 1;
+		}
+	}
 
-			for (uint i = 0, x = 0, j = 0; i < 27; i++) {
-				if (extra_spacing_at[j] == i) {
-					j++;
-					uint add = spacing / (lengthof(extra_spacing_at) - j);
-					spacing -= add;
-					x += add;
-				}
-
-				w->widget[i].left = x;
-				x += (spacing != 0) ? button_width : (w->width - x) / (27 - i);
-				w->widget[i].right = x - 1;
+	virtual void OnTimeout()
+	{
+		for (uint i = 2; i < this->widget_count; i++) {
+			if (this->IsWidgetLowered(i)) {
+				this->RaiseWidget(i);
+				this->InvalidateWidget(i);
 			}
-		} break;
+		}
+	}
 
-		case WE_TIMEOUT:
-			for (uint i = 2; i < w->widget_count; i++) {
-				if (w->IsWidgetLowered(i)) {
-					w->RaiseWidget(i);
-					w->InvalidateWidget(i);
-				}
-			}
-			break;
-
-		case WE_INVALIDATE_DATA:
-			if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
-			break;
+	virtual void OnInvalidateData(int data)
+	{
+		if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
 	}
-}
+};
 
 static const Widget _toolb_normal_widgets[] = {
 {     WWT_IMGBTN,   RESIZE_LEFT,    14,     0,     0,     0,    21, SPR_IMG_PAUSE,           STR_0171_PAUSE_GAME},
@@ -840,7 +858,6 @@
 	WC_MAIN_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
 	_toolb_normal_widgets,
-	MainToolbarWndProc
 };
 
 
@@ -876,163 +893,176 @@
 	ToolbarHelpClick,
 };
 
-static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT:
-			w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR);
-			w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR);
+struct ScenarioEditorToolbarWindow : Window {
+	ScenarioEditorToolbarWindow(const WindowDesc *desc) : Window(desc)
+	{
+		CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
 
-			/* Draw brown-red toolbar bg. */
-			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2);
-			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
-
-			w->DrawWidgets();
+		this->FindWindowPlacementAndResize(desc);
+		PositionMainToolbar(this);
+		DoZoomInOutWindow(ZOOM_NONE, this);
+	}
 
-			SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
-			DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
+	virtual void OnPaint()
+	{
+		this->SetWidgetDisabledState(6, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
+		this->SetWidgetDisabledState(7, _settings_newgame.game_creation.starting_year >= MAX_YEAR);
 
-			/* We hide this panel when the toolbar space gets too small */
-			if (w->widget[4].left != w->widget[4].right) {
-				DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1,  1, STR_0221_OPENTTD, TC_FROMSTRING);
-				DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING);
+		/* Draw brown-red toolbar bg. */
+		GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2);
+		GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
+
+		this->DrawWidgets();
+
+		SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1));
+		DrawStringCenteredTruncated(this->widget[6].right, this->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
+
+		/* We hide this panel when the toolbar space gets too small */
+		if (this->widget[4].left != this->widget[4].right) {
+			DrawStringCenteredTruncated(this->widget[4].left + 1, this->widget[4].right - 1,  1, STR_0221_OPENTTD, TC_FROMSTRING);
+			DrawStringCenteredTruncated(this->widget[4].left + 1, this->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING);
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		if (_game_mode == GM_MENU) return;
+		_scen_toolbar_button_procs[widget](this);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		switch (keycode) {
+			case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break;
+			case WKC_F2: ShowGameOptions(); break;
+			case WKC_F3: MenuClickSaveLoad(0); break;
+			case WKC_F4: ToolbarScenGenLand(this); break;
+			case WKC_F5: ToolbarScenGenTown(this); break;
+			case WKC_F6: ToolbarScenGenIndustry(this); break;
+			case WKC_F7: ToolbarScenBuildRoad(this); break;
+			case WKC_F8: ToolbarScenPlantTrees(this); break;
+			case WKC_F9: ToolbarScenPlaceSign(this); break;
+			case WKC_F10: ShowMusicWindow(); break;
+			case WKC_F11: PlaceLandBlockInfo(); break;
+			case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break;
+			case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break;
+
+			/* those following are all fall through */
+			case WKC_NUM_PLUS:
+			case WKC_EQUALS:
+			case WKC_SHIFT | WKC_EQUALS:
+			case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break;
+
+			/* those following are all fall through */
+			case WKC_NUM_MINUS:
+			case WKC_MINUS:
+			case WKC_SHIFT | WKC_MINUS:
+			case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break;
+
+			case 'L': ShowEditorTerraformToolbar(); break;
+			case 'M': ShowSmallMap(); break;
+			case 'V': ShowExtraViewPortWindow(); break;
+			default: return ES_NOT_HANDLED;
+		}
+		return ES_HANDLED;
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseWidget(25);
+		this->SetDirty();
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		/* There are 15 buttons plus some spacings if the space allows it.
+		 * Furthermore there are two panels of which one is non - essential
+		 * and that one can be removed is the space is too small. */
+		uint buttons_width;
+		uint spacing;
+
+		static int normal_min_width = (15 * 22) + (2 * 130);
+		static int one_less_panel_min_width = (15 * 22) + 130;
+
+		if (this->width >= one_less_panel_min_width) {
+			buttons_width = 15 * 22;
+			spacing = this->width - ((this->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width);
+		} else {
+			buttons_width = this->width - 130;
+			spacing = 0;
+		}
+		uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 };
+
+		/* Yes, it defines about 27 widgets for this toolbar */
+		for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) {
+			switch (i) {
+				case 4:
+					this->widget[i].left = x;
+					if (this->width < normal_min_width) {
+						this->widget[i].right = x;
+						j++;
+						continue;
+					}
+
+					x += 130;
+					this->widget[i].right = x - 1;
+					break;
+
+				case 5: {
+					int offset = x - this->widget[i].left;
+					this->widget[i + 1].left  += offset;
+					this->widget[i + 1].right += offset;
+					this->widget[i + 2].left  += offset;
+					this->widget[i + 2].right += offset;
+					this->widget[i].left = x;
+					x += 130;
+					this->widget[i].right = x - 1;
+					i += 2;
+				} break;
+
+				default:
+					if (this->widget[i].bottom == 0) continue;
+
+					this->widget[i].left = x;
+					x += buttons_width / (15 - b);
+					this->widget[i].right = x - 1;
+					buttons_width -= buttons_width / (15 - b);
+					b++;
+					break;
 			}
 
-			break;
-
-		case WE_CLICK:
-			if (_game_mode == GM_MENU) return;
-			_scen_toolbar_button_procs[e->we.click.widget](w);
-			break;
-
-		case WE_KEYPRESS:
-			switch (e->we.keypress.keycode) {
-				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
-				case WKC_F2: ShowGameOptions(); break;
-				case WKC_F3: MenuClickSaveLoad(0); break;
-				case WKC_F4: ToolbarScenGenLand(w); break;
-				case WKC_F5: ToolbarScenGenTown(w); break;
-				case WKC_F6: ToolbarScenGenIndustry(w); break;
-				case WKC_F7: ToolbarScenBuildRoad(w); break;
-				case WKC_F8: ToolbarScenPlantTrees(w); break;
-				case WKC_F9: ToolbarScenPlaceSign(w); break;
-				case WKC_F10: ShowMusicWindow(); break;
-				case WKC_F11: PlaceLandBlockInfo(); break;
-				case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break;
-				case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break;
-
-				/* those following are all fall through */
-				case WKC_NUM_PLUS:
-				case WKC_EQUALS:
-				case WKC_SHIFT | WKC_EQUALS:
-				case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
-
-				/* those following are all fall through */
-				case WKC_NUM_MINUS:
-				case WKC_MINUS:
-				case WKC_SHIFT | WKC_MINUS:
-				case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
-
-				case 'L': ShowEditorTerraformToolbar(); break;
-				case 'M': ShowSmallMap(); break;
-				case 'V': ShowExtraViewPortWindow(); break;
-				default: return;
+			if (extra_spacing_at[j] == i) {
+				j++;
+				uint add = spacing / (lengthof(extra_spacing_at) - j);
+				spacing -= add;
+				x += add;
 			}
-			e->we.keypress.cont = false;
-			break;
-
-		case WE_PLACE_OBJ:
-			_place_proc(e->we.place.tile);
-			break;
-
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseWidget(25);
-			w->SetDirty();
-			break;
-
-		case WE_RESIZE: {
-			/* There are 15 buttons plus some spacings if the space allows it.
-			* Furthermore there are two panels of which one is non - essential
-			* and that one can be removed is the space is too small. */
-			uint buttons_width;
-			uint spacing;
-
-			static int normal_min_width = (15 * 22) + (2 * 130);
-			static int one_less_panel_min_width = (15 * 22) + 130;
+		}
+	}
 
-			if (w->width >= one_less_panel_min_width) {
-				buttons_width = 15 * 22;
-				spacing = w->width - ((w->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width);
-			} else {
-				buttons_width = w->width - 130;
-				spacing = 0;
-			}
-			uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 };
-
-			/* Yes, it defines about 27 widgets for this toolbar */
-			for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) {
-				switch (i) {
-					case 4:
-						w->widget[i].left = x;
-						if (w->width < normal_min_width) {
-							w->widget[i].right = x;
-							j++;
-							continue;
-						}
-
-						x += 130;
-						w->widget[i].right = x - 1;
-						break;
-
-					case 5: {
-						int offset = x - w->widget[i].left;
-						w->widget[i + 1].left  += offset;
-						w->widget[i + 1].right += offset;
-						w->widget[i + 2].left  += offset;
-						w->widget[i + 2].right += offset;
-						w->widget[i].left = x;
-						x += 130;
-						w->widget[i].right = x - 1;
-						i += 2;
-					} break;
+	virtual void OnTick()
+	{
+		if (this->IsWidgetLowered(0) != !!_pause_game) {
+			this->ToggleWidgetLoweredState(0);
+			this->SetDirty();
+		}
 
-					default:
-						if (w->widget[i].bottom == 0) continue;
-
-						w->widget[i].left = x;
-						x += buttons_width / (15 - b);
-						w->widget[i].right = x - 1;
-						buttons_width -= buttons_width / (15 - b);
-						b++;
-						break;
-				}
+		if (this->IsWidgetLowered(1) != !!_fast_forward) {
+			this->ToggleWidgetLoweredState(1);
+			this->SetDirty();
+		}
+	}
 
-				if (extra_spacing_at[j] == i) {
-					j++;
-					uint add = spacing / (lengthof(extra_spacing_at) - j);
-					spacing -= add;
-					x += add;
-				}
-			}
-		} break;
-
-		case WE_TICK:
-			if (w->IsWidgetLowered(0) != !!_pause_game) {
-				w->ToggleWidgetLoweredState(0);
-				w->SetDirty();
-			}
-
-			if (w->IsWidgetLowered(1) != !!_fast_forward) {
-				w->ToggleWidgetLoweredState(1);
-				w->SetDirty();
-			}
-			break;
-
-		case WE_INVALIDATE_DATA:
-			HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 9, 10);
-			break;
+	virtual void OnInvalidateData(int data)
+	{
+		if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18);
 	}
-}
+};
 
 static const Widget _toolb_scen_widgets[] = {
 {  WWT_IMGBTN, RESIZE_LEFT, 14,   0,   0,  0, 21, SPR_IMG_PAUSE,       STR_0171_PAUSE_GAME},
@@ -1076,7 +1106,6 @@
 	WC_MAIN_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_toolb_scen_widgets,
-	ScenEditToolbarWndProc
 };
 
 /* --- Rendering/handling the drop down menus --- */
@@ -1124,8 +1153,8 @@
 
 	ToolbarMenuWindow(int x, int y, int width, int height, const Widget *widgets, int item_count,
 										int sel_index, int parent_button, StringID base_string, int checked_items,
-										int disabled_mask) :
-			Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets),
+										int disabled_items) :
+			Window(x, y, width, height, WC_TOOLBAR_MENU, widgets),
 			item_count(item_count), sel_index(sel_index), main_button(GB(parent_button, 0, 8)),
 			action_id((GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button),
 			checked_items(checked_items), disabled_items(disabled_items), base_string(base_string)
@@ -1280,7 +1309,7 @@
 	int gray_items;
 
 	ToolbarPlayerMenuWindow(int x, int y, int width, int height, const Widget *widgets, int main_button, int gray) :
-			Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets),
+			Window(x, y, width, height, WC_TOOLBAR_MENU, widgets),
 			item_count(0), main_button(main_button), action_id(main_button), gray_items(gray)
 	{
 		this->flags4 &= ~WF_WHITE_BORDER_MASK;
@@ -1293,6 +1322,8 @@
 				this->sel_index = 0;
 			}
 		}
+
+		this->FindWindowPlacementAndResize(width, height);
 	}
 
 	~ToolbarPlayerMenuWindow()
@@ -1432,15 +1463,9 @@
 	/* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
 	_last_built_roadtype = ROADTYPE_ROAD;
 
-	Window *w = new Window((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
-	assert(w != NULL);
-
-	CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
-
-	w->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button
-	w->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button
-
-	/* 'w' is for sure a WC_MAIN_TOOLBAR */
-	PositionMainToolbar(w);
-	DoZoomInOutWindow(ZOOM_NONE, w);
+	if (_game_mode == GM_EDITOR) {
+		new ScenarioEditorToolbarWindow(&_toolb_scen_desc);;
+	} else {
+		new MainToolbarWindow(&_toolb_normal_desc);
+	}
 }
--- a/src/town.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/town.h	Tue May 27 00:50:55 2008 +0000
@@ -116,6 +116,9 @@
 	 * bit 2 = STADIUM */
 	byte flags12;
 
+	/* level of noise that all the airports are generating */
+	uint16 noise_reached;
+
 	/* Which players have a statue? */
 	byte statues;
 
@@ -184,6 +187,18 @@
 	void InitializeLayout();
 
 	inline TownLayout GetActiveLayout() const;
+
+	/** Calculate the max town noise
+	 * The value is counted using the population divided by the content of the
+	 * entry in town_noise_population corespondig to the town's tolerance.
+	 * To this result, we add 3, which is the noise of the lowest airport.
+	 * So user can at least buld that airport
+	 * @return the maximum noise level the town will tolerate */
+	inline uint16 MaxTownNoise() const {
+		if (this->population == 0) return 0; // no population? no noise
+
+		return ((this->population / _settings.economy.town_noise_population[_settings.difficulty.town_council_tolerance]) + 3);
+	}
 };
 
 /**
@@ -192,7 +207,7 @@
  */
 inline TownLayout Town::GetActiveLayout() const
 {
-	return (_patches.town_layout == TL_RANDOM) ? this->layout : _patches.town_layout;
+	return (_settings.economy.town_layout == TL_RANDOM) ? this->layout : _settings.economy.town_layout;
 }
 
 struct HouseSpec {
--- a/src/town_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/town_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -324,7 +324,7 @@
 	SetDParam(0, t->index);
 	SetDParam(1, t->population);
 	UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24,
-		_patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL);
+		_settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL);
 	MarkTownSignDirty(t);
 }
 
@@ -596,7 +596,7 @@
 		if (callback != CALLBACK_FAILED) {
 			if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4);
 			if (accepts[1] != CT_INVALID) ac[accepts[1]] = GB(callback, 4, 4);
-			if (_opt.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
+			if (_settings.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
 				/* The 'S' bit indicates food instead of goods */
 				ac[CT_FOOD] = GB(callback, 8, 4);
 			} else {
@@ -620,7 +620,7 @@
 		td->str = STR_2058_UNDER_CONSTRUCTION;
 	}
 
-	td->owner = OWNER_TOWN;
+	td->owner[0] = OWNER_TOWN;
 }
 
 static TrackStatus GetTileTrackStatus_Town(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
@@ -1212,14 +1212,14 @@
 		do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir)));
 		tile = TileAddByDiagDir(tile, target_dir);
 
-		if (IsTileType(tile, MP_ROAD)) {
+		if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, ROADTYPE_ROAD)) {
 			/* Don't allow building over roads of other cities */
-			if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) {
+			if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) && GetTownByTile(tile) != t) {
 				_grow_town_result = GROWTH_SUCCEED;
-			} else if (IsTileOwner(tile, OWNER_NONE) && _game_mode == GM_EDITOR) {
+			} else if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) {
 				/* If we are in the SE, and this road-piece has no town owner yet, it just found an
 				 * owner :) (happy happy happy road now) */
-				SetTileOwner(tile, OWNER_TOWN);
+				SetRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN);
 				SetTownIndex(tile, t->index);
 			}
 		}
@@ -1255,7 +1255,7 @@
 	/* Let the town be a ghost town
 	 * The player wanted it in such a way. Thus there he has it. ;)
 	 * Never reached in editor mode. */
-	if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
+	if (_settings.economy.town_layout == TL_NO_ROADS && _generating_world) {
 		return false;
 	}
 
@@ -1367,9 +1367,9 @@
 	 * the other towns may take considerable amount of time (10000 is
 	 * too much). */
 	int tries = 1000;
-	bool grf = (_opt.town_name >= _nb_orig_names);
-	uint32 grfid = grf ? GetGRFTownNameId(_opt.town_name - _nb_orig_names) : 0;
-	uint16 townnametype = grf ? GetGRFTownNameType(_opt.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _opt.town_name;
+	bool grf = (_settings.game_creation.town_name >= _nb_orig_names);
+	uint32 grfid = grf ? GetGRFTownNameId(_settings.game_creation.town_name - _nb_orig_names) : 0;
+	uint16 townnametype = grf ? GetGRFTownNameType(_settings.game_creation.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _settings.game_creation.town_name;
 
 	assert(townnameparts != NULL);
 
@@ -1453,14 +1453,14 @@
 	t->exclusive_counter = 0;
 	t->statues = 0;
 
-	if (_opt.town_name < _nb_orig_names) {
+	if (_settings.game_creation.town_name < _nb_orig_names) {
 		/* Original town name */
 		t->townnamegrfid = 0;
-		t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
+		t->townnametype = SPECSTR_TOWNNAME_START + _settings.game_creation.town_name;
 	} else {
 		/* Newgrf town name */
-		t->townnamegrfid = GetGRFTownNameId(_opt.town_name  - _nb_orig_names);
-		t->townnametype  = GetGRFTownNameType(_opt.town_name - _nb_orig_names);
+		t->townnamegrfid = GetGRFTownNameId(_settings.game_creation.town_name  - _nb_orig_names);
+		t->townnametype  = GetGRFTownNameType(_settings.game_creation.town_name - _nb_orig_names);
 	}
 	t->townnameparts = townnameparts;
 
@@ -1485,11 +1485,13 @@
 			break;
 
 		case TSM_CITY:
-			x *= _patches.initial_city_size;
+			x *= _settings.economy.initial_city_size;
 			t->larger_town = true;
 			break;
 	}
 
+	t->noise_reached = 0;
+
 	t->num_houses += x;
 	UpdateTownRadius(t);
 
@@ -1578,13 +1580,13 @@
 	return NULL;
 }
 
-static const byte _num_initial_towns[4] = {5, 11, 23, 46};
+static const byte _num_initial_towns[4] = {5, 11, 23, 46};  // very low, low, normal, high
 
 bool GenerateTowns()
 {
 	uint num = 0;
-	uint n = ScaleByMapSize(_num_initial_towns[_opt.diff.number_towns] + (Random() & 7));
-	uint num_cities = _patches.larger_towns == 0 ? 0 : n / _patches.larger_towns;
+	uint n = ScaleByMapSize(_num_initial_towns[_settings.difficulty.number_towns] + (Random() & 7));
+	uint num_cities = _settings.economy.larger_towns == 0 ? 0 : n / _settings.economy.larger_towns;
 
 	SetGeneratingWorldProgress(GWP_TOWN, n);
 
@@ -1592,7 +1594,7 @@
 		IncreaseGeneratingWorldProgress(GWP_TOWN);
 		/* try 20 times to create a random-sized town for the first loop. */
 		TownSizeMode mode = num_cities > 0 ? TSM_CITY : TSM_RANDOM;
-		if (CreateRandomTown(20, mode, _patches.initial_city_size) != NULL) num++;
+		if (CreateRandomTown(20, mode, _settings.economy.initial_city_size) != NULL) num++;
 		if (num_cities > 0) num_cities--;
 	} while (--n);
 
@@ -1877,8 +1879,8 @@
 	HouseZonesBits rad = GetTownRadiusGroup(t, tile);
 
 	/* Above snow? */
-	int land = _opt.landscape;
-	if (land == LT_ARCTIC && z >= _opt.snow_line) land = -1;
+	int land = _settings.game_creation.landscape;
+	if (land == LT_ARCTIC && z >= _settings.game_creation.snow_line) land = -1;
 
 	uint bitmask = (1 << rad) + (1 << (land + 12));
 
@@ -2217,7 +2219,7 @@
 static void TownActionBuyRights(Town *t)
 {
 	/* Check if it's allowed to by the rights */
-	if (!_patches.exclusive_rights) return;
+	if (!_settings.economy.exclusive_rights) return;
 
 	t->exclusive_counter = 12;
 	t->exclusivity = _current_player;
@@ -2331,7 +2333,7 @@
 	}
 
 	ClrBit(t->flags12, TOWN_IS_FUNDED);
-	if (_patches.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
+	if (_settings.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
 
 	/** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the
 	 * number of times towns are processed before a new building is built. */
@@ -2350,17 +2352,17 @@
 		if (n == 0 && !Chance16(1, 12)) return;
 	}
 
-	if (_opt.landscape == LT_ARCTIC) {
+	if (_settings.game_creation.landscape == LT_ARCTIC) {
 		if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90)
 			return;
-	} else if (_opt.landscape == LT_TROPIC) {
+	} else if (_settings.game_creation.landscape == LT_TROPIC) {
 		if (GetTropicZone(t->xy) == TROPICZONE_DESERT && (t->act_food == 0 || t->act_water == 0) && t->population > 60)
 			return;
 	}
 
 	/* Use the normal growth rate values if new buildings have been funded in
 	 * this town and the growth rate is set to none. */
-	uint growth_multiplier = _patches.town_growth_rate != 0 ? _patches.town_growth_rate - 1 : 1;
+	uint growth_multiplier = _settings.economy.town_growth_rate != 0 ? _settings.economy.town_growth_rate - 1 : 1;
 
 	m >>= growth_multiplier;
 	if (t->larger_town) m /= 2;
@@ -2403,7 +2405,7 @@
 {
 	if (!IsValidPlayer(_current_player)) return true;
 
-	Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
+	Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority);
 	if (t == NULL) return true;
 
 	if (t->ratings[_current_player] > RATING_VERYPOOR) return true;
@@ -2436,8 +2438,8 @@
 Town *ClosestTownFromTile(TileIndex tile, uint threshold)
 {
 	if (IsTileType(tile, MP_HOUSE) || (
-				IsTileType(tile, MP_ROAD) &&
-				GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN
+				IsTileType(tile, MP_ROAD) && HasTileRoadType(tile, ROADTYPE_ROAD) &&
+				IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)
 			)) {
 		return GetTownByTile(tile);
 	} else {
@@ -2522,7 +2524,7 @@
 	 * owned by a town no removal if rating is lower than ... depends now on
 	 * difficulty setting. Minimum town rating selected by difficulty level
 	 */
-	int modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type];
+	int modemod = _default_rating_settings[_settings.difficulty.town_council_tolerance][type];
 
 	if (GetRating(t) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) {
 		SetDParam(0, t->index);
--- a/src/town_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/town_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -31,16 +31,6 @@
 extern bool GenerateTowns();
 static int _scengen_town_size = 1; // depress medium-sized towns per default
 
-enum TownAuthorityWidget {
-	TWA_CLOSEBOX = 0,
-	TWA_CAPTION,
-	TWA_RATING_INFO,
-	TWA_COMMAND_LIST,
-	TWA_SCROLLBAR,
-	TWA_ACTION_INFO,
-	TWA_EXECUTE,
-};
-
 static const Widget _town_authority_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    13,     0,    10,     0,    13, STR_00C5,                 STR_018B_CLOSE_WINDOW},              // TWA_CLOSEBOX
 {    WWT_CAPTION,   RESIZE_NONE,    13,    11,   316,     0,    13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS},    // TWA_CAPTION
@@ -86,7 +76,7 @@
 	TownActions buttons = TACT_NONE;
 
 	/* Spectators and unwanted have no options */
-	if (pid != PLAYER_SPECTATOR && !(_patches.bribe && t->unwanted[pid])) {
+	if (pid != PLAYER_SPECTATOR && !(_settings.economy.bribe && t->unwanted[pid])) {
 
 		/* Things worth more than this are not shown */
 		Money avail = GetPlayer(pid)->player_money + _price.station_value * 200;
@@ -98,11 +88,11 @@
 			const TownActions cur = (TownActions)(1 << i);
 
 			/* Is the player not able to bribe ? */
-			if (cur == TACT_BRIBE && (!_patches.bribe || t->ratings[pid] >= RATING_BRIBE_MAXIMUM))
+			if (cur == TACT_BRIBE && (!_settings.economy.bribe || t->ratings[pid] >= RATING_BRIBE_MAXIMUM))
 				continue;
 
 			/* Is the player not able to buy exclusive rights ? */
-			if (cur == TACT_BUY_RIGHTS && !_patches.exclusive_rights)
+			if (cur == TACT_BUY_RIGHTS && !_settings.economy.exclusive_rights)
 				continue;
 
 			/* Is the player not able to build a statue ? */
@@ -142,11 +132,25 @@
 }
 
 struct TownAuthorityWindow : Window {
+private:
+	Town *town;
 	int sel_index;
 
+	enum TownAuthorityWidget {
+		TWA_CLOSEBOX = 0,
+		TWA_CAPTION,
+		TWA_RATING_INFO,
+		TWA_COMMAND_LIST,
+		TWA_SCROLLBAR,
+		TWA_ACTION_INFO,
+		TWA_EXECUTE,
+	};
+
+public:
 	TownAuthorityWindow(const WindowDesc *desc, WindowNumber window_number) :
 			Window(desc, window_number), sel_index(-1)
 	{
+		this->town = GetTown(this->window_number);
 		this->vscroll.cap = 5;
 
 		this->FindWindowPlacementAndResize(desc);
@@ -154,9 +158,8 @@
 
 	virtual void OnPaint()
 	{
-		const Town *t = GetTown(this->window_number);
 		int numact;
-		uint buttons = GetMaskOfTownActions(&numact, _local_player, t);
+		uint buttons = GetMaskOfTownActions(&numact, _local_player, this->town);
 
 		SetVScrollCount(this, numact + 1);
 
@@ -176,13 +179,13 @@
 
 		const Player *p;
 		FOR_ALL_PLAYERS(p) {
-			if (p->is_active && (HasBit(t->have_ratings, p->index) || t->exclusivity == p->index)) {
+			if (p->is_active && (HasBit(this->town->have_ratings, p->index) || this->town->exclusivity == p->index)) {
 				DrawPlayerIcon(p->index, 2, y);
 
 				SetDParam(0, p->index);
 				SetDParam(1, p->index);
 
-				int r = t->ratings[p->index];
+				int r = this->town->ratings[p->index];
 				StringID str;
 				(str = STR_3035_APPALLING, r <= RATING_APPALLING) || // Apalling
 				(str++,                    r <= RATING_VERYPOOR)  || // Very Poor
@@ -194,7 +197,7 @@
 				(str++,                    true);                    // Outstanding
 
 				SetDParam(2, str);
-				if (t->exclusivity == p->index) { // red icon for player with exclusive rights
+				if (this->town->exclusivity == p->index) { // red icon for player with exclusive rights
 					DrawSprite(SPR_BLOT, PALETTE_TO_RED, 18, y);
 				}
 
@@ -233,12 +236,11 @@
 	{
 		switch (widget) {
 			case TWA_COMMAND_LIST: {
-				const Town *t = GetTown(this->window_number);
 				int y = (pt.y - 0x6B) / 10;
 
 				if (!IsInsideMM(y, 0, 5)) return;
 
-				y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, t), y + this->vscroll.pos - 1);
+				y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, this->town), y + this->vscroll.pos - 1);
 				if (y >= 0) {
 					this->sel_index = y;
 					this->SetDirty();
@@ -248,7 +250,7 @@
 			}
 
 			case TWA_EXECUTE:
-				DoCommandP(GetTown(this->window_number)->xy, this->window_number, this->sel_index, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
+				DoCommandP(this->town->xy, this->window_number, this->sel_index, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
 				break;
 		}
 	}
@@ -264,7 +266,6 @@
 	WC_TOWN_AUTHORITY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 	_town_authority_widgets,
-	NULL
 };
 
 static void ShowTownAuthorityWindow(uint town)
@@ -272,98 +273,138 @@
 	AllocateWindowDescFront<TownAuthorityWindow>(&_town_authority_desc, town);
 }
 
-
-enum TownViewWidget {
-	TVW_CAPTION = 1,
-	TVW_STICKY,
-	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: {
-			bool ingame = _game_mode != GM_EDITOR;
-			if (t->larger_town) w->widget[TVW_CAPTION].data = STR_CITY;
-			w->SetWidgetHiddenState(TVW_DELETE, ingame);  // hide delete button on game mode
-			w->SetWidgetHiddenState(TVW_EXPAND, ingame);  // hide expand button on game mode
-			w->SetWidgetHiddenState(TVW_SHOWAUTORITY, !ingame); // hide autority button on editor mode
-
-			if (ingame) {
-				/* resize caption bar */
-				w->widget[TVW_CAPTION].right = w->widget[TVW_STICKY].left -1;
-				/* move the rename from top on scenario to bottom in game */
-				w->widget[TVW_CHANGENAME].top = w->widget[TVW_EXPAND].top;
-				w->widget[TVW_CHANGENAME].bottom = w->widget[TVW_EXPAND].bottom;
-				w->widget[TVW_CHANGENAME].right = w->widget[TVW_STICKY].right;
-			}
-		} break;
-
-		case WE_PAINT:
-			/* disable renaming town in network games if you are not the server */
-			w->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server);
-
-			SetDParam(0, t->index);
-			w->DrawWidgets();
-
-			SetDParam(0, t->population);
-			SetDParam(1, t->num_houses);
-			DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING);
+struct TownViewWindow : Window {
+private:
+	Town *town;
 
-			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);
-
-			w->DrawViewport();
-			break;
-
-		case WE_CLICK:
-			switch (e->we.click.widget) {
-				case TVW_CENTERVIEW: /* scroll to location */
-					if (_ctrl_pressed) {
-						ShowExtraViewPortWindow(t->xy);
-					} else {
-						ScrollMainWindowToTile(t->xy);
-					}
-					break;
+	enum TownViewWidget {
+		TVW_CAPTION = 1,
+		TVW_STICKY,
+		TVW_VIEWPORTPANEL,
+		TVW_INFOPANEL = 5,
+		TVW_CENTERVIEW,
+		TVW_SHOWAUTORITY,
+		TVW_CHANGENAME,
+		TVW_EXPAND,
+		TVW_DELETE,
+	};
 
-				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;
+public:
+	TownViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->town = GetTown(this->window_number);
+		bool ingame = _game_mode != GM_EDITOR;
 
-				case TVW_DELETE: /* delete town - only available on Scenario editor */
-					delete t;
-					break;
-			} break;
+		this->flags4 |= WF_DISABLE_VP_SCROLL;
+		InitializeWindowViewport(this, 3, 17, 254, 86, this->town->xy, ZOOM_LVL_TOWN);
 
-		case WE_ON_EDIT_TEXT:
-			if (!StrEmpty(e->we.edittext.str)) {
-				_cmd_text = e->we.edittext.str;
-				DoCommandP(0, w->window_number, 0, NULL,
-					CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
+		if (this->town->larger_town) this->widget[TVW_CAPTION].data = STR_CITY;
+		this->SetWidgetHiddenState(TVW_DELETE, ingame);  // hide delete button on game mode
+		this->SetWidgetHiddenState(TVW_EXPAND, ingame);  // hide expand button on game mode
+		this->SetWidgetHiddenState(TVW_SHOWAUTORITY, !ingame); // hide autority button on editor mode
+
+		if (ingame) {
+			/* resize caption bar */
+			this->widget[TVW_CAPTION].right = this->widget[TVW_STICKY].left -1;
+			/* move the rename from top on scenario to bottom in game */
+			this->widget[TVW_CHANGENAME].top = this->widget[TVW_EXPAND].top;
+			this->widget[TVW_CHANGENAME].bottom = this->widget[TVW_EXPAND].bottom;
+			this->widget[TVW_CHANGENAME].right = this->widget[TVW_STICKY].right;
+		}
+
+		/* Space required for showing noise level information */
+		if (_settings.economy.station_noise_level) {
+			ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
+		}
+
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	virtual void OnPaint()
+	{
+		/* disable renaming town in network games if you are not the server */
+		this->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server);
+
+		SetDParam(0, this->town->index);
+		this->DrawWidgets();
+
+		SetDParam(0, this->town->population);
+		SetDParam(1, this->town->num_houses);
+		DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING);
+
+		SetDParam(0, this->town->act_pass);
+		SetDParam(1, this->town->max_pass);
+		DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING);
+
+		SetDParam(0, this->town->act_mail);
+		SetDParam(1, this->town->max_mail);
+		DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING);
+
+		this->DrawViewport();
+
+		/* only show the town noise, if the noise option is activated. */
+		if (_settings.economy.station_noise_level) {
+			SetDParam(0, this->town->noise_reached);
+			SetDParam(1, this->town->MaxTownNoise());
+			DrawString(2, 137, STR_NOISE_IN_TOWN, 0);
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case TVW_CENTERVIEW: /* scroll to location */
+				if (_ctrl_pressed) {
+					ShowExtraViewPortWindow(this->town->xy);
+				} else {
+					ScrollMainWindowToTile(this->town->xy);
+				}
+				break;
+
+			case TVW_SHOWAUTORITY: /* town authority */
+				ShowTownAuthorityWindow(this->window_number);
+				break;
+
+			case TVW_CHANGENAME: /* rename */
+				SetDParam(0, this->window_number);
+				ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, this, CS_ALPHANUMERAL);
+				break;
+
+			case TVW_EXPAND: /* expand town - only available on Scenario editor */
+				ExpandTown(this->town);
+				break;
+
+			case TVW_DELETE: /* delete town - only available on Scenario editor */
+				delete this->town;
+				break;
+		}
+	}
+
+	virtual void OnInvalidateData(int data = 0)
+	{
+		/* Called when setting station noise have changed, in order to resize the window */
+		this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
+
+		if (_settings.economy.station_noise_level) { // adjust depending
+			if (this->height == 150) { // window is smaller, needs to be bigger
+				ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10);
 			}
-			break;
+		} else {
+			if (this->height != 150) { // window is bigger, needs to be smaller
+				ResizeWindowForWidget(this, TVW_INFOPANEL, 0, -10);
+			}
+		}
 	}
-}
+
+	virtual void OnQueryTextFinished(char *str)
+	{
+		if (!StrEmpty(str)) {
+			_cmd_text = str;
+			DoCommandP(0, this->window_number, 0, NULL,
+				CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
+		}
+	}
+};
 
 
 static const Widget _town_view_widgets[] = {
@@ -386,26 +427,13 @@
 	WC_TOWN_VIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
 	_town_view_widgets,
-	TownViewWndProc
 };
 
 void ShowTownViewWindow(TownID town)
 {
-	Window *w;
-
-	w = AllocateWindowDescFront<Window>(&_town_view_desc, town);
-
-	if (w != NULL) {
-		w->flags4 |= WF_DISABLE_VP_SCROLL;
-		InitializeWindowViewport(w, 3, 17, 254, 86, GetTown(town)->xy, ZOOM_LVL_TOWN);
-	}
+	AllocateWindowDescFront<TownViewWindow>(&_town_view_desc, town);
 }
 
-enum TownDirectoryWidget {
-	TDW_SORTNAME = 3,
-	TDW_SORTPOPULATION,
-	TDW_CENTERTOWN,
-};
 static const Widget _town_directory_widgets[] = {
 {   WWT_CLOSEBOX,   RESIZE_NONE,    13,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
 {    WWT_CAPTION,   RESIZE_NONE,    13,    11,   195,     0,    13, STR_2000_TOWNS,         STR_018C_WINDOW_TITLE_DRAG_THIS},
@@ -478,107 +506,120 @@
 }
 
 
-static void TownDirectoryWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			if (_town_sort_dirty) {
-				_town_sort_dirty = false;
-				MakeSortedTownList();
+struct TownDirectoryWindow : public Window {
+private:
+	enum TownDirectoryWidget {
+		TDW_SORTNAME = 3,
+		TDW_SORTPOPULATION,
+		TDW_CENTERTOWN,
+	};
+
+public:
+	TownDirectoryWindow(const WindowDesc *desc) : Window(desc, 0)
+	{
+		this->vscroll.cap = 16;
+		this->resize.step_height = 10;
+		this->resize.height = this->height - 10 * 6; // minimum of 10 items in the list, each item 10 high
+
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	virtual void OnPaint()
+	{
+		if (_town_sort_dirty) {
+			_town_sort_dirty = false;
+			MakeSortedTownList();
+		}
+
+		SetVScrollCount(this, _num_town_sort);
+
+		this->DrawWidgets();
+		this->DrawSortButtonState((_town_sort_order <= 1) ? TDW_SORTNAME : TDW_SORTPOPULATION, _town_sort_order & 1 ? SBS_DOWN : SBS_UP);
+
+		{
+			int n = 0;
+			uint16 i = this->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 == this->vscroll.cap) break; // max number of towns in 1 window
 			}
 
-			SetVScrollCount(w, _num_town_sort);
-
-			w->DrawWidgets();
-			w->DrawSortButtonState((_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
-				}
-				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;
-					w->SetDirty();
-					break;
+			SetDParam(0, GetWorldPopulation());
+			DrawString(3, this->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING);
+		}
+	}
 
-				case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */
-					_town_sort_order = (_town_sort_order == 2) ? 3 : 2;
-					_town_sort_dirty = true;
-					w->SetDirty();
-					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
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case TDW_SORTNAME: /* Sort by Name ascending/descending */
+				_town_sort_order = (_town_sort_order == 0) ? 1 : 0;
+				_town_sort_dirty = true;
+				this->SetDirty();
+				break;
 
-					t = _town_sort[id_v];
-					assert(t->xy);
-					if (_ctrl_pressed) {
-						ShowExtraViewPortWindow(t->xy);
-					} else {
-						ScrollMainWindowToTile(t->xy);
-					}
-				} break;
+			case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */
+				_town_sort_order = (_town_sort_order == 2) ? 3 : 2;
+				_town_sort_dirty = true;
+				this->SetDirty();
+				break;
+
+			case TDW_CENTERTOWN: { /* Click on Town Matrix */
+				const Town* t;
+
+				uint16 id_v = (pt.y - 28) / 10;
+
+				if (id_v >= this->vscroll.cap) return; // click out of bounds
+
+				id_v += this->vscroll.pos;
+
+				if (id_v >= _num_town_sort) return; // click out of town bounds
+
+				t = _town_sort[id_v];
+				assert(t->xy);
+				if (_ctrl_pressed) {
+					ShowExtraViewPortWindow(t->xy);
+				} else {
+					ScrollMainWindowToTile(t->xy);
+				}
+				break;
 			}
-			break;
+		}
+	}
 
-		case WE_100_TICKS:
-			w->SetDirty();
-			break;
+	virtual void OnHundredthTick()
+	{
+		this->SetDirty();
+	}
 
-		case WE_RESIZE:
-			w->vscroll.cap += e->we.sizing.diff.y / 10;
-			break;
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->vscroll.cap += delta.y / 10;
 	}
-}
+};
 
 static const WindowDesc _town_directory_desc = {
 	WDP_AUTO, WDP_AUTO, 208, 202, 208, 202,
 	WC_TOWN_DIRECTORY, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_town_directory_widgets,
-	TownDirectoryWndProc
 };
 
-
 void ShowTownDirectory()
 {
-	Window *w = AllocateWindowDescFront<Window>(&_town_directory_desc, 0);
-
-	if (w != NULL) {
-		w->vscroll.cap = 16;
-		w->resize.step_height = 10;
-		w->resize.height = w->height - 10 * 6; // minimum of 10 items in the list, each item 10 high
-	}
+	if (BringWindowToFrontById(WC_TOWN_DIRECTORY, 0)) return;
+	new TownDirectoryWindow(&_town_directory_desc);
 }
 
 void CcBuildTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
@@ -596,16 +637,6 @@
 	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},
@@ -622,85 +653,102 @@
 {   WIDGETS_END},
 };
 
-static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
+struct ScenarioEditorTownGenerationWindow : Window
 {
-	switch (e->event) {
-		case WE_PAINT:
-			w->DrawWidgets();
-			break;
-
-		case WE_CREATE:
-			w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
-			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 TSEW_RANDOMTOWN: {
-					Town *t;
-					uint size = min(_scengen_town_size, (int)TSM_CITY);
-					TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
+private:
+	enum TownScenarioEditorWidget {
+		TSEW_NEWTOWN = 4,
+		TSEW_RANDOMTOWN,
+		TSEW_MANYRANDOMTOWNS,
+		TSEW_SMALLTOWN,
+		TSEW_MEDIUMTOWN,
+		TSEW_LARGETOWN,
+		TSEW_CITY,
+	};
 
-					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;
+public:
+	ScenarioEditorTownGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
+		this->FindWindowPlacementAndResize(desc);
+	}
 
-				case TSEW_MANYRANDOMTOWNS:
-					w->HandleButtonClick(TSEW_MANYRANDOMTOWNS);
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
 
-					_generating_world = true;
-					if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
-					_generating_world = false;
-					break;
+	virtual void OnClick(Point pt, int widget)
+	{
+		switch (widget) {
+			case TSEW_NEWTOWN:
+				HandlePlacePushButton(this, TSEW_NEWTOWN, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town);
+				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);
-					w->SetDirty();
-					break;
+			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;
+
+				this->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 WE_TIMEOUT:
-			w->RaiseWidget(TSEW_RANDOMTOWN);
-			w->RaiseWidget(TSEW_MANYRANDOMTOWNS);
-			w->SetDirty();
-			break;
+			case TSEW_MANYRANDOMTOWNS:
+				this->HandleButtonClick(TSEW_MANYRANDOMTOWNS);
 
-		case WE_PLACE_OBJ:
-			_place_proc(e->we.place.tile);
-			break;
+				_generating_world = true;
+				if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0);
+				_generating_world = false;
+				break;
 
-		case WE_ABORT_PLACE_OBJ:
-			w->RaiseButtons();
-			w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
-			w->SetDirty();
-			break;
+			case TSEW_SMALLTOWN: case TSEW_MEDIUMTOWN: case TSEW_LARGETOWN: case TSEW_CITY:
+				this->RaiseWidget(_scengen_town_size + TSEW_SMALLTOWN);
+				_scengen_town_size = widget - TSEW_SMALLTOWN;
+				this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
+				this->SetDirty();
+				break;
+		}
 	}
-}
+
+	virtual void OnTimeout()
+	{
+		this->RaiseWidget(TSEW_RANDOMTOWN);
+		this->RaiseWidget(TSEW_MANYRANDOMTOWNS);
+		this->SetDirty();
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		_place_proc(tile);
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		this->RaiseButtons();
+		this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN);
+		this->SetDirty();
+	}
+};
 
 static const WindowDesc _scen_edit_town_gen_desc = {
 	WDP_AUTO, WDP_AUTO, 160, 95, 160, 95,
 	WC_SCEN_TOWN_GEN, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_scen_edit_town_gen_widgets,
-	ScenEditTownGenWndProc,
 };
 
 void ShowBuildTownWindow()
 {
 	if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return;
-	AllocateWindowDescFront<Window>(&_scen_edit_town_gen_desc, 0);
+	AllocateWindowDescFront<ScenarioEditorTownGenerationWindow>(&_scen_edit_town_gen_desc, 0);
 }
 
--- a/src/town_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/town_type.h	Tue May 27 00:50:55 2008 +0000
@@ -54,7 +54,8 @@
 	RATING_INDUSTRY_DOWN_STEP = -1500,
 	RATING_INDUSTRY_MINIMUM   = RATING_MINIMUM,
 
-	RATING_ROAD_DOWN_STEP = -50,
+	RATING_ROAD_DOWN_STEP_INNER = -50, ///< removing a roadpiece in the middle
+	RATING_ROAD_DOWN_STEP_EDGE  = -18, ///< removing a roadpiece at the edge
 	RATING_ROAD_MINIMUM   = -100,
 	RATING_HOUSE_MINIMUM  = RATING_MINIMUM,
 
--- a/src/train_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/train_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -92,7 +92,7 @@
 byte FreightWagonMult(CargoID cargo)
 {
 	if (!GetCargo(cargo)->is_freight) return 1;
-	return _patches.freight_trains;
+	return _settings.vehicle.freight_trains;
 }
 
 
@@ -278,7 +278,7 @@
 			}
 
 			/* max speed is the minimum of the speed limits of all vehicles in the consist */
-			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) {
+			if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) {
 				uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed);
 				if (speed != 0) max_speed = min(speed, max_speed);
 			}
@@ -726,7 +726,7 @@
 		Vehicle *v = vl[0];
 
 		UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_TRAIN);
-		if (unit_num > _patches.max_trains)
+		if (unit_num > _settings.vehicle.max_trains)
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 		if (flags & DC_EXEC) {
@@ -765,7 +765,7 @@
 			v->u.rail.railtype = rvi->railtype;
 			_new_vehicle_id = v->index;
 
-			v->service_interval = _patches.servint_trains;
+			v->service_interval = _settings.vehicle.servint_trains;
 			v->date_of_last_service = _date;
 			v->build_year = _cur_year;
 			v->cur_image = 0xAC2;
@@ -803,7 +803,7 @@
 			}
 
 			InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
-			RebuildVehicleLists();
+			InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 			InvalidateWindow(WC_COMPANY, v->owner);
 			if (IsLocalPlayer()) {
 				InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
@@ -1001,7 +1001,7 @@
 	if (HasBit(p2, 0) && src_head == dst_head) return CommandCost();
 
 	{
-		int max_len = _patches.mammoth_trains ? 100 : 10;
+		int max_len = _settings.vehicle.mammoth_trains ? 100 : 10;
 
 		/* check if all vehicles in the source train are stopped inside a depot. */
 		int src_len = CheckTrainStoppedInDepot(src_head);
@@ -1044,7 +1044,7 @@
 	/* moving a loco to a new line?, then we need to assign a unitnumber. */
 	if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
 		UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN);
-		if (unit_num > _patches.max_trains)
+		if (unit_num > _settings.vehicle.max_trains)
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 		if (flags & DC_EXEC) src->unitnumber = unit_num;
@@ -1272,7 +1272,7 @@
 			InvalidateWindow(WC_VEHICLE_DEPOT, dst_head->tile);
 		}
 
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 	}
 
 	return CommandCost();
@@ -1353,7 +1353,7 @@
 			DeleteWindowById(WC_VEHICLE_VIEW, first->index);
 		}
 		InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 	}
 
 	CommandCost cost(EXPENSES_NEW_VEHICLES);
@@ -1544,7 +1544,7 @@
 	int old = v->u.rail.last_speed;
 	if (spd != old) {
 		v->u.rail.last_speed = spd;
-		if (_patches.vehicle_speed || (old == 0) != (spd == 0)) {
+		if (_settings.gui.vehicle_speed || (old == 0) != (spd == 0)) {
 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 		}
 	}
@@ -1883,7 +1883,7 @@
 		if (v->vehstatus & VS_CRASHED || v->breakdown_ctr != 0) return CMD_ERROR;
 
 		if (flags & DC_EXEC) {
-			if (_patches.realistic_acceleration && v->cur_speed != 0) {
+			if (_settings.vehicle.realistic_acceleration && v->cur_speed != 0) {
 				ToggleBit(v->u.rail.flags, VRF_REVERSING);
 			} else {
 				v->cur_speed = 0;
@@ -2001,7 +2001,7 @@
 					v->cargo_subtype = new_subtype;
 					InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 					InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
-					RebuildVehicleLists();
+					InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 				}
 			}
 		}
@@ -2058,7 +2058,7 @@
 		return tfdd;
 	}
 
-	switch (_patches.pathfinder_for_trains) {
+	switch (_settings.pf.pathfinder_for_trains) {
 		case VPF_YAPF: { /* YAPF */
 			bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
 			tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
@@ -2369,7 +2369,7 @@
 	/* quick return in case only one possible track is available */
 	if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
 
-	switch (_patches.pathfinder_for_trains) {
+	switch (_settings.pf.pathfinder_for_trains) {
 		case VPF_YAPF: { /* YAPF */
 			Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
 			if (trackdir != INVALID_TRACKDIR) {
@@ -2446,7 +2446,7 @@
 			/* it is first time the problem occurred, set the "path not found" flag */
 			SetBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
 			/* and notify user about the event */
-			if (_patches.lost_train_warn && v->owner == _local_player) {
+			if (_settings.gui.lost_train_warn && v->owner == _local_player) {
 				SetDParam(0, v->unitnumber);
 				AddNewsItem(
 					STR_TRAIN_IS_LOST,
@@ -2474,7 +2474,7 @@
 
 static bool CheckReverseTrain(Vehicle *v)
 {
-	if (_opt.diff.line_reverse_mode != 0 ||
+	if (_settings.difficulty.line_reverse_mode != 0 ||
 			v->u.rail.track == TRACK_BIT_DEPOT || v->u.rail.track == TRACK_BIT_WORMHOLE ||
 			!(v->direction & 1)) {
 		return false;
@@ -2487,7 +2487,7 @@
 
 	assert(v->u.rail.track);
 
-	switch (_patches.pathfinder_for_trains) {
+	switch (_settings.pf.pathfinder_for_trains) {
 		case VPF_YAPF: /* YAPF */
 			reverse_best = YapfCheckReverseTrain(v);
 			break;
@@ -2607,13 +2607,13 @@
 	uint accel;
 
 	if (v->vehstatus & VS_STOPPED || HasBit(v->u.rail.flags, VRF_REVERSING)) {
-		if (_patches.realistic_acceleration) {
+		if (_settings.vehicle.realistic_acceleration) {
 			accel = GetTrainAcceleration(v, AM_BRAKE) * 2;
 		} else {
 			accel = v->acceleration * -2;
 		}
 	} else {
-		if (_patches.realistic_acceleration) {
+		if (_settings.vehicle.realistic_acceleration) {
 			accel = GetTrainAcceleration(v, AM_ACCEL);
 		} else {
 			accel = v->acceleration;
@@ -2754,7 +2754,7 @@
 /** Modify the speed of the vehicle due to a turn */
 static inline void AffectSpeedByDirChange(Vehicle *v, Direction new_dir)
 {
-	if (_patches.realistic_acceleration) return;
+	if (_settings.vehicle.realistic_acceleration) return;
 
 	DirDiff diff = DirDifference(v->direction, new_dir);
 	if (diff == DIRDIFF_SAME) return;
@@ -2766,7 +2766,7 @@
 /** Modify the speed of the vehicle due to a change in altitude */
 static inline void AffectSpeedByZChange(Vehicle *v, byte old_z)
 {
-	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
+	if (old_z == v->z_pos || _settings.vehicle.realistic_acceleration) return;
 
 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
 
@@ -2805,12 +2805,12 @@
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 	}
 
-	RebuildVehicleLists();
-
-	BEGIN_ENUM_WAGONS(v)
+	InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
+
+	for (; v != NULL; v = v->Next()) {
 		v->vehstatus |= VS_CRASHED;
 		MarkSingleVehicleDirty(v);
-	END_ENUM_WAGONS(v)
+	}
 
 	/* must be updated after the train has been marked crashed */
 	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
@@ -2819,9 +2819,11 @@
 static uint CountPassengersInTrain(const Vehicle *v)
 {
 	uint num = 0;
-	BEGIN_ENUM_WAGONS(v)
+
+	for (; v != NULL; v = v->Next()) {
 		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count();
-	END_ENUM_WAGONS(v)
+	}
+
 	return num;
 }
 
@@ -2969,7 +2971,7 @@
 				TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs);
 
 				TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
-				if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) {
+				if (_settings.pf.pathfinder_for_trains != VPF_NTP && _settings.pf.forbid_90_deg && prev == NULL) {
 					/* We allow wagons to make 90 deg turns, because forbid_90_deg
 					 * can be switched on halfway a turn */
 					bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
@@ -2997,12 +2999,12 @@
 							v->cur_speed = 0;
 							v->subspeed = 0;
 							v->progress = 255 - 100;
-							if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20) return;
+							if (++v->load_unload_time_rem < _settings.pf.wait_oneway_signal * 20) return;
 						} else if (HasSignalOnTrackdir(gp.new_tile, i)) {
 							v->cur_speed = 0;
 							v->subspeed = 0;
 							v->progress = 255 - 10;
-							if (++v->load_unload_time_rem < _patches.wait_twoway_signal * 73) {
+							if (++v->load_unload_time_rem < _settings.pf.wait_twoway_signal * 73) {
 								TileIndex o_tile = gp.new_tile + TileOffsByDiagDir(enterdir);
 								Direction rdir = ReverseDir(dir);
 
@@ -3152,7 +3154,7 @@
 		}
 	}
 
-	RebuildVehicleLists();
+	InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 
 	MarkSingleVehicleDirty(v);
 
@@ -3244,7 +3246,7 @@
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
 		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
-			SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ?
+			SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ?
 				SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
 		}
 
@@ -3404,7 +3406,7 @@
 
 	/* mask unreachable track bits if we are forbidden to do 90deg turns */
 	TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
-	if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) {
+	if (_settings.pf.pathfinder_for_trains != VPF_NTP && _settings.pf.forbid_90_deg) {
 		bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
 	}
 
@@ -3537,7 +3539,7 @@
 {
 	static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
 
-	if (_patches.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
+	if (_settings.vehicle.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
 	if (v->IsInDepot()) {
 		VehicleServiceInDepot(v);
 		return;
@@ -3612,7 +3614,7 @@
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
 			/* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
-			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) {
+			if (_settings.gui.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) {
 				SetDParam(1, v->GetDisplayProfitThisYear());
 				SetDParam(0, v->unitnumber);
 				AddNewsItem(
@@ -3651,9 +3653,7 @@
 
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
-			Vehicle *u = v;
-
-			BEGIN_ENUM_WAGONS(u) {
+			for (Vehicle *u = v; u != NULL; u = u->Next()) {
 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
 
 				if (IsMultiheaded(u)) {
@@ -3678,7 +3678,7 @@
 						ClearMultiheaded(u);
 					}
 				}
-			} END_ENUM_WAGONS(u)
+			}
 		}
 	}
 }
@@ -3699,9 +3699,7 @@
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN) {
 			if (HasBit(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
-				Vehicle *u = v;
-
-				BEGIN_ENUM_WAGONS(u) {
+				for (Vehicle *u = v; u != NULL; u = u->Next()) {
 					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
 
 					ClrBit(u->subtype, 7);
@@ -3740,7 +3738,7 @@
 							break;
 						default: NOT_REACHED(); break;
 					}
-				} END_ENUM_WAGONS(u)
+				}
 			}
 		}
 	}
--- a/src/train_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/train_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -18,6 +18,7 @@
 #include "order_func.h"
 #include "engine_func.h"
 #include "engine_base.h"
+#include "window_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -27,8 +28,8 @@
 	if (!success) return;
 
 	/* find a locomotive in the depot. */
-	Vehicle *found = NULL;
-	Vehicle *v;
+	const Vehicle *found = NULL;
+	const Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && IsFrontEngine(v) &&
 				v->tile == tile &&
@@ -43,7 +44,7 @@
 		found = GetLastVehicleInChain(found);
 		/* put the new wagon at the end of the loco. */
 		DoCommandP(0, _new_vehicle_id | (found->index << 16), 0, NULL, CMD_MOVE_RAIL_VEHICLE);
-		RebuildVehicleLists();
+		InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 	}
 }
 
@@ -123,7 +124,7 @@
 			SetDParam(0, v->cargo_type);
 			SetDParam(1, v->cargo.Count());
 			SetDParam(2, v->cargo.Source());
-			SetDParam(3, _patches.freight_trains);
+			SetDParam(3, _settings.vehicle.freight_trains);
 			str = FreightWagonMult(v->cargo_type) > 1 ? STR_FROM_MULT : STR_8813_FROM;
 		}
 		DrawString(x, y, str, TC_FROMSTRING);
@@ -149,7 +150,7 @@
 	if (v->cargo_cap != 0) {
 		SetDParam(0, v->cargo_type);
 		SetDParam(1, v->cargo_cap);
-		SetDParam(2, _patches.freight_trains);
+		SetDParam(2, _settings.vehicle.freight_trains);
 		DrawString(x, y, FreightWagonMult(v->cargo_type) > 1 ? STR_CAPACITY_MULT : STR_013F_CAPACITY, TC_FROMSTRING);
 	}
 }
@@ -248,7 +249,7 @@
 				SetDParam(1, act_cargo[i]); // {CARGO} #2
 				SetDParam(2, i);            // {SHORTCARGO} #1
 				SetDParam(3, max_cargo[i]); // {SHORTCARGO} #2
-				SetDParam(4, _patches.freight_trains);
+				SetDParam(4, _settings.vehicle.freight_trains);
 				DrawString(x, y + 2, FreightWagonMult(i) > 1 ? STR_TOTAL_CAPACITY_MULT : STR_TOTAL_CAPACITY, TC_FROMSTRING);
 			}
 		}
--- a/src/transparency_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/transparency_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -125,7 +125,6 @@
 	WC_TRANSPARENCY_TOOLBAR, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
 	_transparency_widgets,
-	NULL
 };
 
 void ShowTransparencyToolbar(void)
--- a/src/tree_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/tree_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -112,7 +112,7 @@
  */
 static TreeType GetRandomTreeType(TileIndex tile, uint seed)
 {
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_TEMPERATE:
 			return (TreeType)(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE);
 
@@ -249,7 +249,7 @@
 
 		if (CanPlantTreesOnTile(tile, true)) {
 			PlaceTree(tile, r);
-			if (_patches.tree_placer != TP_IMPROVED) continue;
+			if (_settings.game_creation.tree_placer != TP_IMPROVED) continue;
 
 			/* Place a number of trees based on the tile height.
 			 *  This gives a cool effect of multiple trees close together.
@@ -259,7 +259,7 @@
 			j = GetTileZ(tile) / TILE_HEIGHT * 2;
 			while (j--) {
 				/* Above snowline more trees! */
-				if (_opt.landscape == LT_ARCTIC && ht > GetSnowLine()) {
+				if (_settings.game_creation.landscape == LT_ARCTIC && ht > GetSnowLine()) {
 					PlaceTreeAtSameHeight(tile, ht);
 					PlaceTreeAtSameHeight(tile, ht);
 				};
@@ -270,7 +270,7 @@
 	} while (--i);
 
 	/* place extra trees at rainforest area */
-	if (_opt.landscape == LT_TROPIC) {
+	if (_settings.game_creation.landscape == LT_TROPIC) {
 		i = ScaleByMapSize(15000);
 
 		do {
@@ -296,18 +296,18 @@
 {
 	uint i, total;
 
-	if (_patches.tree_placer == TP_NONE) return;
+	if (_settings.game_creation.tree_placer == TP_NONE) return;
 
-	if (_opt.landscape != LT_TOYLAND) PlaceMoreTrees();
+	if (_settings.game_creation.landscape != LT_TOYLAND) PlaceMoreTrees();
 
-	switch (_patches.tree_placer) {
-		case TP_ORIGINAL: i = _opt.landscape == LT_ARCTIC ? 15 : 6; break;
-		case TP_IMPROVED: i = _opt.landscape == LT_ARCTIC ?  4 : 2; break;
+	switch (_settings.game_creation.tree_placer) {
+		case TP_ORIGINAL: i = _settings.game_creation.landscape == LT_ARCTIC ? 15 : 6; break;
+		case TP_IMPROVED: i = _settings.game_creation.landscape == LT_ARCTIC ?  4 : 2; break;
 		default: NOT_REACHED(); return;
 	}
 
 	total = ScaleByMapSize(1000);
-	if (_opt.landscape == LT_TROPIC) total += ScaleByMapSize(15000);
+	if (_settings.game_creation.landscape == LT_TROPIC) total += ScaleByMapSize(15000);
 	total *= i;
 	SetGeneratingWorldProgress(GWP_TREE, total);
 
@@ -332,7 +332,7 @@
 
 	if (p2 >= MapSize()) return CMD_ERROR;
 	/* Check the tree type. It can be random or some valid value within the current climate */
-	if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_opt.landscape] >= _tree_count_by_landscape[_opt.landscape]) return CMD_ERROR;
+	if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_settings.game_creation.landscape] >= _tree_count_by_landscape[_settings.game_creation.landscape]) return CMD_ERROR;
 
 	// make sure sx,sy are smaller than ex,ey
 	ex = TileX(tile);
@@ -390,7 +390,7 @@
 					}
 
 					if (_game_mode != GM_EDITOR && IsValidPlayer(_current_player)) {
-						Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
+						Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority);
 						if (t != NULL) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM);
 					}
 
@@ -533,7 +533,7 @@
 	uint num;
 
 	if (IsValidPlayer(_current_player)) {
-		Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
+		Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority);
 		if (t != NULL) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM);
 	}
 
@@ -560,7 +560,7 @@
 		td->str = tt == TREE_CACTUS ? STR_2810_CACTUS_PLANTS : STR_280E_TREES;
 	}
 
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 }
 
 static void AnimateTile_Trees(TileIndex tile)
@@ -626,7 +626,7 @@
 	if (GetTreeGround(tile) == TREE_GROUND_SHORE) {
 		TileLoop_Water(tile);
 	} else {
-		switch (_opt.landscape) {
+		switch (_settings.game_creation.landscape) {
 			case LT_TROPIC: TileLoopTreesDesert(tile); break;
 			case LT_ARCTIC: TileLoopTreesAlps(tile);   break;
 		}
@@ -652,7 +652,7 @@
 
 	switch (GetTreeGrowth(tile)) {
 		case 3: /* regular sized tree */
-			if (_opt.landscape == LT_TROPIC &&
+			if (_settings.game_creation.landscape == LT_TROPIC &&
 					GetTreeType(tile) != TREE_CACTUS &&
 					GetTropicZone(tile) == TROPICZONE_DESERT) {
 				AddTreeGrowth(tile, 1);
@@ -704,7 +704,7 @@
 					case TREE_GROUND_GRASS: MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); break;
 					case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break;
 					default: // snow or desert
-						MakeClear(tile, _opt.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetTreeDensity(tile));
+						MakeClear(tile, _settings.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetTreeDensity(tile));
 						break;
 				}
 			}
@@ -725,7 +725,7 @@
 	TreeType tree;
 
 	/* place a tree at a random rainforest spot */
-	if (_opt.landscape == LT_TROPIC &&
+	if (_settings.game_creation.landscape == LT_TROPIC &&
 			(r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) &&
 			CanPlantTreesOnTile(tile, false) &&
 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) {
--- a/src/tree_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/tree_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -74,8 +74,8 @@
 
 		this->DrawWidgets();
 
-		int i = this->base = _tree_base_by_landscape[_opt.landscape];
-		int count = this->count = _tree_count_by_landscape[_opt.landscape];
+		int i = this->base = _tree_base_by_landscape[_settings.game_creation.landscape];
+		int count = this->count = _tree_count_by_landscape[_settings.game_creation.landscape];
 
 		int x = 18;
 		int y = 54;
@@ -92,10 +92,6 @@
 	virtual void OnClick(Point pt, int widget)
 	{
 		switch (widget) {
-			case BTW_CLOSE:
-				ResetObjectToPlace();
-				break;
-
 			case BTW_TYPE_11: case BTW_TYPE_12: case BTW_TYPE_13: case BTW_TYPE_14:
 			case BTW_TYPE_21: case BTW_TYPE_22: case BTW_TYPE_23: case BTW_TYPE_24:
 			case BTW_TYPE_31: case BTW_TYPE_32: case BTW_TYPE_33: case BTW_TYPE_34:
@@ -128,12 +124,12 @@
 		VpSetPlaceSizingLimit(20);
 	}
 
-	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt)
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
 	{
 		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
 	}
 
-	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
 	{
 		if (pt.x != -1 && select_proc == DDSP_PLANT_TREES) {
 			DoCommandP(end_tile, this->tree_to_plant, start_tile, NULL,
@@ -179,7 +175,6 @@
 	WC_BUILD_TREES, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 	_build_trees_widgets,
-	NULL
 };
 
 void ShowBuildTreesToolbar()
--- a/src/tunnelbridge_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/tunnelbridge_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -169,7 +169,7 @@
 	if (b->avail_year > _cur_year) return false;
 
 	max = b->max_length;
-	if (max >= 16 && _patches.longbridges) max = 100;
+	if (max >= 16 && _settings.construction.longbridges) max = 100;
 
 	return b->min_length <= bridge_len && bridge_len <= max;
 }
@@ -311,7 +311,7 @@
 	} else {
 		/* Build a new bridge. */
 
-		bool allow_on_slopes = (!_is_old_ai_player && _patches.build_on_slopes);
+		bool allow_on_slopes = (!_is_old_ai_player && _settings.construction.build_on_slopes);
 
 		/* Try and clear the start landscape */
 		ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -576,7 +576,7 @@
 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
-	if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
+	if (IsTileOwner(tile, OWNER_TOWN) && (_settings.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
 	return false;
 }
 
@@ -1123,7 +1123,7 @@
 
 			DrawGroundSpriteAt(image, pal, x, y, z);
 		}
-	} else if (_patches.bridge_pillars) {
+	} else if (_settings.gui.bridge_pillars) {
 		/* draw pillars below for high bridges */
 		DrawBridgePillars(psid, ti, axis, type, x, y, z);
 	}
@@ -1188,7 +1188,7 @@
 	} else { //so it must be a bridge
 		td->str = GetBridgeSpec(GetBridgeType(tile))->transport_name[GetTunnelBridgeTransportType(tile)];
 	}
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 }
 
 
@@ -1200,7 +1200,7 @@
 static void TileLoop_TunnelBridge(TileIndex tile)
 {
 	bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
-	switch (_opt.landscape) {
+	switch (_settings.game_creation.landscape) {
 		case LT_ARCTIC:
 			if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) {
 				SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
@@ -1388,7 +1388,7 @@
 
 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 {
-	if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
+	if (_settings.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
 		DiagDirection direction = GetTunnelBridgeDirection(tile);
 		Axis axis = DiagDirToAxis(direction);
 		CommandCost res;
--- a/src/unmovable_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/unmovable_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -312,7 +312,7 @@
 		case UNMOVABLE_OWNED_LAND:  td->str = STR_5805_COMPANY_OWNED_LAND; break;
 		default:                    td->str = STR_5803_COMPANY_HEADQUARTERS; break;
 	}
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 }
 
 static void AnimateTile_Unmovable(TileIndex tile)
@@ -375,11 +375,11 @@
 
 void GenerateUnmovables()
 {
-	if (_opt.landscape == LT_TOYLAND) return;
+	if (_settings.game_creation.landscape == LT_TOYLAND) return;
 
 	/* add radio tower */
 	int radiotowser_to_build = ScaleByMapSize(15); // maximum number of radio towers on the map
-	int lighthouses_to_build = _opt.landscape == LT_TROPIC ? 0 : ScaleByMapSize1D((Random() & 3) + 7);
+	int lighthouses_to_build = _settings.game_creation.landscape == LT_TROPIC ? 0 : ScaleByMapSize1D((Random() & 3) + 7);
 	SetGeneratingWorldProgress(GWP_UNMOVABLE, radiotowser_to_build + lighthouses_to_build);
 
 	for (uint i = ScaleByMapSize(1000); i != 0; i--) {
@@ -395,7 +395,7 @@
 		}
 	}
 
-	if (_opt.landscape == LT_TROPIC) return;
+	if (_settings.game_creation.landscape == LT_TROPIC) return;
 
 	/* add lighthouses */
 	uint maxx = MapMaxX();
--- a/src/vehicle.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle.cpp	Tue May 27 00:50:55 2008 +0000
@@ -50,6 +50,7 @@
 #include "depot_map.h"
 #include "animated_tile_func.h"
 #include "effectvehicle_base.h"
+#include "core/alloc_func.hpp"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -58,7 +59,7 @@
 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
 
 VehicleID _vehicle_id_ctr_day;
-Vehicle *_place_clicked_vehicle;
+const Vehicle *_place_clicked_vehicle;
 VehicleID _new_vehicle_id;
 uint16 _returned_refit_capacity;
 
@@ -126,20 +127,20 @@
 {
 	if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
 
-	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
+	if (_settings.order.no_servicing_if_no_breakdowns && _settings.difficulty.vehicle_breakdowns == 0) {
 		/* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off.
 		 * Note: If servicing is enabled, we postpone replacement till next service. */
 		return EngineHasReplacementForPlayer(GetPlayer(this->owner), this->engine_type, this->group_id);
 	}
 
-	return _patches.servint_ispercent ?
+	return _settings.vehicle.servint_ispercent ?
 		(this->reliability < GetEngine(this->engine_type)->reliability * (100 - this->service_interval) / 100) :
 		(this->date_of_last_service + this->service_interval < _date);
 }
 
 bool Vehicle::NeedsAutomaticServicing() const
 {
-	if (_patches.gotodepot && VehicleHasDepotOrders(this)) return false;
+	if (_settings.order.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.GetDepotOrderType() != ODTFB_SERVICE) return false;
 	return NeedsServicing();
@@ -531,6 +532,12 @@
 	return v;
 }
 
+const Vehicle *GetLastVehicleInChain(const Vehicle *v)
+{
+	while (v->Next() != NULL) v = v->Next();
+	return v;
+}
+
 uint CountVehiclesInChain(const Vehicle* v)
 {
 	uint count = 0;
@@ -906,7 +913,7 @@
 	if ((rel_old >> 8) != (rel >> 8)) InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
 	if (v->breakdown_ctr != 0 || v->vehstatus & VS_STOPPED ||
-			_opt.diff.vehicle_breakdowns < 1 ||
+			_settings.difficulty.vehicle_breakdowns < 1 ||
 			v->cur_speed < 5 || _game_mode == GM_MENU) {
 		return;
 	}
@@ -923,7 +930,7 @@
 	if (v->type == VEH_SHIP) rel += 0x6666;
 
 	/* reduced breakdowns? */
-	if (_opt.diff.vehicle_breakdowns == 1) rel += 0x6666;
+	if (_settings.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
 
 	/* check if to break down */
 	if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
@@ -982,9 +989,7 @@
  */
 CommandCost CmdMassStartStopVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **vl = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
+	VehicleList list;
 	CommandCost return_value = CMD_ERROR;
 	uint stop_command;
 	VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
@@ -1003,14 +1008,14 @@
 		uint32 id = p1;
 		uint16 window_type = p2 & VLW_MASK;
 
-		engine_count = GenerateVehicleSortList((const Vehicle***)&vl, &engine_list_length, vehicle_type, _current_player, id, window_type);
+		GenerateVehicleSortList(&list, vehicle_type, _current_player, id, window_type);
 	} else {
 		/* Get the list of vehicles in the depot */
-		BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, NULL, NULL, NULL);
+		BuildDepotVehicleList(vehicle_type, tile, &list, NULL);
 	}
 
-	for (uint i = 0; i < engine_count; i++) {
-		const Vehicle *v = vl[i];
+	for (uint i = 0; i < list.Length(); i++) {
+		const Vehicle *v = list[i];
 
 		if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue;
 
@@ -1032,7 +1037,6 @@
 		}
 	}
 
-	free(vl);
 	return return_value;
 }
 
@@ -1044,15 +1048,10 @@
  */
 CommandCost CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **engines = NULL;
-	Vehicle **wagons = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
-	uint16 wagon_list_length = 0;
-	uint16 wagon_count = 0;
+	VehicleList list;
 
 	CommandCost cost(EXPENSES_NEW_VEHICLES);
-	uint  sell_command, total_number_vehicles;
+	uint sell_command;
 	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 
 	switch (vehicle_type) {
@@ -1064,26 +1063,13 @@
 	}
 
 	/* Get the list of vehicles in the depot */
-	BuildDepotVehicleList(vehicle_type, tile, &engines, &engine_list_length, &engine_count,
-						                      &wagons,  &wagon_list_length,  &wagon_count);
-
-	total_number_vehicles = engine_count + wagon_count;
-	for (uint i = 0; i < total_number_vehicles; i++) {
-		const Vehicle *v;
-
-		if (i < engine_count) {
-			v = engines[i];
-		} else {
-			v = wagons[i - engine_count];
-		}
-
-		CommandCost ret = DoCommand(tile, v->index, 1, flags, sell_command);
-
+	BuildDepotVehicleList(vehicle_type, tile, &list, &list);
+
+	for (uint i = 0; i < list.Length(); i++) {
+		CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command);
 		if (CmdSucceeded(ret)) cost.AddCost(ret);
 	}
 
-	free(engines);
-	free(wagons);
 	if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell
 	return cost;
 }
@@ -1099,9 +1085,7 @@
  */
 CommandCost CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **vl = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
+	VehicleList list;
 	CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES);
 	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 	bool all_or_nothing = HasBit(p2, 0);
@@ -1109,10 +1093,10 @@
 	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
-	BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, &vl, &engine_list_length, &engine_count);
-
-	for (uint i = 0; i < engine_count; i++) {
-		Vehicle *v = vl[i];
+	BuildDepotVehicleList(vehicle_type, tile, &list, &list);
+
+	for (uint i = 0; i < list.Length(); i++) {
+		Vehicle *v = (Vehicle*)list[i];
 
 		/* Ensure that the vehicle completely in the depot */
 		if (!v->IsInDepot()) continue;
@@ -1127,22 +1111,18 @@
 				 * We should never reach this if DC_EXEC is set since then it should
 				 * have failed the estimation guess. */
 				assert(!(flags & DC_EXEC));
-				/* Now we will have to return an error.
-				 * This goto will leave the loop and it's ok to do so because
-				 * there is no point in the rest of the loop. */
-				goto error;
+				/* Now we will have to return an error. */
+				return CMD_ERROR;
 			}
 		}
 	}
 
 	if (cost.GetCost() == 0) {
-error:
 		/* Either we didn't replace anything or something went wrong.
 		 * Either way we want to return an error and not execute this command. */
 		cost = CMD_ERROR;
 	}
 
-	free(vl);
 	return cost;
 }
 
@@ -1311,100 +1291,55 @@
 	return total_cost;
 }
 
-
-/* Extend the list size for BuildDepotVehicleList() */
-static inline void ExtendVehicleListSize(const Vehicle ***engine_list, uint16 *engine_list_length, uint16 step_size)
-{
-	*engine_list_length = min(*engine_list_length + step_size, GetMaxVehicleIndex() + 1);
-	*engine_list = ReallocT(*engine_list, *engine_list_length);
-}
-
-/** Generates a list of vehicles inside a depot
- * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0)
- * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL
- * @param type Type of vehicle
- * @param tile The tile the depot is located in
- * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced)
- * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array
- * @param *engine_count The number of engines stored in the list
- * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced)
- * @param *wagon_list_length Allocated size of wagon_list. Needs to be set to 0 when wagon_list points to a NULL array
- * @param *wagon_count The number of engines stored in the list
+/**
+ * Generate a list of vehicles inside a depot.
+ * @param type    Type of vehicle
+ * @param tile    The tile the depot is located on
+ * @param engines Pointer to list to add vehicles to
+ * @param wagons  Pointer to list to add wagons to (can be NULL)
  */
-void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count)
+void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons)
 {
-	Vehicle *v;
-
-	/* This function should never be called without an array to store results */
-	assert(!(engine_list == NULL && type != VEH_TRAIN));
-	assert(!(type == VEH_TRAIN && engine_list == NULL && wagon_list == NULL));
-
-	/* Both array and the length should either be NULL to disable the list or both should not be NULL */
-	assert((engine_list == NULL && engine_list_length == NULL) || (engine_list != NULL && engine_list_length != NULL));
-	assert((wagon_list == NULL && wagon_list_length == NULL) || (wagon_list != NULL && wagon_list_length != NULL));
-
-	assert(!(engine_list != NULL && engine_count == NULL));
-	assert(!(wagon_list != NULL && wagon_count == NULL));
-
-	if (engine_count != NULL) *engine_count = 0;
-	if (wagon_count != NULL) *wagon_count = 0;
-
-	switch (type) {
-		case VEH_TRAIN:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_TRAIN && v->u.rail.track == TRACK_BIT_DEPOT) {
-					if (IsFrontEngine(v)) {
-						if (engine_list == NULL) continue;
-						if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-						(*engine_list)[(*engine_count)++] = v;
-					} else if (IsFreeWagon(v)) {
-						if (wagon_list == NULL) continue;
-						if (*wagon_count == *wagon_list_length) ExtendVehicleListSize((const Vehicle***)wagon_list, wagon_list_length, 25);
-						(*wagon_list)[(*wagon_count)++] = v;
-					}
+	engines->Clear();
+	if (wagons != NULL && wagons != engines) wagons->Clear();
+
+	const Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		/* General tests for all vehicle types */
+		if (v->type != type) continue;
+		if (v->tile != tile) continue;
+
+		switch (type) {
+			case VEH_TRAIN:
+				if (v->u.rail.track != TRACK_BIT_DEPOT) continue;
+				if (wagons != NULL && IsFreeWagon(v)) {
+					*wagons->Append() = v;
+					continue;
 				}
-			}
-			break;
-
-		case VEH_ROAD:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_ROAD && v->IsInDepot() && IsRoadVehFront(v)) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		case VEH_SHIP:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_SHIP && v->IsInDepot()) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		case VEH_AIRCRAFT:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile &&
-						v->type == VEH_AIRCRAFT && IsNormalAircraft(v) &&
-						v->IsInDepot()) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		default: NOT_REACHED();
+				break;
+
+			default:
+				if (!v->IsInDepot()) continue;
+				break;
+		}
+
+		if (!v->IsPrimaryVehicle()) continue;
+
+		*engines->Append() = v;
 	}
+
+	/* Ensure the lists are not wasting too much space. If the lists are fresh
+	 * (i.e. built within a command) then this will actually do nothing. */
+	engines->Compact();
+	if (wagons != NULL && wagons != engines) wagons->Compact();
 }
 
 /**
- * @param sort_list list to store the list in. Either NULL or the length length_of_array tells
- * @param length_of_array informs the length allocated for sort_list. This is not the same as the number of vehicles in the list. Needs to be 0 when sort_list is NULL
- * @param type type of vehicle
- * @param owner PlayerID of owner to generate a list for
- * @param index This parameter has different meanings depending on window_type
+ * Generate a list of vehicles based on window type.
+ * @param list        Pointer to list to add vehicles to
+ * @param type        Type of vehicle
+ * @param owner       Player to generate list for
+ * @param index       This parameter has different meanings depending on window_type
  *    <ul>
  *      <li>VLW_STATION_LIST:  index of station to generate a list for</li>
  *      <li>VLW_SHARED_ORDERS: index of order to generate a list for<li>
@@ -1412,83 +1347,71 @@
  *      <li>VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for</li>
  *      <li>VLW_GROUP_LIST: index of group to generate a list for</li>
  *    </ul>
- * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
- * @return the number of vehicles added to the list
+ * @param window_type The type of window the list is for, using the VLW_ flags in vehicle_gui.h
  */
-uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type)
+void GenerateVehicleSortList(VehicleList *list, VehicleType type, PlayerID owner, uint32 index, uint16 window_type)
 {
-	uint n = 0;
+	list->Clear();
+
 	const Vehicle *v;
 
 	switch (window_type) {
-		case VLW_STATION_LIST: {
+		case VLW_STATION_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle()) {
 					const Order *order;
 
 					FOR_VEHICLE_ORDERS(v, order) {
 						if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == index) {
-							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 50);
-							(*sort_list)[n++] = v;
+							*list->Append() = v;
 							break;
 						}
 					}
 				}
 			}
 			break;
-		}
-
-		case VLW_SHARED_ORDERS: {
+
+		case VLW_SHARED_ORDERS:
 			FOR_ALL_VEHICLES(v) {
 				/* Find a vehicle with the order in question */
-				if (v->orders != NULL && v->orders->index == index) break;
-			}
-
-			if (v != NULL && v->orders != NULL && v->orders->index == index) {
-				/* Only try to make the list if we found a vehicle using the order in question */
-				for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
-					(*sort_list)[n++] = v;
+				if (v->orders != NULL && v->orders->index == index) {
+					/* Add all vehicles from this vehicle's shared order list */
+					for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
+						*list->Append() = v;
+					}
+					break;
 				}
 			}
 			break;
-		}
-
-		case VLW_STANDARD: {
+
+		case VLW_STANDARD:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->owner == owner && v->IsPrimaryVehicle()) {
-					/* TODO find a better estimate on the total number of vehicles for current player */
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4);
-					(*sort_list)[n++] = v;
+					*list->Append() = v;
 				}
 			}
 			break;
-		}
-
-		case VLW_DEPOT_LIST: {
+
+		case VLW_DEPOT_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle()) {
 					const Order *order;
 
 					FOR_VEHICLE_ORDERS(v, order) {
 						if (order->IsType(OT_GOTO_DEPOT) && order->GetDestination() == index) {
-							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
-							(*sort_list)[n++] = v;
+							*list->Append() = v;
 							break;
 						}
 					}
 				}
 			}
 			break;
-		}
 
 		case VLW_GROUP_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle() &&
 						v->owner == owner && v->group_id == index) {
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4);
-
-					(*sort_list)[n++] = v;
+					*list->Append() = v;
 				}
 			}
 			break;
@@ -1496,16 +1419,7 @@
 		default: NOT_REACHED(); break;
 	}
 
-	if ((n + 100) < *length_of_array) {
-		/* We allocated way too much for sort_list.
-		 * Now we will reduce how much we allocated.
-		 * We will still make it have room for 50 extra vehicles to prevent having
-		 * to move the whole array if just one vehicle is added later */
-		*length_of_array = n + 50;
-		*sort_list = ReallocT(*sort_list, (*length_of_array) * sizeof((*sort_list)[0]));
-	}
-
-	return n;
+	list->Compact();
 }
 
 /**
@@ -1519,14 +1433,13 @@
  */
 CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
 {
-	const Vehicle **sort_list = NULL;
-	uint16 array_length = 0;
-
-	uint n = GenerateVehicleSortList(&sort_list, &array_length, type, owner, id, vlw_flag);
+	VehicleList list;
+
+	GenerateVehicleSortList(&list, type, owner, id, vlw_flag);
 
 	/* Send all the vehicles to a depot */
-	for (uint i = 0; i < n; i++) {
-		const Vehicle *v = sort_list[i];
+	for (uint i = 0; i < list.Length(); i++) {
+		const Vehicle *v = list[i];
 		CommandCost ret = DoCommand(v->tile, v->index, (service ? 1 : 0) | DEPOT_DONT_CANCEL, flags, GetCmdSendToDepot(type));
 
 		/* Return 0 if DC_EXEC is not set this is a valid goto depot command)
@@ -1534,12 +1447,10 @@
 			* and we will issue the command. We can now safely quit the loop, knowing
 			* it will succeed at least once. With DC_EXEC we really need to send them to the depot */
 		if (CmdSucceeded(ret) && !(flags & DC_EXEC)) {
-			free((void*)sort_list);
 			return CommandCost();
 		}
 	}
 
-	free((void*)sort_list);
 	return (flags & DC_EXEC) ? CommandCost() : CMD_ERROR;
 }
 
@@ -1733,7 +1644,7 @@
 	if (flags & DC_EXEC) {
 		free(v->name);
 		v->name = strdup(_cmd_text);
-		ResortVehicleLists();
+		InvalidateWindowClassesData(WC_TRAINS_LIST, 1);
 		MarkWholeScreenDirty();
 	}
 
@@ -1915,10 +1826,10 @@
 	static UnitID gmax = 0;
 
 	switch (type) {
-		case VEH_TRAIN:    max = _patches.max_trains; break;
-		case VEH_ROAD:     max = _patches.max_roadveh; break;
-		case VEH_SHIP:     max = _patches.max_ships; break;
-		case VEH_AIRCRAFT: max = _patches.max_aircraft; break;
+		case VEH_TRAIN:    max = _settings.vehicle.max_trains; break;
+		case VEH_ROAD:     max = _settings.vehicle.max_roadveh; break;
+		case VEH_SHIP:     max = _settings.vehicle.max_ships; break;
+		case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break;
 		default: NOT_REACHED();
 	}
 
@@ -1968,14 +1879,14 @@
 	assert(IsPlayerBuildableVehicleType(type));
 
 	if (!IsValidPlayer(_current_player)) return false;
-	if (_patches.always_build_infrastructure) return true;
+	if (_settings.gui.always_build_infrastructure) return true;
 
 	UnitID max;
 	switch (type) {
-		case VEH_TRAIN:    max = _patches.max_trains; break;
-		case VEH_ROAD:     max = _patches.max_roadveh; break;
-		case VEH_SHIP:     max = _patches.max_ships; break;
-		case VEH_AIRCRAFT: max = _patches.max_aircraft; break;
+		case VEH_TRAIN:    max = _settings.vehicle.max_trains; break;
+		case VEH_ROAD:     max = _settings.vehicle.max_roadveh; break;
+		case VEH_SHIP:     max = _settings.vehicle.max_ships; break;
+		case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break;
 		default: NOT_REACHED();
 	}
 
@@ -2007,7 +1918,7 @@
 
 	/* The default livery is always available for use, but its in_use flag determines
 	 * whether any _other_ liveries are in use. */
-	if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) {
+	if (p->livery[LS_DEFAULT].in_use && (_settings.gui.liveries == 2 || (_settings.gui.liveries == 1 && player == _local_player))) {
 		/* Determine the livery scheme to use */
 		switch (GetEngine(engine_type)->type) {
 			default: NOT_REACHED();
@@ -2576,7 +2487,7 @@
 
 			/* Not the first call for this tick, or still loading */
 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
-					(_patches.timetabling && this->current_order_time < wait_time)) return;
+					(_settings.order.timetabling && this->current_order_time < wait_time)) return;
 
 			this->PlayLeaveStationSound();
 
@@ -2807,11 +2718,11 @@
 {
 	if (!ContainsBackup()) return v;
 	if (v != NULL) {
-		ChangeVehicleViewWindow(v, INVALID_VEHICLE);
+		ChangeVehicleViewWindow(v->index, INVALID_VEHICLE);
 		DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v));
 	}
 	v = RestoreBackupVehicle(this->vehicles, p);
-	ChangeVehicleViewWindow(INVALID_VEHICLE, v);
+	ChangeVehicleViewWindow(INVALID_VEHICLE, v->index);
 	if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders);
 	if (economy != NULL) economy->Restore();
 	/* If we stored cargo as well then we should restore it. */
--- a/src/vehicle_base.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle_base.h	Tue May 27 00:50:55 2008 +0000
@@ -566,9 +566,6 @@
 	void Tick() {}
 };
 
-#define BEGIN_ENUM_WAGONS(v) do {
-#define END_ENUM_WAGONS(v) } while ((v = v->Next()) != NULL);
-
 static inline VehicleID GetMaxVehicleIndex()
 {
 	/* TODO - This isn't the real content of the function, but
--- a/src/vehicle_func.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle_func.h	Tue May 27 00:50:55 2008 +0000
@@ -24,6 +24,7 @@
 void VehicleServiceInDepot(Vehicle *v);
 void VehiclePositionChanged(Vehicle *v);
 Vehicle *GetLastVehicleInChain(Vehicle *v);
+const Vehicle *GetLastVehicleInChain(const Vehicle *v);
 uint CountVehiclesInChain(const Vehicle *v);
 bool IsEngineCountable(const Vehicle *v);
 void DeleteVehicleChain(Vehicle *v);
@@ -67,8 +68,8 @@
 void TrainPowerChanged(Vehicle *v);
 Money GetTrainRunningCost(const Vehicle *v);
 
-uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type);
-void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count);
+void GenerateVehicleSortList(VehicleList *list, VehicleType type, PlayerID owner, uint32 index, uint16 window_type);
+void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine_list, VehicleList *wagon_list);
 CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
 void VehicleEnterDepot(Vehicle *v);
 
@@ -173,7 +174,7 @@
 void StopAllVehicles();
 
 extern VehicleID _vehicle_id_ctr_day;
-extern Vehicle *_place_clicked_vehicle;
+extern const Vehicle *_place_clicked_vehicle;
 extern VehicleID _new_vehicle_id;
 extern uint16 _returned_refit_capacity;
 
--- a/src/vehicle_gui.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle_gui.cpp	Tue May 27 00:50:55 2008 +0000
@@ -86,54 +86,13 @@
 	INVALID_STRING_ID
 };
 
-/**
- * Set sort list flag for all vehicle list windows
- * @param sl_flag Sort list flag to set
- */
-static void SetVehicleListsFlag(SortListFlags sl_flag)
-{
-	Window* const *wz;
-
-	FOR_ALL_WINDOWS(wz) {
-		Window *w = *wz;
-
-		switch (w->window_class) {
-			case WC_TRAINS_LIST:
-			case WC_ROADVEH_LIST:
-			case WC_SHIPS_LIST:
-			case WC_AIRCRAFT_LIST:
-				dynamic_cast<VehicleListBase*>(w)->vehicles.flags |= sl_flag;
-				w->SetDirty();
-				break;
-
-			default: break;
-		}
-	}
-}
-
-/**
- * Rebuild all vehicle list windows
- */
-void RebuildVehicleLists()
-{
-	SetVehicleListsFlag(VL_REBUILD);
-}
-
-/**
- * Resort all vehicle list windows
- */
-void ResortVehicleLists()
-{
-	SetVehicleListsFlag(VL_RESORT);
-}
-
 void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
 {
 	if (!(vl->vehicles.flags & VL_REBUILD)) return;
 
 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
 
-	vl->vehicles.list_length = GenerateVehicleSortList(&vl->vehicles.sort_list, &vl->vehicles.list_length, vl->vehicle_type, owner, index, window_type);
+	GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type);
 
 	vl->vehicles.flags &= ~VL_REBUILD;
 	vl->vehicles.flags |= VL_RESORT;
@@ -151,17 +110,18 @@
 	_last_vehicle[0] = _last_vehicle[1] = NULL;
 
 	_internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
-	qsort((void*)vl->vehicles.sort_list, vl->vehicles.list_length, sizeof(vl->vehicles.sort_list[0]),
+	qsort((void*)vl->vehicles.Begin(), vl->vehicles.Length(), sizeof(vl->vehicles.Begin()),
 		_vehicle_sorter[vl->vehicles.sort_type]);
 
 	vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
 	vl->vehicles.flags &= ~VL_RESORT;
 }
 
-void DepotSortList(Vehicle **v, uint16 length)
+void DepotSortList(VehicleList *list)
 {
 	_internal_sort_order = 0;
-	qsort((void*)v, length, sizeof(v[0]), _vehicle_sorter[0]);
+	if (list->Length() < 2) return;
+	qsort((void*)list->Begin(), list->Length(), sizeof(list->Begin()), _vehicle_sorter[0]);
 }
 
 /** draw the vehicle profit button in the vehicle list window. */
@@ -473,7 +433,6 @@
 	WC_VEHICLE_REFIT, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_vehicle_refit_widgets,
-	NULL
 };
 
 /** Show the refit window for a vehicle
@@ -847,8 +806,6 @@
 		PlayerID player = (PlayerID)GB(this->window_number, 0, 8);
 
 		this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
-		this->vehicles.list_length = 0;
-		this->vehicles.sort_list = NULL;
 		this->caption_color = player;
 
 		/* Hide the widgets that we will not use in this window
@@ -966,7 +923,6 @@
 
 	~VehicleListWindow()
 	{
-		free((void*)this->vehicles.sort_list);
 	}
 
 	virtual void OnPaint()
@@ -981,12 +937,12 @@
 
 		BuildVehicleList(this, owner, index, window_type);
 		SortVehicleList(this);
-		SetVScrollCount(this, this->vehicles.list_length);
+		SetVScrollCount(this, this->vehicles.Length());
 
 		/* draw the widgets */
 		switch (window_type) {
 			case VLW_SHARED_ORDERS: /* Shared Orders */
-				if (this->vehicles.list_length == 0) {
+				if (this->vehicles.Length() == 0) {
 					/* We can't open this window without vehicles using this order
 					* and we should close the window when deleting the order      */
 					NOT_REACHED();
@@ -1022,7 +978,7 @@
 			default: NOT_REACHED(); break;
 		}
 
-		this->SetWidgetsDisabledState(this->vehicles.list_length == 0,
+		this->SetWidgetsDisabledState(this->vehicles.Length() == 0,
 			VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
 			VLW_WIDGET_STOP_ALL,
 			VLW_WIDGET_START_ALL,
@@ -1035,9 +991,9 @@
 		/* draw arrow pointing up/down for ascending/descending sorting */
 		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
 
-		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.list_length);
+		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length());
 		for (i = this->vscroll.pos; i < max; ++i) {
-			const Vehicle *v = this->vehicles.sort_list[i];
+			const Vehicle *v = this->vehicles[i];
 			StringID str;
 
 			SetDParam(0, v->GetDisplayProfitThisYear());
@@ -1090,9 +1046,9 @@
 
 				id_v += this->vscroll.pos;
 
-				if (id_v >= this->vehicles.list_length) return; // click out of list bound
+				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
-				v = this->vehicles.sort_list[id_v];
+				v = this->vehicles[id_v];
 
 				ShowVehicleViewWindow(v);
 			} break;
@@ -1141,7 +1097,7 @@
 				}
 				break;
 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
-				assert(this->vehicles.list_length != 0);
+				assert(this->vehicles.Length() != 0);
 
 				switch (index) {
 					case 0: /* Replace window */
@@ -1187,6 +1143,11 @@
 		this->vscroll.cap += delta.y / (int)this->resize.step_height;
 		this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
 	}
+
+	virtual void OnInvalidateData(int data)
+	{
+		this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+	}
 };
 
 static const WindowDesc _player_vehicle_list_train_desc = {
@@ -1194,7 +1155,6 @@
 	WC_TRAINS_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_list_widgets,
-	NULL
 };
 
 static const WindowDesc _player_vehicle_list_road_veh_desc = {
@@ -1202,7 +1162,6 @@
 	WC_ROADVEH_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_list_widgets,
-	NULL
 };
 
 static const WindowDesc _player_vehicle_list_ship_desc = {
@@ -1210,7 +1169,6 @@
 	WC_SHIPS_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_list_widgets,
-	NULL
 };
 
 static const WindowDesc _player_vehicle_list_aircraft_desc = {
@@ -1218,7 +1176,6 @@
 	WC_AIRCRAFT_LIST, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_list_widgets,
-	NULL
 };
 
 static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, VehicleType vehicle_type, uint16 unique_number)
@@ -1260,12 +1217,12 @@
 
 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type)
 {
-	/* If _patches.advanced_vehicle_list > 1, display the Advanced list
-	 * if _patches.advanced_vehicle_list == 1, display Advanced list only for local player
+	/* If _settings.gui.advanced_vehicle_list > 1, display the Advanced list
+	 * if _settings.gui.advanced_vehicle_list == 1, display Advanced list only for local player
 	 * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
 	 */
 
-	if ((_patches.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) {
+	if ((_settings.gui.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) {
 		ShowPlayerGroup(player, vehicle_type);
 	} else {
 		ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0);
@@ -1442,6 +1399,8 @@
 		this->caption_color = v->owner;
 
 		this->tab = 0;
+
+		this->FindWindowPlacementAndResize(desc);
 	}
 
 	/** Checks whether service interval is enabled for the vehicle. */
@@ -1449,10 +1408,10 @@
 	{
 		switch (vehicle_type) {
 			default: NOT_REACHED();
-			case VEH_TRAIN:    return _patches.servint_trains   != 0; break;
-			case VEH_ROAD:     return _patches.servint_roadveh  != 0; break;
-			case VEH_SHIP:     return _patches.servint_ships    != 0; break;
-			case VEH_AIRCRAFT: return _patches.servint_aircraft != 0; break;
+			case VEH_TRAIN:    return _settings.vehicle.servint_trains   != 0; break;
+			case VEH_ROAD:     return _settings.vehicle.servint_roadveh  != 0; break;
+			case VEH_SHIP:     return _settings.vehicle.servint_ships    != 0; break;
+			case VEH_AIRCRAFT: return _settings.vehicle.servint_aircraft != 0; break;
 		}
 		return false; // kill a compiler warning
 	}
@@ -1524,7 +1483,7 @@
 				SetDParam(1, v->u.rail.cached_power);
 				SetDParam(0, v->u.rail.cached_weight);
 				SetDParam(3, v->u.rail.cached_max_te / 1000);
-				DrawString(2, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
+				DrawString(2, 25, (_settings.vehicle.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING);
 				break;
@@ -1552,7 +1511,7 @@
 		/* Draw service interval text */
 		SetDParam(0, v->service_interval);
 		SetDParam(1, v->date_of_last_service);
-		DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
+		DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _settings.vehicle.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
 
 		switch (v->type) {
 			case VEH_TRAIN:
@@ -1649,7 +1608,6 @@
 	WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_vehicle_details_widgets,
-	NULL
 };
 
 /** Shows the vehicle details window of the given vehicle. */
@@ -1685,15 +1643,12 @@
 };
 
 
-static void VehicleViewWndProc(Window *w, WindowEvent *e);
-
 /** Vehicle view window descriptor for all vehicles but trains. */
 static const WindowDesc _vehicle_view_desc = {
 	WDP_AUTO, WDP_AUTO, 250, 116, 250, 116,
 	WC_VEHICLE_VIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_view_widgets,
-	VehicleViewWndProc
 };
 
 /** Vehicle view window descriptor for trains. Only minimum_height and
@@ -1704,7 +1659,6 @@
 	WC_VEHICLE_VIEW, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
 	_vehicle_view_widgets,
-	VehicleViewWndProc
 };
 
 
@@ -1730,300 +1684,6 @@
 static const int VV_INITIAL_VIEWPORT_HEIGHT = 84;
 static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102;
 
-/** Shows the vehicle view window of the given vehicle. */
-void ShowVehicleViewWindow(const Vehicle *v)
-{
-	Window *w = AllocateWindowDescFront<Window>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
-
-	if (w != NULL) {
-		w->caption_color = v->owner;
-		InitializeWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
-												 (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT,
-												 w->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
-	}
-}
-
-/** Initialize a newly created vehicle view window */
-static void CreateVehicleViewWindow(Window *w)
-{
-	const Vehicle *v = GetVehicle(w->window_number);
-
-	/*
-	 * fill in data and tooltip codes for the widgets and
-	 * move some of the buttons for trains
-	 */
-	switch (v->type) {
-		case VEH_TRAIN:
-			w->widget[VVW_WIDGET_CAPTION].data = STR_882E;
-
-			w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK;
-
-			w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN;
-
-			w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT;
-			w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT;
-
-			w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY;
-
-			w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS;
-
-			w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS;
-
-			w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN;
-			w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO;
-
-			w->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN;
-
-
-			/* due to more buttons we must modify the layout a bit for trains */
-			w->widget[VVW_WIDGET_PANEL].bottom = 121;
-			w->widget[VVW_WIDGET_VIEWPORT].bottom = 119;
-
-			w->widget[VVW_WIDGET_START_STOP_VEH].top = 122;
-			w->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133;
-
-			w->widget[VVW_WIDGET_REFIT_VEH].top = 68;
-			w->widget[VVW_WIDGET_REFIT_VEH].bottom = 85;
-
-			w->widget[VVW_WIDGET_SHOW_ORDERS].top = 86;
-			w->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103;
-
-			w->widget[VVW_WIDGET_SHOW_DETAILS].top = 104;
-			w->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121;
-
-			w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122;
-			w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121;
-
-			w->widget[VVW_WIDGET_RESIZE].top = 122;
-			w->widget[VVW_WIDGET_RESIZE].bottom = 133;
-
-			w->widget[VVW_WIDGET_TURN_AROUND].top = 68;
-			w->widget[VVW_WIDGET_TURN_AROUND].bottom = 85;
-			break;
-
-		case VEH_ROAD:
-			w->widget[VVW_WIDGET_CAPTION].data = STR_9002;
-
-			w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION;
-
-			w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE;
-
-			w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT;
-			w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT;
-
-			w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY;
-
-			w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS;
-
-			w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS;
-
-			w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH;
-			w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO;
-
-			w->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true);
-			break;
-
-		case VEH_SHIP:
-			w->widget[VVW_WIDGET_CAPTION].data = STR_980F;
-
-			w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK;
-
-			w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP;
-
-			w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT;
-			w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT;
-
-			w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY;
-
-			w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS;
-
-			w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS;
-
-			w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP;
-			w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO;
-
-			w->SetWidgetsHiddenState(true,
-																	VVW_WIDGET_TURN_AROUND,
-																	VVW_WIDGET_FORCE_PROCEED,
-																	WIDGET_LIST_END);
-			break;
-
-		case VEH_AIRCRAFT:
-			w->widget[VVW_WIDGET_CAPTION].data = STR_A00A;
-
-			w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION;
-
-			w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT;
-
-			w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT;
-			w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR;
-
-			w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY;
-
-			w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS;
-
-			w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS;
-
-			w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT;
-			w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO;
-
-			w->SetWidgetsHiddenState(true,
-																	VVW_WIDGET_TURN_AROUND,
-																	VVW_WIDGET_FORCE_PROCEED,
-																	WIDGET_LIST_END);
-			break;
-
-			default: NOT_REACHED();
-	}
-}
-
-/** Checks whether the vehicle may be refitted at the moment.*/
-static bool IsVehicleRefitable(const Vehicle *v)
-{
-	/* Why is this so different for different vehicles?
-	 * Does maybe work one solution for all?
-	 */
-	switch (v->type) {
-		case VEH_TRAIN:    return false;
-		case VEH_ROAD:     return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot();
-		case VEH_SHIP:     return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot();
-		case VEH_AIRCRAFT: return v->IsStoppedInDepot();
-		default: NOT_REACHED();
-	}
-}
-
-/** Message strings for heading to depot indexed by vehicle type. */
-static const StringID _heading_for_depot_strings[] = {
-	STR_HEADING_FOR_TRAIN_DEPOT,
-	STR_HEADING_FOR_ROAD_DEPOT,
-	STR_HEADING_FOR_SHIP_DEPOT,
-	STR_HEADING_FOR_HANGAR,
-};
-
-/** Message strings for heading to depot and servicing indexed by vehicle type. */
-static const StringID _heading_for_depot_service_strings[] = {
-	STR_HEADING_FOR_TRAIN_DEPOT_SERVICE,
-	STR_HEADING_FOR_ROAD_DEPOT_SERVICE,
-	STR_HEADING_FOR_SHIP_DEPOT_SERVICE,
-	STR_HEADING_FOR_HANGAR_SERVICE,
-};
-
-/** Repaint vehicle view window. */
-static void DrawVehicleViewWindow(Window *w)
-{
-	const Vehicle *v = GetVehicle(w->window_number);
-	StringID str;
-	bool is_localplayer = v->owner == _local_player;
-	bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
-
-	w->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer);
-	w->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH,
-															 !refitable_and_stopped_in_depot || !is_localplayer);
-	w->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer);
-
-	if (v->type == VEH_TRAIN) {
-		w->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer);
-		w->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer);
-
-		/* Cargo refit button is disabled, until we know we can enable it below. */
-
-		if (is_localplayer) {
-			/* See if any vehicle can be refitted */
-			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
-				if (EngInfo(u->engine_type)->refit_mask != 0 ||
-						(RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) {
-					w->EnableWidget(VVW_WIDGET_REFIT_VEH);
-					/* We have a refittable carriage, bail out */
-					break;
-				}
-			}
-		}
-	}
-
-	/* draw widgets & caption */
-	SetDParam(0, v->index);
-	w->DrawWidgets();
-
-	if (v->vehstatus & VS_CRASHED) {
-		str = STR_8863_CRASHED;
-	} else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
-		str = STR_885C_BROKEN_DOWN;
-	} else if (v->vehstatus & VS_STOPPED) {
-		if (v->type == VEH_TRAIN) {
-			if (v->cur_speed == 0) {
-				if (v->u.rail.cached_power == 0) {
-					str = STR_TRAIN_NO_POWER;
-				} else {
-					str = STR_8861_STOPPED;
-				}
-			} else {
-				SetDParam(0, v->GetDisplaySpeed());
-				str = STR_TRAIN_STOPPING + _patches.vehicle_speed;
-			}
-		} else { // no train
-			str = STR_8861_STOPPED;
-		}
-	} else { // vehicle is in a "normal" state, show current order
-		switch (v->current_order.GetType()) {
-			case OT_GOTO_STATION: {
-				SetDParam(0, v->current_order.GetDestination());
-				SetDParam(1, v->GetDisplaySpeed());
-				str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
-			} break;
-
-			case OT_GOTO_DEPOT: {
-				if (v->type == VEH_AIRCRAFT) {
-					/* Aircrafts always go to a station, even if you say depot */
-					SetDParam(0, v->current_order.GetDestination());
-					SetDParam(1, v->GetDisplaySpeed());
-				} else {
-					Depot *depot = GetDepot(v->current_order.GetDestination());
-					SetDParam(0, depot->town_index);
-					SetDParam(1, v->GetDisplaySpeed());
-				}
-				if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
-					str = _heading_for_depot_strings[v->type] + _patches.vehicle_speed;
-				} else {
-					str = _heading_for_depot_service_strings[v->type] + _patches.vehicle_speed;
-				}
-			} break;
-
-			case OT_LOADING:
-				str = STR_882F_LOADING_UNLOADING;
-				break;
-
-			case OT_GOTO_WAYPOINT: {
-				assert(v->type == VEH_TRAIN);
-				SetDParam(0, v->current_order.GetDestination());
-				str = STR_HEADING_FOR_WAYPOINT + _patches.vehicle_speed;
-				SetDParam(1, v->GetDisplaySpeed());
-				break;
-			}
-
-			case OT_LEAVESTATION:
-				if (v->type != VEH_AIRCRAFT) {
-					str = STR_LEAVING;
-					break;
-				}
-				/* fall-through if aircraft. Does this even happen? */
-
-			default:
-				if (v->num_orders == 0) {
-					str = STR_NO_ORDERS + _patches.vehicle_speed;
-					SetDParam(0, v->GetDisplaySpeed());
-				} else {
-					str = STR_EMPTY;
-				}
-				break;
-		}
-	}
-
-	/* draw the flag plus orders */
-	DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1);
-	DrawStringCenteredTruncated(w->widget[VVW_WIDGET_START_STOP_VEH].left + 8, w->widget[VVW_WIDGET_START_STOP_VEH].right, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING);
-	w->DrawViewport();
-}
-
 /** Command indices for the _vehicle_command_translation_table. */
 enum VehicleCommandTranslation {
 	VCT_CMD_START_STOP = 0,
@@ -2061,104 +1721,389 @@
 	},
 };
 
-/** Window event hook for vehicle view. */
-static void VehicleViewWndProc(Window *w, WindowEvent *e)
+/** Checks whether the vehicle may be refitted at the moment.*/
+static bool IsVehicleRefitable(const Vehicle *v)
 {
-	switch (e->event) {
-		case WE_CREATE:
-			CreateVehicleViewWindow(w);
-			break;
-
-		case WE_PAINT:
-			DrawVehicleViewWindow(w);
-			break;
+	/* Why is this so different for different vehicles?
+	 * Does maybe work one solution for all?
+	 */
+	switch (v->type) {
+		case VEH_TRAIN:    return false;
+		case VEH_ROAD:     return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot();
+		case VEH_SHIP:     return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot();
+		case VEH_AIRCRAFT: return v->IsStoppedInDepot();
+		default: NOT_REACHED();
+	}
+}
 
-		case WE_CLICK: {
-			const Vehicle *v = GetVehicle(w->window_number);
+struct VehicleViewWindow : Window {
+	VehicleViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+	{
+		const Vehicle *v = GetVehicle(this->window_number);
 
-			switch (e->we.click.widget) {
-				case VVW_WIDGET_START_STOP_VEH: /* start stop */
-					DoCommandP(v->tile, v->index, 0, NULL,
-										 _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]);
-					break;
-				case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */
-					const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
-					/* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
-					if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) {
-						mainwindow->viewport->follow_vehicle = v->index;
+		this->caption_color = v->owner;
+		InitializeWindowViewport(this, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
+												 (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT,
+												 this->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
+
+		/*
+		 * fill in data and tooltip codes for the widgets and
+		 * move some of the buttons for trains
+		 */
+		switch (v->type) {
+			case VEH_TRAIN:
+				this->widget[VVW_WIDGET_CAPTION].data = STR_882E;
+
+				this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK;
+
+				this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN;
+
+				this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT;
+				this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT;
+
+				this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY;
+
+				this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS;
+
+				this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS;
+
+				this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN;
+				this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO;
+
+				this->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN;
+
+
+				/* due to more buttons we must modify the layout a bit for trains */
+				this->widget[VVW_WIDGET_PANEL].bottom = 121;
+				this->widget[VVW_WIDGET_VIEWPORT].bottom = 119;
+
+				this->widget[VVW_WIDGET_START_STOP_VEH].top = 122;
+				this->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133;
+
+				this->widget[VVW_WIDGET_REFIT_VEH].top = 68;
+				this->widget[VVW_WIDGET_REFIT_VEH].bottom = 85;
+
+				this->widget[VVW_WIDGET_SHOW_ORDERS].top = 86;
+				this->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103;
+
+				this->widget[VVW_WIDGET_SHOW_DETAILS].top = 104;
+				this->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121;
+
+				this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122;
+				this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121;
+
+				this->widget[VVW_WIDGET_RESIZE].top = 122;
+				this->widget[VVW_WIDGET_RESIZE].bottom = 133;
+
+				this->widget[VVW_WIDGET_TURN_AROUND].top = 68;
+				this->widget[VVW_WIDGET_TURN_AROUND].bottom = 85;
+				break;
+
+			case VEH_ROAD:
+				this->widget[VVW_WIDGET_CAPTION].data = STR_9002;
+
+				this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION;
+
+				this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE;
+
+				this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT;
+				this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT;
+
+				this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY;
+
+				this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS;
+
+				this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS;
+
+				this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH;
+				this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO;
+
+				this->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true);
+				break;
+
+			case VEH_SHIP:
+				this->widget[VVW_WIDGET_CAPTION].data = STR_980F;
+
+				this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK;
+
+				this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP;
+
+				this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT;
+				this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT;
+
+				this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY;
+
+				this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS;
+
+				this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS;
+
+				this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP;
+				this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO;
+
+				this->SetWidgetsHiddenState(true,
+																		VVW_WIDGET_TURN_AROUND,
+																		VVW_WIDGET_FORCE_PROCEED,
+																		WIDGET_LIST_END);
+				break;
+
+			case VEH_AIRCRAFT:
+				this->widget[VVW_WIDGET_CAPTION].data = STR_A00A;
+
+				this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION;
+
+				this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT;
+
+				this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT;
+				this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR;
+
+				this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY;
+
+				this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS;
+
+				this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS;
+
+				this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT;
+				this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO;
+
+				this->SetWidgetsHiddenState(true,
+																		VVW_WIDGET_TURN_AROUND,
+																		VVW_WIDGET_FORCE_PROCEED,
+																		WIDGET_LIST_END);
+				break;
+
+				default: NOT_REACHED();
+		}
+
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	~VehicleViewWindow()
+	{
+		DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number);
+		DeleteWindowById(WC_VEHICLE_REFIT, this->window_number);
+		DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number);
+		DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number);
+	}
+
+	virtual void OnPaint()
+	{
+		/** Message strings for heading to depot indexed by vehicle type. */
+		static const StringID _heading_for_depot_strings[] = {
+			STR_HEADING_FOR_TRAIN_DEPOT,
+			STR_HEADING_FOR_ROAD_DEPOT,
+			STR_HEADING_FOR_SHIP_DEPOT,
+			STR_HEADING_FOR_HANGAR,
+		};
+
+		/** Message strings for heading to depot and servicing indexed by vehicle type. */
+		static const StringID _heading_for_depot_service_strings[] = {
+			STR_HEADING_FOR_TRAIN_DEPOT_SERVICE,
+			STR_HEADING_FOR_ROAD_DEPOT_SERVICE,
+			STR_HEADING_FOR_SHIP_DEPOT_SERVICE,
+			STR_HEADING_FOR_HANGAR_SERVICE,
+		};
+
+		const Vehicle *v = GetVehicle(this->window_number);
+		StringID str;
+		bool is_localplayer = v->owner == _local_player;
+		bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
+
+		this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer);
+		this->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH,
+																!refitable_and_stopped_in_depot || !is_localplayer);
+		this->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer);
+
+		if (v->type == VEH_TRAIN) {
+			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer);
+			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer);
+
+			/* Cargo refit button is disabled, until we know we can enable it below. */
+
+			if (is_localplayer) {
+				/* See if any vehicle can be refitted */
+				for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+					if (EngInfo(u->engine_type)->refit_mask != 0 ||
+							(RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) {
+						this->EnableWidget(VVW_WIDGET_REFIT_VEH);
+						/* We have a refittable carriage, bail out */
+						break;
+					}
+				}
+			}
+		}
+
+		/* draw widgets & caption */
+		SetDParam(0, v->index);
+		this->DrawWidgets();
+
+		if (v->vehstatus & VS_CRASHED) {
+			str = STR_8863_CRASHED;
+		} else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
+			str = STR_885C_BROKEN_DOWN;
+		} else if (v->vehstatus & VS_STOPPED) {
+			if (v->type == VEH_TRAIN) {
+				if (v->cur_speed == 0) {
+					if (v->u.rail.cached_power == 0) {
+						str = STR_TRAIN_NO_POWER;
 					} else {
-						ScrollMainWindowTo(v->x_pos, v->y_pos);
+						str = STR_8861_STOPPED;
+					}
+				} else {
+					SetDParam(0, v->GetDisplaySpeed());
+					str = STR_TRAIN_STOPPING + _settings.gui.vehicle_speed;
+				}
+			} else { // no train
+				str = STR_8861_STOPPED;
+			}
+		} else { // vehicle is in a "normal" state, show current order
+			switch (v->current_order.GetType()) {
+				case OT_GOTO_STATION: {
+					SetDParam(0, v->current_order.GetDestination());
+					SetDParam(1, v->GetDisplaySpeed());
+					str = STR_HEADING_FOR_STATION + _settings.gui.vehicle_speed;
+				} break;
+
+				case OT_GOTO_DEPOT: {
+					if (v->type == VEH_AIRCRAFT) {
+						/* Aircrafts always go to a station, even if you say depot */
+						SetDParam(0, v->current_order.GetDestination());
+						SetDParam(1, v->GetDisplaySpeed());
+					} else {
+						Depot *depot = GetDepot(v->current_order.GetDestination());
+						SetDParam(0, depot->town_index);
+						SetDParam(1, v->GetDisplaySpeed());
+					}
+					if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
+						str = _heading_for_depot_strings[v->type] + _settings.gui.vehicle_speed;
+					} else {
+						str = _heading_for_depot_service_strings[v->type] + _settings.gui.vehicle_speed;
 					}
 				} break;
 
-				case VVW_WIDGET_GOTO_DEPOT: /* goto hangar */
-					DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL,
-						_vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]);
-					break;
-				case VVW_WIDGET_REFIT_VEH: /* refit */
-					ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
-					break;
-				case VVW_WIDGET_SHOW_ORDERS: /* show orders */
-					if (_ctrl_pressed) {
-						ShowTimetableWindow(v);
-					} else {
-						ShowOrdersWindow(v);
-					}
+				case OT_LOADING:
+					str = STR_882F_LOADING_UNLOADING;
 					break;
-				case VVW_WIDGET_SHOW_DETAILS: /* show details */
-					ShowVehicleDetailsWindow(v);
-					break;
-				case VVW_WIDGET_CLONE_VEH: /* clone vehicle */
-					DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle,
-										 _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]);
+
+				case OT_GOTO_WAYPOINT: {
+					assert(v->type == VEH_TRAIN);
+					SetDParam(0, v->current_order.GetDestination());
+					str = STR_HEADING_FOR_WAYPOINT + _settings.gui.vehicle_speed;
+					SetDParam(1, v->GetDisplaySpeed());
 					break;
-				case VVW_WIDGET_TURN_AROUND: /* turn around */
-					assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
-					DoCommandP(v->tile, v->index, 0, NULL,
-										 _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
-					break;
-				case VVW_WIDGET_FORCE_PROCEED: /* force proceed */
-					assert(v->type == VEH_TRAIN);
-					DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
+				}
+
+				case OT_LEAVESTATION:
+					if (v->type != VEH_AIRCRAFT) {
+						str = STR_LEAVING;
+						break;
+					}
+					/* fall-through if aircraft. Does this even happen? */
+
+				default:
+					if (v->num_orders == 0) {
+						str = STR_NO_ORDERS + _settings.gui.vehicle_speed;
+						SetDParam(0, v->GetDisplaySpeed());
+					} else {
+						str = STR_EMPTY;
+					}
 					break;
 			}
-		} break;
-
-		case WE_RESIZE:
-			w->viewport->width          += e->we.sizing.diff.x;
-			w->viewport->height         += e->we.sizing.diff.y;
-			w->viewport->virtual_width  += e->we.sizing.diff.x;
-			w->viewport->virtual_height += e->we.sizing.diff.y;
-			break;
-
-		case WE_DESTROY:
-			DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
-			DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
-			DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number);
-			DeleteWindowById(WC_VEHICLE_TIMETABLE, w->window_number);
-			break;
+		}
 
-		case WE_TICK: {
-			const Vehicle *v = GetVehicle(w->window_number);
-			bool veh_stopped = v->IsStoppedInDepot();
+		/* draw the flag plus orders */
+		DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1);
+		DrawStringCenteredTruncated(this->widget[VVW_WIDGET_START_STOP_VEH].left + 8, this->widget[VVW_WIDGET_START_STOP_VEH].right, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING);
+		this->DrawViewport();
+	}
 
-			/* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already
-			 * stopped in depot.
-			 * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is
-			 * allowed only while in depot and stopped.
-			 * This sytem allows to have two buttons, on top of each other.
-			 * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
-			if (veh_stopped != w->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == w->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) {
-				w->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped);  // send to depot
-				w->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone
-				if (v->type == VEH_ROAD || v->type == VEH_TRAIN) {
-					w->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit
-					w->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped);  // force turn around
+	virtual void OnClick(Point pt, int widget)
+	{
+		const Vehicle *v = GetVehicle(this->window_number);
+
+		switch (widget) {
+			case VVW_WIDGET_START_STOP_VEH: // start stop
+				DoCommandP(v->tile, v->index, 0, NULL,
+										_vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]);
+				break;
+			case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */
+				const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
+				/* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
+				if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) {
+					mainwindow->viewport->follow_vehicle = v->index;
+				} else {
+					ScrollMainWindowTo(v->x_pos, v->y_pos);
 				}
-				w->SetDirty();
+			} break;
+
+			case VVW_WIDGET_GOTO_DEPOT: // goto hangar
+				DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL,
+					_vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]);
+				break;
+			case VVW_WIDGET_REFIT_VEH: // refit
+				ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
+				break;
+			case VVW_WIDGET_SHOW_ORDERS: // show orders
+				if (_ctrl_pressed) {
+					ShowTimetableWindow(v);
+				} else {
+					ShowOrdersWindow(v);
+				}
+				break;
+			case VVW_WIDGET_SHOW_DETAILS: // show details
+				ShowVehicleDetailsWindow(v);
+				break;
+			case VVW_WIDGET_CLONE_VEH: // clone vehicle
+				DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle,
+										_vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]);
+				break;
+			case VVW_WIDGET_TURN_AROUND: // turn around
+				assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
+				DoCommandP(v->tile, v->index, 0, NULL,
+										_vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
+				break;
+			case VVW_WIDGET_FORCE_PROCEED: // force proceed
+				assert(v->type == VEH_TRAIN);
+				DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
+				break;
+		}
+	}
+
+	virtual void OnResize(Point new_size, Point delta)
+	{
+		this->viewport->width          += delta.x;
+		this->viewport->height         += delta.y;
+		this->viewport->virtual_width  += delta.x;
+		this->viewport->virtual_height += delta.y;
+	}
+
+	virtual void OnTick()
+	{
+		const Vehicle *v = GetVehicle(this->window_number);
+		bool veh_stopped = v->IsStoppedInDepot();
+
+		/* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already
+		 * stopped in depot.
+		 * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is
+		 * allowed only while in depot and stopped.
+		 * This sytem allows to have two buttons, on top of each other.
+		 * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
+		if (veh_stopped != this->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == this->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) {
+			this->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped);  // send to depot
+			this->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone
+			if (v->type == VEH_ROAD || v->type == VEH_TRAIN) {
+				this->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit
+				this->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped);  // force turn around
 			}
-		} break;
+			this->SetDirty();
+		}
 	}
+};
+
+
+/** Shows the vehicle view window of the given vehicle. */
+void ShowVehicleViewWindow(const Vehicle *v)
+{
+	AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
 }
 
 void DrawVehicleImage(const Vehicle *v, int x, int y, VehicleID selection, int count, int skip)
--- a/src/vehicle_gui.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -11,7 +11,6 @@
 #include "order_type.h"
 #include "station_type.h"
 #include "engine_type.h"
-#include "vehicle_base.h"
 
 void DrawVehicleProfitButton(const Vehicle *v, int x, int y);
 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order);
@@ -90,21 +89,6 @@
  * For ease of use it can be called with both Vehicle pointers and VehicleIDs. */
 void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index);
 
-static inline void ChangeVehicleViewWindow(const Vehicle *from_v, VehicleID to_index)
-{
-	ChangeVehicleViewWindow(from_v->index, to_index);
-}
-
-static inline void ChangeVehicleViewWindow(VehicleID from_index, const Vehicle *to_v)
-{
-	ChangeVehicleViewWindow(from_index, to_v->index);
-}
-
-static inline void ChangeVehicleViewWindow(const Vehicle *from_v, const Vehicle *to_v)
-{
-	ChangeVehicleViewWindow(from_v->index, to_v->index);
-}
-
 static inline uint GetVehicleListHeight(VehicleType type)
 {
 	return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24;
@@ -149,8 +133,6 @@
 extern Sorting _sorting;
 
 /* sorter stuff */
-void RebuildVehicleLists();
-void ResortVehicleLists();
 void SortVehicleList(VehicleListBase *vl);
 void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type);
 
--- a/src/vehicle_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle_type.h	Tue May 27 00:50:55 2008 +0000
@@ -6,6 +6,7 @@
 #define VEHICLE_TYPE_H
 
 #include "core/enum_type.hpp"
+#include "misc/smallvec.h"
 
 typedef uint16 VehicleID;
 
@@ -56,4 +57,6 @@
 	DEPOT_COMMAND_MASK  = 0xF,
 };
 
+typedef SmallVector<const Vehicle*, 32> VehicleList;
+
 #endif /* VEHICLE_TYPE_H */
--- a/src/video/cocoa/event.mm	Mon May 26 20:45:25 2008 +0000
+++ b/src/video/cocoa/event.mm	Tue May 27 00:50:55 2008 +0000
@@ -288,9 +288,9 @@
 	}
 
 	if (_current_mods & NSShiftKeyMask)     key |= WKC_SHIFT;
-	if (_current_mods & NSControlKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
+	if (_current_mods & NSControlKeyMask)   key |= (_settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
 	if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT;
-	if (_current_mods & NSCommandKeyMask)   key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
+	if (_current_mods & NSCommandKeyMask)   key |= (_settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
 
 	return key << 16;
 }
@@ -459,8 +459,8 @@
 		case NSLeftMouseDown:
 		{
 			uint32 keymask = 0;
-			if (_patches.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
-			if (_patches.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
+			if (_settings.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
+			if (_settings.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
 
 			pt = _cocoa_subdriver->GetMouseLocation(event);
 
@@ -602,8 +602,8 @@
 			} /* else: deltaY was 0.0 and we don't want to do anything */
 
 			/* Set the scroll count for scrollwheel scrolling */
-			_cursor.h_wheel -= (int)([ event deltaX ]* 5 * _patches.scrollwheel_multiplier);
-			_cursor.v_wheel -= (int)([ event deltaY ]* 5 * _patches.scrollwheel_multiplier);
+			_cursor.h_wheel -= (int)([ event deltaX ]* 5 * _settings.gui.scrollwheel_multiplier);
+			_cursor.v_wheel -= (int)([ event deltaY ]* 5 * _settings.gui.scrollwheel_multiplier);
 			break;
 
 		default:
@@ -671,7 +671,7 @@
 
 			bool old_ctrl_pressed = _ctrl_pressed;
 
-			_ctrl_pressed = !!(_current_mods & ( _patches.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
+			_ctrl_pressed = !!(_current_mods & ( _settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
 			_shift_pressed = !!(_current_mods & NSShiftKeyMask);
 
 			if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
--- a/src/video/dedicated_v.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/video/dedicated_v.cpp	Tue May 27 00:50:55 2008 +0000
@@ -11,7 +11,7 @@
 #include "../gfx_func.h"
 #include "../network/network.h"
 #include "../network/network_internal.h"
-#include "../console.h"
+#include "../console_func.h"
 #include "../variables.h"
 #include "../genworld.h"
 #include "../fileio.h"
--- a/src/viewport.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/viewport.cpp	Tue May 27 00:50:55 2008 +0000
@@ -1045,7 +1045,7 @@
 						right  > t->sign.left &&
 						left   < t->sign.left + t->sign.width_1) {
 					AddStringToDraw(t->sign.left + 1, t->sign.top + 1,
-						_patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL,
+						_settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL,
 						t->index, t->population);
 				}
 			}
@@ -1061,7 +1061,7 @@
 						right  > t->sign.left &&
 						left   < t->sign.left + t->sign.width_1 * 2) {
 					AddStringToDraw(t->sign.left + 1, t->sign.top + 1,
-						_patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL,
+						_settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL,
 						t->index, t->population);
 				}
 			}
@@ -1616,7 +1616,7 @@
 		int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y;
 
 		if (delta_x != 0 || delta_y != 0) {
-			if (_patches.smooth_scroll) {
+			if (_settings.gui.smooth_scroll) {
 				int max_scroll = ScaleByMapSize1D(512);
 				/* Not at our desired positon yet... */
 				w->viewport->scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll);
@@ -2535,7 +2535,7 @@
 		}
 	}
 
-	if (_patches.measure_tooltip) {
+	if (_settings.gui.measure_tooltip) {
 		TileIndex t0 = TileVirtXY(thd->selstart.x, thd->selstart.y);
 		TileIndex t1 = TileVirtXY(x, y);
 		uint distance = DistanceManhattan(t0, t1) + 1;
@@ -2615,7 +2615,7 @@
 			style = HT_DIR_X;
 
 calc_heightdiff_single_direction:;
-			if (_patches.measure_tooltip) {
+			if (_settings.gui.measure_tooltip) {
 				TileIndex t0 = TileVirtXY(sx, sy);
 				TileIndex t1 = TileVirtXY(x, y);
 				uint distance = DistanceManhattan(t0, t1) + 1;
@@ -2643,7 +2643,7 @@
 			y = sy + Clamp(y - sy, -limit, limit);
 			} /* Fallthrough */
 		case VPM_X_AND_Y: { /* drag an X by Y area */
-			if (_patches.measure_tooltip) {
+			if (_settings.gui.measure_tooltip) {
 				static const StringID measure_strings_area[] = {
 					STR_NULL, STR_NULL, STR_MEASURE_AREA, STR_MEASURE_AREA_HEIGHTDIFF
 				};
@@ -2686,7 +2686,10 @@
 	_thd.selend.y = y;
 }
 
-/** while dragging */
+/**
+ * Handle the mouse while dragging for placement/resizing.
+ * @return Boolean whether search for a handler should continue
+ */
 bool VpHandlePlaceSizingDrag()
 {
 	if (_special_mouse_mode != WSM_SIZING) return true;
--- a/src/water_cmd.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/water_cmd.cpp	Tue May 27 00:50:55 2008 +0000
@@ -738,7 +738,7 @@
 		default: assert(0); break;
 	}
 
-	td->owner = GetTileOwner(tile);
+	td->owner[0] = GetTileOwner(tile);
 }
 
 static void AnimateTile_Water(TileIndex tile)
@@ -774,7 +774,7 @@
 	}
 
 	/* if non-uniform stations are disabled, flood some train in this train station (if there is any) */
-	if (!_patches.nonuniform_stations && IsTileType(tile, MP_STATION) && GetStationType(tile) == STATION_RAIL) {
+	if (!_settings.station.nonuniform_stations && IsTileType(tile, MP_STATION) && GetStationType(tile) == STATION_RAIL) {
 		const Station *st = GetStationByTile(tile);
 
 		BEGIN_TILE_LOOP(t, st->trainst_w, st->trainst_h, st->train_tile)
@@ -823,39 +823,36 @@
 				//TODO: airport->delta_z no longer used. need to get actual height of individual tile in layout
 				//if (v->z_pos != airport->delta_z + 1) return;
 			}
-			Vehicle *u;
 
 			if (v->type != VEH_AIRCRAFT) v = v->First();
-			u = v;
 
 			/* crash all wagons, and count passengers */
-			BEGIN_ENUM_WAGONS(v)
-				if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.Count();
-				v->vehstatus |= VS_CRASHED;
-				MarkSingleVehicleDirty(v);
-			END_ENUM_WAGONS(v)
-
-			v = u;
+			for (Vehicle *u = v; u != NULL; u = u->Next()) {
+				if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
+				u->vehstatus |= VS_CRASHED;
+				MarkSingleVehicleDirty(u);
+			}
 
 			switch (v->type) {
 				default: NOT_REACHED();
 				case VEH_TRAIN:
 					if (IsFrontEngine(v)) pass += 4; // driver
 					v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast
+					InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 					break;
 
 				case VEH_ROAD:
 					if (IsRoadVehFront(v)) pass += 1; // driver
 					v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast
+					InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 					break;
 
 				case VEH_AIRCRAFT:
 					pass += 2; // driver
 					v->u.air.crashed_counter = 9000; // max 10000, disappear pretty fast
+					InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 					break;
 			}
-
-			RebuildVehicleLists();
 		} else {
 			return;
 		}
--- a/src/waypoint.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/waypoint.cpp	Tue May 27 00:50:55 2008 +0000
@@ -210,7 +210,7 @@
 
 	tileh = GetTileSlope(tile, NULL);
 	if (tileh != SLOPE_FLAT &&
-			(!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
+			(!_settings.construction.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
 		return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 	}
 
--- a/src/widgets/dropdown.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/widgets/dropdown.cpp	Tue May 27 00:50:55 2008 +0000
@@ -72,8 +72,9 @@
 	bool drag_mode;
 	int scrolling;
 
-	DropdownWindow(int x, int y, int width, int height, const Widget *widget) : Window(x, y, width, height, NULL, WC_DROPDOWN_MENU, widget)
+	DropdownWindow(int x, int y, int width, int height, const Widget *widget) : Window(x, y, width, height, WC_DROPDOWN_MENU, widget)
 	{
+		this->FindWindowPlacementAndResize(width, height);
 	}
 
 	~DropdownWindow()
--- a/src/window.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/window.cpp	Tue May 27 00:50:55 2008 +0000
@@ -8,7 +8,8 @@
 #include "debug.h"
 #include "player_func.h"
 #include "gfx_func.h"
-#include "console.h"
+#include "console_func.h"
+#include "console_gui.h"
 #include "viewport_func.h"
 #include "variables.h"
 #include "genworld.h"
@@ -48,169 +49,6 @@
 byte _special_mouse_mode;
 
 
-/**
- * Call the window event handler for handling event \a e.
- * This is a temporary helper functions that will be removed
- * once all windows that still rely on WindowEvent and
- * WindowEventCodes have been rewritten to use the 'OnXXX'
- * event handlers.
- * @param e Window event to handle
- */
-void Window::HandleWindowEvent(WindowEvent *e)
-{
-	if (wndproc != NULL) wndproc(this, e);
-}
-
-void Window::OnPaint()
-{
-	WindowEvent e;
-	e.event = WE_PAINT;
-	this->HandleWindowEvent(&e);
-}
-
-bool Window::OnKeyPress(uint16 key, uint16 keycode)
-{
-	WindowEvent e;
-	e.event = WE_KEYPRESS;
-	e.we.keypress.key     = key;
-	e.we.keypress.keycode = keycode;
-	e.we.keypress.cont    = true;
-	this->HandleWindowEvent(&e);
-
-	return e.we.keypress.cont;
-}
-
-bool Window::OnCTRLStateChange()
-{
-	WindowEvent e;
-	e.event = WE_CTRL_CHANGED;
-	e.we.ctrl.cont = true;
-	this->HandleWindowEvent(&e);
-
-	return e.we.ctrl.cont;
-}
-
-void Window::OnClick(Point pt, int widget)
-{
-	WindowEvent e;
-	e.event = WE_CLICK;
-	e.we.click.pt     = pt;
-	e.we.click.widget = widget;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnMouseLoop()
-{
-	WindowEvent e;
-	e.event = WE_MOUSELOOP;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnTick()
-{
-	WindowEvent e;
-	e.event = WE_TICK;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnHundredthTick()
-{
-	WindowEvent e;
-	e.event = WE_100_TICKS;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnTimeout()
-{
-	WindowEvent e;
-	e.event = WE_TIMEOUT;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnResize(Point new_size, Point delta)
-{
-	WindowEvent e;
-	e.event = WE_RESIZE;
-	e.we.sizing.size = new_size;
-	e.we.sizing.diff = delta;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnDropdownSelect(int widget, int index)
-{
-	WindowEvent e;
-	e.event = WE_DROPDOWN_SELECT;
-	e.we.dropdown.button = widget;
-	e.we.dropdown.index  = index;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnQueryTextFinished(char *str)
-{
-	WindowEvent e;
-	e.event = WE_ON_EDIT_TEXT;
-	e.we.edittext.str = str;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnInvalidateData(int data)
-{
-	WindowEvent e;
-	e.event = WE_INVALIDATE_DATA;
-	e.we.invalidate.data = data;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnPlaceObject(Point pt, TileIndex tile)
-{
-	WindowEvent e;
-	e.event = WE_PLACE_OBJ;
-	e.we.place.pt   = pt;
-	e.we.place.tile = tile;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnPlaceObjectAbort()
-{
-	WindowEvent e;
-	e.event = WE_ABORT_PLACE_OBJ;
-	this->HandleWindowEvent(&e);
-}
-
-
-void Window::OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt)
-{
-	WindowEvent e;
-	e.event = WE_PLACE_DRAG;
-	e.we.place.select_method = select_method;
-	e.we.place.select_proc   = select_proc;
-	e.we.place.pt            = pt;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
-{
-	WindowEvent e;
-	e.event = WE_PLACE_MOUSEUP;
-	e.we.place.select_method = select_method;
-	e.we.place.select_proc   = select_proc;
-	e.we.place.pt            = pt;
-	e.we.place.tile          = end_tile;
-	e.we.place.starttile     = start_tile;
-	this->HandleWindowEvent(&e);
-}
-
-void Window::OnPlacePresize(Point pt, TileIndex tile)
-{
-	WindowEvent e;
-	e.event = WE_PLACE_PRESIZE;
-	e.we.place.pt   = pt;
-	e.we.place.tile = tile;
-	this->HandleWindowEvent(&e);
-}
-
-
-
 void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...)
 {
 	va_list wdg_list;
@@ -581,9 +419,6 @@
 		child = FindChildWindow(this);
 	}
 
-	WindowEvent e;
-	e.event = WE_DESTROY;
-	this->HandleWindowEvent(&e);
 	if (this->viewport != NULL) DeleteWindowViewport(this);
 
 	this->SetDirty();
@@ -831,14 +666,13 @@
  * @param y offset in pixels from the top of the screen
  * @param min_width minimum width in pixels of the window
  * @param min_height minimum height in pixels of the window
- * @param *proc see WindowProc function to call when any messages/updates happen to the window
  * @param cls see WindowClass class of the window, used for identification and grouping
  * @param *widget see Widget pointer to the window layout and various elements
  * @param window_number number being assigned to the new window
  * @return Window pointer of the newly created window
  */
 void Window::Initialize(int x, int y, int min_width, int min_height,
-				WindowProc *proc, WindowClass cls, const Widget *widget, int window_number)
+				WindowClass cls, const Widget *widget, int window_number)
 {
 	/* We have run out of windows, close one and use that as the place for our new one */
 	if (_last_z_window == endof(_z_windows)) {
@@ -855,7 +689,6 @@
 	this->top = y;
 	this->width = min_width;
 	this->height = min_height;
-	this->wndproc = proc;
 	AssignWidgetToWindow(this, widget);
 	this->resize.width = min_width;
 	this->resize.height = min_height;
@@ -884,10 +717,6 @@
 
 	*wz = this;
 	_last_z_window++;
-
-	WindowEvent e;
-	e.event = WE_CREATE;
-	this->HandleWindowEvent(&e);
 }
 
 /**
@@ -963,16 +792,13 @@
  * @param y offset in pixels from the top of the screen
  * @param width width in pixels of the window
  * @param height height in pixels of the window
- * @param *proc see WindowProc function to call when any messages/updates happen to the window
  * @param cls see WindowClass class of the window, used for identification and grouping
  * @param *widget see Widget pointer to the window layout and various elements
  * @return Window pointer of the newly created window
  */
-Window::Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget)
+Window::Window(int x, int y, int width, int height, WindowClass cls, const Widget *widget)
 {
-	this->Initialize(x, y, width, height, proc, cls, widget, 0);
-
-	if (proc != NULL) this->FindWindowPlacementAndResize(width, height);
+	this->Initialize(x, y, width, height, cls, widget, 0);
 }
 
 
@@ -1164,10 +990,8 @@
 Window::Window(const WindowDesc *desc, WindowNumber window_number)
 {
 	Point pt = LocalGetWindowPlacement(desc, window_number);
-	this->Initialize(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->proc, desc->cls, desc->widgets, window_number);
+	this->Initialize(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->cls, desc->widgets, window_number);
 	this->desc_flags = desc->flags;
-
-	if (desc->proc != NULL) this->FindWindowPlacementAndResize(desc->default_width, desc->default_height);
 }
 
 /** Do a search for a window at specific coordinates. For this we start
@@ -1393,11 +1217,11 @@
 			int nx = x;
 			int ny = y;
 
-			if (_patches.window_snap_radius != 0) {
+			if (_settings.gui.window_snap_radius != 0) {
 				Window* const *vz;
 
-				int hsnap = _patches.window_snap_radius;
-				int vsnap = _patches.window_snap_radius;
+				int hsnap = _settings.gui.window_snap_radius;
+				int vsnap = _settings.gui.window_snap_radius;
 				int delta;
 
 				FOR_ALL_WINDOWS(vz) {
@@ -1643,7 +1467,7 @@
 
 static bool HandleViewportScroll()
 {
-	bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
+	bool scrollwheel_scrolling = _settings.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
 
 	if (!_scrolling_viewport) return true;
 
@@ -1663,7 +1487,7 @@
 	}
 
 	Point delta;
-	if (_patches.reverse_scroll) {
+	if (_settings.gui.reverse_scroll) {
 		delta.x = -_cursor.delta.x;
 		delta.y = -_cursor.delta.y;
 	} else {
@@ -1802,8 +1626,7 @@
 				w->window_class != WC_COMPANY_PASSWORD_WINDOW) {
 			continue;
 		}
-		;
-		if (!w->OnKeyPress(key, keycode)) return;
+		if (w->OnKeyPress(key, keycode) == Window::ES_HANDLED) return;
 	}
 
 	Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
@@ -1819,7 +1642,7 @@
 	/* Call the event, start with the uppermost window. */
 	for (Window* const *wz = _last_z_window; wz != _z_windows;) {
 		Window *w = *--wz;
-		if (!w->OnCTRLStateChange()) break;
+		if (w->OnCTRLStateChange() == Window::ES_HANDLED) return;
 	}
 }
 
@@ -1844,7 +1667,7 @@
 		return;
 	}
 
-	if (_patches.autoscroll && _game_mode != GM_MENU && !IsGeneratingWorld()) {
+	if (_settings.gui.autoscroll && _game_mode != GM_MENU && !IsGeneratingWorld()) {
 		int x = _cursor.pos.x;
 		int y = _cursor.pos.y;
 		Window *w = FindWindowFromPt(x, y);
@@ -1896,7 +1719,7 @@
 	if (!HandleViewportScroll())     return;
 	if (!HandleMouseOver())          return;
 
-	bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
+	bool scrollwheel_scrolling = _settings.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
 	if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
 
 	int x = _cursor.pos.x;
@@ -1911,7 +1734,7 @@
 	if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return;
 
 	if (mousewheel != 0) {
-		if (_patches.scrollwheel_scrolling == 0) {
+		if (_settings.gui.scrollwheel_scrolling == 0) {
 			/* Send mousewheel event to window */
 			w->OnMouseWheel(mousewheel);
 		}
@@ -2236,7 +2059,7 @@
 		w = FindWindowById(WC_MAIN_TOOLBAR, 0);
 	}
 
-	switch (_patches.toolbar_pos) {
+	switch (_settings.gui.toolbar_pos) {
 		case 1:  w->left = (_screen.width - w->width) / 2; break;
 		case 2:  w->left = _screen.width - w->width; break;
 		default: w->left = 0;
--- a/src/window_gui.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/window_gui.h	Tue May 27 00:50:55 2008 +0000
@@ -20,8 +20,6 @@
  */
 static const int MAX_NUMBER_OF_WINDOWS = 25;
 
-typedef void WindowProc(Window *w, WindowEvent *e);
-
 /* How the resize system works:
     First, you need to add a WWT_RESIZEBOX to the widgets, and you need
      to add the flag WDF_RESIZABLE to the window. Now the window is ready
@@ -106,86 +104,6 @@
 void DrawFrameRect(int left, int top, int right, int bottom, int color, FrameFlags flags);
 
 /**
- * Available window events
- */
-enum WindowEventCodes {
-	WE_CREATE,       ///< Initialize the Window
-	WE_DESTROY,      ///< Prepare for deletion of the window
-	WE_PAINT,        ///< Repaint the window contents
-	WE_KEYPRESS,     ///< Key pressed
-	WE_CLICK,        ///< Left mouse button click
-	WE_MOUSELOOP,    ///< Event for each mouse event in the game (at least once every game tick)
-	WE_TICK,         ///< Regularly occurring event (every game tick)
-	WE_100_TICKS,    ///< Regularly occurring event (every 100 game ticks, approximatelly 3 seconds)
-	WE_TIMEOUT,
-	WE_PLACE_OBJ,
-	WE_ABORT_PLACE_OBJ,
-	WE_ON_EDIT_TEXT,
-	WE_PLACE_DRAG,
-	WE_PLACE_MOUSEUP,
-	WE_PLACE_PRESIZE,
-	WE_DROPDOWN_SELECT,
-	WE_RESIZE,          ///< Request to resize the window, @see WindowEvent.we.resize
-	WE_INVALIDATE_DATA, ///< Notification that data displayed by the window is obsolete
-	WE_CTRL_CHANGED,    ///< CTRL key has changed state
-};
-
-/**
- * Data structures for additional data associated with a window event
- * @see WindowEventCodes
- */
-struct WindowEvent {
-	byte event;
-	union {
-		struct {
-			Point pt;
-			int widget;
-		} click;
-
-		struct {
-			Point pt;
-			TileIndex tile;
-			TileIndex starttile;
-			ViewportPlaceMethod select_method;
-			byte select_proc;
-		} place;
-
-		struct {
-			Point pt;
-			int widget;
-		} dragdrop;
-
-		struct {
-			Point size;
-			Point diff;
-		} sizing;
-
-		struct {
-			char *str;
-		} edittext;
-
-		struct {
-			int button;
-			int index;
-		} dropdown;
-
-		struct {
-			bool cont;      ///< continue the search? (default true)
-			uint16 key;     ///< 16-bit Unicode value of the key
-			uint16 keycode; ///< untranslated key (including shift-state)
-		} keypress;
-
-		struct {
-			int data;
-		} invalidate;
-
-		struct {
-			bool cont;     ///< continue the search? (default true)
-		} ctrl;
-	} we;
-};
-
-/**
  * High level window description
  */
 struct WindowDesc {
@@ -199,7 +117,6 @@
 	WindowClass parent_cls; ///< Class of the parent window, @see WindowClass
 	uint32 flags;           ///< Flags, @see WindowDefaultFlags
 	const Widget *widgets;  ///< List of widgets with their position and size for the window
-	WindowProc *proc;       ///< Window event handler function for the window
 };
 
 /**
@@ -266,18 +183,19 @@
  * Data structure for an opened window
  */
 struct Window : ZeroedMemoryAllocator {
-private:
-	WindowProc *wndproc;   ///< Event handler function for the window. Do not use directly, call HandleWindowEvent() instead.
-	void HandleWindowEvent(WindowEvent *e);
+	enum EventState {
+		ES_HANDLED,
+		ES_NOT_HANDLED,
+	};
 
 protected:
 	void Initialize(int x, int y, int min_width, int min_height,
-			WindowProc *proc, WindowClass cls, const Widget *widget, int window_number);
+			WindowClass cls, const Widget *widget, int window_number);
 	void FindWindowPlacementAndResize(int def_width, int def_height);
 	void FindWindowPlacementAndResize(const WindowDesc *desc);
 
 public:
-	Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget);
+	Window(int x, int y, int width, int height, WindowClass cls, const Widget *widget);
 	Window(const WindowDesc *desc, WindowNumber number = 0);
 
 	virtual ~Window();
@@ -338,24 +256,24 @@
 	/**
 	 * This window is currently being repainted.
 	 */
-	virtual void OnPaint();
+	virtual void OnPaint() {}
 
 
 	/**
 	 * A key has been pressed.
 	 * @param key     the Unicode value of the key.
 	 * @param keycode the untranslated key code including shift state.
-	 * @return true if the key press has been handled and no other
+	 * @return ES_HANDLED if the key press has been handled and no other
 	 *         window should receive the event.
 	 */
-	virtual bool OnKeyPress(uint16 key, uint16 keycode);
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode) { return ES_NOT_HANDLED; }
 
 	/**
 	 * The state of the control key has changed
-	 * @return true if the change has been handled and no other
+	 * @return ES_HANDLED if the change has been handled and no other
 	 *         window should receive the event.
 	 */
-	virtual bool OnCTRLStateChange();
+	virtual EventState OnCTRLStateChange() { return ES_NOT_HANDLED; }
 
 
 	/**
@@ -363,7 +281,7 @@
 	 * @param pt     the point inside the window that has been clicked.
 	 * @param widget the clicked widget.
 	 */
-	virtual void OnClick(Point pt, int widget);
+	virtual void OnClick(Point pt, int widget) {}
 
 	/**
 	 * A double click with the left mouse button has been made on the window.
@@ -410,22 +328,22 @@
 	/**
 	 * Called for every mouse loop run, which is at least once per (game) tick.
 	 */
-	virtual void OnMouseLoop();
+	virtual void OnMouseLoop() {}
 
 	/**
 	 * Called once per (game) tick.
 	 */
-	virtual void OnTick();
+	virtual void OnTick() {}
 
 	/**
 	 * Called once every 100 (game) ticks.
 	 */
-	virtual void OnHundredthTick();
+	virtual void OnHundredthTick() {}
 
 	/**
 	 * Called when this window's timeout has been reached.
 	 */
-	virtual void OnTimeout();
+	virtual void OnTimeout() {}
 
 
 	/**
@@ -433,27 +351,27 @@
 	 * @param new_size the new size of the window.
 	 * @param delta    the amount of which the window size changed.
 	 */
-	virtual void OnResize(Point new_size, Point delta);
+	virtual void OnResize(Point new_size, Point delta) {}
 
 	/**
 	 * A dropdown option associated to this window has been selected.
 	 * @param widget the widget (button) that the dropdown is associated with.
 	 * @param index  the element in the dropdown that is selected.
 	 */
-	virtual void OnDropdownSelect(int widget, int index);
+	virtual void OnDropdownSelect(int widget, int index) {}
 
 	/**
 	 * The query window opened from this window has closed.
 	 * @param str the new value of the string or NULL if the window
 	 *            was cancelled.
 	 */
-	virtual void OnQueryTextFinished(char *str);
+	virtual void OnQueryTextFinished(char *str) {}
 
 	/**
 	 * Some data on this window has become invalid.
 	 * @param data information about the changed data.
 	 */
-	virtual void OnInvalidateData(int data = 0);
+	virtual void OnInvalidateData(int data = 0) {}
 
 
 	/**
@@ -462,12 +380,12 @@
 	 * @param pt   the exact point on the map that has been clicked.
 	 * @param tile the tile on the map that has been clicked.
 	 */
-	virtual void OnPlaceObject(Point pt, TileIndex tile);
+	virtual void OnPlaceObject(Point pt, TileIndex tile) {}
 
 	/**
 	 * The user cancelled a tile highlight mode that has been set.
 	 */
-	virtual void OnPlaceObjectAbort();
+	virtual void OnPlaceObjectAbort() {}
 
 
 	/**
@@ -477,7 +395,7 @@
 	 * @param select_proc   what will be created when the drag is over.
 	 * @param pt            the exact point on the map where the mouse is.
 	 */
-	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt);
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) {}
 
 	/**
 	 * The user has dragged over the map when the tile highlight mode
@@ -488,7 +406,7 @@
 	 * @param start_tile    the begin tile of the drag.
 	 * @param end_tile      the end tile of the drag.
 	 */
-	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile);
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) {}
 
 	/**
 	 * The user moves over the map when a tile highlight mode has been set
@@ -497,7 +415,7 @@
 	 * @param pt   the exact point on the map where the mouse is.
 	 * @param tile the tile on the map where the mouse is.
 	 */
-	virtual void OnPlacePresize(Point pt, TileIndex tile);
+	virtual void OnPlacePresize(Point pt, TileIndex tile) {}
 
 	/*** End of the event handling ***/
 };
@@ -508,7 +426,10 @@
 class PickerWindowBase : public Window {
 
 public:
-	PickerWindowBase(const WindowDesc *desc) : Window(desc) {}; // nothing special yet, just propagation
+	PickerWindowBase(const WindowDesc *desc, Window *parent) : Window(desc)
+	{
+		this->parent = parent;
+	};
 
 	virtual ~PickerWindowBase();
 };
--- a/src/window_type.h	Mon May 26 20:45:25 2008 +0000
+++ b/src/window_type.h	Tue May 27 00:50:55 2008 +0000
@@ -99,7 +99,6 @@
 };
 
 struct Window;
-struct WindowEvent;
 typedef int32 WindowNumber;
 
 #endif /* WINDOW_TYPE_H */
--- a/src/yapf/yapf_base.hpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/yapf/yapf_base.hpp	Tue May 27 00:50:55 2008 +0000
@@ -6,6 +6,7 @@
 #define  YAPF_BASE_HPP
 
 #include "../debug.h"
+#include "../settings_type.h"
 
 extern int _total_pf_time_us;
 
@@ -52,7 +53,7 @@
 protected:
 	Node*                m_pBestDestNode;      ///< pointer to the destination node found at last round
 	Node*                m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found
-	const YapfSettings  *m_settings;           ///< current settings (_patches.yapf)
+	const YAPFSettings  *m_settings;           ///< current settings (_settings.yapf)
 	int                  m_max_search_nodes;   ///< maximum number of nodes we are allowed to visit before we give up
 	const Vehicle*       m_veh;                ///< vehicle that we are trying to drive
 
@@ -73,7 +74,7 @@
 	FORCEINLINE CYapfBaseT()
 		: m_pBestDestNode(NULL)
 		, m_pBestIntermediateNode(NULL)
-		, m_settings(&_patches.yapf)
+		, m_settings(&_settings.pf.yapf)
 		, m_max_search_nodes(PfGetSettings().max_search_nodes)
 		, m_veh(NULL)
 		, m_stats_cost_calcs(0)
@@ -91,7 +92,7 @@
 
 public:
 	/// return current settings (can be custom - player based - but later)
-	FORCEINLINE const YapfSettings& PfGetSettings() const
+	FORCEINLINE const YAPFSettings& PfGetSettings() const
 	{
 		return *m_settings;
 	}
--- a/src/yapf/yapf_rail.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/yapf/yapf_rail.cpp	Tue May 27 00:50:55 2008 +0000
@@ -254,7 +254,7 @@
 	PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack;
 
 	// check if non-default YAPF type needed
-	if (_patches.forbid_90_deg) {
+	if (_settings.pf.forbid_90_deg) {
 		pfnChooseRailTrack = &CYapfRail2::stChooseRailTrack; // Trackdir, forbid 90-deg
 	}
 
@@ -311,7 +311,7 @@
 	PfnCheckReverseTrain pfnCheckReverseTrain = CYapfRail1::stCheckReverseTrain;
 
 	// check if non-default YAPF type needed
-	if (_patches.forbid_90_deg) {
+	if (_settings.pf.forbid_90_deg) {
 		pfnCheckReverseTrain = &CYapfRail2::stCheckReverseTrain; // Trackdir, forbid 90-deg
 	}
 
@@ -341,7 +341,7 @@
 	PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay;
 
 	// check if non-default YAPF type needed
-	if (_patches.forbid_90_deg) {
+	if (_settings.pf.forbid_90_deg) {
 		pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail2::stFindNearestDepotTwoWay; // Trackdir, forbid 90-deg
 	}
 
--- a/src/yapf/yapf_road.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/yapf/yapf_road.cpp	Tue May 27 00:50:55 2008 +0000
@@ -407,7 +407,7 @@
 	PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg
 
 	// check if non-default YAPF type should be used
-	if (_patches.yapf.disable_node_optimization)
+	if (_settings.pf.yapf.disable_node_optimization)
 		pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg
 
 	Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir);
@@ -421,7 +421,7 @@
 	PfnDistanceToTile pfnDistanceToTile = &CYapfRoad2::stDistanceToTile; // default: ExitDir, allow 90-deg
 
 	// check if non-default YAPF type should be used
-	if (_patches.yapf.disable_node_optimization)
+	if (_settings.pf.yapf.disable_node_optimization)
 		pfnDistanceToTile = &CYapfRoad1::stDistanceToTile; // Trackdir, allow 90-deg
 
 	// measure distance in YAPF units
@@ -450,7 +450,7 @@
 	PfnFindNearestDepot pfnFindNearestDepot = &CYapfRoadAnyDepot2::stFindNearestDepot;
 
 	// check if non-default YAPF type should be used
-	if (_patches.yapf.disable_node_optimization)
+	if (_settings.pf.yapf.disable_node_optimization)
 		pfnFindNearestDepot = &CYapfRoadAnyDepot1::stFindNearestDepot; // Trackdir, allow 90-deg
 
 	Depot* ret = pfnFindNearestDepot(v, tile, trackdir);
--- a/src/yapf/yapf_settings.h	Mon May 26 20:45:25 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/* $Id$ */
-
-/** @file yapf_settings.h Penalty settings for YAPF. */
-
-#if !defined(YAPF_SETTINGS_H) || defined(YS_DEF)
-
-# ifndef  YAPF_SETTINGS_H
-#  define  YAPF_SETTINGS_H
-# endif
-
-# ifndef YS_DEF
-/*
- *  if YS_DEF is not defined, we will only do following declaration:
- *  struct YapfSettings {
- *    bool   disable_node_optimization;
- *    uint32 max_search_nodes;
- *    .... all other yapf related settings ...
- *  };
- *
- *  otherwise we will just expand YS_DEF_xx macros and then #undef them
- */
-#  define YS_DEF_BEGIN struct YapfSettings {
-#  define YS_DEF(type, name) type name;
-#  define YS_DEF_END };
-
-# endif /* !YS_DEF */
-
-# ifndef   YS_DEF_BEGIN
-#  define  YS_DEF_BEGIN
-# endif // YS_DEF_BEGIN
-
-# ifndef   YS_DEF_END
-#  define  YS_DEF_END
-# endif // YS_DEF_END
-
-YS_DEF_BEGIN
-	YS_DEF(bool  , disable_node_optimization)  ///< whether to use exit-dir instead of trackdir in node key
-	YS_DEF(uint32, max_search_nodes)           ///< stop path-finding when this number of nodes visited
-	YS_DEF(bool  , ship_use_yapf)              ///< use YAPF for ships
-	YS_DEF(bool  , road_use_yapf)              ///< use YAPF for road
-	YS_DEF(bool  , rail_use_yapf)              ///< use YAPF for rail
-	YS_DEF(uint32, road_slope_penalty)         ///< penalty for up-hill slope
-	YS_DEF(uint32, road_curve_penalty)         ///< penalty for curves
-	YS_DEF(uint32, road_crossing_penalty)      ///< penalty for level crossing
-	YS_DEF(uint32, road_stop_penalty)          ///< penalty for going through a drive-through road stop
-	YS_DEF(bool  , rail_firstred_twoway_eol)   ///< treat first red two-way signal as dead end
-	YS_DEF(uint32, rail_firstred_penalty)      ///< penalty for first red signal
-	YS_DEF(uint32, rail_firstred_exit_penalty) ///< penalty for first red exit signal
-	YS_DEF(uint32, rail_lastred_penalty)       ///< penalty for last red signal
-	YS_DEF(uint32, rail_lastred_exit_penalty)  ///< penalty for last red exit signal
-	YS_DEF(uint32, rail_station_penalty)       ///< penalty for non-target station tile
-	YS_DEF(uint32, rail_slope_penalty)         ///< penalty for up-hill slope
-	YS_DEF(uint32, rail_curve45_penalty)       ///< penalty for curve
-	YS_DEF(uint32, rail_curve90_penalty)       ///< penalty for 90-deg curve
-	YS_DEF(uint32, rail_depot_reverse_penalty) ///< penalty for reversing in the depot
-	YS_DEF(uint32, rail_crossing_penalty)      ///< penalty for level crossing
-	YS_DEF(uint32, rail_look_ahead_max_signals)///< max. number of signals taken into consideration in look-ahead load balancer
-	YS_DEF(int32 , rail_look_ahead_signal_p0)  ///< constant in polynomial penalty function
-	YS_DEF(int32 , rail_look_ahead_signal_p1)  ///< constant in polynomial penalty function
-	YS_DEF(int32 , rail_look_ahead_signal_p2)  ///< constant in polynomial penalty function
-
-	YS_DEF(uint32, rail_longer_platform_penalty)           ///< penalty for longer  station platform than train
-	YS_DEF(uint32, rail_longer_platform_per_tile_penalty)  ///< penalty for longer  station platform than train (per tile)
-	YS_DEF(uint32, rail_shorter_platform_penalty)          ///< penalty for shorter station platform than train
-	YS_DEF(uint32, rail_shorter_platform_per_tile_penalty) ///< penalty for shorter station platform than train (per tile)
-YS_DEF_END
-
-#undef YS_DEF_BEGIN
-#undef YS_DEF
-#undef YS_DEF_END
-
-#endif /* !YAPF_SETTINGS_H || YS_DEF */
--- a/src/yapf/yapf_ship.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/yapf/yapf_ship.cpp	Tue May 27 00:50:55 2008 +0000
@@ -154,9 +154,9 @@
 	PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg
 
 	// check if non-default YAPF type needed
-	if (_patches.forbid_90_deg)
+	if (_settings.pf.forbid_90_deg)
 		pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack; // Trackdir, forbid 90-deg
-	else if (_patches.yapf.disable_node_optimization)
+	else if (_settings.pf.yapf.disable_node_optimization)
 		pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg
 
 	Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);