diff -r 6d1e4fb7f37a config.lib
--- a/config.lib	Sun Dec 27 18:45:17 2009 +0000
+++ b/config.lib	Mon Dec 28 19:19:10 2009 +0100
@@ -11,7 +11,7 @@
 }
 
 set_default() {
-	released_version=""
+	released_version="IS2.1"
 
 	ignore_extra_parameters="0"
 	# We set all kinds of defaults for params. Later on the user can override
diff -r 6d1e4fb7f37a findversion.sh
--- a/findversion.sh	Sun Dec 27 18:45:17 2009 +0000
+++ b/findversion.sh	Mon Dec 28 19:19:10 2009 +0100
@@ -121,4 +121,4 @@
 	REV="${REV}-$BRANCH"
 fi
 
-echo "$REV	$REV_NR	$MODIFIED	$CLEAN_REV"
+echo "IS2.1	$REV_NR	$MODIFIED	IS2.1"
diff -r 6d1e4fb7f37a projects/determineversion.vbs
--- a/projects/determineversion.vbs	Sun Dec 27 18:45:17 2009 +0000
+++ b/projects/determineversion.vbs	Mon Dec 28 19:19:10 2009 +0100
@@ -39,6 +39,7 @@
 		modified = Mid(version, InStrRev(version, Chr(9)) + 1)
 		version  = Mid(version, 1, InStr(version, Chr(9)) - 1)
 	Else
+		version = "IS2.1"
 		revision = 0
 		modified = 1
 	End If
diff -r 6d1e4fb7f37a projects/openttd_vs80.vcproj
--- a/projects/openttd_vs80.vcproj	Sun Dec 27 18:45:17 2009 +0000
+++ b/projects/openttd_vs80.vcproj	Mon Dec 28 19:19:10 2009 +0100
@@ -584,6 +584,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1072,6 +1076,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
diff -r 6d1e4fb7f37a projects/openttd_vs90.vcproj
--- a/projects/openttd_vs90.vcproj	Sun Dec 27 18:45:17 2009 +0000
+++ b/projects/openttd_vs90.vcproj	Mon Dec 28 19:19:10 2009 +0100
@@ -581,6 +581,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1069,6 +1073,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
diff -r 6d1e4fb7f37a source.list
--- a/source.list	Sun Dec 27 18:45:17 2009 +0000
+++ b/source.list	Mon Dec 28 19:19:10 2009 +0100
@@ -31,6 +31,7 @@
 gfxinit.cpp
 heightmap.cpp
 highscore.cpp
+infrastructure.cpp
 ini.cpp
 landscape.cpp
 map.cpp
@@ -177,6 +178,7 @@
 industry.h
 industry_type.h
 industrytype.h
+infrastructure_func.h
 ini_type.h
 landscape.h
 landscape_type.h
diff -r 6d1e4fb7f37a src/aircraft_cmd.cpp
--- a/src/aircraft_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/aircraft_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -35,6 +35,7 @@
 #include "effectvehicle_func.h"
 #include "station_base.h"
 #include "cargotype.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -113,7 +114,7 @@
 	const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
 
 	FOR_ALL_STATIONS(st) {
-		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
+		if (!IsInfraUsageAllowed(st->owner, v->owner, VEH_AIRCRAFT) || !(st->facilities & FACIL_AIRPORT)) continue;
 
 		const AirportFTAClass *afc = st->Airport();
 		if (afc->nof_depots == 0 || (
@@ -144,7 +145,7 @@
 
 	FOR_VEHICLE_ORDERS(v, order) {
 		const Station *st = Station::Get(order->station);
-		if (st->owner == v->owner && (st->facilities & FACIL_AIRPORT)) {
+		if (IsInfraUsageAllowed(st->owner, v->owner, VEH_AIRCRAFT) && (st->facilities & FACIL_AIRPORT)) {
 			/* If an airport doesn't have a hangar, skip it */
 			if (st->Airport()->nof_depots != 0)
 				return true;
@@ -247,7 +248,7 @@
 	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
 	if (flags & DC_QUERY_COST) return value;
 
-	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsHangarTile(tile) || !CheckInfraUsageAllowed(GetTileOwner(tile), VEH_AIRCRAFT)) return CMD_ERROR;
 
 	/* Prevent building aircraft types at places which can't handle them */
 	if (!CanVehicleUseStation(p1, Station::GetByTile(tile))) return CMD_ERROR;
@@ -1533,7 +1534,7 @@
 	/* runway busy or not allowed to use this airstation, circle */
 	if ((apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES)) &&
 			st->airport_tile != INVALID_TILE &&
-			(st->owner == OWNER_NONE || st->owner == v->owner)) {
+			IsInfraUsageAllowed(st->owner, v->owner, VEH_AIRCRAFT)) {
 		/* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
 		 * if it is an airplane, look for LANDING, for helicopter HELILANDING
 		 * it is possible to choose from multiple landing runways, so loop until a free one is found */
diff -r 6d1e4fb7f37a src/depot_gui.cpp
--- a/src/depot_gui.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/depot_gui.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -29,6 +29,7 @@
 #include "tilehighlight_func.h"
 #include "window_gui.h"
 #include "vehiclelist.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -696,7 +697,7 @@
 
 		/* Setup disabled buttons. */
 		TileIndex tile = this->window_number;
-		this->SetWidgetsDisabledState(!IsTileOwner(tile, _local_company),
+		this->SetWidgetsDisabledState(!IsInfraTileUsageAllowed(tile, _local_company, this->type),
 			DEPOT_WIDGET_STOP_ALL,
 			DEPOT_WIDGET_START_ALL,
 			DEPOT_WIDGET_SELL,
diff -r 6d1e4fb7f37a src/economy.cpp
--- a/src/economy.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/economy.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -46,6 +46,7 @@
 #include "waypoint_base.h"
 #include "economy_base.h"
 #include "core/pool_func.hpp"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -366,7 +367,8 @@
 		ClrBit(t->have_ratings, old_owner);
 	}
 
-	{
+	/* Change ownership of vehicles */
+	if (new_owner != INVALID_OWNER) {
 		FreeUnitIDGenerator unitidgen[] = {
 			FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD,     new_owner),
 			FreeUnitIDGenerator(VEH_SHIP,  new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
@@ -375,16 +377,16 @@
 		Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
 			if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
-				if (new_owner == INVALID_OWNER) {
-					if (v->Previous() == NULL) delete v;
-				} else {
-					v->owner = new_owner;
-					v->colourmap = PAL_NONE;
-					if (v->IsEngineCountable()) Company::Get(new_owner)->num_engines[v->engine_type]++;
-					if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
-				}
+				v->owner = new_owner;
+				v->colourmap = PAL_NONE;
+				if (v->IsEngineCountable()) Company::Get(new_owner)->num_engines[v->engine_type]++;
+				if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
 			}
 		}
+	} else {
+		/* Depending on sharing settings, other companies could be affected too.
+		 * Let the infrastructure sharing code handle this. */
+		HandleSharingCompanyDeletion(old_owner);
 	}
 
 	/*  Change ownership of tiles */
@@ -399,23 +401,12 @@
 			 * and signals were not propagated
 			 * Similiar with crossings - it is needed to bar crossings that weren't before
 			 * because of different owner of crossing and approaching train */
-			tile = 0;
-
-			do {
-				if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
-					TrackBits tracks = GetTrackBits(tile);
-					do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
-						Track track = RemoveFirstTrack(&tracks);
-						if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
-					} while (tracks != TRACK_BIT_NONE);
-				} else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
-					UpdateLevelCrossing(tile);
-				}
-			} while (++tile != MapSize());
+			UpdateAllBlockSignals(new_owner);
+		} else if (_settings_game.sharing.sharing_rail) {
+			/* tracks are being removed while sharing is enabled.
+			 * Thus, update all signals and crossings. */
+			UpdateAllBlockSignals();
 		}
-
-		/* update signals in buffer */
-		UpdateSignalsInBuffer();
 	}
 
 	/* convert owner of stations (including deleted ones, but excluding buoys) */
diff -r 6d1e4fb7f37a src/infrastructure.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/infrastructure.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -0,0 +1,335 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file infrastructure.cpp Implementation of infrastructure sharing */
+
+#include "stdafx.h"
+#include "infrastructure_func.h"
+#include "train.h"
+#include "aircraft.h"
+#include "vehicle_func.h"
+#include "station_base.h"
+#include "depot_base.h"
+#include "pbs.h"
+#include "signal_func.h"
+#include "window_func.h"
+#include "gui.h"
+#include "pathfinder/yapf/yapf_cache.h"
+
+#include "table/strings.h"
+
+/**
+ * Helper function for transferring sharing fees
+ * @param v The vehicle involved
+ * @param infra_owner The owner of the infrastructure
+ * @param cost Amount to transfer as money fraction (shifted 8 bits to the left)
+ */
+static void PaySharingFee(Vehicle *v, Owner infra_owner, Money cost)
+{
+	Company *c = Company::Get(v->owner);
+	if (!_settings_game.sharing.payment_in_debt) {
+		/* Do not allow fee payment to drop (money - loan) below 0. */
+		cost = min(cost, (c->money - c->current_loan) << 8);
+		if (cost <= 0) return;
+	}
+	v->profit_this_year -= cost;
+	SubtractMoneyFromCompanyFract(v->owner, CommandCost(v->GetExpenseType(false), cost));
+	SubtractMoneyFromCompanyFract(infra_owner, CommandCost(v->GetExpenseType(true), -cost));
+}
+
+/**
+ * Pay the fee for spending a single tick inside a station.
+ * @param v The vehicle that is using the station.
+ * @param st The station that it uses.
+ */
+void PayStationSharingFee(Vehicle *v, const Station *st)
+{
+	if (v->owner == st->owner || st->owner == OWNER_NONE || v->type == VEH_TRAIN) return;
+	Money cost;
+	switch (v->type) {
+		case VEH_ROAD:     cost = _settings_game.sharing.fee_road;  break;
+		case VEH_SHIP:     cost = _settings_game.sharing.fee_water; break;
+		case VEH_AIRCRAFT: cost = _settings_game.sharing.fee_air;   break;
+		default: NOT_REACHED();
+	}
+	PaySharingFee(v, st->owner, (cost << 8) / DAY_TICKS);
+}
+
+/**
+ * Pay the daily fee for trains on foreign tracks.
+ * @param v The vehicle to pay the fee for.
+ */
+void PayDailyTrackSharingFee(Train *v)
+{
+	Owner owner = GetTileOwner(v->tile);
+	if (owner == v->owner) return;
+	Money cost = _settings_game.sharing.fee_rail << 8;
+	/* Cost is calculated per 1000 tonnes */
+	cost = cost * v->tcache.cached_weight / 1000;
+	/* Only pay the required fraction */
+	cost = cost * v->running_ticks / DAY_TICKS;
+	if (cost != 0) PaySharingFee(v, owner, cost);
+}
+
+/**
+ * Check whether a vehicle is in an allowed position.
+ * @param v     The vehicle to check.
+ * @param owner Owner whose infrastructure is not allowed, because the company will be removed. Ignored if INVALID_OWNER.
+ * @return      True if the vehicle is compeletely in an allowed position.
+ */
+static bool VehiclePositionIsAllowed(const Vehicle *v, Owner owner = INVALID_OWNER)
+{
+	switch (v->type) {
+		case VEH_TRAIN:
+			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+				if (!IsInfraUsageAllowed(GetTileOwner(u->tile), v->owner, VEH_TRAIN) || GetTileOwner(u->tile) == owner) return false;
+			}
+			return true;
+		case VEH_ROAD:
+			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+				if (IsRoadDepotTile(u->tile) || IsStandardRoadStopTile(u->tile)) {
+					if (!IsInfraUsageAllowed(GetTileOwner(u->tile), v->owner, VEH_ROAD) || GetTileOwner(u->tile) == owner) return false;
+				}
+			}
+			return true;
+		case VEH_SHIP:
+			if (IsShipDepotTile(v->tile) && v->IsStoppedInDepot()) {
+				return IsInfraUsageAllowed(GetTileOwner(v->tile), v->owner, VEH_SHIP) && GetTileOwner(v->tile) != owner;
+			}
+			return true;
+		case VEH_AIRCRAFT: {
+			const Aircraft *a = Aircraft::From(v);
+			if (a->state != FLYING && Station::IsValidID(a->targetairport)) {
+				Owner station_owner = Station::Get(a->targetairport)->owner;
+				return IsInfraUsageAllowed(station_owner, a->owner, VEH_AIRCRAFT) && station_owner != owner;
+			}
+			return true;
+		}
+		default: return true;
+	}
+}
+
+/**
+ * Check whether an order has a destination that is allowed.
+ * I.e. it refers to a station/depot/waypoint the vehicle is allowed to visit.
+ * @param order The order to check
+ * @param v     The vehicle this order belongs to.
+ * @param owner Owner whose infrastructure is not allowed, because the company will be removed. Ignored if INVALID_OWNER.
+ * @return      True if the order has an allowed destination.
+ */
+static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owner owner = INVALID_OWNER)
+{
+	Owner dest_owner;
+	switch (order->GetType()) {
+		case OT_GOTO_STATION:
+		case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
+		case OT_GOTO_DEPOT:    dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
+		case OT_LOADING:       dest_owner = Station::Get(v->last_station_visited)->owner; break;
+		default: return true;
+	}
+	return dest_owner != owner && IsInfraUsageAllowed(dest_owner, v->owner, v->type);
+}
+
+/**
+ * Sell a vehicle, no matter where it may be.
+ * @param v The vehicle to sell
+ * @param give_money Do we actually need to give money to the vehicle owner?
+ */
+static void RemoveAndSellVehicle(Vehicle *v, bool give_money)
+{
+	assert(v->Previous() == NULL);
+
+	if (give_money) {
+		/* compute total value and give that to the owner */
+		Money value = 0;
+		for (Vehicle *u = v->First(); u != NULL; u = u->Next()) {
+			value += v->value;
+		}
+		CompanyID old = _current_company;
+		_current_company = v->owner;
+		SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -value));
+		_current_company = old;
+	}
+
+	/* take special measures for trains, but not when sharing is disabled or when the train is a free wagon chain */
+	if (_settings_game.sharing.sharing_rail && v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
+ 		DeleteVisibleTrain(Train::From(v));
+	} else {
+		delete v;
+	}
+}
+
+/**
+ * Check all path reservations, and reserve a new path if the current path is invalid.
+ */
+static void FixAllReservations()
+{
+	/* if this function is called, we can safely assume that sharing of rails is being switched off */
+	assert(!_settings_game.sharing.sharing_rail);
+	Train *v;
+	FOR_ALL_TRAINS(v) {
+		if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) continue;
+		/* It might happen that the train reserved additional tracks,
+		 * but FollowTrainReservation can't detect those because they are no longer reachable.
+		 * detect this by first finding the end of the reservation,
+		 * then switch sharing on and try again. If these two ends differ,
+		 * unreserve the path, switch sharing off and try to reserve a new path */
+		PBSTileInfo end_tile_info = FollowTrainReservation(v);
+
+		/* first do a quick test to determine whether the next tile has any reservation at all */
+		TileIndex next_tile = end_tile_info.tile + TileOffsByDiagDir(TrackdirToExitdir(end_tile_info.trackdir));
+		/* If the next tile doesn't have a reservation at all, the reservation surely ends here. Thus all is well */
+		if (GetReservedTrackbits(next_tile) == TRACK_BIT_NONE) continue;
+
+		/* change sharing setting temporarily */
+		_settings_game.sharing.sharing_rail = true;
+		PBSTileInfo end_tile_info2 = FollowTrainReservation(v);
+		/* if these two reservation ends differ, unreserve the path and try to reserve a new path */
+		if (end_tile_info.tile != end_tile_info2.tile || end_tile_info.trackdir != end_tile_info2.trackdir) {
+			FreeTrainTrackReservation(v);
+			_settings_game.sharing.sharing_rail = false;
+			TryPathReserve(v, true);
+		} else {
+			_settings_game.sharing.sharing_rail = false;
+		}
+	}
+}
+
+/**
+ * Check if a sharing change is possible.
+ * If vehicles are still on others' infrastructure or using others' stations,
+ * The change is not possible and false is returned.
+ * @param type The type of vehicle whose setting will be changed.
+ * @return True if the change can take place, false otherwise.
+ */
+bool CheckSharingChangePossible(VehicleType type)
+{
+	if (type != VEH_AIRCRAFT) YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
+	/* Only do something when sharing is being disabled */
+	if (GetSharingSetting(type)) return true;
+
+	StringID error_message = STR_NULL;
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		if (type != v->type) continue;
+		if (v->Previous() != NULL) continue;
+
+		/* Check vehicle positiion */
+		if (!VehiclePositionIsAllowed(v)) {
+			error_message = STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES;
+			/* Break immediately, this error message takes precedence over the others. */
+			break;
+		}
+
+		/* Check current order */
+		if (!OrderDestinationIsAllowed(&v->current_order, v)) {
+			error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
+		}
+
+		/* Check order list */
+		if (v->FirstShared() != v) continue;
+		Order *o;
+		FOR_VEHICLE_ORDERS(v, o) {
+			if (!OrderDestinationIsAllowed(o, v)) {
+				error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
+			}
+		}
+	}
+
+	if (error_message != STR_NULL) {
+		ShowErrorMessage(error_message, INVALID_STRING_ID, 0, 0);
+		return false;
+	}
+
+	if (type == VEH_TRAIN) FixAllReservations();
+
+	return true;
+}
+
+/**
+ * Handle the removal (through reset_company or bankruptcy) of a company.
+ * i.e. remove all vehicles owned by that company or on its infrastructure,
+ * and delete all now-invalid orders.
+ * @param Owner the company to be removed.
+ */
+void HandleSharingCompanyDeletion(Owner owner)
+{
+	YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
+
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		if (!IsCompanyBuildableVehicleType(v) || v->Previous() != NULL) continue;
+		/* vehicle position */
+		if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
+			RemoveAndSellVehicle(v, v->owner != owner);
+			continue;
+		}
+		/* current order */
+		if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
+			if (v->current_order.IsType(OT_LOADING)) {
+				v->LeaveStation();
+			} else {
+				v->current_order.MakeDummy();
+			}
+			SetWindowDirty(WC_VEHICLE_VIEW, v->index);
+		}
+
+		/* order list */
+		if (v->FirstShared() != v) continue;
+
+		Order *o;
+		int id = -1;
+		FOR_VEHICLE_ORDERS(v, o) {
+			id++;
+			if (OrderDestinationIsAllowed(o, v, owner)) continue;
+
+			o->MakeDummy();
+			for (const Vehicle *w = v; w != NULL; w = w->NextShared()) {
+				/* In GUI, simulate by removing the order and adding it back */
+				InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
+				InvalidateVehicleOrder(w, (id << 8) | INVALID_VEH_ORDER_ID);
+			}
+		}
+	}
+}
+
+/**
+ * Update all block signals on the map.
+ * To be called after the setting for sharing of rails changes.
+ * @param owner Owner whose signals to update. If INVALID_OWNER, update everything.
+ */
+void UpdateAllBlockSignals(Owner owner)
+{
+	Owner last_owner = INVALID_OWNER;
+	TileIndex tile = 0;
+	do {
+		if (IsTileType(tile, MP_RAILWAY) && HasSignals(tile)) {
+			Owner track_owner = GetTileOwner(tile);
+			if (owner != INVALID_OWNER && track_owner != owner) continue;
+
+			if (!IsOneSignalBlock(track_owner, last_owner)) {
+				/* Cannot update signals of two different companies in one run,
+				 * if these signal blocks are not joined */
+				UpdateSignalsInBuffer();
+				last_owner = track_owner;
+			}
+			TrackBits bits = GetTrackBits(tile);
+			do {
+				Track track = RemoveFirstTrack(&bits);
+				if (HasSignalOnTrack(tile, track)) {
+					AddTrackToSignalBuffer(tile, track, track_owner);
+				}
+			} while (bits != TRACK_BIT_NONE);
+		} else if (IsLevelCrossingTile(tile) && (owner == INVALID_OWNER || GetTileOwner(owner) == owner)) {
+			UpdateLevelCrossing(tile);
+		}
+	} while (++tile != MapSize());
+
+	UpdateSignalsInBuffer();
+}
diff -r 6d1e4fb7f37a src/infrastructure_func.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/infrastructure_func.h	Mon Dec 28 19:19:10 2009 +0100
@@ -0,0 +1,115 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file infrastructure_func.h Functions for infrastructure sharing */
+
+#ifndef INFRASTRUCTURE_FUNC_H
+#define INFRASTRUCTURE_FUNC_H
+
+#include "vehicle_base.h"
+#include "functions.h"
+#include "company_func.h"
+
+void PayStationSharingFee(Vehicle *v, const Station *st);
+void PayDailyTrackSharingFee(Train *v);
+bool CheckSharingChangePossible(VehicleType type);
+void HandleSharingCompanyDeletion(Owner owner);
+void UpdateAllBlockSignals(Owner owner = INVALID_OWNER);
+
+/**
+ * Get the value of the sharing setting for a vehicle type.
+ * @param type The type of vehicle.
+ * @return     True if sharing is enabled for the given vehicle type.
+ */
+static FORCEINLINE bool GetSharingSetting(VehicleType type)
+{
+	switch (type) {
+		case VEH_TRAIN:    return _settings_game.sharing.sharing_rail;
+		case VEH_ROAD:     return _settings_game.sharing.sharing_road;
+		case VEH_SHIP:     return _settings_game.sharing.sharing_water;
+		case VEH_AIRCRAFT: return _settings_game.sharing.sharing_air;
+		default: NOT_REACHED();
+	}
+}
+
+/**
+ * Check whether a vehicle of a given owner and type can use the infrastrucutre of a given company.
+ * @param infra_owner The owner of the infrastructure.
+ * @param veh_owner   Owner of the vehicle in question.
+ * @param type        Type of vehicle we are talking about.
+ * @return            True if infrastructure usage is allowed, false otherwise.
+ */
+static FORCEINLINE bool IsInfraUsageAllowed(Owner infra_owner, Owner veh_owner, VehicleType type)
+{
+	return infra_owner == veh_owner || infra_owner == OWNER_NONE || GetSharingSetting(type);
+}
+
+/**
+ * Check whether a vehicle of a given owner and type can use the infrastrucutre on a given tile.
+ * @param infra_owner The tile that may or may not be used.
+ * @param veh_owner   Owner of the vehicle in question.
+ * @param type        Type of vehicle we are talking about.
+ * @return            True if infrastructure usage is allowed, false otherwise.
+ */
+static FORCEINLINE bool IsInfraTileUsageAllowed(TileIndex tile, Owner veh_owner, VehicleType type)
+{
+	return IsInfraUsageAllowed(GetTileOwner(tile), veh_owner, type);
+}
+
+/**
+ * Is a vehicle owned by _current_company allowed to use the infrastructure of infra_owner?
+ * @see IsInfraUsageAllowed
+ * @note This function is to be called from DoCommands.
+ * @param infra_owner Owner of the infrastructure.
+ * @param type        Type of vehicle.
+ * @return            True if infrastructure usage is allowed, false otherwise.
+ */
+static FORCEINLINE bool CheckInfraUsageAllowed(Owner infra_owner, VehicleType type)
+{
+	return infra_owner == OWNER_NONE || GetSharingSetting(type) || CheckOwnership(infra_owner);
+}
+
+/**
+ * Check whether a given company can control this vehicle.
+ * Controlling a vehicle means permission to start, stop or reverse it or to make it ignore signals.
+ * @param v The vehicle which may or may not be controlled.
+ * @param o The company which may or may not control this vehicle.
+ * @return  True if the given company is allowed to control this vehicle.
+ */
+static FORCEINLINE bool IsVehicleControlAllowed(const Vehicle *v, Owner o)
+{
+	return v->owner == o || (v->type == VEH_TRAIN && IsTileOwner(v->tile, o));
+}
+
+/**
+ * Check whether _current_company can control this vehicle.
+ * @note This function is to be called from DoCommands.
+ * @see IsVehicleControlAllowed
+ * @param v The vehicle which may or may not be controlled.
+ * @return  True if _current_company is allowed to control this vehicle.
+ */
+static FORCEINLINE bool CheckVehicleControlAllowed(const Vehicle *v)
+{
+	return (v->type == VEH_TRAIN && IsTileOwner(v->tile, _current_company)) || CheckOwnership(v->owner);
+}
+
+/**
+ * Do signal states propagate from the tracks of one owner to the other?
+ * @note This function should be consistent, so if it returns true for (a, b) and (b, c),
+ * it should also return true for (a, c).
+ * @param o1 First track owner.
+ * @param o2 Second track owner.
+ * @return   True if tracks of the two owners are part of the same signal block.
+ */
+static FORCEINLINE bool IsOneSignalBlock(Owner o1, Owner o2)
+{
+	return o1 == o2 || _settings_game.sharing.sharing_rail;
+}
+
+#endif /* INFRASTRUCTURE_FUNC_H */
diff -r 6d1e4fb7f37a src/lang/english.txt
--- a/src/lang/english.txt	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/lang/english.txt	Mon Dec 28 19:19:10 2009 +0100
@@ -1220,6 +1220,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}Allow AIs in multiplayer: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}#opcodes before AI is suspended: {ORANGE}{STRING1}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Enable sharing of railways: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Enable sharing of road stops and depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Enable sharing of docks and ship depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Enable sharing of airports: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Daily track toll for trains: {ORANGE}{STRING1} per 1000 tonnes
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Stopping fee for road vehicles: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Docking fee for ships: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Terminal fee for aircraft: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Allow companies in debt to pay sharing fees: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Can't change this setting, vehicles are using shared infrastructure.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Can't change this setting, vehicles have orders to destinations of others.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Service intervals are in percents: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Default service interval for trains: {ORANGE}{STRING1} days/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Default service interval for trains: {ORANGE}disabled
@@ -1297,6 +1309,7 @@
 STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS                         :{ORANGE}Signals
 STR_CONFIG_SETTING_STATIONS_CARGOHANDLING                       :{ORANGE}Cargo handling
 STR_CONFIG_SETTING_AI_NPC                                       :{ORANGE}Computer players
