imported patch STS_V50.patch

diff -r af3f5c2dd1e2 projects/openttd_vs100.vcxproj
--- a/projects/openttd_vs100.vcxproj	Sat May 07 00:22:46 2011 +0000
+++ b/projects/openttd_vs100.vcxproj	Sat May 07 17:51:55 2011 +0200
@@ -582,6 +582,7 @@
     <ClInclude Include="..\src\transparency.h" />
     <ClInclude Include="..\src\transparency_gui.h" />
     <ClInclude Include="..\src\transport_type.h" />
+    <ClInclude Include="..\src\ttsep_gui.h" />
     <ClInclude Include="..\src\tunnelbridge.h" />
     <ClInclude Include="..\src\vehicle_base.h" />
     <ClInclude Include="..\src\vehicle_func.h" />
@@ -677,6 +678,7 @@
     <ClCompile Include="..\src\train_gui.cpp" />
     <ClCompile Include="..\src\transparency_gui.cpp" />
     <ClCompile Include="..\src\tree_gui.cpp" />
+    <ClCompile Include="..\src\ttsep_gui.cpp" />
     <ClCompile Include="..\src\vehicle_gui.cpp" />
     <ClCompile Include="..\src\viewport_gui.cpp" />
     <ClCompile Include="..\src\waypoint_gui.cpp" />
diff -r af3f5c2dd1e2 projects/openttd_vs100.vcxproj.filters
--- a/projects/openttd_vs100.vcxproj.filters	Sat May 07 00:22:46 2011 +0000
+++ b/projects/openttd_vs100.vcxproj.filters	Sat May 07 17:51:55 2011 +0200
@@ -966,6 +966,9 @@
     <ClInclude Include="..\src\transport_type.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\ttsep_gui.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\tunnelbridge.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -1251,6 +1254,9 @@
     <ClCompile Include="..\src\tree_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\ttsep_gui.cpp">
+      <Filter>GUI Source Code</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\vehicle_gui.cpp">
       <Filter>GUI Source Code</Filter>
     </ClCompile>
diff -r af3f5c2dd1e2 projects/openttd_vs80.vcproj
--- a/projects/openttd_vs80.vcproj	Sat May 07 00:22:46 2011 +0000
+++ b/projects/openttd_vs80.vcproj	Sat May 07 17:51:55 2011 +0200
@@ -1603,6 +1603,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ttsep_gui.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\tunnelbridge.h"
 				>
 			</File>
@@ -1991,6 +1995,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ttsep_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\vehicle_gui.cpp"
 				>
 			</File>
diff -r af3f5c2dd1e2 projects/openttd_vs90.vcproj
--- a/projects/openttd_vs90.vcproj	Sat May 07 00:22:46 2011 +0000
+++ b/projects/openttd_vs90.vcproj	Sat May 07 17:51:55 2011 +0200
@@ -1600,6 +1600,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ttsep_gui.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\tunnelbridge.h"
 				>
 			</File>
@@ -1988,6 +1992,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ttsep_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\vehicle_gui.cpp"
 				>
 			</File>
diff -r af3f5c2dd1e2 source.list
--- a/source.list	Sat May 07 00:22:46 2011 +0000
+++ b/source.list	Sat May 07 17:51:55 2011 +0200
@@ -315,6 +315,7 @@
 transparency.h
 transparency_gui.h
 transport_type.h
+ttsep_gui.h
 tunnelbridge.h
 vehicle_base.h
 vehicle_func.h
@@ -429,6 +430,7 @@
 train_gui.cpp
 transparency_gui.cpp
 tree_gui.cpp
+ttsep_gui.cpp
 vehicle_gui.cpp
 viewport_gui.cpp
 waypoint_gui.cpp
diff -r af3f5c2dd1e2 src/command.cpp
--- a/src/command.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/command.cpp	Sat May 07 17:51:55 2011 +0200
@@ -172,6 +172,7 @@
 CommandProc CmdSetVehicleOnTime;
 CommandProc CmdAutofillTimetable;
 CommandProc CmdSetTimetableStart;
+CommandProc CmdReinitSeparation;
 
 #define DEF_CMD(proc, flags, type) {proc, #proc, flags, type}
 
@@ -305,6 +306,7 @@
 	DEF_CMD(CmdSetVehicleOnTime,                               0, CMDT_ROUTE_MANAGEMENT      ), // CMD_SET_VEHICLE_ON_TIME
 	DEF_CMD(CmdAutofillTimetable,                              0, CMDT_ROUTE_MANAGEMENT      ), // CMD_AUTOFILL_TIMETABLE
 	DEF_CMD(CmdSetTimetableStart,                              0, CMDT_ROUTE_MANAGEMENT      ), // CMD_SET_TIMETABLE_START
+	DEF_CMD(CmdReinitSeparation,                               0, CMDT_ROUTE_MANAGEMENT      ), // CMD_REINIT_SEPARATION
 };
 
 /*!
diff -r af3f5c2dd1e2 src/command_type.h
--- a/src/command_type.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/command_type.h	Sat May 07 17:51:55 2011 +0200
@@ -269,6 +269,7 @@
 	CMD_SET_VEHICLE_ON_TIME,          ///< set the vehicle on time feature (timetable)
 	CMD_AUTOFILL_TIMETABLE,           ///< autofill the timetable
 	CMD_SET_TIMETABLE_START,          ///< set the date that a timetable should start
+	CMD_REINIT_SEPARATION,            ///< reinit timetable separation with new parameters
 
 	CMD_END                           ///< Must ALWAYS be on the end of this list!! (period)
 };
diff -r af3f5c2dd1e2 src/date.cpp
--- a/src/date.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/date.cpp	Sat May 07 17:51:55 2011 +0200
@@ -153,9 +153,13 @@
 
 	return DAYS_TILL(year) + days;
 }
+/**
+ * Converts the current day counter and date fraction into an absolute tick value.
+ * @returns current time as ticks
+ */
+Ticks GetCurrentTickCount() { return _date * DAY_TICKS + _date_fract; }
 
 /** Functions used by the IncreaseDate function */
-
 extern void EnginesDailyLoop();
 extern void DisasterDailyLoop();
 extern void IndustryDailyLoop();
