diff -r ee55d0546576 .hgtags
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgtags	Sat Apr 25 19:58:24 2009 +0200
@@ -0,0 +1,2 @@
+b40dd43fc1f27083cf2696c57ec6b907855fb007 2.0-beta1
+4cd407daac0d6fbaa012ef49eec43ffaf32bb207 2.0-beta2
diff -r ee55d0546576 config.lib
--- a/config.lib	Sat Apr 25 12:00:54 2009 +0000
+++ b/config.lib	Sat Apr 25 19:58:24 2009 +0200
@@ -5,7 +5,7 @@
 }
 
 set_default() {
-	released_version=""
+	released_version="IS2.0-beta2"
 
 	ignore_extra_parameters="0"
 	# We set all kinds of defaults for params. Later on the user can override
diff -r ee55d0546576 projects/determineversion.vbs
--- a/projects/determineversion.vbs	Sat Apr 25 12:00:54 2009 +0000
+++ b/projects/determineversion.vbs	Sat Apr 25 19:58:24 2009 +0200
@@ -32,6 +32,7 @@
 		modified = Mid(version, InStrRev(version, Chr(9)) + 1)
 		version  = Mid(version, 1, InStr(version, Chr(9)) - 1)
 	Else
+		version = "IS2.0-beta2"
 		revision = 0
 		modified = 1
 	End If
diff -r ee55d0546576 projects/openttd_vs80.vcproj
--- a/projects/openttd_vs80.vcproj	Sat Apr 25 12:00:54 2009 +0000
+++ b/projects/openttd_vs80.vcproj	Sat Apr 25 19:58:24 2009 +0200
@@ -576,6 +576,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1057,6 +1061,14 @@
 			</File>
 			<File
 				RelativePath=".\..\src\industry_type.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\infrastructure.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\infrastructure_func.h"
 				>
 			</File>
 			<File
diff -r ee55d0546576 projects/openttd_vs90.vcproj
--- a/projects/openttd_vs90.vcproj	Sat Apr 25 12:00:54 2009 +0000
+++ b/projects/openttd_vs90.vcproj	Sat Apr 25 19:58:24 2009 +0200
@@ -573,6 +573,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1054,6 +1058,14 @@
 			</File>
 			<File
 				RelativePath=".\..\src\industry_type.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\infrastructure.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\infrastructure_func.h"
 				>
 			</File>
 			<File
diff -r ee55d0546576 source.list
--- a/source.list	Sat Apr 25 12:00:54 2009 +0000
+++ b/source.list	Sat Apr 25 19:58:24 2009 +0200
@@ -31,6 +31,7 @@
 gfxinit.cpp
 heightmap.cpp
 highscore.cpp
+infrastructure.cpp
 ini.cpp
 landscape.cpp
 map.cpp
@@ -195,6 +196,8 @@
 highscore.h
 industry.h
 industry_type.h
+infrastructure.h
+infrastructure_func.h
 ini_type.h
 landscape.h
 landscape_type.h
diff -r ee55d0546576 src/aircraft_cmd.cpp
--- a/src/aircraft_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/aircraft_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -28,6 +28,7 @@
 #include "company_func.h"
 #include "effectvehicle_func.h"
 #include "settings_type.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -105,7 +106,7 @@
 	TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
 
 	FOR_ALL_STATIONS(st) {
-		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
+		if (!(st->facilities & FACIL_AIRPORT) || !IsStationUsageAllowed(st, v)) continue;
 
 		const AirportFTAClass *afc = st->Airport();
 		if (afc->nof_depots == 0 || (
@@ -137,7 +138,7 @@
 
 	FOR_VEHICLE_ORDERS(v, order) {
 		const Station *st = GetStation(order->station);
-		if (st->owner == v->owner && st->facilities & FACIL_AIRPORT) {
+		if (IsStationUsageAllowed(st, v) && st->facilities & FACIL_AIRPORT) {
 			/* If an airport doesn't have a hangar, skip it */
 			if (st->Airport()->nof_depots != 0)
 				return true;
@@ -260,7 +261,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 (!AreDepotOperationsAllowed(tile, _current_company, VEH_AIRCRAFT)) return CMD_ERROR;
 
 	/* Prevent building aircraft types at places which can't handle them */
 	if (!CanVehicleUseStation(p1, GetStationByTile(tile))) return CMD_ERROR;
@@ -1621,7 +1622,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)) {
+			IsStationUsageAllowed(st, v)) {
 		/* {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 ee55d0546576 src/command.cpp
--- a/src/command.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/command.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -191,6 +191,7 @@
 DEF_COMMAND(CmdChangeTimetable);
 DEF_COMMAND(CmdSetVehicleOnTime);
 DEF_COMMAND(CmdAutofillTimetable);
+DEF_COMMAND(CmdChangeSharingSetting);
 #undef DEF_COMMAND
 
 /**
@@ -335,6 +336,7 @@
 	{CmdChangeTimetable,                            0}, // CMD_CHANGE_TIMETABLE
 	{CmdSetVehicleOnTime,                           0}, // CMD_SET_VEHICLE_ON_TIME
 	{CmdAutofillTimetable,                          0}, // CMD_AUTOFILL_TIMETABLE
+	{CmdChangeSharingSetting,                       0}, // CMD_CHANGE_SHARING_SETTING
 };
 
 /*!
diff -r ee55d0546576 src/command_type.h
--- a/src/command_type.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/command_type.h	Sat Apr 25 19:58:24 2009 +0200
@@ -286,6 +286,7 @@
 	CMD_CHANGE_TIMETABLE,             ///< change the timetable for a vehicle
 	CMD_SET_VEHICLE_ON_TIME,          ///< set the vehicle on time feature (timetable)
 	CMD_AUTOFILL_TIMETABLE,           ///< autofill the timetable
+	CMD_CHANGE_SHARING_SETTING,       ///< change one of the settings for infrastructure sharing
 };
 
 /**
diff -r ee55d0546576 src/company_base.h
--- a/src/company_base.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/company_base.h	Sat Apr 25 19:58:24 2009 +0200
@@ -15,6 +15,7 @@
 #include "autoreplace_type.h"
 #include "economy_type.h"
 #include "tile_type.h"
+#include "infrastructure.h"
 
 struct CompanyEconomyEntry {
 	Money income;
@@ -84,6 +85,10 @@
 	uint32 engine_renew_money;
 	uint16 *num_engines; ///< caches the number of engines of each type the company owns (no need to save this)
 
+	byte sharing_delay;                           ///< number of months before new settings go in effect
+	CompanySharingSettingsEntry sharing_current;  ///< settings currently in effect
+	CompanySharingSettingsEntry sharing_future;   ///< future settings, will go in effect after (sharing_delay) months.
+
 	inline bool IsValid() const { return this->name_1 != 0; }
 };
 
diff -r ee55d0546576 src/company_cmd.cpp
--- a/src/company_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/company_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -173,12 +173,14 @@
 	if (HasBit(1 << EXPENSES_TRAIN_INC    |
 	           1 << EXPENSES_ROADVEH_INC  |
 	           1 << EXPENSES_AIRCRAFT_INC |
-	           1 << EXPENSES_SHIP_INC, cost.GetExpensesType())) {
+	           1 << EXPENSES_SHIP_INC     |
+	           1 << EXPENSES_SHARED_INC, cost.GetExpensesType())) {
 		c->cur_economy.income -= cost.GetCost();
 	} else if (HasBit(1 << EXPENSES_TRAIN_RUN    |
 	                  1 << EXPENSES_ROADVEH_RUN  |
 	                  1 << EXPENSES_AIRCRAFT_RUN |
 	                  1 << EXPENSES_SHIP_RUN     |
+	                  1 << EXPENSES_SHARED_RUN   |
 	                  1 << EXPENSES_PROPERTY     |
 	                  1 << EXPENSES_LOAN_INT, cost.GetExpensesType())) {
 		c->cur_economy.expenses -= cost.GetCost();
@@ -452,11 +454,29 @@
 	c->engine_renew_months = _settings_client.gui.autorenew_months;
 	c->engine_renew_money = _settings_client.gui.autorenew_money;
 
+	/* sharing settings */
+	c->sharing_current.CopyFromGameSettings();
+	c->sharing_future.CopyFromGameSettings();
+
+	if (!_settings_game.sharing.enable_sharing || _settings_game.sharing.individual_allowed) {
+		/* only allow own company */
+		c->sharing_current.allowed_companies = 1 << c->index;
+		c->sharing_future.allowed_companies  = 1 << c->index;
+	} else {
+		/* enable this company in all companies */
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			SetBit(c->sharing_current.allowed_companies, c->index);
+			SetBit(c->sharing_future.allowed_companies, c->index);
+		}
+	}
+
 	GeneratePresidentName(c);
 
 	InvalidateWindow(WC_GRAPH_LEGEND, 0);
 	InvalidateWindow(WC_TOOLBAR_MENU, 0);
 	InvalidateWindow(WC_CLIENT_LIST, 0);
+	InvalidateWindowClasses(WC_SHARING_OPTIONS);
 
 	if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
 
diff -r ee55d0546576 src/company_gui.cpp
--- a/src/company_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/company_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -24,6 +24,10 @@
 #include "widgets/dropdown_type.h"
 #include "tilehighlight_func.h"
 #include "settings_type.h"
+#include "currency.h"
+#include "openttd.h"
+#include "company_gui.h"
+#include "window_func.h"
 
 #include "table/strings.h"
 
@@ -33,9 +37,51 @@
 
 static void DoShowCompanyFinances(CompanyID company, bool show_small, bool show_stickied, int top = FIRST_GUI_CALL, int left = FIRST_GUI_CALL);
 static void DoSelectCompanyManagerFace(Window *parent, bool show_big, int top =  FIRST_GUI_CALL, int left = FIRST_GUI_CALL);
+static void ShowSharingSettingsWindow(CompanyID company);
 
-/** Standard unsorted list of expenses. */
+/** Standard unsorted list of expenses with infrastructure sharing enabled. */
 static ExpensesType _expenses_list_1[] = {
+	EXPENSES_CONSTRUCTION,
+	EXPENSES_NEW_VEHICLES,
+	EXPENSES_TRAIN_RUN,
+	EXPENSES_ROADVEH_RUN,
+	EXPENSES_AIRCRAFT_RUN,
+	EXPENSES_SHIP_RUN,
+	EXPENSES_SHARED_RUN,
+	EXPENSES_PROPERTY,
+	EXPENSES_TRAIN_INC,
+	EXPENSES_ROADVEH_INC,
+	EXPENSES_AIRCRAFT_INC,
+	EXPENSES_SHIP_INC,
+	EXPENSES_SHARED_INC,
+	EXPENSES_LOAN_INT,
+	EXPENSES_OTHER,
+};
+
+/** Grouped list of expenses with infrastructure sharing enabled. */
+static ExpensesType _expenses_list_2[] = {
+	EXPENSES_TRAIN_INC,
+	EXPENSES_ROADVEH_INC,
+	EXPENSES_AIRCRAFT_INC,
+	EXPENSES_SHIP_INC,
+	EXPENSES_SHARED_INC,
+	INVALID_EXPENSES,
+	EXPENSES_TRAIN_RUN,
+	EXPENSES_ROADVEH_RUN,
+	EXPENSES_AIRCRAFT_RUN,
+	EXPENSES_SHIP_RUN,
+	EXPENSES_SHARED_RUN,
+	EXPENSES_PROPERTY,
+	EXPENSES_LOAN_INT,
+	INVALID_EXPENSES,
+	EXPENSES_CONSTRUCTION,
+	EXPENSES_NEW_VEHICLES,
+	EXPENSES_OTHER,
+	INVALID_EXPENSES,
+};
+
+/** Standard unsorted list of expenses with infrastructure sharing disabled. */
+static ExpensesType _expenses_list_3[] = {
 	EXPENSES_CONSTRUCTION,
 	EXPENSES_NEW_VEHICLES,
 	EXPENSES_TRAIN_RUN,
@@ -51,8 +97,8 @@
 	EXPENSES_OTHER,
 };
 
-/** Grouped list of expenses. */
-static ExpensesType _expenses_list_2[] = {
+/** Grouped list of expenses with infrastructure sharing disabled. */
+static ExpensesType _expenses_list_4[] = {
 	EXPENSES_TRAIN_INC,
 	EXPENSES_ROADVEH_INC,
 	EXPENSES_AIRCRAFT_INC,
@@ -81,6 +127,8 @@
 static const ExpensesList _expenses_list_types[] = {
 	{ _expenses_list_1, lengthof(_expenses_list_1), lengthof(_expenses_list_1) * 10 },
 	{ _expenses_list_2, lengthof(_expenses_list_2), lengthof(_expenses_list_2) * 10 + 3 * 12 },
+	{ _expenses_list_3, lengthof(_expenses_list_3), lengthof(_expenses_list_3) * 10 },
+	{ _expenses_list_4, lengthof(_expenses_list_4), lengthof(_expenses_list_4) * 10 + 3 * 12 },
 };
 
 /** Widgets of the company finances windows. */
@@ -104,7 +152,7 @@
 
 static void DrawCompanyEconomyStats(const Company *c, bool small, const Widget *widget)
 {
-	int type = _settings_client.gui.expenses_layout;
+	int type = _settings_game.sharing.enable_sharing ? _settings_client.gui.expenses_layout : _settings_client.gui.expenses_layout + 2;
 	int y;
 	const Money (*tbl)[EXPENSES_END];
 	StringID str;
@@ -333,7 +381,7 @@
 		const Company *c = GetCompany(company);
 
 		if (!small) {
-			int type = _settings_client.gui.expenses_layout;
+			int type = _settings_game.sharing.enable_sharing ? _settings_client.gui.expenses_layout : _settings_client.gui.expenses_layout + 2;
 			if (this->widget[CFW_EXPS_PANEL].bottom < this->widget[CFW_EXPS_PANEL].top) {
 				this->widget[CFW_EXPS_PANEL].bottom = this->widget[CFW_EXPS_PANEL].top;
 			}
@@ -1394,6 +1442,7 @@
 	CW_WIDGET_RELOCATE_HQ,
 	CW_WIDGET_BUY_SHARE,
 	CW_WIDGET_SELL_SHARE,
+	CW_WIDGET_COMPANY_SHARING,
 	CW_WIDGET_COMPANY_PASSWORD,
 	CW_WIDGET_COMPANY_JOIN,
 };
@@ -1410,6 +1459,7 @@
 {    WWT_TEXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,    32,    43, STR_RELOCATE_HQ,                        STR_RELOCATE_COMPANY_HEADQUARTERS},
 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,     0,   179,   158,   169, STR_COMPANY_VIEW_BUY_SHARE_BUTTON,      STR_COMPANY_VIEW_BUY_SHARE_TOOLTIP},
 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   180,   359,   158,   169, STR_COMPANY_VIEW_SELL_SHARE_BUTTON,     STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP},
+{ WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,    46,    57, STR_COMPANY_SHARING,                    STR_COMPANY_SHARING_TOOLTIP},
 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,   138,   149, STR_COMPANY_PASSWORD,                   STR_COMPANY_PASSWORD_TOOLTIP},
 { WWT_PUSHTXTBTN,   RESIZE_NONE,  COLOUR_GREY,   266,   355,   138,   149, STR_COMPANY_JOIN,                       STR_COMPANY_JOIN_TIP},
 {   WIDGETS_END},
@@ -1529,6 +1579,7 @@
 		this->SetWidgetHiddenState(CW_WIDGET_RELOCATE_HQ,      !local || c->location_of_HQ == INVALID_TILE);
 		this->SetWidgetHiddenState(CW_WIDGET_BUY_SHARE,        local);
 		this->SetWidgetHiddenState(CW_WIDGET_SELL_SHARE,       local);
+		this->SetWidgetHiddenState(CW_WIDGET_COMPANY_SHARING,  !(_settings_game.sharing.enable_sharing && _settings_game.sharing.individual_allowed));
 		this->SetWidgetHiddenState(CW_WIDGET_COMPANY_PASSWORD, !local || !_networking);
 		this->SetWidgetHiddenState(CW_WIDGET_COMPANY_JOIN,     local || !_networking);
 		this->SetWidgetDisabledState(CW_WIDGET_COMPANY_JOIN,   !IsHumanCompany(c->index));
@@ -1645,6 +1696,10 @@
 				DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
 				break;
 
+			case CW_WIDGET_COMPANY_SHARING:
+				ShowSharingSettingsWindow((CompanyID)this->window_number);
+				break;
+
 #ifdef ENABLE_NETWORK
 			case CW_WIDGET_COMPANY_PASSWORD:
 				if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
@@ -1783,3 +1838,453 @@
 {
 	AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, company);
 }
+
+/** per-company sharing settings window */
+enum SharingSettingsWindowWidgets {
+	SSW_WIDGET_CLOSEBOX = 0,
+	SSW_WIDGET_CAPTION,
+	SSW_WIDGET_STICKY,
+	SSW_WIDGET_PANEL,
+	SSW_WIDGET_ICONS,
+	SSW_WIDGET_SETTINGS,
+	SSW_WIDGET_CURRENT,
+	SSW_WIDGET_BUTTONS,
+	SSW_WIDGET_FUTURE,
+	SSW_WIDGET_SCROLL,
+	SSW_WIDGET_OPTIONS,
+	SSW_WIDGET_COMPANIES,
+	SSW_WIDGET_RESIZE,
+};
+
+/** Min / max for the height of a text line. */
+enum {
+	MIN_LINE_HEIGHT    = 11,
+	MAX_LINE_HEIGHT    = 15,
+};
+
+/** String lookup table for station names ('Station', 'road stop' etc) */
+static const StringID _sharing_station_string[] = {
+	STR_SHARING_SETTING_STATION,
+	STR_SHARING_SETTING_ROADSTOP,
+	STR_SHARING_SETTING_DOCK,
+	STR_SHARING_SETTING_AIRPORT,
+};
+
+struct SharingSettingsWindow : public Window {
+private:
+	Company *company;                     ///< The company this window belongs to
+	CompanySharingSettingsEntry *future;  ///< future sharing settings
+	CompanySharingSettingsEntry *current; ///< current sharing settings
+
+	bool companies_tab;                   ///< Is the companies tab currently open?
+
+	VehicleType current_query_type;       ///< type of vehicle for which a querystring window is open.
+	byte clicked_row;                     ///< which of the arrow sets was clicked
+	byte clicked_side;                    ///< was the left or the right arrow clicked?
+
+	byte line_height;                     ///< The height of a line of text (FONT_HEIGHT_NORMAL, clamped between MIN/MAX_LINE_HEIGHT)
+
+public:
+	/** Constructor */
+	SharingSettingsWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
+	{
+		assert(IsValidCompanyID((CompanyID)number));
+		this->owner = (Owner)number;
+		this->company = GetCompany(number);
+		this->future = &company->sharing_future;
+		this->current = &company->sharing_current;
+
+		int text_height = this->widget[SSW_WIDGET_PANEL].bottom - this->widget[SSW_WIDGET_PANEL].top - 1;
+		this->line_height = Clamp(FONT_HEIGHT_NORMAL + 1, MIN_LINE_HEIGHT, MAX_LINE_HEIGHT);
+		this->resize.step_height = this->line_height;
+		this->vscroll.cap = text_height / this->line_height;
+
+		/* Resize the window, so it fits an exact number of lines */
+		int delta_y = this->line_height - (text_height % this->line_height);
+		this->resize.height += delta_y;
+		ResizeWindow(this, 0, delta_y);
+
+		this->FindWindowPlacementAndResize(desc);
+
+		/* Make sure the size is exactly correct */
+		assert(this->widget[SSW_WIDGET_PANEL].top + this->vscroll.cap * this->line_height + 1 == this->widget[SSW_WIDGET_PANEL].bottom);
+	}
+
+	/** Draw the value of a boolean setting ([Not] Allowed) in the column 'current' or 'future'.
+	 * @param top The y-coordinate where the string should be drawn.
+	 * @param value The boolean value to draw (Allowed / Not allowed).
+	 * @param future If true, draw in the column 'future', if false, draw in the column 'current'. */
+	inline void DrawBoolValue(int top, bool value, bool future)
+	{
+		const Widget *widget = future ? &this->widget[SSW_WIDGET_FUTURE] : &this->widget[SSW_WIDGET_CURRENT];
+		DrawString(widget->left + 2, widget->right - 2, top, value ? STR_SHARING_VALUE_ALLOWED : STR_SHARING_VALUE_NOT_ALLOWED, TC_ORANGE);
+ 	}
+
+	/** Draw a boolean sharing setting.
+	 * @param str The string to draw. (any parameters can be set beforehand)
+	 * @param top The y-coordinate where the string should be drawn. Is increased by this->line_height after drawing.
+	 * @param value_current The boolean value to draw (Allowed / Not allowed) in the column 'current'.
+	 * @param value_future The boolean value to draw (Allowed / Not allowed) in the column 'future'.
+	 */
+	void DrawSharingOption(StringID str, int &top, bool value_current, bool value_future)
+	{
+		static const Colours _button_colour_table[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
+		DrawFrameRect(this->widget[SSW_WIDGET_BUTTONS].left, top, this->widget[SSW_WIDGET_BUTTONS].right, top + 8,
+			_button_colour_table[!!value_future][_local_company == this->owner], value_future ? FR_LOWERED : FR_NONE);
+
+		DrawString(this->widget[SSW_WIDGET_SETTINGS].left, this->widget[SSW_WIDGET_SETTINGS].right, top, str, TC_BLACK);
+		DrawBoolValue(top, value_current, false);
+		DrawBoolValue(top, value_future, true);
+		top += this->line_height;
+	}
+
+	/** Should the text line given by the parameter be drawn on de screen? (depends on scrolling)
+	 * Parameter 'line' is passed by reference, and always incremented by one.
+	 * @param Line the line to draw or not to draw.
+	 * @return True if the line is to be drawn.
+	 */
+	inline bool ShouldDrawLine(int &line)
+	{
+		if (IsInsideMM(line, this->vscroll.pos, this->vscroll.pos + this->vscroll.cap)) {
+			line++;
+			return true;
+		}
+		line++;
+		return false;
+	}
+
+	virtual void OnPaint()
+	{
+		this->SetWidgetDisabledState(SSW_WIDGET_OPTIONS, !this->companies_tab);
+		this->SetWidgetDisabledState(SSW_WIDGET_COMPANIES, this->companies_tab);
+
+		/* Determine the number of items that will be shown in the list (i.e. this->vscroll.count) */
+		byte num_scroll = 1; //1 line for headers
+		if (this->companies_tab) {
+			Company *c;
+			FOR_ALL_COMPANIES(c) {
+				if (this->owner != c->index) num_scroll++;
+			}
+		} else {
+			num_scroll += 13; //4 lines for the train settings, 3 * 2 for the other vehtypes, and 3 blank lines
+		}
+		if (this->company->sharing_delay > 0) {
+			num_scroll += 2; //1 blank line and 1 line for the delay
+		}
+		SetVScrollCount(this, num_scroll);
+		this->DrawWidgets();
+
+		int top = this->widget[SSW_WIDGET_PANEL].top + 1;
+		int current_line = 0;
+
+		/* draw text headers */
+		if (ShouldDrawLine(current_line)) {
+			DrawString(this->widget[SSW_WIDGET_CURRENT].left, this->widget[SSW_WIDGET_CURRENT].right, top, STR_SHARING_CURRENT, TC_BLACK);
+			DrawString(this->widget[SSW_WIDGET_FUTURE].left,  this->widget[SSW_WIDGET_FUTURE].right,  top, STR_SHARING_FUTURE,  TC_BLACK);
+			top += this->line_height;
+		}
+
+		if (this->companies_tab) {
+			Company *c;
+			FOR_ALL_COMPANIES(c) {
+				if (c->index == this->owner) continue; //Skip our own company, as it would be silly to allow / disallow yourself.
+				if (ShouldDrawLine(current_line)) {
+					DrawCompanyIcon(c->index, this->widget[SSW_WIDGET_ICONS].left + 2, top + 1);
+					SetDParam(0, c->index);
+					DrawSharingOption(STR_SHARING_SETTING_COMPANY, top, HasBit(this->current->allowed_companies, c->index), HasBit(this->future->allowed_companies, c->index));
+				}
+			}
+
+			if (ShouldDrawLine(current_line)) {
+				/* No companies at all, apart from ourselves? */
+				if (current_line == 2) {
+					/* The SSW_WIDGET_SETTINGS widget on its own is too narrow to fit the string */
+					DrawString(min(this->widget[SSW_WIDGET_ICONS].left, this->widget[SSW_WIDGET_SETTINGS].left),
+						max(this->widget[SSW_WIDGET_ICONS].right, this->widget[SSW_WIDGET_SETTINGS].right),
+						top, STR_SHARING_SETTING_NO_COMPANIES, TC_BLACK);
+					return; //don't draw the sharing delay
+				}
+				/* Blank line */
+				top += this->line_height;
+			}
+		} else {
+			/* draw text and buttons for all vehicle types */
+			for (VehicleType type = VEH_TRAIN; type < SHARING_VEHTYPES; type++) {
+				SubSprite sub = {0, (this->vscroll.pos - current_line) * this->line_height, INT32_MAX, (this->vscroll.pos + this->vscroll.cap - current_line) * this->line_height - 1};
+				DrawSprite(SPR_IMG_TRAINLIST + type, PAL_NONE, this->widget[SSW_WIDGET_ICONS].left, top, &sub);
+
+				/* Some special lines for trains */
+				if (type == VEH_TRAIN) {
+					if (ShouldDrawLine(current_line)) {
+						this->DrawSharingOption(STR_SHARING_SETTING_TRACK, top,
+							(this->current->GetSharingOption(VEH_TRAIN) & SHARING_TRACK) != 0,
+							(this->future->GetSharingOption(VEH_TRAIN) & SHARING_TRACK) != 0);
+					}
+					if (ShouldDrawLine(current_line)) {
+						this->DrawSharingOption(STR_SHARING_SETTING_DEPOT, top,
+							(this->current->GetSharingOption(VEH_TRAIN) & SHARING_DEPOT) != 0,
+							(this->future->GetSharingOption(VEH_TRAIN) & SHARING_DEPOT) != 0);
+					}
+				}
+
+				if (ShouldDrawLine(current_line)) {
+					this->DrawSharingOption(_sharing_station_string[type], top,
+						(this->current->GetSharingOption(type) & SHARING_STATION) != 0,
+						(this->future->GetSharingOption(type) & SHARING_STATION) != 0);
+				}
+
+				/* sharing fee */
+				if (ShouldDrawLine(current_line)) {
+					/* Draw arrow buttons in the correct state */
+					bool l_clickable = this->owner == _local_company && this->future->GetSharingFee(type) > 0;
+					bool r_clickable = this->owner == _local_company && this->future->GetSharingFee(type) < MAX_SHARING_FEE;
+					byte arrow_clicked = (type == this->clicked_row) ? this->clicked_side : 0;
+					if ((arrow_clicked == 1 && !l_clickable) || (arrow_clicked == 2 && !r_clickable)) {
+						this->OnTimeout();
+						arrow_clicked = 0;
+					}
+					DrawArrowButtons(this->widget[SSW_WIDGET_BUTTONS].left, top, COLOUR_YELLOW, arrow_clicked, l_clickable, r_clickable);
+
+					/* Draw the fee strings */
+					DrawString(this->widget[SSW_WIDGET_SETTINGS].left, this->widget[SSW_WIDGET_SETTINGS].right, top, type == VEH_TRAIN ? STR_SHARING_SETTING_MONTHLY_TOLL : STR_SHARING_SETTING_FEE, TC_BLACK);
+					SetDParam(0, this->current->GetSharingFee(type));
+					DrawString(this->widget[SSW_WIDGET_CURRENT].left,  this->widget[SSW_WIDGET_CURRENT].right,  top, STR_CONFIG_SETTING_CURRENCY, TC_ORANGE);
+					SetDParam(0, this->future->GetSharingFee(type));
+					DrawString(this->widget[SSW_WIDGET_FUTURE].left,   this->widget[SSW_WIDGET_FUTURE].right,   top, STR_CONFIG_SETTING_CURRENCY, TC_ORANGE);
+					top += this->line_height;
+				}
+				/* Add some spacing */
+				if (ShouldDrawLine(current_line)) top += this->line_height;
+			}
+		}
+
+		/* draw sharing delay */
+		if (ShouldDrawLine(current_line) && this->company->sharing_delay > 0) {
+			DrawString(this->widget[SSW_WIDGET_SETTINGS].left, this->widget[SSW_WIDGET_SETTINGS].right, top, STR_SHARING_CHANGES_TAKE_EFFECT, TC_WHITE);
+			SetDParam(0, this->company->sharing_delay);
+			DrawString(this->widget[SSW_WIDGET_CURRENT].left, this->widget[SSW_WIDGET_CURRENT].right, top, STR_SHARING_TAKE_EFFECT_MONTHS, TC_ORANGE);
+		}
+	}
+
+	virtual void OnResize(Point delta)
+	{
+		this->vscroll.cap = (this->widget[SSW_WIDGET_PANEL].bottom - this->widget[SSW_WIDGET_PANEL].top - 1) / this->line_height;
+		/* Make sure the size is exactly correct */
+		assert(this->widget[SSW_WIDGET_PANEL].top + this->vscroll.cap * this->line_height + 1 == this->widget[SSW_WIDGET_PANEL].bottom);
+
+		if (delta.x == 0) return;
+
+		bool ltr = this->widget[SSW_WIDGET_OPTIONS].left < this->widget[SSW_WIDGET_COMPANIES].left;
+		int center = (this->widget[SSW_WIDGET_PANEL].right - this->widget[SSW_WIDGET_PANEL].left + 1) >> 1;
+		/* Resize both buttons evenly */
+		this->widget[ltr ? SSW_WIDGET_OPTIONS : SSW_WIDGET_COMPANIES].right = center - 1;
+		this->widget[ltr ? SSW_WIDGET_COMPANIES : SSW_WIDGET_OPTIONS].left = center;
+	}
+
+	/** Handle a click on a boolean option.
+	 * @param type The vehicle type that was clicked on.
+	 * @param option Bitmask of sharing options (station/depot/tracks) to be changed.
+	 */
+	void HandleOptionClick(VehicleType type, uint8 option)
+	{
+		byte value = this->future->GetSharingOption(type) ^ option;
+		/* for trains, we don't want tracks to be disabled while stations or depots are enabled */
+		if (type == VEH_TRAIN && value != 0 && (value & SHARING_TRACK) == 0) {
+			if (option == SHARING_TRACK) {
+				/* tracks were just disabled, so clear all other bits as well */
+				value = 0;
+			} else {
+				/* stations or depots were just enabled, so enable tracks as well */
+				value |= SHARING_TRACK;
+			}
+		}
+		DoCommandP(0, SHARING_SETTING_RAIL + type, value, CMD_CHANGE_SHARING_SETTING | CMD_MSG(STR_CANT_CHANGE_SHARING_SETTING));
+	}
+
+	/** Handle a click on one of the fees.
+	 * @param type The vehicle type for which the fee is to be adjusted.
+	 * @param x The x-coordinate of the click, relative to the left edge of the button.
+	 * This is used to determine whether the left or right button was clicked.
+	 */
+	void HandleFeeClick(VehicleType type, int x)
+	{
+		if ((this->flags4 & WF_TIMEOUT_MASK) > WF_TIMEOUT_TRIGGER) {
+			_left_button_clicked = false;
+			return;
+		}
+		int half_button_width = (this->widget[SSW_WIDGET_BUTTONS].right - this->widget[SSW_WIDGET_BUTTONS].left + 1) / 2;
+
+		uint16 value = this->future->GetSharingFee(type);
+		uint16 new_value = value;
+		if (x < half_button_width && value > 0) {
+			/* left button */
+			this->clicked_row = type;
+			this->clicked_side = 1;
+			new_value = value - min(10, value);
+		} else if (x >= half_button_width && value < MAX_SHARING_FEE) {
+			/* right button */
+			this->clicked_row = type;
+			this->clicked_side = 2;
+			new_value = value + min(10, MAX_SHARING_FEE - value);
+		}
+		if (new_value != value) {
+			DoCommandP(0, SHARING_FEE_RAIL + type, new_value, CMD_CHANGE_SHARING_SETTING | CMD_MSG(STR_CANT_CHANGE_SHARING_SETTING));
+			this->flags4 |= WF_TIMEOUT_BEGIN;
+			_left_button_clicked = false;
+		}
+	}
+
+	/** Handle a click on one of the companies in the companies tab.
+	 * @param index Index in the list of the clicked company. NOT the same as CompanyID.
+	 */
+	void HandleCompanyClick(byte index)
+	{
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			if (c->index == this->owner) continue;
+			if (index-- == 0) {
+				DoCommandP(0, SHARING_ALLOWED_COMPANIES, this->future->allowed_companies ^ (1 << c->index), CMD_CHANGE_SHARING_SETTING | CMD_MSG(STR_CANT_CHANGE_SHARING_SETTING));
+			}
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget)
+	{
+		int y, line;
+		switch (widget) {
+			case SSW_WIDGET_OPTIONS:
+				/* Switch to options tab */
+				this->companies_tab = false;
+				this->SetDirty();
+				return;
+			case SSW_WIDGET_COMPANIES:
+				/* Switch to companies tab */
+				this->companies_tab = true;
+				this->SetDirty();
+				return;
+			case SSW_WIDGET_PANEL:
+				if (this->owner != _local_company) return;
+
+				y = pt.y - this->widget[SSW_WIDGET_BUTTONS].top;
+				/* Ignore clicks on the top or bottom pixel, to avoid changing invisible settings */
+				if (y == this->widget[SSW_WIDGET_BUTTONS].top || y == this->widget[SSW_WIDGET_BUTTONS].bottom) return;
+				line = (y / this->line_height) - 1 + this->vscroll.pos;
+
+				if (pt.x >= this->widget[SSW_WIDGET_BUTTONS].left && pt.x <= this->widget[SSW_WIDGET_BUTTONS].right) {
+					/* A button is clicked, process the click further below */
+					break;
+				} else if (pt.x >= this->widget[SSW_WIDGET_FUTURE].left && pt.x <= this->widget[SSW_WIDGET_FUTURE].right) {
+					/* Possibly clicked a fee, if that is the case, show a query string window.
+					 * Line numbers correspond to the line numbers in the switch statement below */
+					switch (line) {
+						case 3:  this->current_query_type = VEH_TRAIN;    break;
+						case 6:  this->current_query_type = VEH_ROAD;     break;
+						case 9:  this->current_query_type = VEH_SHIP;     break;
+						case 12: this->current_query_type = VEH_AIRCRAFT; break;
+						default: return;
+					}
+					SetDParam(0, this->future->GetSharingFee(this->current_query_type) * _currency->rate);
+					ShowQueryString(STR_CONFIG_SETTING_INT32, STR_CONFIG_SETTING_QUERY_CAPT, 8, 100, this, CS_NUMERAL, QSF_NONE);
+				}
+				return;
+			default: return;
+		}
+
+		if (this->companies_tab) {
+			this->HandleCompanyClick(line);
+			return;
+		}
+
+		int x = pt.x - this->widget[SSW_WIDGET_BUTTONS].left;
+		switch (line) {
+			/* This is basically a table to map line numbers to certain actions */
+			case 0: this->HandleOptionClick(VEH_TRAIN, SHARING_TRACK); return;
+			case 1: this->HandleOptionClick(VEH_TRAIN, SHARING_DEPOT); return;
+			case 2: this->HandleOptionClick(VEH_TRAIN, SHARING_STATION); return;
+			case 3: this->HandleFeeClick(VEH_TRAIN, x); return;
+			/* blank line */
+			case 5: this->HandleOptionClick(VEH_ROAD, SHARING_STATION | SHARING_DEPOT); return;
+			case 6: this->HandleFeeClick(VEH_ROAD, x); return;
+			/* blank line */
+			case 8: this->HandleOptionClick(VEH_SHIP, SHARING_STATION | SHARING_DEPOT); return;
+			case 9: this->HandleFeeClick(VEH_SHIP, x); return;
+			/* blank line */
+			case 11: this->HandleOptionClick(VEH_AIRCRAFT, SHARING_STATION | SHARING_DEPOT); return;
+			case 12: this->HandleFeeClick(VEH_AIRCRAFT, x); return;
+		}
+	}
+
+	virtual void OnQueryTextFinished(char *str)
+	{
+		if (StrEmpty(str)) return;
+		int32 value = atoi(str);
+		value /= _currency->rate;
+		value = Clamp(value, 0, MAX_SHARING_FEE);
+		DoCommandP(0, SHARING_FEE_RAIL + this->current_query_type, value, CMD_CHANGE_SHARING_SETTING | CMD_MSG(STR_CANT_CHANGE_SHARING_SETTING));
+	}
+
+	virtual void OnTimeout()
+	{
+		this->clicked_row = 0;
+		this->clicked_side = 0;
+		this->SetDirty();
+	}
+};
+
+/** widget definition for infrastructure sharing window */
+static const Widget _sharing_settings_widgets[] = {
+	{   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_BLACK_CROSS,       STR_TOOLTIP_CLOSE_WINDOW},            // SSW_WIDGET_CLOSEBOX
+	{    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_GREY,    11,   371,     0,    13, STR_SHARING_CAPTION,   STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS},  // SSW_WIDGET_CAPTION
+	{  WWT_STICKYBOX,     RESIZE_LR,  COLOUR_GREY,   372,   383,     0,    13, 0x0,                   STR_STICKY_BUTTON},                   // SSW_WIDGET_STICKY
+	{      WWT_PANEL,     RESIZE_RB,  COLOUR_GREY,     0,   371,    14,   103, 0x0,                   STR_SHARING_PANEL_TOOLTIP},           // SSW_WIDGET_PANEL
+	{      WWT_EMPTY, RESIZE_BOTTOM,  COLOUR_GREY,     2,    21,    14,   103, 0x0,                   STR_NULL},                            // SSW_WIDGET_ICONS
+	{      WWT_EMPTY,     RESIZE_RB,  COLOUR_GREY,    24,   183,    14,   103, 0x0,                   STR_NULL},                            // SSW_WIDGET_SETTINGS
+	{      WWT_EMPTY,    RESIZE_LRB,  COLOUR_GREY,   186,   265,    14,   103, 0x0,                   STR_NULL},                            // SSW_WIDGET_CURRENT
+	{      WWT_EMPTY,    RESIZE_LRB,  COLOUR_GREY,   268,   287,    14,   103, 0x0,                   STR_NULL},                            // SSW_WIDGET_BUTTONS
+	{      WWT_EMPTY,    RESIZE_LRB,  COLOUR_GREY,   290,   369,    14,   103, 0x0,                   STR_NULL},                            // SSW_WIDGET_FUTURE
+	{  WWT_SCROLLBAR,    RESIZE_LRB,  COLOUR_GREY,   372,   383,    14,   103, 0x0,                   STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST},// SSW_WIDGET_SCROLL
+	{ WWT_PUSHTXTBTN,    RESIZE_RTB,  COLOUR_GREY,     0,   185,    104,  115, STR_SHARING_OPTIONS,   STR_SHARING_OPTIONS_TOOLTIP},         // SSW_WIDGET_OPTIONS
+	{ WWT_PUSHTXTBTN,   RESIZE_LRTB,  COLOUR_GREY,   186,   371,    104,  115, STR_SHARING_COMPANIES, STR_SHARING_COMPANIES_TOOLTIP},       // SSW_WIDGET_COMPANIES
+	{  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_GREY,   372,   383,    104,  115, 0x0,                   STR_RESIZE_BUTTON},                   // SSW_WIDGET_RESIZE
+	{   WIDGETS_END},
+};
+
+static const NWidgetPart _nested_sharing_settings_widgets[] = {
+	NWidget(NWID_HORIZONTAL), // Window header
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY, SSW_WIDGET_CLOSEBOX),
+		NWidget(WWT_CAPTION, COLOUR_GREY, SSW_WIDGET_CAPTION), SetDataTip(STR_SHARING_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY, SSW_WIDGET_STICKY),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PANEL, COLOUR_GREY, SSW_WIDGET_PANEL), SetDataTip(0x0, STR_SHARING_PANEL_TOOLTIP), SetFill(1, 1),
+			NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
+				/* Empty widgets to position the text columns */
+				NWidget(WWT_EMPTY, COLOUR_GREY, SSW_WIDGET_ICONS),    SetMinimalSize(20,  90), SetResize(0, 1),
+				NWidget(WWT_EMPTY, COLOUR_GREY, SSW_WIDGET_SETTINGS), SetMinimalSize(160, 90), SetResize(1, 1),
+				NWidget(WWT_EMPTY, COLOUR_GREY, SSW_WIDGET_CURRENT),  SetMinimalSize(80,  90), SetResize(1, 1),
+				NWidget(WWT_EMPTY, COLOUR_GREY, SSW_WIDGET_BUTTONS),  SetMinimalSize(20,  90), SetResize(0, 1),
+				NWidget(WWT_EMPTY, COLOUR_GREY, SSW_WIDGET_FUTURE),   SetMinimalSize(80,  90), SetResize(1, 1),
+			EndContainer(),
+		EndContainer(),
+		NWidget(WWT_SCROLLBAR, COLOUR_GREY, SSW_WIDGET_SCROLL),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SSW_WIDGET_OPTIONS),   SetMinimalSize(0, 12), SetResize(1, 0), SetDataTip(STR_SHARING_OPTIONS, STR_SHARING_OPTIONS_TOOLTIP), SetFill(1, 0),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SSW_WIDGET_COMPANIES), SetMinimalSize(0, 12), SetResize(1, 0), SetDataTip(STR_SHARING_COMPANIES, STR_SHARING_COMPANIES_TOOLTIP), SetFill(1, 0),
+		NWidget(WWT_RESIZEBOX,  COLOUR_GREY, SSW_WIDGET_RESIZE),
+	EndContainer(),
+};
+
+static const WindowDesc _sharing_settings_desc(
+	WDP_AUTO, WDP_AUTO, 384, 116, 384, 215,
+	WC_SHARING_OPTIONS, WC_COMPANY,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
+	_sharing_settings_widgets, _nested_sharing_settings_widgets, lengthof(_nested_sharing_settings_widgets)
+);
+
+static void ShowSharingSettingsWindow(CompanyID company)
+{
+	if (_settings_game.sharing.enable_sharing && _settings_game.sharing.individual_allowed && IsValidCompanyID(company)) {
+		AllocateWindowDescFront<SharingSettingsWindow>(&_sharing_settings_desc, company);
+	}
+}
diff -r ee55d0546576 src/depot_gui.cpp
--- a/src/depot_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/depot_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -21,6 +21,7 @@
 #include "tilehighlight_func.h"
 #include "window_gui.h"
 #include "vehiclelist.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -311,7 +312,7 @@
 		uint16 boxes_in_each_row = this->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
 
 		/* setup disabled buttons */
-		this->SetWidgetsDisabledState(!IsTileOwner(tile, _local_company),
+		this->SetWidgetsDisabledState(!AreDepotOperationsAllowed(this->window_number, _local_company, this->type),
 			DEPOT_WIDGET_STOP_ALL,
 			DEPOT_WIDGET_START_ALL,
 			DEPOT_WIDGET_SELL,
diff -r ee55d0546576 src/economy.cpp
--- a/src/economy.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/economy.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -32,6 +32,7 @@
 #include "autoreplace_func.h"
 #include "company_gui.h"
 #include "signs_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -367,6 +368,32 @@
 		}
 	}
 
+	/* make the sharing settings the most permissive of the two companies */
+	if (new_owner != INVALID_OWNER) {
+		CompanySharingSettingsEntry *old_settings = &GetCompany(old_owner)->sharing_current;
+		CompanySharingSettingsEntry *new_settings = &GetCompany(new_owner)->sharing_current;
+		for (VehicleType vt = VEH_TRAIN; vt < SHARING_VEHTYPES; vt++) {
+			new_settings->SetSharingOption(vt, old_settings->GetSharingOption(vt) | new_settings->GetSharingOption(vt));
+			new_settings->SetSharingFee(vt, min(old_settings->GetSharingFee(vt), new_settings->GetSharingFee(vt)));
+		}
+		new_settings->allowed_companies |= old_settings->allowed_companies;
+	} else {
+		/* Disable sharing for the old company
+		 * This will cause all vehicles on the old company's infrastructure
+		 * to be removed when HandleSharingChange is called */
+		for (VehicleType vt = VEH_TRAIN; vt < SHARING_VEHTYPES; vt++) {
+			GetCompany(old_owner)->sharing_current.SetSharingOption(vt, 0);
+		}
+		HandleSharingChange();
+	}
+
+	/* disallow the old company from all infrastructure */
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		ClrBit(c->sharing_future.allowed_companies, old_owner);
+		ClrBit(c->sharing_current.allowed_companies, old_owner);
+	}
+
 	/*  Change ownership of tiles */
 	{
 		TileIndex tile = 0;
@@ -660,6 +687,23 @@
 
 		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
 	}