+STR_CONFIG_SETTING_SHARING                                      :{ORANGE}Infrastructure sharing
 STR_CONFIG_SETTING_VEHICLES_AUTORENEW                           :{ORANGE}Autorenew
 STR_CONFIG_SETTING_VEHICLES_SERVICING                           :{ORANGE}Servicing
 STR_CONFIG_SETTING_VEHICLES_ROUTING                             :{ORANGE}Routing
diff -r 6d1e4fb7f37a src/order_cmd.cpp
--- a/src/order_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/order_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -27,6 +27,7 @@
 #include "station_base.h"
 #include "waypoint_base.h"
 #include "roadstop_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -464,7 +465,7 @@
 			const Station *st = Station::GetIfValid(new_order.GetDestination());
 			if (st == NULL) return CMD_ERROR;
 
-			if (st->owner != OWNER_NONE && !CheckOwnership(st->owner)) return CMD_ERROR;
+			if (!CheckInfraUsageAllowed(st->owner, v->type)) return CMD_ERROR;
 
 			if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
 			for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
@@ -508,7 +509,7 @@
 				if (v->type == VEH_AIRCRAFT) {
 					const Station *st = Station::GetIfValid(new_order.GetDestination());
 
-					if (st == NULL || !CheckOwnership(st->owner) ||
+					if (st == NULL || !CheckInfraUsageAllowed(st->owner, v->type) ||
 							!CanVehicleUseStation(v, st) ||
 							st->Airport()->nof_depots == 0) {
 						return CMD_ERROR;
@@ -516,7 +517,7 @@
 				} else {
 					const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
 
-					if (dp == NULL || !CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
+					if (dp == NULL || !CheckInfraUsageAllowed(GetTileOwner(dp->xy), v->type)) return CMD_ERROR;
 
 					switch (v->type) {
 						case VEH_TRAIN:
@@ -554,14 +555,13 @@
 
 				case VEH_TRAIN:
 					if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
-					if (!CheckOwnership(wp->owner)) return CMD_ERROR;
 					break;
 
 				case VEH_SHIP:
 					if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
-					if (!CheckOwnership(wp->owner) && wp->owner != OWNER_NONE) return CMD_ERROR;
 					break;
 			}
+			if (!CheckInfraUsageAllowed(wp->owner, v->type)) return CMD_ERROR;
 
 			/* Order flags can be any of the following for waypoints:
 			 * [non-stop]
diff -r 6d1e4fb7f37a src/order_gui.cpp
--- a/src/order_gui.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/order_gui.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -31,6 +31,7 @@
 #include "network/network.h"
 #include "station_base.h"
 #include "waypoint_base.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -316,7 +317,7 @@
 	if (_settings_game.order.gotodepot) {
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY:
-				if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_company)) {
+				if (v->type == VEH_TRAIN && IsInfraTileUsageAllowed(tile, v->owner, VEH_TRAIN)) {
 					if (IsRailDepot(tile)) {
 						order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
 								_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
@@ -327,7 +328,7 @@
 				break;
 
 			case MP_ROAD:
-				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_company)) {
+				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsInfraTileUsageAllowed(tile, v->owner, VEH_ROAD)) {
 					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
 							_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
@@ -337,7 +338,7 @@
 
 			case MP_STATION:
 				if (v->type != VEH_AIRCRAFT) break;
-				if (IsHangar(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsHangar(tile) && IsInfraTileUsageAllowed(tile, v->owner, VEH_AIRCRAFT)) {
 					order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
@@ -346,7 +347,7 @@
 
 			case MP_WATER:
 				if (v->type != VEH_SHIP) break;
-				if (IsShipDepot(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsShipDepot(tile) && IsInfraTileUsageAllowed(tile, v->owner, VEH_SHIP)) {
 					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
@@ -360,7 +361,7 @@
 	/* check waypoint */
 	if (IsRailWaypointTile(tile) &&
 			v->type == VEH_TRAIN &&
-			IsTileOwner(tile, _local_company)) {
+			IsInfraTileUsageAllowed(tile, v->owner, VEH_TRAIN)) {
 		order.MakeGoToWaypoint(Waypoint::GetByTile(tile)->index);
 		if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
 		return order;
@@ -375,7 +376,7 @@
 		StationID st_index = GetStationIndex(tile);
 		const Station *st = Station::Get(st_index);
 
-		if (st->owner == _local_company || st->owner == OWNER_NONE) {
+		if (IsInfraUsageAllowed(st->owner, v->owner, v->type)) {
 			byte facil;
 			(facil = FACIL_DOCK, v->type == VEH_SHIP) ||
 			(facil = FACIL_TRAIN, v->type == VEH_TRAIN) ||
diff -r 6d1e4fb7f37a src/os/windows/ottdres.rc.in
--- a/src/os/windows/ottdres.rc.in	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/os/windows/ottdres.rc.in	Mon Dec 28 19:19:10 2009 +0100
@@ -79,8 +79,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,!!REVISION!!
- PRODUCTVERSION 1,0,0,!!REVISION!!
+ FILEVERSION 1,0,0,18637
+ PRODUCTVERSION 1,0,0,18637
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -98,14 +98,14 @@
             VALUE "Comments", "This program is licensed under the GNU General Public License version 2.\0"
             VALUE "CompanyName", "OpenTTD Development Team\0"
             VALUE "FileDescription", "OpenTTD\0"
-            VALUE "FileVersion", "Development !!VERSION!!\0"
+            VALUE "FileVersion", "Development IS2.1\0"
             VALUE "InternalName", "openttd\0"
             VALUE "LegalCopyright", "Copyright \xA9 OpenTTD Developers 2002-2009. All Rights Reserved.\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "openttd.exe\0"
             VALUE "PrivateBuild", "\0"
             VALUE "ProductName", "OpenTTD\0"
-            VALUE "ProductVersion", "Development !!VERSION!!\0"
+            VALUE "ProductVersion", "Development IS2.1\0"
             VALUE "SpecialBuild", "-\0"
         END
     END
diff -r 6d1e4fb7f37a src/pathfinder/follow_track.hpp
--- a/src/pathfinder/follow_track.hpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/pathfinder/follow_track.hpp	Mon Dec 28 19:19:10 2009 +0100
@@ -19,6 +19,7 @@
 #include "../train.h"
 #include "../tunnelbridge.h"
 #include "../tunnelbridge_map.h"
+#include "../infrastructure_func.h"
 #include "pf_performance_timer.hpp"
 
 /** Track follower helper template class (can serve pathfinders and vehicle
@@ -283,6 +284,11 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
+			/* road stops shouldn't be entered unless allowed to */
+			if (!IsInfraTileUsageAllowed(m_new_tile, m_veh_owner, VEH_ROAD)) {
+				m_err = EC_OWNER;
+				return false;
+			}
 		}
 
 		/* single tram bits can only be entered from one direction */
@@ -301,8 +307,8 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
-			/* don't try to enter other company's depots */
-			if (GetTileOwner(m_new_tile) != m_veh_owner) {
+			/* don't try to enter other company's depots if not allowed */
+			if (!IsInfraTileUsageAllowed(m_new_tile, m_veh_owner, VEH_ROAD)) {
 				m_err = EC_OWNER;
 				return false;
 			}
@@ -315,8 +321,8 @@
 			}
 		}
 
-		/* rail transport is possible only on tiles with the same owner as vehicle */
-		if (IsRailTT() && GetTileOwner(m_new_tile) != m_veh_owner) {
+		/* rail transport is possible only on tiles with the same owner as vehicle if sharing of tracks is disabled */
+		if (IsRailTT() && !IsInfraTileUsageAllowed(m_new_tile, m_veh_owner, VEH_TRAIN)) {
 			/* different owner */
 			m_err = EC_NO_WAY;
 			return false;
diff -r 6d1e4fb7f37a src/pathfinder/npf/npf.cpp
--- a/src/pathfinder/npf/npf.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/pathfinder/npf/npf.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -22,6 +22,7 @@
 #include "../../ship.h"
 #include "../../train.h"
 #include "../../roadstop_base.h"
+#include "../../infrastructure_func.h"
 #include "../pathfinder_func.h"
 #include "../pathfinder_type.h"
 #include "../follow_track.hpp"
@@ -674,25 +675,31 @@
  */
 static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
 {
-	if (IsTileType(tile, MP_RAILWAY) || // Rail tile (also rail depot)
-			HasStationTileRail(tile) ||     // Rail station tile/waypoint
-			IsRoadDepotTile(tile) ||        // Road depot tile
-			IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
-		return IsTileOwner(tile, owner);  // You need to own these tiles entirely to use them
-	}
+	switch (GetTileType(tile)) {
+		case MP_RAILWAY:
+			return IsInfraTileUsageAllowed(tile, owner, VEH_TRAIN); // Rail tile (also rail depot)
 
-	switch (GetTileType(tile)) {
 		case MP_ROAD:
 			/* rail-road crossing : are we looking at the railway part? */
 			if (IsLevelCrossing(tile) &&
 					DiagDirToAxis(enterdir) != GetCrossingRoadAxis(tile)) {
-				return IsTileOwner(tile, owner); // Railway needs owner check, while the street is public
+				return IsInfraTileUsageAllowed(tile, owner, VEH_TRAIN); // Railway needs owner check, while the street is public
+			} else if (IsRoadDepot(tile)) { // Road depot tile
+				return IsInfraTileUsageAllowed(tile, owner, VEH_ROAD);
+			}
+			break;
+
+		case MP_STATION:
+			if (HasStationRail(tile)) { // Rail station tile/waypoint
+				return IsInfraTileUsageAllowed(tile, owner, VEH_TRAIN);
+			} else if (IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
+				return IsInfraTileUsageAllowed(tile, owner, VEH_ROAD);
 			}
 			break;
 
 		case MP_TUNNELBRIDGE:
 			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
-				return IsTileOwner(tile, owner);
+				return IsInfraTileUsageAllowed(tile, owner, VEH_TRAIN);
 			}
 			break;
 
diff -r 6d1e4fb7f37a src/rev.cpp.in
--- a/src/rev.cpp.in	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/rev.cpp.in	Mon Dec 28 19:19:10 2009 +0100
@@ -27,7 +27,7 @@
  * norev000 is for non-releases that are made on systems without
  * subversion or sources that are not a checkout of subversion.
  */
-const char _openttd_revision[] = "!!VERSION!!";
+const char _openttd_revision[] = "IS2.1";
 
 /**
  * The text version of OpenTTD's build date.
@@ -60,11 +60,11 @@
  * final release will always have a lower version number than the released
  * version, thus making comparisions on specific revisions easy.
  */
-const uint32 _openttd_newgrf_version = 1 << 28 | 0 << 24 | 0 << 20 | 0 << 19 | (!!REVISION!! & ((1 << 19) - 1));
+const uint32 _openttd_newgrf_version = 1 << 28 | 0 << 24 | 0 << 20 | 0 << 19 | (18637 & ((1 << 19) - 1));
 
 #ifdef __MORPHOS__
 /**
  * Variable used by MorphOS to show the version.
  */
-extern const char morphos_versions_tag[] = "$VER: OpenTTD !!VERSION!! (!!DATE!!) OpenTTD Team [MorphOS, PowerPC]";
+extern const char morphos_versions_tag[] = "$VER: OpenTTD IS2.1 (!!DATE!!) OpenTTD Team [MorphOS, PowerPC]";
 #endif
diff -r 6d1e4fb7f37a src/roadveh_cmd.cpp
--- a/src/roadveh_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/roadveh_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -38,6 +38,7 @@
 #include "cargotype.h"
 #include "spritecache.h"
 #include "debug.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -209,7 +210,7 @@
 	/* The ai_new queries the vehicle cost before building the route,
 	 * so we must check against cheaters no sooner than now. --pasky */
 	if (!IsRoadDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!CheckInfraUsageAllowed(GetTileOwner(tile), VEH_ROAD)) return CMD_ERROR;
 
 	if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
 
@@ -414,7 +415,7 @@
 CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	RoadVehicle *v = RoadVehicle::GetIfValid(p1);
-	if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
+	if (v == NULL || !CheckVehicleControlAllowed(v)) return CMD_ERROR;
 
 	if ((v->vehstatus & VS_STOPPED) ||
 			(v->vehstatus & VS_CRASHED) ||
@@ -938,14 +939,14 @@
 	TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
 
 	if (IsTileType(tile, MP_ROAD)) {
-		if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
+		if (IsRoadDepot(tile) && (!IsInfraTileUsageAllowed(tile, v->owner, VEH_ROAD) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
 			/* Road depot owned by another company or with the wrong orientation */
 			trackdirs = TRACKDIR_BIT_NONE;
 		}
 	} else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
 		/* Standard road stop (drive-through stops are treated as normal road) */
 
-		if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
+		if (!IsInfraTileUsageAllowed(tile, v->owner, VEH_ROAD) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
 			/* different station owner or wrong orientation or the vehicle has articulated parts */
 			trackdirs = TRACKDIR_BIT_NONE;
 		} else {
@@ -1439,7 +1440,7 @@
 			/* In case an RV is stopped in a road stop, why not try to load? */
 			if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 					v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-					v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
+					IsInfraTileUsageAllowed(v->tile, v->owner, VEH_ROAD) && !v->current_order.IsType(OT_LEAVESTATION) &&
 					GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
 				Station *st = Station::GetByTile(v->tile);
 				v->last_station_visited = st->index;
@@ -1473,7 +1474,7 @@
 			_road_veh_data_1[v->state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->frame) ||
 			(IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 			v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-			v->owner == GetTileOwner(v->tile) &&
+			IsInfraTileUsageAllowed(v->tile, v->owner, VEH_ROAD) &&
 			GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
 			v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
diff -r 6d1e4fb7f37a src/saveload/saveload.cpp
--- a/src/saveload/saveload.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/saveload/saveload.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -47,7 +47,7 @@
 
 #include "saveload_internal.h"
 
-extern const uint16 SAVEGAME_VERSION = 132;
+extern const uint16 SAVEGAME_VERSION = 133;
 
 SavegameType _savegame_type; ///< type of savegame we are loading
 
diff -r 6d1e4fb7f37a src/settings.cpp
--- a/src/settings.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/settings.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -64,6 +64,7 @@
 
 #include "void_map.h"
 #include "station_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/settings.h"
@@ -983,6 +984,28 @@
 	return true;
 }
 
+static bool CheckSharingRail(int32 p1)
+{
+	if (!CheckSharingChangePossible(VEH_TRAIN)) return false;
+	UpdateAllBlockSignals();
+	return true;
+}
+
+static bool CheckSharingRoad(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_ROAD);
+}
+
+static bool CheckSharingWater(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_SHIP);
+}
+
+static bool CheckSharingAir(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_AIRCRAFT);
+}
+
 #ifdef ENABLE_NETWORK
 
 static bool UpdateClientName(int32 p1)
diff -r 6d1e4fb7f37a src/settings_gui.cpp
--- a/src/settings_gui.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/settings_gui.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -1387,8 +1387,23 @@
 /** Computer players sub-page */
 static SettingsPage _settings_ai_npc_page = {_settings_ai_npc, lengthof(_settings_ai_npc)};
 
+static SettingEntry _settings_sharing[] = {
+	SettingEntry("sharing.sharing_rail"),
+	SettingEntry("sharing.sharing_road"),
+	SettingEntry("sharing.sharing_water"),
+	SettingEntry("sharing.sharing_air"),
+	SettingEntry("sharing.fee_rail"),
+	SettingEntry("sharing.fee_road"),
+	SettingEntry("sharing.fee_water"),
+	SettingEntry("sharing.fee_air"),
+	SettingEntry("sharing.payment_in_debt"),
+};
+/** Infrastructure sharing sub-page */
+static SettingsPage _settings_sharing_page = {_settings_sharing, lengthof(_settings_sharing)};
+
 static SettingEntry _settings_ai[] = {
 	SettingEntry(&_settings_ai_npc_page, STR_CONFIG_SETTING_AI_NPC),
+	SettingEntry(&_settings_sharing_page, STR_CONFIG_SETTING_SHARING),
 	SettingEntry("economy.give_money"),
 	SettingEntry("economy.allow_shares"),
 };
diff -r 6d1e4fb7f37a src/settings_type.h
--- a/src/settings_type.h	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/settings_type.h	Mon Dec 28 19:19:10 2009 +0100
@@ -354,6 +354,19 @@
 	byte   station_spread;                   ///< amount a station may spread
 };
 
+/** Settings related to infrastructure sharing */
+struct SharingSettings {
+	bool   sharing_rail;                     ///< Enable infrastructure sharing for rails, including stations and depots
+	bool   sharing_road;                     ///< Enable infrastructure sharing for road stops and depots
+	bool   sharing_water;                    ///< Enable infrastructure sharing for docks and ship depots
+	bool   sharing_air;                      ///< Enable infrastructure sharing for airports
+	uint   fee_rail;                         ///< Track toll for trains
+	uint   fee_road;                         ///< Loading fee for road vehicles
+	uint   fee_water;                        ///< Loading fee for aircraft
+	uint   fee_air;                          ///< Loading fee for aircraft
+	bool   payment_in_debt;                  ///< Whether to allow fee payment for companies with more loan than money. Switch off to prevent MP exploits.
+};
+
 /** Default settings for vehicles. */
 struct VehicleDefaultSettings {
 	bool   servint_ispercent;                ///< service intervals are in percents
@@ -385,6 +398,7 @@
 	EconomySettings      economy;            ///< settings to change the economy
 	StationSettings      station;            ///< settings related to station management
 	LocaleSettings       locale;             ///< settings related to used currency/unit system in the current game
+	SharingSettings      sharing;            ///< settings related to infrastructure sharing
 };
 
 /** All settings that are only important for the local client. */
diff -r 6d1e4fb7f37a src/ship_cmd.cpp
--- a/src/ship_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/ship_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -36,6 +36,7 @@
 #include "ai/ai.hpp"
 #include "pathfinder/opf/opf_ship.h"
 #include "landscape_type.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -111,7 +112,7 @@
 
 	FOR_ALL_DEPOTS(depot) {
 		TileIndex tile = depot->xy;
-		if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
+		if (IsShipDepotTile(tile) && IsInfraTileUsageAllowed(tile, v->owner, VEH_SHIP)) {
 			uint dist = DistanceManhattan(tile, v->tile);
 			if (dist < best_dist) {
 				best_dist = dist;
@@ -623,7 +624,7 @@
 	/* The ai_new queries the vehicle cost before building the route,
 	 * so we must check against cheaters no sooner than now. --pasky */
 	if (!IsShipDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!CheckInfraUsageAllowed(GetTileOwner(tile), VEH_SHIP)) return CMD_ERROR;
 
 	unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_SHIP);
 
diff -r 6d1e4fb7f37a src/signal.cpp
--- a/src/signal.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/signal.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -16,6 +16,7 @@
 #include "vehicle_func.h"
 #include "functions.h"
 #include "train.h"
+#include "infrastructure_func.h"
 
 
 /** these are the maximums used for updating signal blocks */
@@ -278,7 +279,7 @@
 
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY: {
-				if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 
 				if (IsRailDepot(tile)) {
 					if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
@@ -351,7 +352,7 @@
 
 			case MP_STATION:
 				if (!HasStationRail(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
 				if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
 
@@ -361,7 +362,7 @@
 
 			case MP_ROAD:
 				if (!IsLevelCrossing(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
 
 				if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
@@ -369,7 +370,7 @@
 				break;
 
 			case MP_TUNNELBRIDGE: {
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
 				DiagDirection dir = GetTunnelBridgeDirection(tile);
 
@@ -583,8 +584,9 @@
 		DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
 	};
 
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
@@ -608,8 +610,9 @@
  */
 void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
 {
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
diff -r 6d1e4fb7f37a src/table/settings.h
--- a/src/table/settings.h	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/table/settings.h	Mon Dec 28 19:19:10 2009 +0100
@@ -34,6 +34,10 @@
 static bool ChangeDynamicEngines(int32 p1);
 static bool StationCatchmentChanged(int32 p1);
 static bool InvalidateVehTimetableWindow(int32 p1);
+static bool CheckSharingRail(int32 p1);
+static bool CheckSharingRoad(int32 p1);
+static bool CheckSharingWater(int32 p1);
+static bool CheckSharingAir(int32 p1);
 
 #ifdef ENABLE_NETWORK
 static bool UpdateClientName(int32 p1);
@@ -446,6 +450,16 @@
 	    SDT_BOOL(GameSettings, ai.ai_disable_veh_ship,                                              0, 0, false,                    STR_CONFIG_SETTING_AI_BUILDS_SHIPS,        NULL),
 	 SDT_CONDVAR(GameSettings, ai.ai_max_opcode_till_suspend,       SLE_UINT32,107, SL_MAX_VERSION, 0, NG, 10000, 5000,250000,2500, STR_CONFIG_SETTING_AI_MAX_OPCODES,         NULL),
 
+	SDT_CONDBOOL(GameSettings, sharing.sharing_rail,                           133, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_RAIL,           CheckSharingRail),
+	SDT_CONDBOOL(GameSettings, sharing.sharing_road,                           133, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_ROAD,           CheckSharingRoad),
+	SDT_CONDBOOL(GameSettings, sharing.sharing_water,                          133, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_WATER,          CheckSharingWater),
+	SDT_CONDBOOL(GameSettings, sharing.sharing_air,                            133, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_AIR,            CheckSharingAir),
+	 SDT_CONDVAR(GameSettings, sharing.fee_rail,                      SLE_UINT,133, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_RAIL,       NULL),
+	 SDT_CONDVAR(GameSettings, sharing.fee_road,                      SLE_UINT,133, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_ROAD,       NULL),
+	 SDT_CONDVAR(GameSettings, sharing.fee_water,                     SLE_UINT,133, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_WATER,      NULL),
+	 SDT_CONDVAR(GameSettings, sharing.fee_air,                       SLE_UINT,133, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_AIR,        NULL),
+	SDT_CONDBOOL(GameSettings, sharing.payment_in_debt,                        133, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT,NULL),
+
 	     SDT_VAR(GameSettings, vehicle.extend_vehicle_life,          SLE_UINT8,                     0, 0,     0,     0,     100, 0, STR_NULL,                                  NULL),
 	     SDT_VAR(GameSettings, economy.dist_local_authority,         SLE_UINT8,                     0, 0,    20,     5,      60, 0, STR_NULL,                                  NULL),
 	     SDT_VAR(GameSettings, pf.wait_oneway_signal,                SLE_UINT8,                     0, 0,    15,     2,     255, 0, STR_NULL,                                  NULL),
diff -r 6d1e4fb7f37a src/train.h
--- a/src/train.h	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/train.h	Mon Dec 28 19:19:10 2009 +0100
@@ -55,6 +55,8 @@
 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
 
+void DeleteVisibleTrain(Train *v);
+
 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
 
 void TrainConsistChanged(Train *v, bool same_length);
diff -r 6d1e4fb7f37a src/train_cmd.cpp
--- a/src/train_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/train_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -38,6 +38,7 @@
 #include "gamelog.h"
 #include "network/network.h"
 #include "spritecache.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/train_cmd.h"
@@ -850,7 +851,7 @@
 	/* Check if the train is actually being built in a depot belonging
 	 * to the company. Doesn't matter if only the cost is queried */
 	if (!IsRailDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!CheckInfraUsageAllowed(GetTileOwner(tile), VEH_TRAIN)) return CMD_ERROR;
 
 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags);
 
@@ -1971,7 +1972,7 @@
 CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	Train *v = Train::GetIfValid(p1);
-	if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
+	if (v == NULL || !CheckVehicleControlAllowed(v)) return CMD_ERROR;
 
 	if (p2 != 0) {
 		/* turn a single unit around */
@@ -2038,7 +2039,7 @@
 CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	Train *t = Train::GetIfValid(p1);
-	if (t == NULL || !CheckOwnership(t->owner)) return CMD_ERROR;
+	if (t == NULL || !CheckVehicleControlAllowed(t)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		/* If we are forced to proceed, cancel that order.
@@ -3082,7 +3083,7 @@
 static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
 {
 	return
-		IsTileOwner(tile, v->owner) && (
+		IsInfraTileUsageAllowed(tile, v->owner, VEH_TRAIN) && (
 			!v->IsFrontEngine() ||
 			HasBit(v->compatible_railtypes, GetRailType(tile))
 		);
@@ -4196,6 +4197,9 @@
 			/* running costs */
 			CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR  * DAY_TICKS));
 
+			/* sharing fee */
+			PayDailyTrackSharingFee(this);
+
 			this->profit_this_year -= cost.GetCost();
 			this->running_ticks = 0;
 
@@ -4226,3 +4230,45 @@
 
 	return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
 }
+
+/**
+ * Delete a train while it is visible.
+ * This happens when a company bankrupts when infrastructure sharing is enabled.
+ * @param v The train to delete.
+ */
+void DeleteVisibleTrain(Train *v)
+{
+	FreeTrainTrackReservation(v);
+	TileIndex crossing = TrainApproachingCrossingTile(v);
+
+	/* delete train from back to front */
+	Train *u;
+	Train *prev = v->Last();
+	do {
+		u = prev;
+		/* 'u' shouldn't be accessed after it has been deleted */
+		TileIndex tile = u->tile;
+		TrackBits trackbits = u->track;
+
+		prev = u->Previous();
+		delete u;
+
+		if (trackbits == TRACK_BIT_WORMHOLE) {
+			/* Vehicle is inside a wormhole, u->track contains no useful value then. */
+			trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile));
+		}
+
+		Track track = TrackBitsToTrack(trackbits);
+		if (HasReservedTracks(tile, trackbits)) UnreserveRailTrack(tile, track);
+		if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
+
+		/* Update signals */
+		if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
+			UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, GetTileOwner(tile));
+		} else {
+			SetSignalsOnBothDir(tile, track, GetTileOwner(tile));
+		}
+	} while (prev != NULL);
+
+	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
+}
diff -r 6d1e4fb7f37a src/vehicle.cpp
--- a/src/vehicle.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/vehicle.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -47,6 +47,7 @@
 #include "economy_base.h"
 #include "articulated_vehicles.h"
 #include "roadstop_base.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -1585,6 +1586,9 @@
 		case OT_LOADING: {
 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
 
+			/* Pay the loading fee for using someone else's station, if appropriate */
+			if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
+
 			/* Not the first call for this tick, or still loading */
 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
 					(_settings_game.order.timetabling && this->current_order_time < wait_time)) return;
diff -r 6d1e4fb7f37a src/vehicle_cmd.cpp
--- a/src/vehicle_cmd.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/vehicle_cmd.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -27,6 +27,7 @@
 #include "string_func.h"
 #include "depot_map.h"
 #include "vehiclelist.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -74,7 +75,7 @@
 	if ((flags & DC_AUTOREPLACE) == 0) SetBit(p2, 0);
 
 	Vehicle *v = Vehicle::GetIfValid(p1);
-	if (v == NULL || !CheckOwnership(v->owner) || !v->IsPrimaryVehicle()) return CMD_ERROR;
+	if (v == NULL || !CheckVehicleControlAllowed(v) || !v->IsPrimaryVehicle()) return CMD_ERROR;
 
 	switch (v->type) {
 		case VEH_TRAIN:
@@ -217,7 +218,7 @@
 	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 	bool all_or_nothing = HasBit(p2, 0);
 
-	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsDepotTile(tile) || !CheckInfraUsageAllowed(GetTileOwner(tile), vehicle_type)) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
 	BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
diff -r 6d1e4fb7f37a src/vehicle_gui.cpp
--- a/src/vehicle_gui.cpp	Sun Dec 27 18:45:17 2009 +0000
+++ b/src/vehicle_gui.cpp	Mon Dec 28 19:19:10 2009 +0100
@@ -40,6 +40,7 @@
 #include "articulated_vehicles.h"
 #include "cargotype.h"
 #include "spritecache.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -1954,6 +1955,7 @@
 	{
 		const Vehicle *v = Vehicle::Get(this->window_number);
 		bool is_localcompany = v->owner == _local_company;
+		bool can_control = IsVehicleControlAllowed(v, _local_company);
 		bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
 
 		this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localcompany);
@@ -1962,8 +1964,8 @@
 
 		if (v->type == VEH_TRAIN) {
 			this->SetWidgetLoweredState(VVW_WIDGET_FORCE_PROCEED, Train::From(v)->force_proceed == 2);
-			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localcompany);
-			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localcompany);
+			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !can_control);
+			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !can_control);
 		}
 
 		this->DrawWidgets();