diff -r af3f5c2dd1e2 src/date_func.h
--- a/src/date_func.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/date_func.h	Sat May 07 17:51:55 2011 +0200
@@ -23,7 +23,7 @@
 void SetDate(Date date, DateFract fract);
 void ConvertDateToYMD(Date date, YearMonthDay *ymd);
 Date ConvertYMDToDate(Year year, Month month, Day day);
-
+Ticks GetCurrentTickCount();
 /**
  * Checks whether the given year is a leap year or not.
  * @param yr The year to check.
diff -r af3f5c2dd1e2 src/lang/english.txt
--- a/src/lang/english.txt	Sat May 07 00:22:46 2011 +0000
+++ b/src/lang/english.txt	Sat May 07 17:51:55 2011 +0200
@@ -1237,6 +1237,7 @@
 STR_CONFIG_SETTING_LOADING_INDICATORS                           :{LTBLUE}Use loading indicators: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_TIMETABLE_IN_TICKS                           :{LTBLUE}Show timetable in ticks rather than days: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE             :{LTBLUE}Show arrival and departure in timetables: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_TIMETABLE_ENABLE_SEPARATION                  :{LTBLUE}Enable automatic timetable separation: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_QUICKGOTO                                    :{LTBLUE}Quick creation of vehicle orders: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE                            :{LTBLUE}Default rail type (after new game/game load): {ORANGE}{STRING1}
 STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST                      :First available
@@ -3396,6 +3397,32 @@
 STR_FEEDER                                                      :{YELLOW}Transfer: {CURRENCY}
 STR_MESSAGE_ESTIMATED_COST                                      :{WHITE}Estimated Cost: {CURRENCY}
 STR_MESSAGE_ESTIMATED_INCOME                                    :{WHITE}Estimated Income: {CURRENCY}
+# Timetable Separation stuff
+STR_TTSEPARATION_AUTO                                           :{BLACK}Auto
+STR_TTSEPARATION_MAN_NUM                                        :{BLACK}Man N
+STR_TTSEPARATION_MAN_TIME                                       :{BLACK}Man T
+STR_TTSEPARATION_OFF                                            :{BLACK}Off
+STR_TTSEPARATION_TIME_DESC                                      :{BLACK}Time between Vehicles:
+STR_TTSEPARATION_NUM_DESC                                       :{BLACK}Number of Vehicles:
+STR_TTSEPARATION_VIEW_SETTINGS                                  :{BLACK}Separation
+STR_TTSEPARATION_SETTINGS_TITLE                                 :{WHITE}Separation
+STR_TTSEPARATION_APPLY                                          :{BLACK}Apply
+STR_TTSEPARATION_RESET                                          :{BLACK}Reset
+# Timetable separation new gui stuff
+STR_TTSEPARATION_MODE_DESC                                      :{BLACK}Separation mode
+STR_TTSEPARATION_SETTINGS_DESC                                  :{BLACK}Separation settings
+STR_TTSEPARATION_SET_TIME                                       :{BLACK}Set time
+STR_TTSEPARATION_SET_NUM                                        :{BLACK}Set number
+#STR_TTSEPARATION_STATUS_DESC                                    :{BLACK}Status:{}{STRING} // Replacement for dummy below
+STR_TTSEPARATION_STATUS_INIT                                    :Initializing
+STR_TTSEPARATION_STATUS_RUNNING                                 :Running
+STR_TTSEPARATION_STATUS_OFF                                     :Off
+#STR_TTSEPARATION_REQ_TIME_DESC                                  :{BLACK}{NUM} ticks{}between vehicles // Replacement for dummy below
+STR_TTSEPARATION_REQ_NUM_DESC                                   :{BLACK}Required time:{}{NUM} ticks
+
+#dummies
+STR_TTSEPARATION_STATUS_DESC                                    :{BLACK}Status:{}{DKGREEN}Running
+STR_TTSEPARATION_REQ_TIME_DESC                                  :{BLACK}88888 ticks{}between vehicles
 
 # Saveload messages
 STR_ERROR_SAVE_STILL_IN_PROGRESS                                :{WHITE}Saving still in progress,{}please wait until it is finished!
diff -r af3f5c2dd1e2 src/order_base.h
--- a/src/order_base.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/order_base.h	Sat May 07 17:51:55 2011 +0200
@@ -20,7 +20,7 @@
 #include "station_type.h"
 #include "vehicle_type.h"
 #include "date_type.h"
-
+#include "date_func.h"
 typedef Pool<Order, OrderID, 256, 64000> OrderPool;
 typedef Pool<OrderList, OrderListID, 128, 64000> OrderListPool;
 extern OrderPool _order_pool;
@@ -179,9 +179,23 @@
 
 void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord);
 void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord);
-
 /**
  * Shared order list linking together the linked list of orders and the list
+/** Working modes for timetable separation */
+enum TTSep_Mode {
+	TTS_MODE_AUTO,
+	TTS_MODE_OFF,
+	TTS_MODE_MAN_T,
+	TTS_MODE_MAN_N,
+};
+
+struct TTSepSettings {
+	TTSep_Mode mode;
+	uint num_veh, sep_ticks;
+	TTSepSettings() : mode(TTS_MODE_AUTO), num_veh(0), sep_ticks(0) { }
+};
+
+/** Shared order list linking together the linked list of orders and the list
  *  of vehicles sharing this order list.
  */
 struct OrderList : OrderListPool::PoolItem<&_orderlist_pool> {
@@ -194,15 +208,20 @@
 	VehicleOrderID num_manual_orders; ///< NOSAVE: How many manually added orders are there in the list.
 	uint num_vehicles;                ///< NOSAVE: Number of vehicles that share this order list.
 	Vehicle *first_shared;            ///< NOSAVE: pointer to the first vehicle in the shared order chain.
-
 	Ticks timetable_duration;         ///< NOSAVE: Total duration of the order list
+	Ticks last_timetable_init;          ///< The last absolute time of initialization in Ticks.
+	uint separation_counter;            ///< Counts the vehicles that arrive at the first shared order for separation timing.
+	bool is_separation_valid;           ///< Is true if the separation has been initialized since last load or vehicle list change.
+	Ticks current_separation;           ///< The current separation between vehicles in the shared order list.
+	TTSep_Mode current_sep_mode;        ///< The current mode of vehicle separation
+	uint num_sep_vehicles;              ///< Number of planned vehicles for separation
 
 public:
 	/** Default constructor producing an invalid order list. */
 	OrderList(VehicleOrderID num_orders = INVALID_VEH_ORDER_ID)
 		: first(NULL), num_orders(num_orders), num_manual_orders(0), num_vehicles(0), first_shared(NULL),
-		  timetable_duration(0) { }
-
+		  timetable_duration(0), separation_counter(0), last_timetable_init(INVALID_TICKS),
+		  is_separation_valid(false), current_separation(INVALID_TICKS) { }
 	/**
 	 * Create an order list with the given order chain for the given vehicle.
 	 *  @param chain pointer to the first order of the order chain
@@ -262,10 +281,26 @@
 	 * @return the count of vehicles that use this shared orders list
 	 */
 	inline uint GetNumVehicles() const { return this->num_vehicles; }
+	/**
+	 * Return the amount of separation time between vehicles
+	 * @return the amount of separation time between vehicles
+	 */
+	inline uint GetSepTime() const {
+		if (this->is_separation_valid)
+		{
+			return this->current_separation;
+		} else {
+			return this->GetTimetableTotalDuration() / this->GetNumVehicles();
+		}
+	}
+
+	TTSepSettings GetSepSettings();
+
+	void SetSepSettings(TTSepSettings s);
+	void SetSepSettings(TTSep_Mode Mode, uint Parameter);
 
 	bool IsVehicleInSharedOrdersList(const Vehicle *v) const;
 	int GetPositionInSharedOrderList(const Vehicle *v) const;
-
 	/**
 	 * Adds the given vehicle to this shared order list.
 	 * @note This is supposed to be called after the vehicle has been inserted
@@ -295,9 +330,51 @@
 	 * @param delta By how many ticks has the timetable duration changed
 	 */
 	void UpdateOrderTimetable(Ticks delta) { this->timetable_duration += delta; }
+	/**
+	 * Gets the last absolute time in Ticks since separation was initalized.
+	 * @return last arrival time of first vehicle at first order
+	 */
+	inline Ticks GetSeparationInitTime() const { return this->last_timetable_init; }
+
+	/**
+	 * Gets the current value of the timetable separation counter.
+	 */
+	inline uint GetSeparationCounter() const { return this->separation_counter; }
+
+	/**
+	 * Increases the Timetable separation counter.
+	 */
+	void IncreaseSeparationCounter() { this->separation_counter++; }
+
+	/**
+	 * Marks timetable separation invalid so it has to be initialized again.
+	 */
+	void MarkSeparationInvalid()
+	{
+		if (current_sep_mode == TTS_MODE_AUTO)
+		{
+			this->is_separation_valid = false;
+		}
+	}
+
+	/**
+	 * Returns the new delay for the current vehicle and increases the separation counter.
+	 * @return the new delay
+	 */
+	Ticks SeparateVehicle();
+
+	/**
+	 * Gets whether the timetable separation is currently valid or not.
+	 * @return whether the timetable separation is currently valid or not.
+	 */
+	inline bool IsSeparationValid() const { return this->is_separation_valid; }
+
+	/**
+	 * Initializes the separation system.
+	 */
+	void InitializeSeparation();
 
 	void FreeChain(bool keep_orderlist = false);
-
 	void DebugCheckSanity() const;
 };
 