+}
+
+static void CompaniesUpdateSharing()
+{
+	Company *c;
+	byte changed_vehtypes = 0;
+	FOR_ALL_COMPANIES(c) {
+		if (c->sharing_delay > 0 && --c->sharing_delay == 0 && !c->sharing_current.Equals(&c->sharing_future)) {
+			changed_vehtypes |= c->sharing_current.Copy(&c->sharing_future);
+			if (c->index != _local_company) {
+				SetDParam(0, c->index);
+				AddNewsItem(STR_SHARING_CHANGE_HAPPENED, NS_COMPANY_SHARING, 0, 0);
+			}
+		}
+	}
+	HandleSharingChange(changed_vehtypes);
+	InvalidateWindowClasses(WC_SHARING_OPTIONS);
 }
 
 static void HandleEconomyFluctuations()
@@ -1823,6 +1867,7 @@
 	CompaniesGenStatistics();
 	if (_settings_game.economy.inflation) AddInflation();
 	CompaniesPayInterest();
+	CompaniesUpdateSharing();
 	/* Reset the _current_company flag */
 	_current_company = OWNER_NONE;
 	HandleEconomyFluctuations();
diff -r ee55d0546576 src/economy_type.h
--- a/src/economy_type.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/economy_type.h	Sat Apr 25 19:58:24 2009 +0200
@@ -126,6 +126,8 @@
 	EXPENSES_SHIP_INC,
 	EXPENSES_LOAN_INT,
 	EXPENSES_OTHER,
+	EXPENSES_SHARED_RUN,
+	EXPENSES_SHARED_INC,
 	EXPENSES_END,
 	INVALID_EXPENSES      = 0xFF,
 };
diff -r ee55d0546576 src/infrastructure.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/infrastructure.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -0,0 +1,415 @@
+/** @file infrastructure.cpp Implementation of infrastructure sharing */
+
+#include "infrastructure.h"
+#include "settings_type.h"
+#include "company_base.h"
+#include "command_func.h"
+#include "company_func.h"
+#include "window_func.h"
+#include "infrastructure_func.h"
+#include "depot_base.h"
+#include "train.h"
+#include "tunnelbridge_map.h"
+#include "pbs.h"
+#include "vehicle_func.h"
+#include "news_func.h"
+#include "strings_func.h"
+#include "core/mem_func.hpp"
+
+#include "table/strings.h"
+
+bool CompanySharingSettingsEntry::Equals(CompanySharingSettingsEntry *o)
+{
+	/* Since memcmp/MemCmpT is not guaranteed to work properly for structs, we do it this way */
+	return MemCmpT(this->option, o->option, SHARING_VEHTYPES) == 0
+		&& MemCmpT(this->fee, o->fee, SHARING_VEHTYPES) == 0
+		&& this->allowed_companies == o->allowed_companies;
+}
+
+byte CompanySharingSettingsEntry::Copy(CompanySharingSettingsEntry *o)
+{
+	byte changed_vehtypes = 0;
+	for (VehicleType vt = VEH_TRAIN; vt < SHARING_VEHTYPES; vt++) {
+		if (this->GetSharingOption(vt) != o->GetSharingOption(vt)) {
+			SetBit(changed_vehtypes, vt);
+		}
+	}
+	if ((this->allowed_companies & o->allowed_companies) != this->allowed_companies) changed_vehtypes = 0xF;
+
+	MemCpyT(this, o);
+
+	return changed_vehtypes;
+}
+
+byte CompanySharingSettingsEntry::CopyFromGameSettings()
+{
+	byte old_options[SHARING_VEHTYPES] = {0};
+	MemCpyT(old_options, this->option, SHARING_VEHTYPES);
+
+	if (_settings_game.sharing.enable_sharing) {
+		this->SetSharingOption(VEH_TRAIN,    _settings_game.sharing.rail_sharing > 0 ? _settings_game.sharing.rail_sharing + 3 : 0);
+		this->SetSharingOption(VEH_ROAD,     _settings_game.sharing.road_sharing ? SHARING_DEPOT | SHARING_STATION : 0);
+		this->SetSharingOption(VEH_SHIP,     _settings_game.sharing.water_sharing ? SHARING_DEPOT | SHARING_STATION : 0);
+		this->SetSharingOption(VEH_AIRCRAFT, _settings_game.sharing.air_sharing ? SHARING_DEPOT | SHARING_STATION : 0);
+	} else {
+		MemSetT(this->option, 0, SHARING_VEHTYPES);
+	}
+
+	/* Check which vehicle types have changed */
+	byte changed_vehtypes = 0;
+	for (VehicleType vt = VEH_TRAIN; vt < SHARING_VEHTYPES; vt++) {
+		if (old_options[vt] != this->GetSharingOption(vt)) SetBit(changed_vehtypes, vt);
+	}
+
+	/* Set the sharing fees to match the advanced settings */
+	this->SetSharingFee(VEH_TRAIN,    _settings_game.sharing.rail_fee);
+	this->SetSharingFee(VEH_ROAD,     _settings_game.sharing.road_fee);
+	this->SetSharingFee(VEH_SHIP,     _settings_game.sharing.water_fee);
+	this->SetSharingFee(VEH_AIRCRAFT, _settings_game.sharing.air_fee);
+
+	uint16 old_companies = this->allowed_companies;
+
+	/* allow all existing companies */
+	this->allowed_companies = 0;
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		SetBit(this->allowed_companies, c->index);
+	}
+
+	/* If any company permission is removed, invalidate all vehicle types */
+	if ((this->allowed_companies & old_companies) != old_companies) changed_vehtypes = 0xF;
+
+	return changed_vehtypes;
+}
+
+/**
+ * Helper function for transferring sharing fees
+ * @param v The vehicle involved
+ * @param owner The owner of the infrastructure
+ * @param cost Amount to transfer
+ */
+
+static void PaySharingFee(Vehicle *v, Owner owner, Money cost)
+{
+	v->profit_this_year -= cost;
+	SubtractMoneyFromCompanyFract(v->owner, CommandCost(EXPENSES_SHARED_RUN, cost));
+	SubtractMoneyFromCompanyFract(owner, CommandCost(EXPENSES_SHARED_INC, -cost));
+}
+
+void PayStationSharingFee(Vehicle *v, const Station *st)
+{
+	if (v->owner == st->owner || st->owner == OWNER_NONE || v->type == VEH_TRAIN) return;
+	Money cost = GetSharingFee(st->owner, v->type);
+	PaySharingFee(v, st->owner, (cost << 8) / DAY_TICKS);
+}
+
+void PayDailyTrackSharingFee(Vehicle *v)
+{
+	Owner owner = GetTileOwner(v->tile);
+	if (owner == v->owner || v->type != VEH_TRAIN) return;
+	Money cost = GetSharingFee(owner, VEH_TRAIN);
+	cost = (cost << 8) * v->u.rail.cached_total_length / 8;
+	cost = cost * 12 / DAYS_IN_YEAR; //cost is per month, but we pay daily.
+	PaySharingFee(v, owner, cost);
+}
+
+/**
+ * Change the company sharing settings
+ * @param tile unused
+ * @param flags operation to perform
+ * @param p1 var to change
+ * @param p2 value to change it to
+ * @param text unused
+ */
+CommandCost CmdChangeSharingSetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	if (!(_settings_game.sharing.enable_sharing && _settings_game.sharing.individual_allowed)) return CMD_ERROR;
+	VehicleType type = (VehicleType)(p1 % SHARING_VEHTYPES);
+	if (p1 < SHARING_FEE_RAIL) {
+		if (type == VEH_TRAIN) {
+			if (p2 > (SHARING_TRACK | SHARING_DEPOT | SHARING_STATION)) return CMD_ERROR;
+			/* don't allow any sharing without tracks enabled */
+			if (p2 > 0 && (p2 & SHARING_TRACK) == 0) return CMD_ERROR;
+		} else {
+			if (p2 != 0 && p2 != (SHARING_DEPOT | SHARING_STATION)) return CMD_ERROR;
+		}
+	} else if (p1 < SHARING_ALLOWED_COMPANIES) {
+		if (p2 > MAX_SHARING_FEE) return CMD_ERROR;
+	} else if (p1 == SHARING_ALLOWED_COMPANIES) {
+		/* a company mask should not have (1 << MAX_COMPANIES) or any higher bit set */
+		if (p2 >= (1 << MAX_COMPANIES)) return CMD_ERROR;
+		for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
+			if (HasBit(p2, c) && !IsValidCompanyID(c)) return CMD_ERROR;
+		}
+		/* we prefer to keep ourselves allowed */
+		if (!HasBit(p2, _current_company)) return CMD_ERROR;
+	} else {
+		return CMD_ERROR;
+	}
+
+	if (flags & DC_EXEC) {
+		Company *c = GetCompany(_current_company);
+		if (p1 < SHARING_FEE_RAIL) {
+			c->sharing_future.SetSharingOption(type, p2);
+		} else if (p1 < SHARING_ALLOWED_COMPANIES) {
+			c->sharing_future.SetSharingFee(type, p2);
+		} else {
+			c->sharing_future.allowed_companies = p2;
+		}
+
+		/* Set the sharing delay, and copy the future settings to the current settings if needed */
+		if (c->sharing_future.Equals(&c->sharing_current)) {
+			c->sharing_delay = 0;
+		} else {
+			if (_settings_game.sharing.new_individual_delay == 0) {
+				/* Change is applied immediately, so warn users */
+				if (_current_company != _local_company) {
+					SetDParam(0, _current_company);
+					AddNewsItem(STR_SHARING_CHANGE_HAPPENED, NS_COMPANY_SHARING, 0, 0);
+				}
+
+				uint16 old_companies = c->sharing_current.allowed_companies;
+				c->sharing_current.Copy(&c->sharing_future);
+				if (p1 < SHARING_FEE_RAIL) {
+					HandleSharingChange(1 << p1);
+				} else if (p1 == SHARING_ALLOWED_COMPANIES) {
+					if ((p2 & old_companies) != old_companies) HandleSharingChange();
+				}
+			} else if (_current_company != _local_company) {
+				SetDParam(0, _current_company);
+				SetDParam(1, _current_company);
+				AddNewsItem(STR_SHARING_CHANGE_ANNOUNCED, NS_COMPANY_SHARING, 0, 0);
+			}
+			c->sharing_delay = _settings_game.sharing.new_individual_delay;
+		}
+
+		InvalidateWindow(WC_SHARING_OPTIONS, _current_company);
+	}
+	return CommandCost();
+}
+
+/**
+ * Sell a vehicle, no matter where it may be.
+ * Also make sure no artifacts are left, such as PBS paths
+ * @param v The vehicle to sell
+ */
+static void RemoveAndSellVehicle(Vehicle *v)
+{
+	if (v->type == VEH_TRAIN && !HASBITS(v->vehstatus, VS_CRASHED)) {
+		/* Clear path reservation. This will not clear any reservation that has become invalid, we will do that later */
+		FreeTrainTrackReservation(v);
+		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+			ClearPathReservation(u, u->tile, GetVehicleTrackdir(u));
+			if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
+				/* ClearPathReservation will not free the wormhole exit
+				 * if the train has just entered the wormhole. */
+				SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(u->tile), false);
+			}
+		}
+	}
+	SubtractMoneyFromCompanyFract(v->owner, CommandCost(EXPENSES_NEW_VEHICLES, -(v->value << 8)));
+	delete v;
+}
+
+
+/**
+ * Check the positions of all vehicles.
+ * If it is not in an allowed position,
+ * (e.g. it is in a depot when sharing of depots is disabled)
+ * then it is sold immediately.
+ * @param changed_vehtypes bitmask of vehicle types that were affected by a sharing setting change.
+ */
+static void CheckAllVehiclePositions(byte changed_vehtypes)
+{
+	uint num_sold_vehicles = 0;
+	Vehicle *v, *u;
+	FOR_ALL_VEHICLES(v) {
+		if (!(v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && IsFreeWagon(v)))) continue;
+		if (!HasBit(changed_vehtypes, v->type)) continue;
+		switch (v->type) {
+			case VEH_TRAIN:
+				for (u = v; u != NULL; u = u->Next()) {
+					/* If any wagon is on a disallowed tile, sell the entire train */
+					if (!IsRailwayTileUsageAllowed(u->tile, v->owner)) {
+						if (v->owner == _local_company) num_sold_vehicles++;
+						RemoveAndSellVehicle(v);
+						break;
+					}
+				}
+				break;
+			case VEH_ROAD:
+				if ((IsRoadDepotTile(v->tile) && !IsDepotUsageAllowed(v->tile, v)) ||
+					(IsStandardRoadStopTile(v->tile) && !IsStationUsageAllowed(v->tile, v))) {
+						if (v->owner == _local_company) num_sold_vehicles++;
+						RemoveAndSellVehicle(v);
+				}
+				break;
+			case VEH_SHIP:
+				if (IsShipDepotTile(v->tile) && !IsDepotUsageAllowed(v->tile, v)) {
+					if (v->owner == _local_company) num_sold_vehicles++;
+					RemoveAndSellVehicle(v);
+				}
+				break;
+			case VEH_AIRCRAFT:
+				if (v->u.air.state == FLYING) break;
+				if (IsValidStationID(v->u.air.targetairport) &&
+					!IsStationUsageAllowed(GetStation(v->u.air.targetairport), v)) {
+						if (v->owner == _local_company) num_sold_vehicles++;
+						RemoveAndSellVehicle(v);
+				}
+				break;
+			default: break;
+		}
+	}
+	if (num_sold_vehicles > 0) {
+		SetDParam(0, num_sold_vehicles);
+		AddNewsItem(STR_SHARING_CHANGE_SOLD_VEHICLES, NS_COMPANY_SHARING, 0, 0);
+	}
+}
+
+/**
+ * Check whether an order has an allowed destination.
+ * I.e. it refers to a station/depot/waypoint the vehicle is allowed to visit.
+ * @param o The order to check
+ * @param v The vehicle this order belongs to.
+ * @return true if the order has an allowed destination.
+ */
+static bool OrderDestinationIsAllowed(const Order *o, const Vehicle *v)
+{
+	DestinationID dest = o->GetDestination();
+	switch (o->GetType()) {
+		case OT_GOTO_STATION:  return IsStationUsageAllowed(GetStation(dest), v);
+		case OT_GOTO_DEPOT:    return v->type == VEH_AIRCRAFT ? IsStationUsageAllowed(GetStation(dest), v) : IsDepotUsageAllowed(GetDepot(dest)->xy, v);
+		case OT_GOTO_WAYPOINT: return IsWaypointUsageAllowed(GetWaypoint(dest), v->owner);
+		default: return true;
+	}
+}
+
+/**
+ * Review the orders of all vehicles
+ * This makes sure they don't have any orders to destinations
+ * where they are not allowed to go.
+ * @param changed_vehtypes bitmask of vehicle types that were affected by a sharing setting change.
+ */
+static void ReviewAllVehicleOrders(byte changed_vehtypes)
+{
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		if (!(v->IsPrimaryVehicle() && HasBit(changed_vehtypes, v->type))) continue;
+
+		if (!OrderDestinationIsAllowed(&v->current_order, v)) {
+			v->current_order.MakeDummy();
+			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
+		} else if (v->current_order.IsType(OT_LOADING)) {
+			if (!IsStationUsageAllowed(GetStation(v->last_station_visited), v)) {
+				v->LeaveStation();
+			}
+		}
+
+		if (v->FirstShared() != v) continue;
+
+		Order *o;
+		int id = -1;
+		FOR_VEHICLE_ORDERS(v, o) {
+			id++;
+			if (OrderDestinationIsAllowed(o, v)) continue;
+
+			o->MakeDummy();
+			for (const Vehicle *w = v->FirstShared(); 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, (INVALID_VEH_ORDER_ID << 8) | id);
+			}
+		}
+	}
+}
+/**
+ * Helper proc for HasVehicleOnPos to determine whether there is a train on a certain track.
+ * @param v The vehicle that may be on this track
+ * @param track the track the train should be on.
+ * @return v if it is on this track, or null otherwise.
+ */
+static Vehicle *HasTrainOnTrackProc(Vehicle *v, void *track)
+{
+	if (v->type == VEH_TRAIN && (TrackBitsToTrack(v->u.rail.track) == *(Track *)track || v->u.rail.track == TRACK_BIT_WORMHOLE)) {
+		return v;
+	}
+	return NULL;
+}
+
+/**
+ * Check the reservations of all tiles.
+ * If these to not seem to belong to a train or the train is not allowed to use them, unreserve them.
+ */
+static void CheckAllReservations()
+{
+	Vehicle *v;
+	TrackBits bits;
+	Track track;
+	for (TileIndex tile = 0; tile < MapSize(); tile++) {
+		bits = GetReservedTrackbits(tile);
+		while (bits != TRACK_BIT_NONE) {
+			track = RemoveFirstTrack(&bits);
+			/* Don't bother continuing if there is a vehicle on this tile */
+			if (HasVehicleOnPos(tile, &track, &HasTrainOnTrackProc)) continue;
+
+			v = GetTrainForReservation(tile, track);
+			if (v == NULL) {
+				UnreserveRailTrack(tile, track);
+				/* make any PBS signal red */
+				Trackdir td = TrackToTrackdir(track);
+				if (HasPbsSignalOnTrackdir(tile, td)) SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
+				if (HasPbsSignalOnTrackdir(tile, ReverseTrackdir(td))) SetSignalStateByTrackdir(tile, ReverseTrackdir(td), SIGNAL_STATE_RED);
+			}
+		}
+	}
+}
+
+/* Small struct to store a tile/track combination */
+struct SignalPosition {
+	TileIndex tile;
+	Track     track;
+	SignalPosition(TileIndex _tile, Track _track) : tile(_tile), track(_track) {};
+};
+
+/**
+ * Update all signals on the map.
+ * Since whe do not know which ones are affected by the sharing change, we invalidate them all.
+ * Updating signals can only be done on a per-company basis.
+ * Therefore, we cache all signals into lists, one per company
+ * Then we update all signals in each list.
+ */
+static void UpdateBlockSignals()
+{
+	SmallVector<SignalPosition, 256> signal_lists[MAX_COMPANIES];
+
+	for (TileIndex tile = 0; tile < MapSize(); tile++) {
+		if (IsTileType(tile, MP_RAILWAY) && HasSignals(tile)) {
+			TrackBits bits = GetTrackBits(tile);
+			do {
+				Track track = RemoveFirstTrack(&bits);
+				if (HasSignalOnTrack(tile, track)) {
+					*signal_lists[GetTileOwner(tile)].Append() = SignalPosition(tile, track);
+				}
+			} while (bits != TRACK_BIT_NONE);
+		}
+	}
+	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
+		for (uint i = 0; i < signal_lists[c].Length(); i++) {
+			AddTrackToSignalBuffer(signal_lists[c][i].tile, signal_lists[c][i].track, c);
+		}
+		UpdateSignalsInBuffer();
+		signal_lists[c].Reset();
+	}
+}
+
+void HandleSharingChange(byte changed_vehtypes)
+{
+	if (changed_vehtypes == 0) return;
+	CheckAllVehiclePositions(changed_vehtypes);
+	ReviewAllVehicleOrders(changed_vehtypes);
+	if (HasBit(changed_vehtypes, VEH_TRAIN)) {
+		CheckAllReservations();
+		UpdateBlockSignals();
+	}
+}
diff -r ee55d0546576 src/infrastructure.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/infrastructure.h	Sat Apr 25 19:58:24 2009 +0200
@@ -0,0 +1,125 @@
+/** @file infrastructure.h Define struct and enums for (shared) infrastructure */
+
+#ifndef INFRASTRUCTURE_H
+#define INFRASTRUCTURE_H
+
+#include "stdafx.h"
+#include "core/bitmath_func.hpp"
+#include "vehicle_type.h"
+#include "company_type.h"
+
+/** flags for enabling / disabling various types of infrastructure */
+enum SharingOption {
+	SHARING_STATION = 1 << 0, ///< Stations are shared
+	SHARING_DEPOT   = 1 << 1, ///< Depots are shared
+	SHARING_TRACK   = 1 << 2, ///< Tracks are shared. (Trains only)
+};
+
+/** which part of the sharing settings do we want to modify? */
+enum ModifySharingFlag {
+	SHARING_SETTING_RAIL,      ///< train setting
+	SHARING_SETTING_ROAD,      ///< road vehicle setting
+	SHARING_SETTING_WATER,     ///< ship setting
+	SHARING_SETTING_AIR,       ///< air setting
+
+	SHARING_FEE_RAIL,          ///< train fee
+	SHARING_FEE_ROAD,          ///< road stopping fee
+	SHARING_FEE_WATER,         ///< ship docking fee
+	SHARING_FEE_AIR,           ///< air landing fee
+
+	SHARING_ALLOWED_COMPANIES, ///< allowed companies bitmask
+	SHARING_END,
+};
+
+/** maximum fee for any of the sharing fees */
+static const uint MAX_SHARING_FEE = 50000;
+
+/** number of relevant vehicle types */
+static const byte SHARING_VEHTYPES = 4;
+
+struct CompanySharingSettingsEntry {
+	byte option[SHARING_VEHTYPES]; ///< sharing options for rail/road/water/air
+	uint16 fee[SHARING_VEHTYPES];  ///< fees for rail/road/water/air
+	CompanyMask allowed_companies; ///< which companies do we allow to use our infrastructure?
+
+	/** Constructor */
+	CompanySharingSettingsEntry() {}
+
+	/**
+	 * Compare two sets of sharing settings with eachother.
+	 * @param o The sharing settings entry to compare with.
+	 * @return True if all settings are equal, false otherwise.
+	 */
+	bool Equals(CompanySharingSettingsEntry *o);
+
+	/**
+	 * Copy the data of a specified sharing settings entry to this one.
+	 * @param o The sharing settings entry to use as source.
+	 * @return a bitmask of vehicle types whose permissions were reduced.
+	 */
+	byte Copy(CompanySharingSettingsEntry *o);
+
+	/**
+	 * Get the sharing option for a vehicle type.
+	 * @param type The vehicle type.
+	 * @return The sharing option for the specified vehicle type
+	 */
+	inline byte GetSharingOption(VehicleType type) const
+	{
+		assert(type < SHARING_VEHTYPES);
+		return this->option[type];
+	}
+
+	/**
+	 * Get the sharing fee for a specified vehicle type.
+	 * @param type The vehicle type.
+	 * @return The sharing fee for the given vehicle type.
+	 */
+	inline uint16 GetSharingFee(VehicleType type) const
+	{
+		assert(type < SHARING_VEHTYPES);
+		return this->fee[type];
+	}
+
+	/**
+	 * Set the sharing fee for a vehicle type.
+	 * @param type The vehicle type.
+	 * @value The sharing option to set for the given vehicle type.
+	 */
+	inline void SetSharingOption(VehicleType type, byte value)
+	{
+		assert(type < SHARING_VEHTYPES);
+		this->option[type] = value;
+	}
+
+	/**
+	 * Set the sharing fee for a specified vehicle type.
+	 * @param type The vehicle type.
+	 * @param value The new sharing fee.
+	 */
+	inline void SetSharingFee(VehicleType type, uint16 value)
+	{
+		assert(type < SHARING_VEHTYPES);
+		this->fee[type] = value;
+	}
+
+	/**
+	 * Check whether a company is allowed to use the infrastructure.
+	 * i.e. it's corresponding bit in allowed_companies is set.
+	 * @param c The company to check.
+	 * @return true if the given company is allowed to use the infrastructure
+	 */
+	inline bool IsCompanyAllowed(CompanyID c)
+	{
+		return HasBit(this->allowed_companies, c);
+	}
+
+	/**
+	 * Fill this struct with the values from _settings_game.
+	 * This also enables all companies in the allowed_companies mask.
+	 * @return a bitmask of vehicle types whose permissions were reduced.
+	 */
+	byte CopyFromGameSettings();
+};
+
+#endif /* INFRASTRUCTURE_H */
diff -r ee55d0546576 src/infrastructure_func.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/infrastructure_func.h	Sat Apr 25 19:58:24 2009 +0200
@@ -0,0 +1,221 @@
+/** @file infrastructure_func.h Functions for infrastructure sharing */
+
+#ifndef INFRASTRUCTURE_FUNC_H
+#define INFRASTRUCTURE_FUNC_H
+
+#include "station_map.h"
+#include "functions.h"
+#include "company_base.h"
+#include "waypoint.h"
+#include "vehicle_base.h"
+#include "company_func.h"
+
+/**
+ * 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);
+
+/**
+ * Pay the daily fee for trains on foreign tracks.
+ * @param v The vehicle to pay the fee for.
+ */
+void PayDailyTrackSharingFee(Vehicle *v);
+
+/**
+ * Handle a change of sharing settings.
+ * This involves checking all orders,
+ * making sure all vehicles are not on disallowed territory,
+ * checking all PBS paths
+ * and updating signals.
+ * @param changed_vehtypes Bitmask of vehicle types whose sharing settings were changed. Default is 0xF (all types)
+ */
+void HandleSharingChange(byte changed_vehtypes = 0xF);
+
+/**
+ * Get the sharing setting for a given infrastructure owner, vehicle owner and vehicle type.
+ * This also checks whether the vehicle owner is allowed according to the allowed_companies bitmask.
+ * @see SharingOption
+ * @param 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 The sharing option(s) that apply here.
+ */
+static inline byte GetSharingSetting(Owner owner, Owner veh_owner, VehicleType type) {
+	Company *c = GetCompany(owner);
+	return c->sharing_current.IsCompanyAllowed(veh_owner) ? c->sharing_current.GetSharingOption(type) : 0;
+}
+
+/**
+ * Get the sharing fee the infrastructure owner asks for using the infrastructure for a vehicle type.
+ * @param owner The owner of the infrastructure.
+ * @param type The vehicle type.
+ * @return The sharing fee that applies here.
+ */
+static inline uint16 GetSharingFee(Owner owner, VehicleType type) {
+	return GetCompany(owner)->sharing_current.GetSharingFee(type);
+}
+
+/**
+ * Check whether the given owner is allowed to use rails on this tile.
+ * It should either own the tile, or the tile owner should have sharing of tracks enabled (for this company).
+ * @param t The (railway) tile.
+ * @param owner The owner of the vehicle that wants to use this tile.
+ * @return true if the given owner is allowed to use this railway tile.
+ */
+static inline bool IsRailUsageAllowed(TileIndex t, Owner owner) {
+	return IsTileOwner(t, owner) || GetSharingSetting(GetTileOwner(t), owner, VEH_TRAIN) & SHARING_TRACK;
+}
+
+/**
+ * Check whether the given owner is allowed to use this waypoint for his trains.
+ * It should either own the waypoint, or the waypoint owner should have sharing of tracks enabled (for this company).
+ * @param wp The waypoint to test.
+ * @param owner The owner of the vehicle that wants to use this waypoint.
+ * @return true if the given owner is allowed to use this waypoint.
+ */
+static inline bool IsWaypointUsageAllowed(const Waypoint *wp, Owner owner) {
+	return wp->owner == owner || GetSharingSetting(wp->owner, owner, VEH_TRAIN) & SHARING_TRACK;
+}
+
+/**
+ * Check whether the given owner is allowed to use this depot.
+ * It should either own the depot, or the depot owner should have sharing of depots enabled (for this company).
+ * For non-trains, depot sharing is enabled automagically when sharing of stations is enabled.
+ * @param t The depot tile.
+ * @param owner The owner of the vehicle that wants to use this depot.
+ * @param type The vehicle type we are talking about.
+ * @return true if the given owner is allowed to use this depot.
+ */
+static inline bool IsDepotUsageAllowed(TileIndex t, Owner owner, VehicleType type) {
+	return IsTileOwner(t, owner) || GetSharingSetting(GetTileOwner(t), owner, type) & SHARING_DEPOT;
+}
+
+/**
+ * Check whether the given vehicle is allowed to use this depot.
+ * The vehicle owner should either own the depot, or the depot owner should have sharing of depots enabled (for this company).
+ * For non-trains, depot sharing is enabled automagically when sharing of stations is enabled.
+ * @param t The depot tile.
+ * @param v The vehicle that intends to use this depot.
+ * @return true if the given vehicle is allowed to use this depot.
+ */
+static inline bool IsDepotUsageAllowed(TileIndex t, const Vehicle *v) {
+	return IsDepotUsageAllowed(t, v->owner, v->type);
+}
+
+/**
+ * Check whether a given vehicle owner is allowed to use a station.
+ * He should either own the station, the station should have a non-company owner (oil rigs/buoys),
+ * or the station owner should have sharing of stations enabled (for this company).
+ * @param st A tile of the station.
+ * @param owner The vehicle owner
+ * @param type The vehicle type to test.
+ * @return true if the given owner is allowed to use this station.
+ */
+static inline bool IsStationUsageAllowed(TileIndex t, Owner owner, VehicleType type) {
+	Owner tile_owner = GetTileOwner(t);
+	return tile_owner == owner || tile_owner == OWNER_NONE || tile_owner == OWNER_WATER || GetSharingSetting(tile_owner, owner, type) & SHARING_STATION;
+}
+
+/**
+ * Check whether the given vehicle is allowed to use this station.
+ * The vehicle owner should either own the station, the station should have a non-company owner (oil rigs/buoys),
+ * or the station owner should have sharing of stations enabled (for this company).
+ * @param st The station.
+ * @param v The vehicle that intends to use this station.
+ * @return true if the given vehicle is allowed to use this station.
+ */
+static inline bool IsStationUsageAllowed(const Station *st, const Vehicle *v) {
+	return st->owner == v->owner || st->owner == OWNER_NONE || st->owner == OWNER_WATER || GetSharingSetting(st->owner, v->owner, v->type) & SHARING_STATION;
+}
+
+/**
+ * Check whether the given vehicle is allowed to use a station.
+ * The vehicle owner should either own the station, the station should have no owner (oil rigs),
+ * or the depot owner should have sharing of stations enabled (for this company).
+ * @param st A tile of the station.
+ * @param v The vehicle that intends to use this station.
+ * @return true if the given vehicle is allowed to use this station.
+ */
+static inline bool IsStationUsageAllowed(TileIndex t, const Vehicle *v) {
+	return IsStationUsageAllowed(t, v->owner, v->type);
+}
+
+/**
+ * Check whether the current company can control this vehicle.
+ * The vehicle owner can always control a vehicle.
+ * Trains on foreign tracks can also be controlled by the track owner.
+ * Controlling a train 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.
+ * @return true if the current company is allowed to control this vehicle.
+ */
+static inline bool IsVehicleControlAllowed(const Vehicle *v) {
+	return CheckOwnership(v->owner) || (v->type == VEH_TRAIN && CheckTileOwnership(v->tile));
+}
+
+/**
+ * Check whether a given company can control this vehicle.
+ * The vehicle owner can always control a vehicle.
+ * Trains on foreign tracks can also be controlled by the track owner.
+ * Controlling a train 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 c The company which may or may not control this vehicle
+ * @return true if the given company is allowed to control this vehicle.
+ */
+static inline bool IsVehicleControlAllowed(const Vehicle *v, CompanyByte c) {
+	return v->owner == c || (v->type == VEH_TRAIN && IsTileOwner(v->tile, c));
+}
+
+/**
+ * Check whether usage of a railway tile is allowed.
+ * The tile to check can be any tile with rail on it,
+ * such as normal rail, depots, stations or bridges.
+ * This is actually assumed to be the case, but not checked.
+ * @param tile The tile to check.
+ * @param owner Owner of the train that wants to use that tile.
+ * @return true if the vehicle can use the tile.
+ */
+static inline bool IsRailwayTileUsageAllowed(TileIndex tile, Owner owner)
+{
+	if (IsTileType(tile, MP_STATION)) return IsStationUsageAllowed(tile, owner, VEH_TRAIN);
+	if (IsRailDepotTile(tile)) return IsDepotUsageAllowed(tile, owner, VEH_TRAIN);
+	return IsRailUsageAllowed(tile, owner);
+}
+
+/**
+ * Are the tracks of two owners part of the same signal block?
+ * This is the case if the owners are equal, or if infrastructure sharing is enabled
+ * @param o1 First company.
+ * @param o2 Second company.
+ * @return true if the tracks of the given owners are part of the same signal block
+ */
+static inline bool AreSignalBlocksJoined(Owner o1, Owner o2)
+{
+	return (o1 == o2) || _settings_game.sharing.enable_sharing;
+}
+
+/**
+ * Is a company allowed to do depot operations? (buying/selling/reordering/autoreplace)
+ * This is allowed if the company is allowed to use the depot.
+ * For the sake of flexibility, a separate function (this one) is used.
+ * @param tile The tile of the depot.
+ * @param owner The company what wants to do depot operations.
+ * @param type The type of vehicle
+ * @return True it the depot operations are allowed
+ */
+static inline bool AreDepotOperationsAllowed(TileIndex tile, Owner owner, VehicleType type)
+{
+	return IsDepotUsageAllowed(tile, owner, type);
+}
+
+/**
+ * Should the smallmap window show whether rail tracks are accessible?
+ * @return true if the local company is valid and sharing is enabled
+ */
+static inline bool ShowSharingOnMap()
+{
+	return _settings_game.sharing.enable_sharing && IsValidCompanyID(_local_company);
+}
+
+#endif /* INFRASTRUCTURE_FUNC_H */
diff -r ee55d0546576 src/lang/english.txt
--- a/src/lang/english.txt	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/lang/english.txt	Sat Apr 25 19:58:24 2009 +0200
@@ -207,6 +207,8 @@
 STR_SMALLMAP_TYPE_OWNERS                                        :Owners
 STR_SMALLMAP_LEGENDA_ROADS                                      :{BLACK}{TINYFONT}Roads
 STR_SMALLMAP_LEGENDA_RAILROADS                                  :{BLACK}{TINYFONT}Railways