diff -r af3f5c2dd1e2 src/order_cmd.cpp
--- a/src/order_cmd.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/order_cmd.cpp	Sat May 07 17:51:55 2011 +0200
@@ -468,6 +468,8 @@
  */
 bool OrderList::IsCompleteTimetable() const
 {
+	if(this == NULL) return false;
+
 	for (Order *o = this->first; o != NULL; o = o->next) {
 		/* Automatic orders are, by definition, not timetabled. */
 		if (o->IsType(OT_AUTOMATIC)) continue;
@@ -506,6 +508,121 @@
 			(uint)this->num_orders, (uint)this->num_manual_orders,
 			this->num_vehicles, this->timetable_duration);
 }
+/**
+* (Re-)Initializes Separation if necessary and possible.
+*/
+void OrderList::InitializeSeparation()
+{
+	int num_running_vehicles = 0;
+
+	if (this->IsCompleteTimetable()
+		&& (this->current_sep_mode != TTS_MODE_OFF))
+	{
+		this->last_timetable_init = GetCurrentTickCount();
+		this->separation_counter = 0;
+
+		switch (current_sep_mode) {
+		case TTS_MODE_AUTO:
+
+			for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
+				if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) num_running_vehicles++;
+			}
+
+			this->current_separation = this->GetTimetableTotalDuration() / num_running_vehicles;
+			break;
+
+		case TTS_MODE_MAN_N:
+			this->current_separation = this->GetTimetableTotalDuration() / this->num_sep_vehicles;
+			break;
+		}
+
+		this->is_separation_valid = true;
+
+	} else {
+		this->is_separation_valid = false;
+	}
+}
+
+/**
+* Returns the delay setting required for correct separation and increases the separation counter by 1.
+*/
+Ticks OrderList::SeparateVehicle()
+{
+	if (this->is_separation_valid
+		&& (this->current_sep_mode != TTS_MODE_OFF))
+	{
+		Ticks result = GetCurrentTickCount() - (this->separation_counter * this->current_separation + this->last_timetable_init);
+		this->separation_counter++;
+		return result;
+	} else {
+		return INVALID_TICKS;
+	}
+}
+
+/**
+* Returns current separation settings.
+*/
+TTSepSettings OrderList::GetSepSettings() {
+	TTSepSettings result;
+	result.mode = this->current_sep_mode;
+
+	/*
+	* To be kept around until I'm sure that the () ? :-construction below works as intended.
+	*/
+/*	switch (result.mode)
+	{
+	case TTS_MODE_OFF:
+		result.num_veh = GetNumVehicles();
+		result.sep_ticks = 0;
+		break;
+	case TTS_MODE_AUTO:
+		result.num_veh = GetNumVehicles();
+		result.sep_ticks = GetSepTime();
+		break;
+	case TTS_MODE_MAN_N:
+		result.num_veh = num_sep_vehicles;
+		result.sep_ticks = GetSepTime();
+		break;
+	case TTS_MODE_MAN_T:
+		result.num_veh = GetNumVehicles();
+		result.sep_ticks = GetSepTime();
+		break;
+	} */
+
+	result.sep_ticks = (result.mode != TTS_MODE_OFF) ? GetSepTime() : 0;
+	result.num_veh = (result.mode == TTS_MODE_MAN_N) ? num_sep_vehicles : GetNumVehicles();
+	return result;
+}
+
+/**
+* Sets new separation settings.
+*/
+void OrderList::SetSepSettings(TTSepSettings s)
+{
+	uint32 p2 = GB<uint32>(s.mode,0,2);
+	AB<uint32, uint>(p2,2,30, (s.mode == TTS_MODE_MAN_N) ? s.num_veh : s.sep_ticks);
+	DoCommandP(0, this->first_shared->index, p2, CMD_REINIT_SEPARATION);
+}
+
+void OrderList::SetSepSettings(TTSep_Mode Mode, uint Parameter)
+{
+	this->current_sep_mode = Mode;
+
+	switch(this->current_sep_mode)
+	{
+	case TTS_MODE_MAN_N:
+		this->current_separation = this->GetTimetableTotalDuration() / Parameter;
+		this->num_sep_vehicles = Parameter;
+		break;
+
+	case TTS_MODE_MAN_T:
+		this->current_separation = Parameter;
+		this->num_sep_vehicles = this->GetTimetableTotalDuration() / current_separation;
+		break;
+	}
+
+	is_separation_valid = false;
+}
 
 /**
  * Checks whether the order goes to a station or not, i.e. whether the
diff -r af3f5c2dd1e2 src/saveload/order_sl.cpp
--- a/src/saveload/order_sl.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/saveload/order_sl.cpp	Sat May 07 17:51:55 2011 +0200
@@ -204,9 +204,15 @@
 {
 	static const SaveLoad _orderlist_desc[] = {
 		SLE_REF(OrderList, first,              REF_ORDER),
+		SLE_CONDVAR(OrderList, current_sep_mode, SLE_UINT, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, num_sep_vehicles, SLE_UINT, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, separation_counter, SLE_UINT, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, separation_counter, SLE_UINT, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, is_separation_valid, SLE_BOOL, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, current_separation, SLE_INT, SL_TTSEP_VER, SL_MAX_VERSION),
+		SLE_CONDVAR(OrderList, last_timetable_init, SLE_INT, SL_TTSEP_VER, SL_MAX_VERSION),
 		SLE_END()
 	};
-
 	return _orderlist_desc;
 }
 
diff -r af3f5c2dd1e2 src/saveload/saveload.cpp
--- a/src/saveload/saveload.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/saveload/saveload.cpp	Sat May 07 17:51:55 2011 +0200
@@ -226,10 +226,8 @@
  *  159   21962
  *  160   21974
  */