+STR_SMALLMAP_LEGENDA_RAILROADS_ACCESSIBLE                       :{BLACK}{TINYFONT}Railways (accessible)
+STR_SMALLMAP_LEGENDA_RAILROADS_INACCESSIBLE                     :{BLACK}{TINYFONT}Railways (not accessible)
 STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS                    :{BLACK}{TINYFONT}Stations/Airports/Docks
 STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES                       :{BLACK}{TINYFONT}Buildings/Industries
 STR_SMALLMAP_LEGENDA_VEHICLES                                   :{BLACK}{TINYFONT}Vehicles
@@ -1118,6 +1120,23 @@
 STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD                        :{LTBLUE}Remove absurd road-elements during the road construction: {ORANGE}{STRING1}
 
+STR_CONFIG_SETTING_SHARING_ENABLE                               :{LTBLUE}Enable infrastructure sharing: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_INDIVIDUAL                           :{LTBLUE}Allow individual settings: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_INDIVIDUAL_TIME                      :{LTBLUE}Delay for new individual settings to take effect: {ORANGE}{STRING1} months
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Railway sharing: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_RAIL_NONE                            :None
+STR_CONFIG_SETTING_SHARING_RAIL_RAILWAY                         :Only railway
+STR_CONFIG_SETTING_SHARING_RAIL_RAILSTATION                     :Railway and stations
+STR_CONFIG_SETTING_SHARING_RAIL_RAILDEPOT                       :Railway and rail depots
+STR_CONFIG_SETTING_SHARING_RAIL_ALL                             :Everything
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Road stops and depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Docks and ship depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Airports: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_RAIL_FEE                             :{LTBLUE}Monthly track toll: {ORANGE}{STRING1} per train tile
+STR_CONFIG_SETTING_SHARING_ROAD_FEE                             :{LTBLUE}Stopping fee for road vehicles: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_WATER_FEE                            :{LTBLUE}Docking fee for ship: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_AIR_FEE                              :{LTBLUE}Terminal fee for aircraft: {ORANGE}{STRING1} per day
+
 STR_CONFIG_SETTING_GUI                                          :{ORANGE}Interface
 STR_CONFIG_SETTING_CONSTRUCTION                                 :{ORANGE}Construction
 STR_CONFIG_SETTING_VEHICLES                                     :{ORANGE}Vehicles