-extern const uint16 SAVEGAME_VERSION = 160; ///< Current savegame version of OpenTTD.
-
+extern const uint16 SAVEGAME_VERSION = SL_TTSEP_VER; ///< Current savegame version of OpenTTD.
 SavegameType _savegame_type; ///< type of savegame we are loading
-
 uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
diff -r af3f5c2dd1e2 src/saveload/saveload.h
--- a/src/saveload/saveload.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/saveload/saveload.h	Sat May 07 17:51:55 2011 +0200
@@ -18,9 +18,9 @@
 #ifdef SIZE_MAX
 #undef SIZE_MAX
 #endif
+#define SL_TTSEP_VER 161
 
 #define SIZE_MAX ((size_t)-1)
-
 /** Save or load result codes. */
 enum SaveOrLoadResult {
 	SL_OK     = 0, ///< completed successfully
diff -r af3f5c2dd1e2 src/settings_gui.cpp
--- a/src/settings_gui.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/settings_gui.cpp	Sat May 07 17:51:55 2011 +0200
@@ -1557,6 +1557,7 @@
 	SettingEntry("vehicle.max_ships"),
 	SettingEntry("vehicle.plane_speed"),
 	SettingEntry("vehicle.plane_crashes"),
+	SettingEntry("order.automatic_timetable_separation"),
 	SettingEntry("vehicle.dynamic_engines"),
 	SettingEntry("vehicle.roadveh_acceleration_model"),
 	SettingEntry("vehicle.roadveh_slope_steepness"),
diff -r af3f5c2dd1e2 src/settings_type.h
--- a/src/settings_type.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/settings_type.h	Sat May 07 17:51:55 2011 +0200
@@ -356,9 +356,9 @@
 	bool   gradual_loading;                  ///< load vehicles gradually
 	bool   selectgoods;                      ///< only send the goods to station if a train has been there
 	bool   no_servicing_if_no_breakdowns;    ///< dont send vehicles to depot when breakdowns are disabled
+	bool   automatic_timetable_separation;   ///< enable automatic separation of vehicles in the timetable
 	bool   serviceathelipad;                 ///< service helicopters at helipads automatically (no need to send to depot)
 };
-
 /** Settings related to vehicles. */
 struct VehicleSettings {
 	uint8  max_train_length;                 ///< maximum length for trains
diff -r af3f5c2dd1e2 src/table/settings.ini
--- a/src/table/settings.ini	Sat May 07 00:22:46 2011 +0000
+++ b/src/table/settings.ini	Sat May 07 17:51:55 2011 +0200
@@ -874,6 +874,12 @@
 var      = order.selectgoods
 def      = true
 str      = STR_CONFIG_SETTING_SELECTGOODS
+[SDT_BOOL]
+base     = GameSettings
+var      = order.automatic_timetable_separation
+from     = SL_TTSEP_VER
+def      = true
+str      = STR_CONFIG_SETTING_TIMETABLE_ENABLE_SEPARATION
 
 [SDTC_BOOL]
 var      = gui.sg_new_nonstop
diff -r af3f5c2dd1e2 src/timetable_cmd.cpp
--- a/src/timetable_cmd.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/timetable_cmd.cpp	Sat May 07 17:51:55 2011 +0200
@@ -46,6 +46,7 @@
 			} else {
 				v->current_order.wait_time = time;
 			}
+			v->MarkSeparationInvalid();
 		}
 		SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
 	}
@@ -230,6 +231,32 @@
 }
 
 /**
+ * Set new separation parameters
+ * @param tile Not used.
+ * @param flags Operation to perform.
+ * @param p1 Order lit id.
+ * @param p2 
+ - p2 = (bit 0-1) - Separation mode (off / Auto / Man N / Man T)
+ - p2 = (bit 2-31) - Separation parameter (Unused if off | Auto, Number of vehicles if Man N, Separation delay in Ticks if Man T)
+ * @param text Not used.
+ * @return The error or cost of the operation.
+ */
+CommandCost CmdReinitSeparation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+	Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
+	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
+
+	CommandCost ret = CheckOwnership(v->owner);
+	if (ret.Failed()) return ret;
+
+	if (flags & DC_EXEC) {
+		v->SetSepSettings((TTSep_Mode)GB(p2,0,2), GB(p2,2,29));
+	}
+
+	return CommandCost();
+}
+
+/**
  * Update the timetable for the vehicle.
  * @param v The vehicle to update the timetable for.
  * @param travelling Whether we just travelled or waited at a station.
diff -r af3f5c2dd1e2 src/timetable_gui.cpp
--- a/src/timetable_gui.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/timetable_gui.cpp	Sat May 07 17:51:55 2011 +0200
@@ -24,13 +24,14 @@
 #include "date_gui.h"
 #include "vehicle_gui.h"
 #include "settings_type.h"
-
+#include "ttsep_gui.h"
 #include "table/sprites.h"
 #include "table/strings.h"
 
 enum TimetableViewWindowWidgets {
 	TTV_CAPTION,
 	TTV_ORDER_VIEW,
+	TTV_TTSEP_VIEW,
 	TTV_TIMETABLE_PANEL,
 	TTV_ARRIVAL_DEPARTURE_PANEL,      ///< Panel with the expected/scheduled arrivals
 	TTV_SCROLLBAR,
@@ -44,6 +45,10 @@
 	TTV_SHARED_ORDER_LIST,           ///< Show the shared order list
 	TTV_ARRIVAL_DEPARTURE_SELECTION, ///< Disable/hide the arrival departure panel
 	TTV_EXPECTED_SELECTION,          ///< Disable/hide the expected selection button
+	TTV_TTSEP_MODE_DROPDOWN,         ///< Select separation mode dropdown
+	TTV_TTSEP_SET_PARAMETER,         ///< Set the separation parameter (time / number)
+	TTV_TTSEP_INFO_TEXT,             ///< Contains separation info
+	TTV_TTSEP_STATUS_TEXT,           ///< Contains status info
 };
 
 /** Container for the arrival/departure dates of a vehicle */
@@ -351,9 +356,9 @@
 			this->DisableWidget(TTV_AUTOFILL);
 			this->DisableWidget(TTV_SHARED_ORDER_LIST);
 		}
-
 		this->SetWidgetLoweredState(TTV_AUTOFILL, HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE));
-
+		this->SetWidgetDisabledState(TTV_TTSEP_VIEW, !(_settings_game.order.automatic_timetable_separation
+			&& this->vehicle->orders.list->IsCompleteTimetable()));
 		this->DrawWidgets();
 	}
 
@@ -524,10 +529,12 @@
 			case TTV_ORDER_VIEW: // Order view button
 				ShowOrdersWindow(v);
 				break;
+			case TTV_TTSEP_VIEW: // Separation view button
+				ShowTTSeparationSettings(v->orders.list);
+				break;
 
 			case TTV_TIMETABLE_PANEL: { // Main panel.
 				int selected = GetOrderFromTimetableWndPt(pt.y, v);
-
 				this->DeleteChildWindows();
 				this->sel_index = (selected == INVALID_ORDER || selected == this->sel_index) ? -1 : selected;
 				break;
@@ -626,18 +633,32 @@
 	NWidget(NWID_HORIZONTAL),
 		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
 		NWidget(WWT_CAPTION, COLOUR_GREY, TTV_CAPTION), SetDataTip(STR_TIMETABLE_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_TTSEP_VIEW), SetMinimalSize(61, 14), SetDataTip( STR_TTSEPARATION_VIEW_SETTINGS, STR_NULL),
 		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_ORDER_VIEW), SetMinimalSize(61, 14), SetDataTip( STR_TIMETABLE_ORDER_VIEW, STR_TIMETABLE_ORDER_VIEW_TOOLTIP),
 		NWidget(WWT_SHADEBOX, COLOUR_GREY),
 		NWidget(WWT_STICKYBOX, COLOUR_GREY),
 	EndContainer(),
 	NWidget(NWID_HORIZONTAL),
-		NWidget(WWT_PANEL, COLOUR_GREY, TTV_TIMETABLE_PANEL), SetMinimalSize(388, 82), SetResize(1, 10), SetDataTip(STR_NULL, STR_TIMETABLE_TOOLTIP), SetScrollbar(TTV_SCROLLBAR), EndContainer(),
-		NWidget(NWID_SELECTION, INVALID_COLOUR, TTV_ARRIVAL_DEPARTURE_SELECTION),
-			NWidget(WWT_PANEL, COLOUR_GREY, TTV_ARRIVAL_DEPARTURE_PANEL), SetMinimalSize(110, 0), SetFill(0, 1), SetDataTip(STR_NULL, STR_TIMETABLE_TOOLTIP), SetScrollbar(TTV_SCROLLBAR), EndContainer(),
+		NWidget(NWID_VERTICAL),
+			NWidget(NWID_HORIZONTAL),
+				NWidget(WWT_PANEL, COLOUR_GREY, TTV_TIMETABLE_PANEL), SetMinimalSize(388, 82), SetResize(1, 10), SetDataTip(STR_NULL, STR_TIMETABLE_TOOLTIP), SetScrollbar(TTV_SCROLLBAR), EndContainer(),
+				NWidget(NWID_SELECTION, INVALID_COLOUR, TTV_ARRIVAL_DEPARTURE_SELECTION),
+					NWidget(WWT_PANEL, COLOUR_GREY, TTV_ARRIVAL_DEPARTURE_PANEL), SetMinimalSize(110, 0), SetFill(0, 1), SetDataTip(STR_NULL, STR_TIMETABLE_TOOLTIP), SetScrollbar(TTV_SCROLLBAR), EndContainer(),
+				EndContainer(),
+				NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TTV_SCROLLBAR),
+			EndContainer(),
+			NWidget(WWT_PANEL, COLOUR_GREY, TTV_SUMMARY_PANEL), SetMinimalSize(400, 22), SetResize(1, 0), EndContainer(),
 		EndContainer(),