@@ -1129,6 +1148,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_AI_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
@@ -2193,6 +2213,8 @@
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Ship Income
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Loan Interest
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Other
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Infrastructure Costs
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Infrastructure Income
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
 STR_FINANCES_TOTAL_CAPTION                                      :{WHITE}Total:
@@ -3633,3 +3655,34 @@
 STR_CONTENT_INTRO_MISSING_BUTTON                                :{BLACK}Find missing content online
 STR_CONTENT_INTRO_MISSING_BUTTON_TIP                            :{BLACK}Check whether the missing content can be found online
 ########
+
+############ Infrastructure sharing
+STR_COMPANY_SHARING                                             :{BLACK}Sharing
+STR_COMPANY_SHARING_TOOLTIP                                     :{BLACK}Set the sharing options for your infrastructure
+STR_SHARING_CAPTION                                             :{WHITE}Shared infrastructure
+STR_SHARING_PANEL_TOOLTIP                                       :{BLACK}View and edit the infrastructure sharing settings for this company.
+STR_SHARING_OPTIONS                                             :{BLACK}Options
+STR_SHARING_OPTIONS_TOOLTIP                                     :{BLACK}View and edit the sharing options
+STR_SHARING_COMPANIES                                           :{BLACK}Companies
+STR_SHARING_COMPANIES_TOOLTIP                                   :{BLACK}View and edit which companies are allowed on infrastructure of this company
+STR_SHARING_CURRENT                                             :Currently:
+STR_SHARING_FUTURE                                              :In the future:
+STR_SHARING_SETTING_TRACK                                       :Tracks:
+STR_SHARING_SETTING_DEPOT                                       :Depots:
+STR_SHARING_SETTING_STATION                                     :Stations:
+STR_SHARING_SETTING_ROADSTOP                                    :Road stops:
+STR_SHARING_SETTING_DOCK                                        :Docks:
+STR_SHARING_SETTING_AIRPORT                                     :Airports:
+STR_SHARING_SETTING_MONTHLY_TOLL                                :Monthly toll per train tile:
+STR_SHARING_SETTING_FEE                                         :Loading fee per day:
+STR_SHARING_SETTING_COMPANY                                     :{COMPANY}:
+STR_SHARING_SETTING_NO_COMPANIES                                :No companies to allow or disallow
+STR_SHARING_VALUE_ALLOWED                                       :Allowed
+STR_SHARING_VALUE_NOT_ALLOWED                                   :Not allowed
+STR_SHARING_CHANGES_TAKE_EFFECT                                 :Changes will take effect in:
+STR_SHARING_TAKE_EFFECT_MONTHS                                  :{NUM} month{P "" s}
+STR_CANT_CHANGE_SHARING_SETTING                                 :{WHITE}Can't change the infrastructure sharing settings...
+STR_SHARING_CHANGE_ANNOUNCED                                    :{BLACK}{BIGFONT}{COMPANY} announced to change its infrastructure sharing settings in {NUM} month{P "" s}!
+STR_SHARING_CHANGE_HAPPENED                                     :{BLACK}{BIGFONT}{COMPANY} has changed its infrastructure sharing settings!
+STR_SHARING_CHANGE_SOLD_VEHICLES                                :{BLACK}{BIGFONT}Because of a change in infrastructure sharing settings, {COMMA} of your vehicles {P was were} sold!
+########
diff -r ee55d0546576 src/news_gui.cpp
--- a/src/news_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/news_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -114,6 +114,7 @@
 	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_MERGER
 	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_BANKRUPT
 	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_TILE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_NEW