-		NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TTV_SCROLLBAR),
+		NWidget(WWT_PANEL, COLOUR_GREY),
+			NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_TTSEPARATION_SETTINGS_DESC, STR_NULL), SetPadding(3),
+				NWidget(WWT_DROPDOWN, COLOUR_GREY, TTV_TTSEP_MODE_DROPDOWN), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_MAN_NUM, STR_TIMETABLE_TOOLTIP),
+				NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TTV_TTSEP_SET_PARAMETER), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_SET_TIME, STR_TIMETABLE_TOOLTIP),
+				NWidget(WWT_TEXT, COLOUR_GREY, TTV_TTSEP_INFO_TEXT), SetDataTip(STR_TTSEPARATION_REQ_TIME_DESC, STR_TIMETABLE_TOOLTIP), SetResize(1,0),
+				NWidget(WWT_TEXT, COLOUR_GREY, TTV_TTSEP_STATUS_TEXT), SetDataTip(STR_TTSEPARATION_STATUS_DESC, STR_TIMETABLE_TOOLTIP),
+				NWidget(NWID_SPACER), SetFill(1,1),
+			EndContainer(),
+		EndContainer(),
 	EndContainer(),
-	NWidget(WWT_PANEL, COLOUR_GREY, TTV_SUMMARY_PANEL), SetMinimalSize(400, 22), SetResize(1, 0), EndContainer(),
 	NWidget(NWID_HORIZONTAL),
 		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
 			NWidget(NWID_VERTICAL, NC_EQUALSIZE),
diff -r af3f5c2dd1e2 src/ttsep_gui.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ttsep_gui.cpp	Sat May 07 17:51:55 2011 +0200
@@ -0,0 +1,294 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file ttsep_gui.cpp GUI related to timetable separation settings. */
+
+#include "stdafx.h"
+#include "window_gui.h"
+#include "gfx_func.h"
+#include "textbuf_gui.h"
+#include "strings_func.h"
+#include "order_base.h"
+#include "command_func.h"
+#include "command_type.h"
+#include "string_func.h"
+#include "table/sprites.h"
+#include "table/strings.h"
+
+typedef void OnButtonClick(Window *w);
+
+static void TTSepSettingsClick_Reset(Window *w);
+
+enum TTSepSettingsWidgets {
+	TTS_BUTTONS_START,                    ///< Start of pushable buttons
+	TTS_AUTO = TTS_BUTTONS_START,         ///< Auto calculate button
+	TTS_OFF,
+	TTS_MAN_TIME,                         ///< Manual separation time button
+	TTS_MAN_NUM,                          ///< Manual vehicle count button
+	TTS_DEC_TIME,                         ///< Reduce Time button
+	TTS_SET_TIME,                         ///< Set Time button
+	TTS_INC_TIME,                         ///< Raise Time button
+	TTS_DEC_NUM,                          ///< Reduce Number button
+	TTS_SET_NUM,                          ///< Set Number button
+	TTS_INC_NUM,                          ///< Raise Number button
+	TTS_APPLY,                            ///< Apply button
+	TTS_RESET,                            ///< Reset button
+};
+
+static OnButtonClick * const _ttsepsettings_button_proc[] = {
+	TTSepSettingsClick_Reset,
+};
+
+struct TTSepSettingsWindow : Window {
+private:
+	OrderList *pTimetable;
+	TTSepSettings CurSettings;
+	uint8 widget_id;
+
+public:
+	TTSepSettingsWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
+	{
+		this->InitNested(desc, window_number);
+	}
+
+	~TTSepSettingsWindow()
+	{
+	}
+
+	virtual void OnPaint()
+	{
+		this->DrawWidgets();
+	}
+
+	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
+	{
+		if (!gui_scope) return;
+
+		this->SetWidgetLoweredState(TTS_OFF, CurSettings.mode == TTS_MODE_OFF);
+		this->SetWidgetLoweredState(TTS_AUTO, CurSettings.mode == TTS_MODE_AUTO);
+		this->SetWidgetLoweredState(TTS_MAN_TIME, CurSettings.mode == TTS_MODE_MAN_T);
+		this->SetWidgetLoweredState(TTS_MAN_NUM, CurSettings.mode == TTS_MODE_MAN_N);
+
+		SetWidgetsDisabledState((this->CurSettings.mode == TTS_OFF)||(this->CurSettings.mode == TTS_MAN_NUM)||(this->CurSettings.mode == TTS_AUTO), TTS_INC_TIME, TTS_DEC_TIME, TTS_SET_TIME, WIDGET_LIST_END);
+		SetWidgetsDisabledState((this->CurSettings.mode == TTS_OFF)||(this->CurSettings.mode == TTS_MAN_TIME)||(this->CurSettings.mode == TTS_AUTO), TTS_INC_NUM, TTS_DEC_NUM, TTS_SET_NUM, WIDGET_LIST_END);
+
+		switch(CurSettings.mode)
+		{
+		case TTS_MODE_MAN_T:
+			CurSettings.num_veh = this->pTimetable->GetTimetableTotalDuration() / CurSettings.sep_ticks;
+			break;
+
+		case TTS_MODE_MAN_N:
+			CurSettings.sep_ticks = this->pTimetable->GetTimetableTotalDuration() / CurSettings.num_veh;
+			break;
+		}
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch(widget)
+		{
+		case TTS_AUTO:
+			this->CurSettings.mode = TTS_MODE_AUTO;
+			this->InvalidateData();
+			break;
+
+		case TTS_OFF:
+			this->CurSettings.mode = TTS_MODE_OFF;
+			this->InvalidateData();
+			break;
+
+		case TTS_MAN_NUM:
+			this->CurSettings.mode = TTS_MODE_MAN_N;
+			this->InvalidateData();
+			break;
+
+		case TTS_MAN_TIME:
+			this->CurSettings.mode = TTS_MODE_MAN_T;
+			this->InvalidateData();
+			break;
+
+		case TTS_APPLY:
+			this->pTimetable->SetSepSettings(CurSettings);
+			break;
+
+		case TTS_INC_NUM:
+			/* FALL-THROUGH only! */
+		case TTS_DEC_NUM:
+			/* Don't allow too fast scrolling */
+			if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER)
+			{
+				this->HandleButtonClick(widget);
+				CurSettings.num_veh = Clamp(CurSettings.num_veh + widget - TTS_SET_NUM, 1, 65535);
+				this->InvalidateData();
+			}
+			_left_button_clicked = false;
+			break;
+
+		case TTS_SET_NUM:
+			this->widget_id = TTS_SET_NUM;
+			SetDParam(0, CurSettings.num_veh);
+			ShowQueryString(STR_JUST_INT, STR_TTSEPARATION_NUM_DESC, 8, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
+			break;
+
+		case TTS_INC_TIME:
+			/* FALL-THROUGH only! */
+		case TTS_DEC_TIME:
+			/* Don't allow too fast scrolling */
+			if ((this->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER)
+			{
+				this->HandleButtonClick(widget);
+				CurSettings.sep_ticks = Clamp(CurSettings.sep_ticks + widget - TTS_SET_TIME, 1, 65535);
+				this->InvalidateData();
+			}
+			_left_button_clicked = false;
+			break;
+
+		case TTS_SET_TIME:
+			this->widget_id = TTS_SET_TIME;
+			SetDParam(0, CurSettings.sep_ticks);
+			ShowQueryString(STR_JUST_INT, STR_TTSEPARATION_TIME_DESC, 8, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
+			break;
+
+		case TTS_RESET:
+			TTSepSettingsClick_Reset(this);
+			break;
+		}
+	}
+
+	virtual void OnTimeout()
+	{
+		static const int raise_widgets[] = {TTS_INC_TIME, TTS_DEC_TIME, TTS_INC_NUM, TTS_DEC_NUM, WIDGET_LIST_END};
+		for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++)
+		{
+			if (this->IsWidgetLowered(*widget))
+			{
+				this->RaiseWidget(*widget);
+				this->SetWidgetDirty(*widget);
+			}
+		}
+	}
+
+	virtual void OnQueryTextFinished(char *str)
+	{
+		/* Was 'cancel' pressed? */
+		if (str == NULL) return;
+
+		int32 value;
+		if (!StrEmpty(str))
+		{
+			value = atoi(str);
+		}
+
+		switch (this->widget_id)
+		{
+		case TTS_SET_NUM:
+				this->SetWidgetDirty(TTS_SET_NUM);
+				this->CurSettings.num_veh = Clamp(value, 1, 65535);
+				break;
+
+		case TTS_SET_TIME:
+				this->SetWidgetDirty(TTS_SET_TIME);
+				this->CurSettings.sep_ticks = Clamp(value, 1, 65535);
+				break;
+		}
+
+		this->InvalidateData();
+	}
+
+	virtual void SetStringParameters(int widget) const
+	{
+		switch(widget)
+		{
+			case TTS_SET_TIME: SetDParam(0, CurSettings.sep_ticks); break;
+			case TTS_SET_NUM: SetDParam(0, CurSettings.num_veh); break;
+		}
+	}
+
+	virtual void DrawWidget(const Rect &r, int widget) {
+		SetStringParameters(widget);
+	}
+
+	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
+	{
+		return ES_NOT_HANDLED;
+	}
+
+	virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
+	{
+		Point pt = GetToolbarAlignedWindowPosition(sm_width);
+		pt.y += sm_height;
+		return pt;
+	}
+
+	void SetTimetable(OrderList *l)
+	{
+		this->pTimetable = l;
+	}
+
+	void ReloadSettings() {
+		this->CurSettings = this->pTimetable->GetSepSettings();
+	}
+};
+
+static const NWidgetPart _nested_ttsepsettings_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
+		NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_TTSEPARATION_SETTINGS_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_STICKYBOX, COLOUR_GREY),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(NWID_VERTICAL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_OFF), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_OFF, STR_NULL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_MAN_NUM), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_MAN_NUM, STR_NULL),
+		EndContainer(),
+		NWidget(NWID_VERTICAL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_AUTO), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_AUTO, STR_NULL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_MAN_TIME), SetFill(1, 0), SetDataTip(STR_TTSEPARATION_MAN_TIME, STR_NULL),
+		EndContainer(),
+	EndContainer(),
+	NWidget(WWT_PANEL, COLOUR_GREY),
+		NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_TTSEPARATION_NUM_DESC, STR_NULL),
+		NWidget(NWID_HORIZONTAL),
+			NWidget(WWT_IMGBTN, COLOUR_ORANGE, TTS_DEC_NUM), SetDataTip(SPR_ARROW_DOWN, STR_NULL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_SET_NUM), SetFill(1,0), SetDataTip(STR_BLACK_INT, STR_NULL),
+			NWidget(WWT_IMGBTN, COLOUR_ORANGE, TTS_INC_NUM), SetDataTip(SPR_ARROW_UP, STR_NULL),
+		EndContainer(),
+		NWidget(WWT_TEXT), SetFill(1,0), SetDataTip(STR_TTSEPARATION_TIME_DESC, STR_NULL),
+		NWidget(NWID_HORIZONTAL),
+			NWidget(WWT_IMGBTN, COLOUR_ORANGE, TTS_DEC_TIME), SetDataTip(SPR_ARROW_DOWN, STR_NULL),
+			NWidget(WWT_TEXTBTN, COLOUR_YELLOW, TTS_SET_TIME), SetFill(1, 0), SetMinimalSize(5, 5), SetDataTip(STR_BLACK_INT, STR_NULL),
+			NWidget(WWT_IMGBTN, COLOUR_ORANGE, TTS_INC_TIME), SetDataTip(SPR_ARROW_DOWN, STR_NULL),
+		EndContainer(),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, TTS_RESET), SetFill(1,0), SetDataTip(STR_TTSEPARATION_RESET, STR_NULL),
+		NWidget(WWT_TEXTBTN, COLOUR_GREY, TTS_APPLY), SetFill(1,0), SetDataTip(STR_TTSEPARATION_APPLY, STR_NULL),
+	EndContainer(),
+};
+
+static const WindowDesc _ttsepsettings_desc(
+	WDP_MANUAL, 0, 0,
+	WC_TIMETABLE_SEPARATION, WC_NONE,
+	0,
+	_nested_ttsepsettings_widgets, lengthof(_nested_ttsepsettings_widgets)
+);
+
+Window *ShowTTSeparationSettings(OrderList *l) {
+	TTSepSettingsWindow *w;
+	w = AllocateWindowDescFront<TTSepSettingsWindow>(&_ttsepsettings_desc, l->index);
+
+	if(w != NULL)
+	{
+		w->SetTimetable(l);
+		TTSepSettingsClick_Reset(w);
+	}
+	return w;
+}
+
+static void TTSepSettingsClick_Reset(Window *w) {
+	((TTSepSettingsWindow*)w)->ReloadSettings();
+	w->InvalidateData();
+}
diff -r af3f5c2dd1e2 src/ttsep_gui.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ttsep_gui.h	Sat May 07 17:51:55 2011 +0200
@@ -0,0 +1,20 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file ttsep_gui.h GUI stuff related to the Timetable Separation Settings. */
+
+#ifndef TTSEP_GUI_H
+#define TTSEP_GUI_H
+
+#include "order_base.h"
+
+
+Window *ShowTTSeparationSettings(OrderList *l);
+
+//struct TTSepSettingsWindow : Window;
+
+#endif /* GUI_H */
diff -r af3f5c2dd1e2 src/vehicle.cpp
--- a/src/vehicle.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/vehicle.cpp	Sat May 07 17:51:55 2011 +0200
@@ -198,6 +198,15 @@
 	return pass;
 }
 