+	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                NULL                    }, ///< NS_COMPANY_SHARING
 	{ NT_INDUSTRY_OPEN,    NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_OPEN
 	{ NT_INDUSTRY_CLOSE,   NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_CLOSE
 	{ NT_ECONOMY,          NM_NORMAL,   NF_NONE,                NULL                    }, ///< NS_ECONOMY
diff -r ee55d0546576 src/news_type.h
--- a/src/news_type.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/news_type.h	Sat Apr 25 19:58:24 2009 +0200
@@ -43,6 +43,7 @@
 	NS_COMPANY_MERGER,   ///< NT_COMPANY_INFO (merger)
 	NS_COMPANY_BANKRUPT, ///< NT_COMPANY_INFO (bankrupt)
 	NS_COMPANY_NEW,      ///< NT_COMPANY_INFO (new company)
+	NS_COMPANY_SHARING,  ///< NT_COMPANY_INFO (change of sharing settings)
 	NS_INDUSTRY_OPEN,    ///< NT_INDUSTRY_OPEN
 	NS_INDUSTRY_CLOSE,   ///< NT_INDUSTRY_CLOSE
 	NS_ECONOMY,          ///< NT_ECONOMY
diff -r ee55d0546576 src/npf.cpp
--- a/src/npf.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/npf.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -16,6 +16,7 @@
 #include "pbs.h"
 #include "settings_type.h"
 #include "pathfind.h"
+#include "infrastructure_func.h"
 
 static AyStar _npf_aystar;
 
@@ -548,25 +549,35 @@
  */
 static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
 {
-	if (IsTileType(tile, MP_RAILWAY) || // Rail tile (also rail depot)
-			IsRailwayStationTile(tile) ||   // Rail station tile
-			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:
+			/* rail depot */
+			if (IsRailDepot(tile)) return IsDepotUsageAllowed(tile, owner, VEH_TRAIN);
+			/* waypoint */
+			if (IsRailWaypoint(tile)) return IsWaypointUsageAllowed(GetWaypointByTile(tile), owner);
+			/* other rail tile */
+			return IsRailUsageAllowed(tile, owner);
 
-	switch (GetTileType(tile)) {
 		case MP_ROAD:
+			/* road depot */
+			if (IsRoadDepot(tile)) return IsDepotUsageAllowed(tile, owner, VEH_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 IsRailUsageAllowed(tile, owner); // Railway needs owner check, while the street is public
 			}
+			break;
+
+		case MP_STATION:
+			/* rail station */
+			if (IsRailwayStation(tile)) return IsStationUsageAllowed(tile, owner, VEH_TRAIN);
+			/* standard road stop */
+			if (IsStandardRoadStopTile(tile)) return IsStationUsageAllowed(tile, owner, VEH_ROAD);
 			break;
 
 		case MP_TUNNELBRIDGE:
 			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
-				return IsTileOwner(tile, owner);
+				return IsRailUsageAllowed(tile, owner);
 			}
 			break;
 
@@ -977,7 +988,7 @@
 	FOR_ALL_DEPOTS(depot) {
 		/* Check if this is really a valid depot, it is of the needed type and
 		 * owner */
-		if (IsDepotTypeTile(depot->xy, type) && IsTileOwner(depot->xy, owner))
+		if (IsDepotTypeTile(depot->xy, type) && IsDepotUsageAllowed(depot->xy, owner, (VehicleType)type))
 			/* If so, let's add it to the queue, sorted by distance */
 			depots.push(&depots, depot, DistanceManhattan(tile, depot->xy));
 	}
diff -r ee55d0546576 src/order_cmd.cpp
--- a/src/order_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/order_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -20,6 +20,7 @@
 #include "oldpool_func.h"
 #include "depot_base.h"
 #include "settings_type.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -432,7 +433,7 @@
 
 			const Station *st = GetStation(new_order.GetDestination());
 
-			if (st->owner != OWNER_NONE && !CheckOwnership(st->owner)) return CMD_ERROR;
+			if (!IsStationUsageAllowed(st, v)) 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()) {
@@ -478,7 +479,7 @@
 
 					const Station *st = GetStation(new_order.GetDestination());
 
-					if (!CheckOwnership(st->owner) ||
+					if (!IsStationUsageAllowed(st, v) ||
 							!CanVehicleUseStation(v, st) ||
 							st->Airport()->nof_depots == 0) {
 						return CMD_ERROR;
@@ -488,7 +489,7 @@
 
 					const Depot *dp = GetDepot(new_order.GetDestination());
 
-					if (!CheckOwnership(GetTileOwner(dp->xy))) return CMD_ERROR;
+					if (!IsDepotUsageAllowed(dp->xy, v)) return CMD_ERROR;
 
 					switch (v->type) {
 						case VEH_TRAIN:
@@ -523,7 +524,7 @@
 			if (!IsValidWaypointID(new_order.GetDestination())) return CMD_ERROR;
 			const Waypoint *wp = GetWaypoint(new_order.GetDestination());
 
-			if (!CheckOwnership(wp->owner)) return CMD_ERROR;
+			if (!IsWaypointUsageAllowed(wp, v->owner)) return CMD_ERROR;
 
 			/* Order flags can be any of the following for waypoints:
 			 * [non-stop]
diff -r ee55d0546576 src/order_gui.cpp
--- a/src/order_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/order_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -24,6 +24,7 @@
 #include "tilehighlight_func.h"
 #include "network/network.h"
 #include "settings_type.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -297,18 +298,16 @@
 	if (_settings_game.order.gotodepot) {
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY:
-				if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_company)) {
-					if (IsRailDepot(tile)) {
-						order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS);
-						if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
-						if (_settings_client.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
-						return order;
-					}
+				if (IsRailDepot(tile) && v->type == VEH_TRAIN && IsDepotUsageAllowed(tile, v)) {
+					order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS);
+					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
+					if (_settings_client.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
+					return order;
 				}
 				break;
 
 			case MP_ROAD:
-				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_company)) {
+				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsDepotUsageAllowed(tile, v)) {
 					order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					if (_settings_client.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
@@ -318,7 +317,7 @@
 
 			case MP_STATION:
 				if (v->type != VEH_AIRCRAFT) break;
-				if (IsHangar(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsHangar(tile) && IsStationUsageAllowed(tile, v)) {
 					order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
@@ -327,7 +326,7 @@
 
 			case MP_WATER:
 				if (v->type != VEH_SHIP) break;
-				if (IsShipDepot(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsShipDepot(tile) && IsDepotUsageAllowed(tile, v)) {
 					TileIndex tile2 = GetOtherShipDepotTile(tile);
 
 					order.MakeGoToDepot(GetDepotByTile(tile < tile2 ? tile : tile2)->index, ODTFB_PART_OF_ORDERS);
@@ -343,7 +342,7 @@
 	/* check waypoint */
 	if (IsRailWaypointTile(tile) &&
 			v->type == VEH_TRAIN &&
-			IsTileOwner(tile, _local_company)) {
+			IsWaypointUsageAllowed(GetWaypointByTile(tile), v->owner)) {
 		order.MakeGoToWaypoint(GetWaypointByTile(tile)->index);
 		if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
 		return order;
@@ -353,7 +352,7 @@
 		StationID st_index = GetStationIndex(tile);
 		const Station *st = GetStation(st_index);
 
-		if (st->owner == _local_company || st->owner == OWNER_NONE) {
+		if (IsStationUsageAllowed(tile, v)) {
 			byte facil;
 			(facil = FACIL_DOCK, v->type == VEH_SHIP) ||
 			(facil = FACIL_TRAIN, v->type == VEH_TRAIN) ||
diff -r ee55d0546576 src/ottdres.rc.in
--- a/src/ottdres.rc.in	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/ottdres.rc.in	Sat Apr 25 19:58:24 2009 +0200
@@ -64,8 +64,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,8,0,@@REVISION@@
- PRODUCTVERSION 0,8,0,@@REVISION@@
+ FILEVERSION 0,8,0,16141
+ PRODUCTVERSION 0,8,0,16141
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -83,14 +83,14 @@
             VALUE "Comments", "This program is licensed under the GNU General Public License.\0"
             VALUE "CompanyName", "OpenTTD Development Team\0"
             VALUE "FileDescription", "OpenTTD\0"
-            VALUE "FileVersion", "Development @@VERSION@@\0"
+            VALUE "FileVersion", "IS2.0-beta2\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", "IS2.0-beta2\0"
             VALUE "SpecialBuild", "-\0"
         END
     END
diff -r ee55d0546576 src/pbs.cpp
--- a/src/pbs.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/pbs.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -233,7 +233,7 @@
 {
 	FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data;
 
-	if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info->res.trackdir))) {
+	if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && (v->u.rail.track == TRACK_BIT_WORMHOLE || HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info->res.trackdir)))) {
 		v = v->First();
 
 		/* ALWAYS return the lowest ID (anti-desync!) */
@@ -268,6 +268,40 @@
 }
 
 /**
+ * Find a train on a reservation in a single direction.
+ * @param tile The reserved tile.
+ * @param trackdir The reserved trackdir to start searching.
+ * @param owner The owner of the vehicle. If no owner is known yet, specify INVALID_OWNER.
+ * @param rts The railtypes the vehicle can use. If not known yet, specify INVALID_RAILTYPES.
+ * @return The vehicle this reservation (possibly) belongs to.
+ */
+static Vehicle *FindTrainForReservationDir(TileIndex tile, Trackdir trackdir, Owner owner, RailTypes rts)
+{
+	FindTrainOnTrackInfo ftoti;
+	/* Ignore one-way signals, as we might be searching the wrong way */
+	ftoti.res = FollowReservation(owner, rts, tile, trackdir, true);
+
+	FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
+	if (ftoti.best != NULL) return ftoti.best;
+
+	/* Special case for stations: check the whole platform for a vehicle. */
+	if (IsRailwayStationTile(ftoti.res.tile)) {
+		TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
+		for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
+			FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
+			if (ftoti.best != NULL) return ftoti.best;
+		}
+	}
+
+	/* Special case for bridges/tunnels: check the other end as well. */
+	if (IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) {
+		FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
+		if (ftoti.best != NULL) return ftoti.best;
+	}
+	return NULL;
+}
+
+/**
  * Find the train which has reserved a specific path.
  *
  * @param tile A tile on the path.
@@ -279,31 +313,22 @@
 	assert(HasReservedTracks(tile, TrackToTrackBits(track)));
 	Trackdir  trackdir = TrackToTrackdir(track);
 
-	RailTypes rts = GetRailTypeInfo(GetTileRailType(tile))->compatible_railtypes;
-
 	/* Follow the path from tile to both ends, one of the end tiles should
-	 * have a train on it. We need FollowReservation to ignore one-way signals
-	 * here, as one of the two search directions will be the "wrong" way. */
+	 * have a train on it. Since we don't know the vehicle yet,
+	 * we don't know which tiles it can access with regards to ownership and infrastructure sharing,
+	 * nor do we know which rail types it is compatible with.
+	 * Therefore we first do a test run without ownership or railtype checks.
+	 * If this yields a vehicle, we test again using the now-known owner and railtype info.
+	 * If this still yields a vehicle, we return it as it is the correct one.
+	 */
 	for (int i = 0; i < 2; ++i, trackdir = ReverseTrackdir(trackdir)) {
-		FindTrainOnTrackInfo ftoti;
-		ftoti.res = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true);
-
-		FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
-		if (ftoti.best != NULL) return ftoti.best;
-
-		/* Special case for stations: check the whole platform for a vehicle. */
-		if (IsRailwayStationTile(ftoti.res.tile)) {
-			TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
-			for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
-				FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
-				if (ftoti.best != NULL) return ftoti.best;
-			}
-		}
-
-		/* Special case for bridges/tunnels: check the other end as well. */
-		if (IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) {
-			FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
-			if (ftoti.best != NULL) return ftoti.best;
+		Vehicle *v = FindTrainForReservationDir(tile, trackdir, INVALID_OWNER, INVALID_RAILTYPES);
+		if (v == NULL) continue;
+		RailTypes rts = GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes;
+		v = FindTrainForReservationDir(tile, trackdir, v->owner, rts);
+		/* Also verify that the train can actally use the start tile */
+		if (v != NULL && IsRailwayTileUsageAllowed(tile, v->owner) && HasBit(rts, GetTileRailType(tile))) {
+			return v;
 		}
 	}
 
diff -r ee55d0546576 src/rev.cpp.in
--- a/src/rev.cpp.in	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/rev.cpp.in	Sat Apr 25 19:58:24 2009 +0200
@@ -20,7 +20,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.0-beta2";
 
 /**
  * Let us know if current build was modified. This detection
@@ -45,11 +45,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 = 0 << 28 | 8 << 24 | 0 << 20 | 0 << 19 | (@@REVISION@@ & ((1 << 19) - 1));
+const uint32 _openttd_newgrf_version = 0 << 28 | 8 << 24 | 0 << 20 | 0 << 19 | (16141 & ((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.0-beta2 (@@DATE@@) OpenTTD Team [MorphOS, PowerPC]";
 #endif
diff -r ee55d0546576 src/roadveh_cmd.cpp
--- a/src/roadveh_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/roadveh_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -30,6 +30,7 @@
 #include "depot_base.h"
 #include "effectvehicle_func.h"
 #include "settings_type.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -175,7 +176,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 (!AreDepotOperationsAllowed(tile, _current_company, VEH_ROAD)) return CMD_ERROR;
 
 	if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
 
@@ -363,7 +364,7 @@
 	tile += TileOffsByDiagDir(_road_pf_directions[trackdir]);
 
 	if (IsRoadDepotTile(tile) &&
-			IsTileOwner(tile, rfdd->owner) &&
+			IsDepotUsageAllowed(tile, rfdd->owner, VEH_ROAD) &&
 			length < rfdd->best_length) {
 		rfdd->best_length = length;
 		rfdd->tile = tile;
@@ -456,7 +457,7 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
+	if (v->type != VEH_ROAD || !IsVehicleControlAllowed(v)) return CMD_ERROR;
 
 	if (v->vehstatus & VS_STOPPED ||
 			v->vehstatus & VS_CRASHED ||
@@ -1032,14 +1033,14 @@
 	TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
 
 	if (IsTileType(tile, MP_ROAD)) {
-		if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.compatible_roadtypes) == 0)) {
+		if (IsRoadDepot(tile) && (!IsDepotUsageAllowed(tile, v) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->u.road.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 || RoadVehHasArticPart(v)) {
+		if (!IsStationUsageAllowed(tile, v) || GetRoadStopDir(tile) == enterdir || RoadVehHasArticPart(v)) {
 			/* different station owner or wrong orientation or the vehicle has articulated parts */
 			trackdirs = TRACKDIR_BIT_NONE;
 		} else {
@@ -1648,7 +1649,7 @@
 			_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_settings_game.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)) &&
-			v->owner == GetTileOwner(v->tile) &&
+			IsStationUsageAllowed(v->tile, v) &&
 			GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
 			v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
diff -r ee55d0546576 src/saveload/afterload.cpp
--- a/src/saveload/afterload.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/saveload/afterload.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -1805,6 +1805,36 @@
 		}
 	}
 
+	if (CheckSavegameVersion(SL_IS)) {
+		/* Set the sharing settings to the standard values (no sharing)
+		 * as we do not want these to be copied from the newgame settings. */
+		_settings_game.sharing.enable_sharing       = false;
+		_settings_game.sharing.individual_allowed   = false;
+		_settings_game.sharing.new_individual_delay = 12;
+		_settings_game.sharing.rail_sharing         = 0;
+		_settings_game.sharing.road_sharing         = false;
+		_settings_game.sharing.water_sharing        = false;
+		_settings_game.sharing.air_sharing          = false;
+		_settings_game.sharing.rail_fee             = 100;
+		_settings_game.sharing.road_fee             = 100;
+		_settings_game.sharing.water_fee            = 100;
+		_settings_game.sharing.air_fee              = 100;
+
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			c->sharing_future.CopyFromGameSettings();
+			c->sharing_current.CopyFromGameSettings();
+			/* yearly_expenses has 3*15 entries now, saveload code gave us 3*13.
+			 * Move the old data to the right place in the new array and clear the new data.
+			 * The move has to be done in reverse order (first 2, then 1). */
+			MemMoveT(&c->yearly_expenses[2][0], &c->yearly_expenses[0][2 * 13], 13);
+			MemMoveT(&c->yearly_expenses[1][0], &c->yearly_expenses[0][13],     13);
+			/* Clear the old location of just-moved data, so sharing income/expenses is set to 0 */
+			MemSetT(&c->yearly_expenses[0][13], 0, 2);
+			MemSetT(&c->yearly_expenses[1][13], 0, 2);
+		}
+	}
+
 	AfterLoadLabelMaps();
 
 	GamelogPrintDebug(1);
diff -r ee55d0546576 src/saveload/company_sl.cpp
--- a/src/saveload/company_sl.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/saveload/company_sl.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -125,7 +125,8 @@
 
 	/* yearly expenses was changed to 64-bit in savegame version 2. */
 	SLE_CONDARR(Company, yearly_expenses,       SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, 0, 1),
-	SLE_CONDARR(Company, yearly_expenses,       SLE_INT64, 3 * 13,                  2, SL_MAX_VERSION),
+	SLE_CONDARR(Company, yearly_expenses,       SLE_INT64, 3 * 13,                  2, SL_IS - 1),
+	SLE_CONDARR(Company, yearly_expenses,       SLE_INT64, 3 * 15,              SL_IS, SL_MAX_VERSION),
 
 	SLE_CONDVAR(Company, is_ai,                 SLE_BOOL,                    2, SL_MAX_VERSION),
 	SLE_CONDNULL(1, 107, 111), ///< is_noai
@@ -138,6 +139,8 @@
 	SLE_CONDVAR(Company, engine_renew_months,   SLE_INT16,                  16, SL_MAX_VERSION),
 	SLE_CONDVAR(Company, engine_renew_money,    SLE_UINT32,                 16, SL_MAX_VERSION),
 	SLE_CONDVAR(Company, renew_keep_length,     SLE_BOOL,                    2, SL_MAX_VERSION), // added with 16.1, but was blank since 2
+
+	SLE_CONDVAR(Company, sharing_delay,         SLE_UINT8,               SL_IS, SL_MAX_VERSION),
 
 	/* Reserve extra space in savegame here. (currently 63 bytes) */
 	SLE_CONDNULL(63, 2, SL_MAX_VERSION),
@@ -212,6 +215,13 @@
 	SLE_END()
 };
 
+static const SaveLoad _company_sharing_desc[] = {
+	SLE_CONDARR(CompanySharingSettingsEntry,            option,  SLE_UINT8, 4, SL_IS, SL_MAX_VERSION),
+	SLE_CONDARR(CompanySharingSettingsEntry,               fee, SLE_UINT16, 4, SL_IS, SL_MAX_VERSION),
+	SLE_CONDVAR(CompanySharingSettingsEntry, allowed_companies, SLE_UINT16,    SL_IS, SL_MAX_VERSION),
+	SLE_END()
+};
+
 static void SaveLoad_PLYR(Company *c)
 {
 	int i;
@@ -228,6 +238,10 @@
 			SlObject(&nothing, _company_ai_build_rec_desc);
 		}
 	}
+
+	/* Write sharing settings */
+	SlObject(&c->sharing_current, _company_sharing_desc);
+	SlObject(&c->sharing_future,  _company_sharing_desc);
 
 	/* Write economy */
 	SlObject(&c->cur_economy, _company_economy_desc);
diff -r ee55d0546576 src/saveload/saveload.cpp
--- a/src/saveload/saveload.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/saveload/saveload.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -40,7 +40,7 @@
 
 #include "saveload_internal.h"
 
-extern const uint16 SAVEGAME_VERSION = 118;
+extern const uint16 SAVEGAME_VERSION = SL_IS;
 
 SavegameType _savegame_type; ///< type of savegame we are loading
 
diff -r ee55d0546576 src/saveload/saveload.h
--- a/src/saveload/saveload.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/saveload/saveload.h	Sat Apr 25 19:58:24 2009 +0200
@@ -72,6 +72,7 @@
 };
 
 #define SL_MAX_VERSION 255
+#define SL_IS 119
 
 enum {
 	INC_VEHICLE_COMMON = 0,
diff -r ee55d0546576 src/settings.cpp
--- a/src/settings.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/settings.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -60,6 +60,8 @@
 
 #include "void_map.h"
 #include "station_base.h"
+#include "infrastructure_func.h"
+#include "core/mem_func.hpp"
 
 #include "table/strings.h"
 #include "table/settings.h"
@@ -969,6 +971,83 @@
 	return true;
 }
 
+/**
+ * Update the sharing settings of all companies if sharing is enabled, and individual settings are disabled
+ * @param p1 unused
+ * @return always true
+ */
+static bool UpdateAllSharingSettings(int32 p1)
+{
+	InvalidateWindowClasses(WC_COMPANY);
+	if (!(_settings_game.sharing.enable_sharing && _settings_game.sharing.individual_allowed)) {
+		DeleteWindowByClass(WC_SHARING_OPTIONS);
+	}
+	if (_settings_game.sharing.individual_allowed) return true;
+	/* If individual settings are disallowed, copy the game settings to all companies */
+	Company *c;
+	byte changed_vehtypes = 0;
+	FOR_ALL_COMPANIES(c) {
+		changed_vehtypes |= c->sharing_current.CopyFromGameSettings();
+		c->sharing_future.CopyFromGameSettings();
+		c->sharing_delay = 0;
+	}
+	HandleSharingChange(changed_vehtypes);
+
+	return true;
+}
+
+/**
+ * Update all sharing settings if sharing is globally enabled / disabled.
+ * @param p1 unused
+ * @return always true
+ */
+static bool UpdateSharingEnabled(int32 p1)
+{
+	if (!_settings_game.sharing.enable_sharing) {
+		/* Sharing was disabled, do this for all companies */
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			/* Disable all sharing options */
+			MemSetT(c->sharing_current.option, 0, SHARING_VEHTYPES);
+			/* Make future settings the same as current ones */
+			c->sharing_future.Copy(&c->sharing_current);
+			c->sharing_delay = 0;
+			/* Always allow our own company */
+			c->sharing_current.allowed_companies = 1 << c->index;
+			c->sharing_future.allowed_companies  = 1 << c->index;
+		}
+		HandleSharingChange(); //invalidate everything
+	} else {
+		HandleSharingChange(1 << VEH_TRAIN); //Invalidate all signal blocks.
+	}
+	/* Invalidate / delete windows, and possibly copy game settings to companies,
+	 * if individual settings are off and sharing has just been enabled */
+	UpdateAllSharingSettings(0);
+	InvalidateWindowClasses(WC_FINANCES);
+	return true;
+}
+
+/**
+ * Cap sharing_delay for all companies to the new delay setting
+ * @param p1 new delay setting
+ * @return always true
+ */
+static bool UpdateSharingDelay(int32 p1)
+{
+	if (!(_settings_game.sharing.enable_sharing && _settings_game.sharing.individual_allowed)) return true;
+
+	byte changed_vehtypes = 0;
+	Company *c;
+	FOR_ALL_COMPANIES(c) {
+		c->sharing_delay = min(c->sharing_delay, p1);
+		/* Delay set to 0 and we have changes pending, apply them now */
+		if (p1 == 0 && !c->sharing_current.Equals(&c->sharing_future)) changed_vehtypes |= c->sharing_current.Copy(&c->sharing_future);
+	}
+	HandleSharingChange(changed_vehtypes);
+	InvalidateWindowClasses(WC_SHARING_OPTIONS);
+	return true;
+}
+
 #ifdef ENABLE_NETWORK
 
 static bool UpdateClientName(int32 p1)
diff -r ee55d0546576 src/settings_gui.cpp
--- a/src/settings_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/settings_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -1235,8 +1235,25 @@
 /** Computer players sub-page */
 static SettingsPage _settings_ai_npc_page = {_settings_ai_npc, lengthof(_settings_ai_npc)};
 
+static SettingEntry _settings_ai_sharing[] = {
+	SettingEntry("sharing.enable_sharing"),
+	SettingEntry("sharing.individual_allowed"),
+	SettingEntry("sharing.new_individual_delay"),
+	SettingEntry("sharing.rail_sharing"),
+	SettingEntry("sharing.road_sharing"),
+	SettingEntry("sharing.water_sharing"),
+	SettingEntry("sharing.air_sharing"),
+	SettingEntry("sharing.rail_fee"),
+	SettingEntry("sharing.road_fee"),
+	SettingEntry("sharing.water_fee"),
+	SettingEntry("sharing.air_fee"),
+};
+/** Infrastructure sharing sub-page */
+static SettingsPage _settings_ai_sharing_page = {_settings_ai_sharing, lengthof(_settings_ai_sharing)};
+
 static SettingEntry _settings_ai[] = {
 	SettingEntry(&_settings_ai_npc_page, STR_CONFIG_SETTING_AI_NPC),
+	SettingEntry(&_settings_ai_sharing_page, STR_CONFIG_SETTING_AI_SHARING),
 	SettingEntry("economy.give_money"),
 	SettingEntry("economy.allow_shares"),
 };
diff -r ee55d0546576 src/settings_type.h
--- a/src/settings_type.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/settings_type.h	Sat Apr 25 19:58:24 2009 +0200
@@ -185,6 +185,23 @@
 	uint32 ai_max_opcode_till_suspend;       ///< max opcode calls till AI will suspend
 };
 