+void Vehicle::MarkSeparationInvalid()
+{
+	if (this->orders.list != NULL) this->orders.list->MarkSeparationInvalid();
+}
+
+void Vehicle::SetSepSettings(TTSep_Mode Mode, uint Parameter)
+{
+	if (this->orders.list != NULL) this->orders.list->SetSepSettings(Mode, Parameter);
+}
 
 /**
  * Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
@@ -1313,6 +1322,7 @@
 				AddVehicleNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, NS_ADVICE, v->index);
 			}
 			AI::NewEvent(v->owner, new AIEventVehicleWaitingInDepot(v->index));
+			v->MarkSeparationInvalid();
 		}
 	}
 }
@@ -1928,9 +1938,13 @@
 		}
 		this->current_order.MakeLoading(false);
 	}
+	if (_settings_game.order.automatic_timetable_separation && this->IsOrderListShared() && this->orders.list->IsCompleteTimetable()
+		&& (this->cur_real_order_index == 0)) {
+		if (!this->orders.list->IsSeparationValid()) this->orders.list->InitializeSeparation();
+		this->lateness_counter = this->orders.list->SeparateVehicle();
+	}
 
 	Station::Get(this->last_station_visited)->loading_vehicles.push_back(this);
-
 	PrepareUnload(this);
 
 	SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
@@ -2326,10 +2340,10 @@
 	shared_chain->next_shared = this;
 
 	if (this->next_shared != NULL) this->next_shared->previous_shared = this;
+	shared_chain->orders.list->AddVehicle(this);
 
-	shared_chain->orders.list->AddVehicle(this);
+	shared_chain->orders.list->MarkSeparationInvalid();
 }
-
 /**
  * Removes the vehicle from the shared order list.
  */
@@ -2339,9 +2353,8 @@
 	 * as this changes first if needed. */
 	bool were_first = (this->FirstShared() == this);
 	VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
-
+	this->orders.list->MarkSeparationInvalid();
 	this->orders.list->RemoveVehicle(this);
-
 	if (!were_first) {
 		/* We are not the first shared one, so only relink our previous one. */
 		this->previous_shared->next_shared = this->NextShared();
diff -r af3f5c2dd1e2 src/vehicle_base.h
--- a/src/vehicle_base.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/vehicle_base.h	Sat May 07 17:51:55 2011 +0200
@@ -703,6 +703,8 @@
 	bool IsEngineCountable() const;
 	bool HasDepotOrder() const;
 	void HandlePathfindingResult(bool path_found);
+	void MarkSeparationInvalid();
+	void SetSepSettings(TTSep_Mode Mode, uint Parameter);
 
 	/**
 	 * Check if the vehicle is a front engine.
diff -r af3f5c2dd1e2 src/vehicle_cmd.cpp
--- a/src/vehicle_cmd.cpp	Sat May 07 00:22:46 2011 +0000
+++ b/src/vehicle_cmd.cpp	Sat May 07 17:51:55 2011 +0200
@@ -450,6 +450,8 @@
 		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 		SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 		SetWindowClassesDirty(GetWindowClassForVehicleType(v->type));
+
+		v->MarkSeparationInvalid();
 	}
 	return CommandCost();
 }
diff -r af3f5c2dd1e2 src/window_type.h
--- a/src/window_type.h	Sat May 07 00:22:46 2011 +0000
+++ b/src/window_type.h	Sat May 07 17:51:55 2011 +0200
@@ -109,9 +109,9 @@
 	WC_NEWGRF_INSPECT,
 	WC_SPRITE_ALIGNER,
 	WC_INDUSTRY_CARGOES,
+	WC_TIMETABLE_SEPARATION,
 	WC_GRF_PARAMETERS,
 	WC_BUILD_OBJECT,
-
 	WC_INVALID = 0xFFFF
 };
 