+/** Settings related to sharing. */
+struct SharingSettings {
+	bool   enable_sharing;                   ///< globally enable/disable infrastructure sharing
+	bool   individual_allowed;               ///< allow individual settings?
+	byte   new_individual_delay;             ///< time (in months) it takes for new individual settings to take effect
+
+	byte   rail_sharing;                     ///< sharing rail
+	bool   road_sharing;                     ///< sharing road
+	bool   water_sharing;                    ///< sharing water
+	bool   air_sharing;                      ///< sharing air
+
+	uint16 rail_fee;                         ///< train fee
+	uint16 road_fee;                         ///< road vehicle fee
+	uint16 water_fee;                        ///< ship fee
+	uint16 air_fee;                          ///< aircraft fee
+};
+
 /** Settings related to the old pathfinder. */
 struct OPFSettings {
 	uint16 pf_maxlength;                     ///< maximum length when searching for a train route for new pathfinder
@@ -354,6 +371,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 ee55d0546576 src/ship_cmd.cpp
--- a/src/ship_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/ship_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -30,6 +30,7 @@
 #include "settings_type.h"
 #include "ai/ai.hpp"
 #include "pathfind.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -113,7 +114,7 @@
 
 	FOR_ALL_DEPOTS(depot) {
 		TileIndex tile = depot->xy;
-		if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
+		if (IsShipDepotTile(tile) && IsDepotUsageAllowed(tile, v)) {
 			uint dist = DistanceManhattan(tile, v->tile);
 			if (dist < best_dist) {
 				best_dist = dist;
@@ -741,7 +742,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 (!AreDepotOperationsAllowed(tile, _current_company, VEH_SHIP)) return CMD_ERROR;
 
 	unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_SHIP);
 
diff -r ee55d0546576 src/signal.cpp
--- a/src/signal.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/signal.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -9,6 +9,7 @@
 #include "vehicle_func.h"
 #include "vehicle_base.h"
 #include "functions.h"
+#include "infrastructure_func.h"
 
 
 /** these are the maximums used for updating signal blocks */
@@ -272,7 +273,7 @@
 
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY: {
-				if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
+				if (!AreSignalBlocksJoined(owner, GetTileOwner(tile))) continue; // check whether tile should be part of the same block, owner-wise
 
 				if (IsRailDepot(tile)) {
 					if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
@@ -353,7 +354,7 @@
 
 			case MP_STATION:
 				if (!IsRailwayStation(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!AreSignalBlocksJoined(owner, GetTileOwner(tile)))
 				if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
 				if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
 
@@ -363,7 +364,7 @@
 
 			case MP_ROAD:
 				if (!IsLevelCrossing(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!AreSignalBlocksJoined(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
 
 				if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
@@ -371,7 +372,7 @@
 				break;
 
 			case MP_TUNNELBRIDGE: {
-				if (GetTileOwner(tile) != owner) continue;
+				if (!AreSignalBlocksJoined(owner, GetTileOwner(tile))) continue;
 				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
 				DiagDirection dir = GetTunnelBridgeDirection(tile);
 
diff -r ee55d0546576 src/smallmap_gui.cpp
--- a/src/smallmap_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/smallmap_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -20,6 +20,7 @@
 #include "vehicle_base.h"
 #include "sound_func.h"
 #include "window_func.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -97,6 +98,20 @@
 static const LegendAndColour _legend_routes[] = {
 	MK(0xD7, STR_SMALLMAP_LEGENDA_ROADS),
 	MK(0x0A, STR_SMALLMAP_LEGENDA_RAILROADS),
+	MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
+	MS(0x56, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
+
+	MK(0xC2, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
+	MK(0xBF, STR_SMALLMAP_LEGENDA_BUS_STATION),
+	MK(0xB8, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
+	MK(0x98, STR_SMALLMAP_LEGENDA_DOCK),
+	MKEND()
+};
+
+static const LegendAndColour _legend_routes_sharing[] = {
+	MK(0xD7, STR_SMALLMAP_LEGENDA_ROADS),
+	MK(0x0E, STR_SMALLMAP_LEGENDA_RAILROADS_ACCESSIBLE),
+	MK(0x11, STR_SMALLMAP_LEGENDA_RAILROADS_INACCESSIBLE),
 	MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
 	MS(0x56, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
 
@@ -395,6 +410,14 @@
 			case STATION_BUS:     bits = MKCOLOUR(0xBFBFBFBF); break;
 			case STATION_DOCK:    bits = MKCOLOUR(0x98989898); break;
 			default:              bits = MKCOLOUR(0xFFFFFFFF); break;
+		}
+	} else if (t == MP_RAILWAY && ShowSharingOnMap()) {
+		if (IsRailwayTileUsageAllowed(tile, _local_company)) {
+			/* Make rails color 0x0E (light grey), ground colour 0x54 (green) */
+			bits = MKCOLOUR(0x540E0E54);
+		} else {
+			/* Make rails color 0x11 (dark grey), ground colour 0x54 (green) */
+			bits = MKCOLOUR(0x54111154);
 		}
 	} else {
 		/* ground colour */
@@ -840,7 +863,8 @@
 		int x = 4;
 		int y = y_org;
 
-		for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
+		const LegendAndColour *tbl = (this->map_type == SMT_ROUTES && ShowSharingOnMap()) ? _legend_routes_sharing : _legend_table[this->map_type];
+		while (!tbl->end) {
 			if (tbl->col_break || y >= legend->bottom) {
 				/* Column break needed, continue at top, COLUMN_WIDTH pixels
 				 * (one "row") to the right. */
@@ -870,6 +894,7 @@
 			GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour); // legend colour
 
 			y += 6;
+			tbl++;
 		}
 
 		const Widget *wi = &this->widget[SM_WIDGET_MAP];
diff -r ee55d0546576 src/table/settings.h
--- a/src/table/settings.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/table/settings.h	Sat Apr 25 19:58:24 2009 +0200
@@ -27,6 +27,9 @@
 static int32 CheckNoiseToleranceLevel(const char *value);
 static bool CheckFreeformEdges(int32 p1);
 static bool ChangeDynamicEngines(int32 p1);
+static bool UpdateAllSharingSettings(int32 p1);
+static bool UpdateSharingEnabled(int32 p1);
+static bool UpdateSharingDelay(int32 p1);
 
 #ifdef ENABLE_NETWORK
 static bool UpdateClientName(int32 p1);
@@ -434,6 +437,18 @@
 	    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.enable_sharing,                       SL_IS, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_ENABLE,         UpdateSharingEnabled),
+	SDT_CONDBOOL(GameSettings, sharing.individual_allowed,                   SL_IS, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_INDIVIDUAL,     UpdateAllSharingSettings),
+ 	 SDT_CONDVAR(GameSettings, sharing.new_individual_delay,       SLE_UINT8,SL_IS, SL_MAX_VERSION, 0, 0, 12, 0,            120, 1, STR_CONFIG_SETTING_SHARING_INDIVIDUAL_TIME,UpdateSharingDelay),
+	 SDT_CONDVAR(GameSettings, sharing.rail_sharing,               SLE_UINT8,SL_IS, SL_MAX_VERSION, 0,MS,  0, 0,              4, 0, STR_CONFIG_SETTING_SHARING_RAIL,           UpdateAllSharingSettings),
+	SDT_CONDBOOL(GameSettings, sharing.road_sharing,                         SL_IS, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_ROAD,           UpdateAllSharingSettings),
+	SDT_CONDBOOL(GameSettings, sharing.water_sharing,                        SL_IS, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_WATER,          UpdateAllSharingSettings),
+	SDT_CONDBOOL(GameSettings, sharing.air_sharing,                          SL_IS, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_AIR,            UpdateAllSharingSettings),
+	 SDT_CONDVAR(GameSettings, sharing.rail_fee,                  SLE_UINT16,SL_IS, SL_MAX_VERSION, 0,CR,100, 0,MAX_SHARING_FEE,10, STR_CONFIG_SETTING_SHARING_RAIL_FEE,       UpdateAllSharingSettings),
+	 SDT_CONDVAR(GameSettings, sharing.road_fee,                  SLE_UINT16,SL_IS, SL_MAX_VERSION, 0,CR,100, 0,MAX_SHARING_FEE,10, STR_CONFIG_SETTING_SHARING_ROAD_FEE,       UpdateAllSharingSettings),
+	 SDT_CONDVAR(GameSettings, sharing.water_fee,                 SLE_UINT16,SL_IS, SL_MAX_VERSION, 0,CR,100, 0,MAX_SHARING_FEE,10, STR_CONFIG_SETTING_SHARING_WATER_FEE,      UpdateAllSharingSettings),
+	 SDT_CONDVAR(GameSettings, sharing.air_fee,                   SLE_UINT16,SL_IS, SL_MAX_VERSION, 0,CR,100, 0,MAX_SHARING_FEE,10, STR_CONFIG_SETTING_SHARING_AIR_FEE,        UpdateAllSharingSettings),
+
 	     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 ee55d0546576 src/train.h
--- a/src/train.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/train.h	Sat Apr 25 19:58:24 2009 +0200
@@ -298,6 +298,7 @@
 void CheckTrainsLengths();
 
 void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
+void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir);
 bool TryPathReserve(Vehicle *v, bool mark_as_stuck = false, bool first_tile_okay = false);
 
 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length);
diff -r ee55d0546576 src/train_cmd.cpp
--- a/src/train_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/train_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -33,6 +33,7 @@
 #include "effectvehicle_func.h"
 #include "gamelog.h"
 #include "network/network.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/train_cmd.h"
@@ -793,7 +794,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 (!AreDepotOperationsAllowed(tile, _current_company, VEH_TRAIN)) return CMD_ERROR;
 
 	const RailVehicleInfo *rvi = RailVehInfo(p1);
 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags);
@@ -1966,7 +1967,7 @@
 
 	Vehicle *v = GetVehicle(p1);
 
-	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+	if (v->type != VEH_TRAIN || !IsVehicleControlAllowed(v)) return CMD_ERROR;
 
 	if (p2 != 0) {
 		/* turn a single unit around */
@@ -2027,7 +2028,7 @@
 
 	Vehicle *v = GetVehicle(p1);
 
-	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+	if (v->type != VEH_TRAIN || !IsVehicleControlAllowed(v)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
 
@@ -2147,8 +2148,8 @@
 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
 {
 	if (IsTileType(tile, MP_RAILWAY) &&
-			IsTileOwner(tile, tfdd->owner) &&
-			IsRailDepot(tile)) {
+			IsRailDepot(tile) &&
+			IsDepotUsageAllowed(tile, tfdd->owner, VEH_TRAIN)) {
 		/* approximate number of tiles by dividing by DIAG_FACTOR */
 		tfdd->best_length = length / DIAG_FACTOR;
 		tfdd->tile = tile;
@@ -2473,7 +2474,7 @@
 }
 
 /** Clear the reservation of a tile that was just left by a wagon on track_dir. */
-static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir)
+void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir)
 {
 	DiagDirection dir = TrackdirToExitdir(track_dir);
 
@@ -3418,7 +3419,7 @@
 static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
 {
 	return
-		IsTileOwner(tile, v->owner) && (
+		IsRailwayTileUsageAllowed(tile, v->owner) && (
 			!IsFrontEngine(v) ||
 			HasBit(v->u.rail.compatible_railtypes, GetRailType(tile))
 		);
@@ -4510,6 +4511,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;
 
diff -r ee55d0546576 src/vehicle.cpp
--- a/src/vehicle.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/vehicle.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -37,6 +37,7 @@
 #include "depot_func.h"
 #include "settings_type.h"
 #include "network/network.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -1551,6 +1552,9 @@
 		case OT_LOADING: {
 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
 
+			/* Pay the loading fee when using someone else's station */
+			if (!(mode || this->type == VEH_TRAIN)) PayStationSharingFee(this, GetStation(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 ee55d0546576 src/vehicle_cmd.cpp
--- a/src/vehicle_cmd.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/vehicle_cmd.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -18,6 +18,7 @@
 #include "string_func.h"
 #include "depot_map.h"
 #include "vehiclelist.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -65,7 +66,7 @@
 
 	Vehicle *v = GetVehicle(p1);
 
-	if (!CheckOwnership(v->owner)) return CMD_ERROR;
+	if (!IsVehicleControlAllowed(v)) return CMD_ERROR;
 	if (!v->IsPrimaryVehicle()) return CMD_ERROR;
 
 	switch (v->type) {
@@ -223,7 +224,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) || !AreDepotOperationsAllowed(tile, _current_company, vehicle_type)) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
 	BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
diff -r ee55d0546576 src/vehicle_gui.cpp
--- a/src/vehicle_gui.cpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/vehicle_gui.cpp	Sat Apr 25 19:58:24 2009 +0200
@@ -30,6 +30,7 @@
 #include "vehiclelist.h"
 #include "settings_type.h"
 #include "articulated_vehicles.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -1893,6 +1894,7 @@
 		const Vehicle *v = GetVehicle(this->window_number);
 		StringID str;
 		bool is_localcompany = v->owner == _local_company;
+		bool can_control = IsVehicleControlAllowed(v);
 		bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
 
 		this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localcompany);
@@ -1901,8 +1903,8 @@
 		this->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localcompany);
 
 		if (v->type == VEH_TRAIN) {
-			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);
 		}
 
 		/* draw widgets & caption */
diff -r ee55d0546576 src/window_type.h
--- a/src/window_type.h	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/window_type.h	Sat Apr 25 19:58:24 2009 +0200
@@ -99,6 +99,7 @@
 	WC_AI_DEBUG,
 	WC_AI_LIST,
 	WC_AI_SETTINGS,
+	WC_SHARING_OPTIONS,
 
 	WC_INVALID = 0xFFFF
 };
diff -r ee55d0546576 src/yapf/follow_track.hpp
--- a/src/yapf/follow_track.hpp	Sat Apr 25 12:00:54 2009 +0000
+++ b/src/yapf/follow_track.hpp	Sat Apr 25 19:58:24 2009 +0200
@@ -7,6 +7,7 @@
 
 #include "yapf.hpp"
 #include "../depot_map.h"
+#include "../infrastructure_func.h"
 
 /** Track follower helper template class (can serve pathfinders and vehicle
  *  controllers). See 6 different typedefs below for 3 different transport
@@ -53,12 +54,12 @@
 	{
 		assert(!IsRailTT() || (v != NULL && v->type == VEH_TRAIN));
 		m_veh = v;
-		Init(v != NULL ? v->owner : INVALID_OWNER, railtype_override == INVALID_RAILTYPES ? v->u.rail.compatible_railtypes : railtype_override, pPerf);
+		Init(v != NULL ? v->owner : INVALID_OWNER, (railtype_override == INVALID_RAILTYPES && v != NULL) ? v->u.rail.compatible_railtypes : railtype_override, pPerf);
 	}
 
 	FORCEINLINE void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf)
 	{
-		assert((!IsRoadTT() || m_veh != NULL) && (!IsRailTT() || railtype_override != INVALID_RAILTYPES));
+		assert(!IsRoadTT() || m_veh != NULL);
 		m_veh_owner = o;
 		m_pPerf = pPerf;
 		/* don't worry, all is inlined so compiler should remove unnecessary initializations */
@@ -263,11 +264,17 @@
 	/** return true if we can enter m_new_tile from m_exitdir */
 	FORCEINLINE bool CanEnterNewTile()
 	{
+		bool ignore_owner = (m_veh_owner == INVALID_OWNER);
 		if (IsRoadTT() && IsStandardRoadStopTile(m_new_tile)) {
 			/* road stop can be entered from one direction only unless it's a drive-through stop */
 			DiagDirection exitdir = GetRoadStopDir(m_new_tile);
 			if (ReverseDiagDir(exitdir) != m_exitdir) {
 				m_err = EC_NO_WAY;
+				return false;
+			}
+			/* road stops shouldn't be entered unless allowed to */
+			if (!(ignore_owner || IsStationUsageAllowed(m_new_tile, m_veh_owner, VEH_ROAD))) {
+				m_err = EC_OWNER;
 				return false;
 			}
 		}
@@ -288,22 +295,22 @@
 				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 companies' depots, unless allowed to */
+			if (!(ignore_owner || IsDepotUsageAllowed(m_new_tile, m_veh_owner, VEH_ROAD))) {
 				m_err = EC_OWNER;
 				return false;
 			}
 		}
 		if (IsRailTT() && IsDepotTypeTile(m_new_tile, TT())) {
 			DiagDirection exitdir = GetRailDepotDirection(m_new_tile);
-			if (ReverseDiagDir(exitdir) != m_exitdir) {
+			if (ReverseDiagDir(exitdir) != m_exitdir || !(ignore_owner || IsDepotUsageAllowed(m_new_tile, m_veh_owner, VEH_TRAIN))) {
 				m_err = EC_NO_WAY;
 				return false;
 			}
 		}
 
-		/* 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 where the vehicle is allowed */
+		if (IsRailTT() && !(ignore_owner || IsRailwayTileUsageAllowed(m_new_tile, m_veh_owner))) {
 			/* different owner */
 			m_err = EC_NO_WAY;
 			return false;
