(svn r1323) Adding autoreplace feature
authorbjarni
Sun, 02 Jan 2005 17:23:04 +0000
changeset 842 efc3546bc313
parent 841 4874b9ce2765
child 843 f51135b17930
(svn r1323) Adding autoreplace feature
This feature works much like autorenew, but it will get you a new engine type instead of a new one of the same type. Once
ordered, it will automatically replace the engines while they visits a depot. The GUI for setting this up have been added on the
vehicle overview windows
Note: autorenew is now autoreplace, but to the same engine type
Nice new features, that was added to make this possible
- windows can now have two independant vertical scrollbars
- CMD_SHOW_NO_ERROR have been added as a flag for DoCommandP. It will make it do the action instead of showing the red box with
estimated costs even if shift is pressed
- fixed problem where enginetypes where not initialized when loading a game. It's now done in InitializeGame()
aircraft_cmd.c
aircraft_gui.c
command.c
command.h
engine.c
engine.h
gui.h
lang/english.txt
misc.c
misc_gui.c
network_gui.c
roadveh_cmd.c
roadveh_gui.c
settings_gui.c
ship_cmd.c
ship_gui.c
train_cmd.c
train_gui.c
ttd.h
variables.h
vehicle.c
vehicle.h
vehicle_gui.c
vehicle_gui.h
widget.c
window.c
window.h
--- a/aircraft_cmd.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/aircraft_cmd.c	Sun Jan 02 17:23:04 2005 +0000
@@ -406,29 +406,32 @@
 }
 
 // p1 = vehicle
-// p2 = new cargo type
+// p2 = new cargo type(0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
 int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v,*u;
 	int pass, mail;
 	int32 cost;
+	byte SkipStoppedInHangerCheck = (p2 & 0x100) >> 8; //excludes the cargo value
+	byte new_cargo_type = p2 & 0xFF; //gets the cargo number
 
 	SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
 
 	v = &_vehicles[p1];
-	if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v))
+	if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck)))
 		return CMD_ERROR;
 
 	pass = AircraftVehInfo(v->engine_type)->passanger_capacity;
-	if (p2 != 0) {
+	if (new_cargo_type != CT_PASSENGERS) {
 		pass >>= 1;
-		if (p2 != 5)
+		if (new_cargo_type != CT_GOODS)
 			pass >>= 1;
 	}
 	_aircraft_refit_capacity = pass;
 
 	cost = 0;
-	if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) {
+	if (IS_HUMAN_PLAYER(v->owner) && new_cargo_type != v->cargo_type) {
 		cost = _price.aircraft_base >> 7;
 	}
 
@@ -437,12 +440,15 @@
 
 		u = v->next;
 		mail = AircraftVehInfo(v->engine_type)->mail_capacity;
-		if (p2 != 0) {
+		if (new_cargo_type != CT_PASSENGERS) {
 			mail = 0;
 		}
 		u->cargo_cap = mail;
-		v->cargo_count = u->cargo_count = 0;
-		v->cargo_type = (byte)p2;
+		//autorefitted planes wants to keep the cargo
+		//it will be checked if the cargo is valid in CmdReplaceVehicle
+		if (!(SkipStoppedInHangerCheck))
+			v->cargo_count = u->cargo_count = 0;
+		v->cargo_type = new_cargo_type;
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 	}
 
@@ -1157,7 +1163,7 @@
 
 	ServiceAircraft(v);
 
-	MaybeRenewVehicle(v);
+	MaybeReplaceVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
--- a/aircraft_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/aircraft_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -13,6 +13,26 @@
 #include "player.h"
 
 
+void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number)
+{
+	const AircraftVehicleInfo *avi = AircraftVehInfo(engine_number);
+	Engine *e;
+	YearMonthDay ymd;
+	
+	SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
+	SetDParam(1, avi->max_speed * 8);
+	SetDParam(2, avi->passanger_capacity);
+	SetDParam(3, avi->mail_capacity);
+	SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
+
+	e = &_engines[engine_number];
+	SetDParam(6, e->lifelength);
+	SetDParam(7, e->reliability * 100 >> 16);
+	ConvertDayToYMD(&ymd, e->intro_date);
+	SetDParam(5, ymd.year + 1920);
+	
+}
+
 static void DrawAircraftImage(Vehicle *v, int x, int y, VehicleID selection)
 {
 	int image = GetAircraftImage(v, 6);
@@ -43,8 +63,6 @@
 
 static void NewAircraftWndProc(Window *w, WindowEvent *e)
 {
-	YearMonthDay ymd;
-
 	switch(e->event) {
 
 	case WE_PAINT: {
@@ -89,20 +107,7 @@
 			WP(w,buildtrain_d).sel_engine = selected_id;
 
 			if (selected_id != -1) {
-				const AircraftVehicleInfo *avi = AircraftVehInfo(selected_id);
-				Engine *e;
-
-				SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
-				SetDParam(1, avi->max_speed * 8);
-				SetDParam(2, avi->passanger_capacity);
-				SetDParam(3, avi->mail_capacity);
-				SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
-
-				e = &_engines[selected_id];
-				SetDParam(6, e->lifelength);
-				SetDParam(7, e->reliability * 100 >> 16);
-				ConvertDayToYMD(&ymd, e->intro_date);
-				SetDParam(5, ymd.year + 1920);
+				Set_DPARAM_Aircraft_Build_Window(selected_id);
 
 				DrawString(2, 111, STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
 			}
@@ -899,7 +904,7 @@
 {     WWT_MATRIX,    14,     0,   248,    26,   169, 0x401,									STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
 {  WWT_SCROLLBAR,    14,   249,   259,    26,   169, 0x0,										STR_0190_SCROLL_BAR_SCROLLS_LIST},
 { WWT_PUSHTXTBTN,    14,     0,   129,   170,   181, STR_A003_NEW_AIRCRAFT,	STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
-{      WWT_PANEL,    14,   130,   259,   170,   181, 0x0,										STR_NULL},
+{ WWT_PUSHTXTBTN,    14,   130,   259,   170,   181, STR_REPLACE_VEHICLES,						STR_REPLACE_HELP},
 {   WIDGETS_END},
 };
 
@@ -1005,7 +1010,7 @@
 			break;
 
 		case 4: case 5:/* Select sorting criteria dropdown menu */
-			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
 			return;
 
 		case 7: { /* Matrix to show vehicles */
@@ -1044,6 +1049,11 @@
 
 			ShowBuildAircraftWindow(0);
 		} break;
+		
+		case 10: 
+			ShowReplaceVehicleWindow(VEH_Aircraft);
+			break;
+		
 		}
 	}	break;
 
--- a/command.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/command.c	Sun Jan 02 17:23:04 2005 +0000
@@ -167,7 +167,7 @@
 
 DEF_COMMAND(CmdBuildManySignals);
 
-DEF_COMMAND(CmdRenewVehicle);
+DEF_COMMAND(CmdReplaceVehicle);
 
 /* The master command table */
 static CommandProc * const _command_proc_table[] = {
@@ -309,7 +309,7 @@
 	CmdDestroyCompanyHQ,					/* 111 */
 	CmdGiveMoney,									/* 112 */
 	CmdChangePatchSetting,				/* 113 */
-	CmdRenewVehicle,							/* 114 */
+	CmdReplaceVehicle,							/* 114 */
 };
 
 int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
@@ -431,7 +431,7 @@
 	_docommand_recursive = 1;
 
 	// cost estimation only?
-	if (_shift_pressed && _current_player == _local_player && !(cmd & CMD_NETWORK_COMMAND)) {
+	if (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
 		// estimate the cost.
 		res = proc(x, y, flags, p1, p2);
 		if ((uint32)res >> 16 == 0x8000) {
--- a/command.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/command.h	Sun Jan 02 17:23:04 2005 +0000
@@ -149,7 +149,7 @@
 	CMD_GIVE_MONEY = 112,
 	CMD_CHANGE_PATCH_SETTING = 113,
 
-	CMD_RENEW_VEHICLE = 114,
+	CMD_REPLACE_VEHICLE = 114,
 };
 
 enum {
@@ -172,6 +172,7 @@
 	CMD_NO_WATER = 0x400,
 	CMD_NETWORK_COMMAND = 0x800,		// execute the command without sending it on the network
 	CMD_NO_TEST_IF_IN_NETWORK = 0x1000, // When enabled, the command will bypass the no-DC_EXEC round if in network
+	CMD_SHOW_NO_ERROR = 0x2000,
 };
 
 //#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
--- a/engine.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/engine.c	Sun Jan 02 17:23:04 2005 +0000
@@ -115,6 +115,29 @@
 	}
 }
 
+void AddTypeToEngines()
+{
+	Engine *e;
+	uint32 counter = 0;
+	
+	for(e=_engines; e != endof(_engines); e++, counter++) {
+
+		e->type = VEH_Train;
+		if 	(counter >= ROAD_ENGINES_INDEX) {
+			e->type = VEH_Road;
+			if 	(counter >= SHIP_ENGINES_INDEX) {
+				e->type = VEH_Ship;
+				if 	(counter >= AIRCRAFT_ENGINES_INDEX) {
+					e->type = VEH_Aircraft;
+					if 	(counter >= TOTAL_NUM_ENGINES) {
+						e->type = VEH_Special;
+					}
+				}
+			}
+		}
+	}
+}
+
 void StartupEngines()
 {
 	Engine *e;
@@ -123,8 +146,8 @@
 
 	SetupEngineNames();
 
+	for(e=_engines, ei=_engine_info; e != endof(_engines); e++, ei++, counter++) {
 
-	for(e=_engines, ei=_engine_info; e != endof(_engines); e++, ei++, counter++) {
 		e->age = 0;
 		e->railtype = ei->railtype_climates >> 4;
 		e->flags = 0;
@@ -170,19 +193,6 @@
 		   It should hopefully be the same as when you ask a vehicle what it is
 		   but using this, you can ask what type an engine number is
 		   even if it is not a vehicle (yet)*/
-		e->type = VEH_Train;
-		if 	(counter >= ROAD_ENGINES_INDEX) {
-			e->type = VEH_Road;
-			if 	(counter >= SHIP_ENGINES_INDEX) {
-				e->type = VEH_Ship;
-				if 	(counter >= AIRCRAFT_ENGINES_INDEX) {
-					e->type = VEH_Aircraft;
-					if 	(counter >= TOTAL_NUM_ENGINES) {
-						e->type = VEH_Special;
-					}
-				}
-			}
-		}
 	}
 
 	AdjustAvailAircraft();
--- a/engine.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/engine.h	Sun Jan 02 17:23:04 2005 +0000
@@ -80,6 +80,7 @@
 };
 
 
+void AddTypeToEngines();
 void StartupEngines();
 
 
--- a/gui.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/gui.h	Sun Jan 02 17:23:04 2005 +0000
@@ -85,6 +85,7 @@
 void ShowSmallMap();
 void ShowExtraViewPortWindow();
 void SetVScrollCount(Window *w, int num);
+void SetVScroll2Count(Window *w, int num);
 void SetHScrollCount(Window *w, int num);
 int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
 
--- a/lang/english.txt	Sun Jan 02 12:03:43 2005 +0000
+++ b/lang/english.txt	Sun Jan 02 17:23:04 2005 +0000
@@ -2763,3 +2763,25 @@
 STR_SCHEDULED_ROAD_VEHICLES_TIP					:{BLACK}Show all road vehicles which have this station on their schedule
 STR_SCHEDULED_AIRCRAFT_TIP					:{BLACK}Show all aircraft which have this station on their schedule
 STR_SCHEDULED_SHIPS_TIP						:{BLACK}Show all ships which have this station on their schedule
+
+STR_REPLACE_VEHICLES						:{BLACK}Replace Vehicles
+STR_REPLACE_VEHICLES_START					:{BLACK}Start Replacing Vehicles
+STR_REPLACE_VEHICLES_STOP					:{BLACK}Stop Replaing Vehicles
+STR_NOT_REPLACING						:{BLACK}Not replacing
+STR_NOT_REPLACING_VEHICLE_SELECTED				:{BLACK}No vehicle selected
+STR_REPLACE_HELP_LEFT_ARRAY					:{BLACK}Select a type of engine to replace{}Select an engine on the right side to replace to
+STR_REPLACE_HELP_RIGHT_ARRAY					:{BLACK}Select an engine to replace to{}It will replace the engines selected on the left side
+STR_REPLACE_HELP_STOP_BUTTON					:{BLACK}Press this button if you don't want to replace the engine, you selected on the left
+STR_REPLACE_HELP_START_BUTTON					:{BLACK}Press this button if you want to replace the engine selected on the left with the one selected on the right
+STR_REPLACE_HELP_RAILTYPE					:{BLACK}Select a railtype you want to select engines for
+STR_REPLACE_HELP_REPLACE_INFO_TAB				:{BLACK}This displays what engine the selected engine on the left are being replaced to
+STR_REPLACE_HELP						:{BLACK}This feature allows you to select an enginetype and replace that one with another one. This will then be done automatically when the vehicles enters a depot anyway
+
+############ Lists rail types
+
+STR_RAIL_VEHICLES						:{BLACK}Rail Vehicles
+STR_MONORAIL_VEHICLES						:{BLACK}Monorail Vehicles
+STR_MAGLEV_VEHICLES						:{BLACK}Maglev Vehicles
+
+############ End of list of rail types
+
--- a/misc.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/misc.c	Sun Jan 02 17:23:04 2005 +0000
@@ -9,6 +9,7 @@
 #include "network.h"
 #include "network_data.h"
 #include "network_server.h"
+#include "engine.h"
 
 extern void StartupEconomy();
 extern void InitNewsItemStructs();
@@ -182,6 +183,13 @@
 
 void InitializeGame()
 {
+	// Initialize the autoreplace array. Needs to be cleared between each game
+	int i;
+	for (i = 0; i < 256; i++) {
+		_autoreplace_array[i] = i;
+	}
+	AddTypeToEngines(); // make sure all engines have a type
+	
 	SetObjectToPlace(1, 0, 0, 0);
 
 	_pause = 0;
--- a/misc_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/misc_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -692,6 +692,14 @@
 	if (num < w->vscroll.pos) w->vscroll.pos = num;
 }
 
+void SetVScroll2Count(Window *w, int num)
+{ 
+	w->vscroll2.count = num;
+	num -= w->vscroll2.cap;
+	if (num < 0) num = 0;
+	if (num < w->vscroll2.pos) w->vscroll2.pos = num;
+}
+
 void SetHScrollCount(Window *w, int num)
 {
 	w->hscroll.count = num;
@@ -700,7 +708,6 @@
 	if (num < w->hscroll.pos) w->hscroll.pos = num;
 }
 
-
 int HandleEditBoxKey(Window *w, int wid, WindowEvent *we)
 {
 	byte *p;
--- a/network_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/network_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -231,7 +231,7 @@
 			DeleteWindowById(WC_NETWORK_WINDOW, 0);
 			break;
 		case 4: case 5:
-			ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0); // do it for widget 5
+			ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
 			break;
 		case 10: { /* Matrix to show networkgames */
 			uint32 id_v = (e->click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
@@ -540,13 +540,13 @@
 			SetWindowDirty(w);
 			} break;
 		case 7: case 8: /* Connection type */
-			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0); // do it for widget 8
+			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
 			break;
 		case 9: case 10: /* Number of Players */
-			ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max - 2, 10, 0); // do it for widget 10
+			ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max - 2, 10, 0, 0); // do it for widget 10
 			return;
 		case 11: case 12: /* Language */
-			ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 12, 0); // do it for widget 12
+			ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 12, 0, 0); // do it for widget 12
 			return;
 		case 13: /* Start game */
 			_is_network_server = true;
--- a/roadveh_cmd.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/roadveh_cmd.c	Sun Jan 02 17:23:04 2005 +0000
@@ -105,6 +105,8 @@
 	return ((_price.roadveh_base >> 3) * RoadVehInfo(engine_type)->base_cost) >> 5;
 }
 
+// p1 = engine_type
+// p2 not used
 int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	int32 cost;
@@ -211,6 +213,8 @@
 	return 0;
 }
 
+//  p1 = vehicle index in &_vehicles[]
+//  p2 not used
 int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
@@ -1379,7 +1383,7 @@
 
 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
-	MaybeRenewVehicle(v);
+	MaybeReplaceVehicle(v);
 
 	VehicleServiceInDepot(v);
 
--- a/roadveh_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/roadveh_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -12,6 +12,25 @@
 #include "player.h"
 #include "engine.h"
 
+void Set_DPARAM_Road_Veh_Build_Window(uint16 engine_number)
+{
+	const RoadVehicleInfo *rvi = RoadVehInfo(engine_number);
+	Engine *e;
+	YearMonthDay ymd;
+
+	SetDParam(0, rvi->base_cost * (_price.roadveh_base>>3)>>5);
+	SetDParam(1, rvi->max_speed * 10 >> 5);
+	SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
+	SetDParam(4, rvi->capacity);
+	SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
+
+	e = &_engines[engine_number];
+	SetDParam(6, e->lifelength);
+	SetDParam(7, e->reliability * 100 >> 16);
+	ConvertDayToYMD(&ymd, e->intro_date);
+	SetDParam(5, ymd.year + 1920);
+}
+
 static void DrawRoadVehImage(Vehicle *v, int x, int y, VehicleID selection)
 {
 	int image = GetRoadVehImage(v, 6);
@@ -307,8 +326,6 @@
 
 static void DrawNewRoadVehWindow(Window *w)
 {
-	YearMonthDay ymd;
-
 	if (w->window_number == 0)
 		w->disabled_state = 1 << 5;
 
@@ -350,20 +367,7 @@
 
 		WP(w,buildtrain_d).sel_engine = selected_id;
 		if (selected_id != -1) {
-			const RoadVehicleInfo *rvi = RoadVehInfo(selected_id);
-			Engine *e;
-
-			SetDParam(0, rvi->base_cost * (_price.roadveh_base>>3)>>5);
-			SetDParam(1, rvi->max_speed * 10 >> 5);
-			SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
-			SetDParam(4, rvi->capacity);
-			SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
-
-			e = &_engines[selected_id];
-			SetDParam(6, e->lifelength);
-			SetDParam(7, e->reliability * 100 >> 16);
-			ConvertDayToYMD(&ymd, e->intro_date);
-			SetDParam(5, ymd.year + 1920);
+			Set_DPARAM_Road_Veh_Build_Window(selected_id);
 
 			DrawString(2, 127, STR_9008_COST_SPEED_RUNNING_COST, 0);
 		}
@@ -714,7 +718,7 @@
 {  WWT_SCROLLBAR,    14,   249,   259,    26,   207, 0x0,											STR_0190_SCROLL_BAR_SCROLLS_LIST},
 /* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */
 { WWT_PUSHTXTBTN,    14,     0,   129,   208,   219, STR_8815_NEW_VEHICLES,		STR_901B_BUILD_NEW_ROAD_VEHICLES},
-{      WWT_PANEL,    14,   130,   259,   208,   219, 0x0,											STR_NULL},
+{ WWT_PUSHTXTBTN,    14,   130,   259,   208,   219, STR_REPLACE_VEHICLES,		STR_REPLACE_HELP},
 {   WIDGETS_END},
 };
 
@@ -818,7 +822,7 @@
 			break;
 
 		case 4: case 5:/* Select sorting criteria dropdown menu */
-			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
 			return;
 		case 7: { /* Matrix to show vehicles */
 			uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL;
@@ -856,6 +860,10 @@
 
 			ShowBuildRoadVehWindow(0);
 		} break;
+		case 10: {
+			ShowReplaceVehicleWindow(VEH_Road);
+			break;
+		}
 		}
 	}	break;
 
--- a/settings_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/settings_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -92,35 +92,35 @@
 	case WE_CLICK:
 		switch(e->click.widget) {
 		case 5:
-			ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies());
+			ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);
 			return;
 		case 8:
-			ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0);
+			ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0, 0);
 			return;
 		case 11: {
 			int i = _opt_mod_ptr->road_side;
-			ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
+			ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i), 0);
 			return;
 		}
 		case 14: {
 			int i = _opt_mod_ptr->town_name;
-			ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ORIGINAL_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
+			ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ORIGINAL_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i), 0);
 			return;
 		}
 		case 17:
-			ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0);
+			ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0, 0);
 			return;
 		case 20:
-			ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2);
+			ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2, 0);
 			return;
 		case 21:
 			return;
 		case 24:
-			ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0);
+			ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0, 0);
 			return;
 		case 27:
 			// setup resolution dropdown
-			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0);
+			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0, 0);
 			return;
 		case 28: /* Click fullscreen on/off */
 			(_fullscreen) ? CLRBIT(w->click_state, 28) : SETBIT(w->click_state, 28);
@@ -128,7 +128,7 @@
 			SetWindowDirty(w);
 			return;
 		case 31: /* Setup screenshot format dropdown */
-			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0);
+			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0, 0);
 			return;
 
 		}
--- a/ship_cmd.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/ship_cmd.c	Sun Jan 02 17:23:04 2005 +0000
@@ -400,7 +400,7 @@
 
 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
-	MaybeRenewVehicle(v);
+	MaybeReplaceVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
@@ -975,30 +975,38 @@
 
 
 // p1 = vehicle
-// p2 = new cargo
+// p2 = new cargo (0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
 int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
 	int32 cost;
+	byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8; //excludes the cargo value
 
+	p2 = p2 & 0xFF;
 	SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
 
 	v = &_vehicles[p1];
 	if (!CheckOwnership(v->owner))
 		return CMD_ERROR;
 
-	if (!IsShipDepotTile(v->tile) ||
-			!(v->vehstatus&VS_STOPPED) ||
-			v->u.ship.state != 0x80)
-		return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
-
+	if (!( SkipStoppedInDepotCheck )) {
+		if (!IsShipDepotTile(v->tile) ||
+				!(v->vehstatus&VS_STOPPED) ||
+				v->u.ship.state != 0x80)
+			return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
+		}
+		
 	cost = 0;
 	if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) {
 		cost = _price.ship_base >> 7;
 	}
 
 	if (flags & DC_EXEC) {
-		v->cargo_count = 0;
+		//autorefitted ships wants to keep the cargo
+		//it will be checked if the cargo is valid in CmdRenewVehicle
+		if (!(SkipStoppedInDepotCheck))
+			v->cargo_count = 0;	
 		v->cargo_type = (byte)p2;
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 	}
--- a/ship_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/ship_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -12,6 +12,25 @@
 #include "player.h"
 #include "engine.h"
 
+void Set_DPARAM_Ship_Build_Window(uint16 engine_number)
+{
+	YearMonthDay ymd;
+	const ShipVehicleInfo *svi = ShipVehInfo(engine_number);
+	Engine *e;
+
+	SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5);
+	SetDParam(1, svi->max_speed * 10 >> 5);
+	SetDParam(2, _cargoc.names_long_p[svi->cargo_type]);
+	SetDParam(3, svi->capacity);
+	SetDParam(4, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
+	SetDParam(5, svi->running_cost * _price.ship_running >> 8);
+
+	e = &_engines[engine_number];
+	SetDParam(7, e->lifelength);
+	SetDParam(8, e->reliability * 100 >> 16);
+	ConvertDayToYMD(&ymd, e->intro_date);
+	SetDParam(6, ymd.year + 1920);
+}
 
 static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection);
 
@@ -317,7 +336,6 @@
 
 static void NewShipWndProc(Window *w, WindowEvent *e)
 {
-	YearMonthDay ymd;
 	switch(e->event) {
 	case WE_PAINT:
 		if (w->window_number == 0)
@@ -362,21 +380,7 @@
 			WP(w,buildtrain_d).sel_engine = selected_id;
 
 			if (selected_id != -1) {
-				const ShipVehicleInfo *svi = ShipVehInfo(selected_id);
-				Engine *e;
-
-				SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5);
-				SetDParam(1, svi->max_speed * 10 >> 5);
-				SetDParam(2, _cargoc.names_long_p[svi->cargo_type]);
-				SetDParam(3, svi->capacity);
-				SetDParam(4, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
-				SetDParam(5, svi->running_cost * _price.ship_running >> 8);
-
-				e = &_engines[selected_id];
-				SetDParam(7, e->lifelength);
-				SetDParam(8, e->reliability * 100 >> 16);
-				ConvertDayToYMD(&ymd, e->intro_date);
-				SetDParam(6, ymd.year + 1920);
+				Set_DPARAM_Ship_Build_Window(selected_id);
 
 				DrawString(2, 111, STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
 			}
@@ -881,7 +885,7 @@
 {     WWT_MATRIX,    14,     0,   248,    26,   169, 0x401,									STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
 {  WWT_SCROLLBAR,    14,   249,   259,    26,   169, 0x0,										STR_0190_SCROLL_BAR_SCROLLS_LIST},
 { WWT_PUSHTXTBTN,    14,     0,   129,   170,   181, STR_9804_NEW_SHIPS,		STR_9824_BUILD_NEW_SHIPS_REQUIRES},
-{      WWT_PANEL,    14,   130,   259,   170,   181, 0x0,										STR_NULL},
+{ WWT_PUSHTXTBTN,    14,   130,   259,   170,   181, STR_REPLACE_VEHICLES,					STR_REPLACE_HELP},
 {   WIDGETS_END},
 };
 
@@ -986,7 +990,7 @@
 			SetWindowDirty(w);
 			break;
 		case 4: case 5:/* Select sorting criteria dropdown menu */
-			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
 			return;
 		case 7: { /* Matrix to show vehicles */
 			uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG;
@@ -1024,7 +1028,12 @@
 
 			ShowBuildShipWindow(0);
 		} break;
+		
+		case 10: {
+			ShowReplaceVehicleWindow(VEH_Ship);
+			break;
 		}
+	}
 	}	break;
 
 	case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
--- a/train_cmd.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/train_cmd.c	Sun Jan 02 17:23:04 2005 +0000
@@ -1057,23 +1057,27 @@
 }
 
 // p1 = vehicle to refit
-// p2 = new cargo
-
+// p2 = new cargo (0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
 int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
 	int32 cost;
 	uint num;
 
+	byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8;
+
+	p2 = p2 & 0xFF;
+
 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
-
+	
 	v = &_vehicles[p1];
-	if (!CheckOwnership(v->owner) || CheckStoppedInDepot(v) < 0)
+	if (!CheckOwnership(v->owner) || ((CheckStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck)))
 		return CMD_ERROR;
 
 	cost = 0;
 	num = 0;
-
+	
 	do {
 		/* XXX: We also refit all the attached wagons en-masse if they
 		 * can be refitted. This is how TTDPatch does it.  TODO: Have
@@ -1084,12 +1088,16 @@
 			cost += (_price.build_railvehicle >> 8);
 			num += v->cargo_cap;
 			if (flags & DC_EXEC) {
-				v->cargo_count = 0;
+		//autorefitted train cars wants to keep the cargo
+		//it will be checked if the cargo is valid in CmdReplaceVehicle
+				if (!(SkipStoppedInDepotCheck))
+					v->cargo_count = 0;
 				v->cargo_type = (byte)p2;
 				InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 			}
 		}
-	} while ( (v=v->next) != NULL);
+	// SkipStoppedInDepotCheck is called by CmdReplace and it should only apply to the single car it is called for
+	} while ( (v=v->next) != NULL || SkipStoppedInDepotCheck );
 
 	_returned_refit_amount = num;
 
@@ -2618,7 +2626,7 @@
 	v->load_unload_time_rem = 0;
 	v->cur_speed = 0;
 
-	MaybeRenewVehicle(v);
+	MaybeReplaceVehicle(v);
 
 	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
--- a/train_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/train_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -16,6 +16,44 @@
 
 int _traininfo_vehicle_pitch = 0;
 
+void Set_DPARAM_Train_Engine_Build_Window(uint16 engine_number)
+{
+	const RailVehicleInfo *rvi = RailVehInfo(engine_number);
+	Engine *e;
+	int multihead = (rvi->flags&RVI_MULTIHEAD?1:0);
+	YearMonthDay ymd;
+
+
+	SetDParam(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5);
+	SetDParam(2, rvi->max_speed * 10 >> 4);
+	SetDParam(3, rvi->power << multihead);
+	SetDParam(1, rvi->weight << multihead);
+	SetDParam(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead);
+
+	SetDParam(5, STR_8838_N_A);
+	if (rvi->capacity != 0) {
+		SetDParam(6, rvi->capacity << multihead);
+		SetDParam(5, _cargoc.names_long_p[rvi->cargo_type]);
+	}
+
+	e = &_engines[engine_number];
+
+	SetDParam(8, e->lifelength);
+	SetDParam(9, e->reliability * 100 >> 16);
+	ConvertDayToYMD(&ymd, e->intro_date);
+	SetDParam(7, ymd.year + 1920);
+}
+
+void Set_DPARAM_Train_Car_Build_Window(Window *w, uint16 engine_number)
+{
+	const RailVehicleInfo *rvi = RailVehInfo(engine_number);
+	
+	SetDParam(0, DoCommandByTile(w->window_number, engine_number, 0, DC_QUERY_COST, CMD_BUILD_RAIL_VEHICLE) );
+	SetDParam(4, rvi->capacity);
+	SetDParam(1, rvi->weight);
+	SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
+	SetDParam(2, (_cargoc.weights[rvi->cargo_type] * rvi->capacity >> 4) + rvi->weight);
+}
 
 void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2)
 {
@@ -131,43 +169,16 @@
 
 			if (selected_id != -1) {
 				const RailVehicleInfo *rvi = RailVehInfo(selected_id);
-				Engine *e;
-				YearMonthDay ymd;
 
 				if (!(rvi->flags & RVI_WAGON)) {
 					/* it's an engine */
-					int multihead = (rvi->flags&RVI_MULTIHEAD?1:0);
-
-					SetDParam(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5);
-					SetDParam(2, rvi->max_speed * 10 >> 4);
-					SetDParam(3, rvi->power << multihead);
-					SetDParam(1, rvi->weight << multihead);
-					SetDParam(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead);
-
-					SetDParam(5, STR_8838_N_A);
-					if (rvi->capacity != 0) {
-						SetDParam(6, rvi->capacity << multihead);
-						SetDParam(5, _cargoc.names_long_p[rvi->cargo_type]);
-					}
-
-					e = &_engines[selected_id];
-
-					SetDParam(8, e->lifelength);
-					SetDParam(9, e->reliability * 100 >> 16);
-					ConvertDayToYMD(&ymd, e->intro_date);
-					SetDParam(7, ymd.year + 1920);
+					Set_DPARAM_Train_Engine_Build_Window(selected_id);
 
 					DrawString(2, 0x7F, STR_8817_COST_WEIGHT_T_SPEED_POWER, 0);
 				} else {
 					/* it's a wagon */
-
-					SetDParam(0,
-						DoCommandByTile(w->window_number, selected_id, 0, DC_QUERY_COST, CMD_BUILD_RAIL_VEHICLE)
-					);
-					SetDParam(4, rvi->capacity);
-					SetDParam(1, rvi->weight);
-					SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
-					SetDParam(2, (_cargoc.weights[rvi->cargo_type] * rvi->capacity >> 4) + rvi->weight);
+					Set_DPARAM_Train_Car_Build_Window(w, selected_id);
+					
 					DrawString(2, 0x7F, STR_8821_COST_WEIGHT_T_T_CAPACITY, 0);
 				}
 			}
@@ -1183,7 +1194,7 @@
 {     WWT_MATRIX,    14,     0,   313,    26,   207, 0x701,									STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
 {  WWT_SCROLLBAR,    14,   314,   324,    26,   207, 0x0,										STR_0190_SCROLL_BAR_SCROLLS_LIST},
 { WWT_PUSHTXTBTN,    14,     0,   161,   208,   219, STR_8815_NEW_VEHICLES,	STR_883E_BUILD_NEW_TRAINS_REQUIRES},
-{      WWT_PANEL,    14,   162,   324,   208,   219, 0x0,										STR_NULL},
+{ WWT_PUSHTXTBTN,    14,   162,   324,   208,   219, STR_REPLACE_VEHICLES,					STR_REPLACE_HELP},
 {   WIDGETS_END},
 };
 
@@ -1289,7 +1300,7 @@
 			break;
 
 		case 4: case 5:/* Select sorting criteria dropdown menu */
-			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+			ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
 			return;
 
 		case 7: { /* Matrix to show vehicles */
@@ -1328,6 +1339,11 @@
 
 			ShowBuildTrainWindow(0);
 		} break;
+		case 10: {
+			ShowReplaceVehicleWindow(VEH_Train);
+			break;
+ 		}
+
 		}
 	}	break;
 
--- a/ttd.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/ttd.h	Sun Jan 02 17:23:04 2005 +0000
@@ -439,6 +439,7 @@
 	WC_CLIENT_LIST = 0x49,
 	WC_NETWORK_STATUS_WINDOW = 0x4A,
 	WC_CUSTOM_CURRENCY = 0x4B,
+	WC_REPLACE_VEHICLE = 0x4C,
 };
 
 
--- a/variables.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/variables.h	Sun Jan 02 17:23:04 2005 +0000
@@ -431,6 +431,9 @@
 /* tunnelbridge */
 #define MAX_BRIDGES 13
 
+/* Autoreplace vehicle stuff*/
+VARDEF byte _autoreplace_array[255];
+
 /* Debugging levels */
 VARDEF int _debug_spritecache_level;
 VARDEF int _debug_misc_level;
--- a/vehicle.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/vehicle.c	Sun Jan 02 17:23:04 2005 +0000
@@ -4,7 +4,6 @@
 #include "map.h"
 #include "vehicle.h"
 #include "gfx.h"
-//#include "station.h"
 #include "viewport.h"
 #include "news.h"
 #include "command.h"
@@ -1394,35 +1393,45 @@
 extern int32 EstimateRoadVehCost(byte engine_type);
 extern int32 EstimateShipCost(uint16 engine_type);
 extern int32 EstimateAircraftCost(uint16 engine_type);
+extern int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+extern int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+extern int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
 
-/* Renews a vehicle
+/* Replaces a vehicle (used to be called autorenew)
     p1 - Index of vehicle
     p2 - Type of new engine */
-int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	byte new_engine_type = p2;
+	/* makesvariables to inform about how much money the player wants to have left after replacing
+	 and which engine to replace with out of p2.
+	 the first 16 bit is the money. The last 5 digits (all 0) were removed when sent, so we add them again.
+	 This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches
+	 This is a nice way to send 32 bit and only use 16 bit
+	 the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
+	uint16 new_engine_type = (uint16)(p2 & 0xFFFF);
+	uint32 autorefit_money = (p2  >> 16) * 100000; 
 	Vehicle *v = DEREF_VEHICLE(p1);
 	int cost, build_cost;
-
-	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
+	
+	if (v->type != _engines[new_engine_type].type) return CMD_ERROR;
 
 	switch (v->type) {
-		case VEH_Train:    build_cost = EstimateTrainCost(RailVehInfo(v->engine_type)); break;
-		case VEH_Road:     build_cost = EstimateRoadVehCost(new_engine_type);           break;
-		case VEH_Ship:     build_cost = EstimateShipCost(v->engine_type);               break;
-		case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type);          break;
+		case VEH_Train:    build_cost = EstimateTrainCost(RailVehInfo(new_engine_type)); break;
+		case VEH_Road:     build_cost = EstimateRoadVehCost(new_engine_type);            break;
+		case VEH_Ship:     build_cost = EstimateShipCost(new_engine_type);               break;
+		case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type);           break;
 		default: return CMD_ERROR;
 	}
 
 	/* In a rare situation, when 2 clients are connected to 1 company and have the same
 	    settings, a vehicle can be replaced twice.. check if this is the situation here */
-	if (v->age == 0)
+	if (v->engine_type == new_engine_type && v->age == 0)
 		return CMD_ERROR;
 
 	/* Check if there is money for the upgrade.. if not, give a nice news-item
 	    (that is needed, because this CMD is called automaticly) */
-	if (DEREF_PLAYER(v->owner)->money64 < _patches.autorenew_money + build_cost - v->value) {
-		if (_local_player == v->owner) {
+	if ( DEREF_PLAYER(v->owner)->money64 < (int32)(autorefit_money + build_cost - v->value)) {
+		if (( _local_player == v->owner ) && ( v->unitnumber != 0 )) {  //v->unitnumber = 0 for train cars
 			int message;
 			SetDParam(0, v->unitnumber);
 			switch (v->type) {
@@ -1439,21 +1448,106 @@
 
 		return CMD_ERROR;
 	}
-
 	cost = build_cost - v->value;
 
-	if (flags & DC_QUERY_COST)
-		return cost;
 
 	if (flags & DC_EXEC) {
 		Engine *e;
+		e = &_engines[new_engine_type];
+		
+		// TODO make it check if refit is possible before actually doing it
 
 		/* We do not really buy a new vehicle, we upgrade the old one */
 		if (v->engine_type != new_engine_type) {
-			/* XXX - We need to do some more stuff here, when we are going to upgrade
-			    to a new engine! */
+			byte cargo_type = v->cargo_type;
+			v->engine_type = new_engine_type;
+			v->max_age = e->lifelength * 366;
+		
+			/* Update limits of the vehicle (for when upgraded) */
+			switch (v->type) {
+			case VEH_Train:
+			// using if (true) to declare the const
+				{
+				const RailVehicleInfo *rvi = RailVehInfo(new_engine_type);
+				byte capacity = rvi->capacity;
+
+				v->spritenum = rvi->image_index;
+				v->cargo_type = rvi->cargo_type;
+				v->cargo_cap = rvi->capacity;
+				v->max_speed = rvi->max_speed;
+
+				v->u.rail.railtype = e->railtype;
+				
+				// 0x0100 means that we skip the check for being stopped inside the depot
+				// since we do not stop it for autorefitting
+				if (v->cargo_type != cargo_type && capacity) {
+					// BUG: somehow v->index is not transfered properly
+					//CmdRefitRailVehicle(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+					v->cargo_type = cargo_type; // workaround, but it do not check the refit table
+				} else {
+					v->cargo_type = rvi->cargo_type;
+				}
+				break;
+				}
+			case VEH_Road:
+			// using if (true) to declare the const
+				if (true) {
+				const RoadVehicleInfo *rvi = RoadVehInfo(new_engine_type);
+
+				v->spritenum = rvi->image_index;
+				v->cargo_type = rvi->cargo_type;
+				v->cargo_cap = rvi->capacity;
+				v->max_speed = rvi->max_speed;
+				break;
+				}
+			case VEH_Ship:
+			// using if (true) to declare the const
+				if (true) {
+				const ShipVehicleInfo *svi = ShipVehInfo(new_engine_type);
+
+				v->spritenum = svi->image_index;
+				v->cargo_type = svi->cargo_type;
+				v->cargo_cap = svi->capacity;
+				v->max_speed = svi->max_speed;
+				
+				// 0x0100 means that we skip the check for being stopped inside the depot
+				// since we do not stop it for autorefitting
+				if (v->cargo_type != cargo_type)
+					CmdRefitShip(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+				break;
+				}
+			case VEH_Aircraft:
+			// using if (true) to declare the const
+				if (true) {
+				const AircraftVehicleInfo *avi = AircraftVehInfo(new_engine_type);
+				Vehicle *u;
+
+				v->max_speed = avi->max_speed;
+				v->acceleration = avi->acceleration;
+				v->spritenum = avi->image_index;
+
+					if ( cargo_type == CT_PASSENGERS ) {
+						v->cargo_cap = avi->passanger_capacity;
+						u = v->next;
+						u->cargo_cap = avi->mail_capacity;
+					} else {
+						// 0x0100 means that we skip the check for being stopped inside the hangar
+						// since we do not stop it for autorefitting
+						CmdRefitAircraft(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+					}
+				break;
+				}
+			default: return CMD_ERROR;
+			}
+			// makes sure that the cargo is still valid compared to new capacity
+			if (v->cargo_count != 0) {
+				if ( v->cargo_type != cargo_type )
+					v->cargo_count = 0;
+				else if ( v->cargo_count > v->cargo_cap )
+					v->cargo_count = v->cargo_cap;
+			}
 		}
-		e = &_engines[new_engine_type];
+		
 		v->reliability = e->reliability;
 		v->reliability_spd_dec = e->reliability_spd_dec;
 		v->age = 0;
@@ -1465,26 +1559,58 @@
 
 		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 	}
+	//needs to be down here because refitting will change SET_EXPENSES_TYPE if called
+	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
 
 	return cost;
 }
 
-void MaybeRenewVehicle(Vehicle *v)
+void MaybeReplaceVehicle(Vehicle *v)
 {
+	uint32 new_engine_and_autoreplace_money;
+	
 	if (v->owner != _local_player)
 		return;
+	// uncomment next line if you want to see what engine type just entered a depot
+	//printf("engine type: %d\n", v->engine_type);
 
 	// A vehicle is autorenewed when it it gets the amount of months
 	//  give by _patches.autorenew_months away for his max age.
 	//  Standard is -6, meaning 6 months before his max age
 	//  It can be any value between -12 and 12.
-	if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30))
-		return;
-
+	//  Here it also checks if the vehicles is listed for replacement
+	if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30)) {  //replace if engine is too old
+		if (_autoreplace_array[v->engine_type] == v->engine_type && v->type != VEH_Train) //updates to a new model
+			return;
+	}
+	/* Now replace the vehicle */
 	_current_player = v->owner;
-
-	/* Now renew the vehicle */
-	DoCommandP(v->tile, v->index, v->engine_type, NULL, CMD_RENEW_VEHICLE);
+	
+	/* makes the variable to inform about how much money the player wants to have left after replacing
+	 and which engine to replace with
+	 the first 16 bit is the money. Since we know the last 5 digits is 0, they are thrown away.
+	 This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches
+	 This is a nice way to send 32 bit and only use 16 bit
+	 the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
+	new_engine_and_autoreplace_money = (((_patches.autorenew_money / 100000) & 0xFFFF) << 16)
+	 + _autoreplace_array[v->engine_type];
+	
+	assert(v->type == _engines[ _autoreplace_array[v->engine_type] ].type);
+	
+	if ( v->type != VEH_Train ) {
+		DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+	} else {
+	// checks if the front engine is outdated
+		if (v->engine_type != _autoreplace_array[v->engine_type] )  
+			DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+	//we will check all the cars and engines if they should be replaced
+		while (v->next != NULL){
+			v = v->next;
+			if (v->engine_type != _autoreplace_array[v->engine_type] || v->age - v->max_age < (_patches.autorenew_months * 30))
+				DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money , NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+			}
+	}
+	_current_player = OWNER_NONE;
 }
 
 
--- a/vehicle.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/vehicle.h	Sun Jan 02 17:23:04 2005 +0000
@@ -361,7 +361,7 @@
 void DecreaseVehicleValue(Vehicle *v);
 void CheckVehicleBreakdown(Vehicle *v);
 void AgeVehicle(Vehicle *v);
-void MaybeRenewVehicle(Vehicle *v);
+void MaybeReplaceVehicle(Vehicle *v);
 
 void DeleteCommandFromVehicleSchedule(Order cmd);
 
--- a/vehicle_gui.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/vehicle_gui.c	Sun Jan 02 17:23:04 2005 +0000
@@ -3,6 +3,10 @@
 #include "table/strings.h"
 #include "vehicle.h"
 #include "window.h"
+#include "engine.h"
+#include "gui.h"
+#include "command.h"
+#include "gfx.h"
 
 VehicleSortListingTypeFunctions * const _vehicle_sorter[] = {
 	&VehicleUnsortedSorter,
@@ -29,6 +33,13 @@
 	INVALID_STRING_ID
 };
 
+const StringID _rail_types_list[] = {
+	STR_RAIL_VEHICLES,
+	STR_MONORAIL_VEHICLES,
+	STR_MAGLEV_VEHICLES,
+	INVALID_STRING_ID
+};
+
 void RebuildVehicleLists(void)
 {
 	Window *w;
@@ -294,3 +305,636 @@
 
 	return (_internal_sort_order & 1) ? -r : r;
 }
+
+// this define is to match engine.c, but engine.c keeps it to itself
+// ENGINE_AVAILABLE is used in ReplaceVehicleWndProc
+#define ENGINE_AVAILABLE ((e->flags & 1 && HASBIT(info->railtype_climates, _opt.landscape)) || HASBIT(e->player_avail, _local_player))
+
+/*  if show_outdated is selected, it do not sort psudo engines properly but it draws all engines
+ *	if used compined with show_cars set to false, it will work as intended. Replace window do it like that 
+ *  this was a big hack even before show_outdated was added. Stupid newgrf :p										*/
+static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, int *selected_id, byte railtype, 
+	uint8 lines_drawn, bool is_engine, bool show_cars, bool show_outdated)
+{
+	int i;
+	byte colour;
+	
+	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
+		const Engine *e = DEREF_ENGINE(i);
+		const RailVehicleInfo *rvi = RailVehInfo(i);
+		const EngineInfo *info = &_engine_info[i];
+
+		if ( rvi->power == 0 && !(show_cars) )   // disables display of cars (works since they do not have power)
+			continue;
+			
+		if (*sel == 0) *selected_id = i;
+
+
+		colour = *sel == 0 ? 0xC : 0x10;
+		if (!(ENGINE_AVAILABLE && show_outdated && RailVehInfo(i)->power && e->railtype == railtype)) {
+			if (e->railtype != railtype || !(rvi->flags & RVI_WAGON) != is_engine ||
+				!HASBIT(e->player_avail, _local_player))
+				continue;
+		} /*else { 
+		// TODO find a nice red colour for vehicles being replaced
+			if ( _autoreplace_array[i] != i )
+				colour = *sel == 0 ? 0x44 : 0x45;
+		} */
+				
+		if (IS_INT_INSIDE(--*pos, -lines_drawn, 0)) {
+			DrawString(*x + 59, *y + 2, GetCustomEngineName(i),
+				colour);
+			DrawTrainEngine(*x + 29, *y + 6, i,
+				SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+			*y += 14;
+		}
+		--*sel;
+	}
+}
+
+
+static void SetupScrollStuffForReplaceWindow(Window *w)
+{
+	byte railtype;
+	int selected_id[2] = {-1,-1};
+	int sel[2] = { WP(w,replaceveh_d).sel_index[0], WP(w,replaceveh_d).sel_index[1]};
+	int count = 0;
+	int count2 = 0;
+	int engine_id;
+				
+	switch (WP(w,replaceveh_d).vehicletype) {
+		case VEH_Train: {
+			railtype = WP(w,replaceveh_d).railtype;
+			for (engine_id = 0; engine_id < NUM_TRAIN_ENGINES; engine_id++) {
+				const Engine *e = DEREF_ENGINE(engine_id);
+				const EngineInfo *info = &_engine_info[engine_id];
+							
+				if (ENGINE_AVAILABLE && RailVehInfo(engine_id)->power && e->railtype == railtype) {
+					count++;
+					if (sel[0]==0)  selected_id[0] = engine_id;
+					sel[0]--;
+					if (HASBIT(e->player_avail, _local_player)) {
+						if (sel[1]==0)  selected_id[1] = engine_id;
+							count2++;
+							sel[1]--;
+						}
+					}
+				}
+			break;
+			}
+		case VEH_Road: {
+			int num = NUM_ROAD_ENGINES;
+			Engine *e = &_engines[ROAD_ENGINES_INDEX];
+			byte cargo;
+			EngineInfo *info;
+			engine_id = ROAD_ENGINES_INDEX;
+
+			do {
+				info = &_engine_info[engine_id];
+				if (ENGINE_AVAILABLE) {
+					if (sel[0]==0)  selected_id[0] = engine_id;
+					count++;
+					sel[0]--;							
+				}
+			} while (++engine_id,++e,--num);
+					
+			if ( selected_id[0] != -1 ) {   // only draw right array if we have anything in the left one
+				num = NUM_ROAD_ENGINES;
+				engine_id = ROAD_ENGINES_INDEX;
+				e = &_engines[ROAD_ENGINES_INDEX];
+				cargo = RoadVehInfo(selected_id[0])->cargo_type;
+					
+				do {
+					if ( cargo == RoadVehInfo(engine_id)->cargo_type && HASBIT(e->player_avail, _local_player)) {
+						count2++;
+						if (sel[1]==0)  selected_id[1] = engine_id;
+						sel[1]--;
+					}
+				} while (++engine_id,++e,--num);
+			}					
+			break;
+		}
+	
+		case VEH_Ship: {
+			int num = NUM_SHIP_ENGINES;
+			Engine *e = &_engines[SHIP_ENGINES_INDEX];
+			byte cargo; 
+			EngineInfo *info;
+			engine_id = SHIP_ENGINES_INDEX;
+			byte refittable;
+
+			do {
+				info = &_engine_info[engine_id];
+				if (ENGINE_AVAILABLE) {
+					if ( sel[0] == 0 )  selected_id[0] = engine_id;
+					count++;
+					sel[0]--;							
+				}
+			} while (++engine_id,++e,--num);
+					
+			if ( selected_id[0] != -1 ) {
+				num = NUM_SHIP_ENGINES;
+				e = &_engines[SHIP_ENGINES_INDEX];
+				engine_id = SHIP_ENGINES_INDEX;
+				cargo = ShipVehInfo(selected_id[0])->cargo_type;
+				refittable = ShipVehInfo(selected_id[0])->refittable;
+					
+				do {											
+					if (HASBIT(e->player_avail, _local_player) 
+					&& ( cargo == ShipVehInfo(engine_id)->cargo_type || refittable & ShipVehInfo(engine_id)->refittable)) {
+									
+						if ( sel[1]==0)  selected_id[1] = engine_id;
+						sel[1]--;
+						count2++;
+					}
+				} while (++engine_id,++e,--num);
+			}
+			break;
+		}   //end of ship
+				
+		case VEH_Aircraft:{
+			int num = NUM_AIRCRAFT_ENGINES;
+			Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX];
+			EngineInfo *info;
+			engine_id = AIRCRAFT_ENGINES_INDEX;
+			byte subtype;
+
+			do {
+				info = &_engine_info[engine_id];
+				if (ENGINE_AVAILABLE) {
+					count++;
+					if (sel[0]==0)  selected_id[0] = engine_id;
+					sel[0]--;
+				}
+			} while (++engine_id,++e,--num);
+					
+			if ( selected_id[0] != -1 ) {
+				num = NUM_AIRCRAFT_ENGINES;
+				e = &_engines[AIRCRAFT_ENGINES_INDEX];
+				subtype = AircraftVehInfo(selected_id[0])->subtype;
+				engine_id = AIRCRAFT_ENGINES_INDEX;
+				do {
+					if (HASBIT(e->player_avail, _local_player)) {
+						if ( (subtype && AircraftVehInfo(engine_id)->subtype) || (!(subtype) && !AircraftVehInfo(engine_id)->subtype) ) {
+							count2++;
+							if (sel[1]==0)  selected_id[1] = engine_id;
+							sel[1]--;
+						}
+					}
+				} while (++engine_id,++e,--num);
+			}
+			break;
+		}
+	}
+	// sets up the number of items in each list
+	SetVScrollCount(w, count);
+	SetVScroll2Count(w, count2);
+	WP(w,replaceveh_d).sel_engine[0] = selected_id[0];
+	WP(w,replaceveh_d).sel_engine[1] = selected_id[1];
+	
+	WP(w,replaceveh_d).count[0] = count;
+	WP(w,replaceveh_d).count[1] = count2;
+	return;
+}
+
+
+static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int y2, int pos, int pos2,
+	int sel1, int sel2, int selected_id1, int selected_id2) 
+{
+	int sel[2] = {sel1, sel2};
+	int selected_id[2] = {selected_id1, selected_id2};
+	switch (WP(w,replaceveh_d).vehicletype) {
+		case VEH_Train: {
+			byte railtype = WP(w,replaceveh_d).railtype;
+			DrawString(157, 89 + (14 * w->vscroll.cap), _rail_types_list[railtype], 0x10);
+			/* draw sorting criteria string */
+
+			/* Ensure that custom engines which substituted wagons
+			* are sorted correctly.
+			* XXX - DO NOT EVER DO THIS EVER AGAIN! GRRR hacking in wagons as
+			* engines to get more types.. Stays here until we have our own format
+			* then it is exit!!! */
+			train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, true, false, true); // True engines
+			train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, true, false, false); // True engines
+			train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, false, false); // Feeble wagons
+			break;
+		}
+			
+		case VEH_Road: {
+			int num = NUM_ROAD_ENGINES;
+			Engine *e = &_engines[ROAD_ENGINES_INDEX];
+			int engine_id = ROAD_ENGINES_INDEX;
+			byte cargo;
+			EngineInfo *info;
+				
+			if ( selected_id[0] >= ROAD_ENGINES_INDEX && selected_id[0] <= SHIP_ENGINES_INDEX )
+				cargo = RoadVehInfo(selected_id[0])->cargo_type; 
+
+			do {
+				info = &_engine_info[engine_id];
+				if (ENGINE_AVAILABLE) {
+					if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+						DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+						DrawRoadVehEngine(x+29, y+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+						y += 14;
+					}
+						
+					if ( RoadVehInfo(engine_id)->cargo_type == cargo && HASBIT(e->player_avail, _local_player) ) {
+						if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0) && RoadVehInfo(engine_id)->cargo_type == cargo) {
+							DrawString(x2+59, y2+2, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+							DrawRoadVehEngine(x2+29, y2+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+							y2 += 14;
+						}
+						sel[1]--;
+					}
+				sel[0]--;
+				}
+			} while (++engine_id, ++e,--num);
+
+			break;
+		}
+				
+		case VEH_Ship: {
+			int num = NUM_SHIP_ENGINES;
+			Engine *e = &_engines[SHIP_ENGINES_INDEX];
+			int engine_id = SHIP_ENGINES_INDEX;
+			byte cargo, refittable;  
+			EngineInfo *info;
+
+			if ( selected_id[0] != -1 ) {
+				cargo = ShipVehInfo(selected_id[0])->cargo_type;
+				refittable = ShipVehInfo(selected_id[0])->refittable;
+			}
+				
+			do {
+				info = &_engine_info[engine_id];
+				if (ENGINE_AVAILABLE) {
+					if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+						DrawString(x+75, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+						DrawShipEngine(x+35, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+						y += 24;
+					}
+					if ( selected_id[0] != -1 ) {
+						if (HASBIT(e->player_avail, _local_player) && ( cargo == ShipVehInfo(engine_id)->cargo_type || refittable & ShipVehInfo(engine_id)->refittable)) {
+							if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
+								DrawString(x2+75, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+								DrawShipEngine(x2+35, y2+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+								y2 += 24;
+							}
+							sel[1]--;
+						}
+					}
+					sel[0]--;
+				}
+			} while (++engine_id, ++e,--num);
+		break;
+		}   //end of ship
+			
+		case VEH_Aircraft: {
+			if ( selected_id[0] != -1 ) {
+				int num = NUM_AIRCRAFT_ENGINES;
+				Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX];
+				int engine_id = AIRCRAFT_ENGINES_INDEX;
+				byte subtype = AircraftVehInfo(selected_id[0])->subtype;
+				EngineInfo *info;
+
+				do {
+					info = &_engine_info[engine_id];
+					if (ENGINE_AVAILABLE) {
+						if (sel[0]==0) selected_id[0] = engine_id;
+						if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+							DrawString(x+62, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+							DrawAircraftEngine(x+29, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+							y += 24;
+						}
+						if ( ((subtype && AircraftVehInfo(engine_id)->subtype) || (!(subtype) && !AircraftVehInfo(engine_id)->subtype))
+							&& HASBIT(e->player_avail, _local_player) ) {
+							if (sel[1]==0) selected_id[1] = engine_id;
+							if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
+								DrawString(x2+62, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+								DrawAircraftEngine(x2+29, y2+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+								y2 += 24;
+							}
+						sel[1]--;
+						}
+					sel[0]--;
+					}
+				} while (++engine_id, ++e,--num);
+			}
+			break;
+		}   // end of aircraft
+	}
+
+}
+static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
+{
+	// these 3 variables is used if any of the lists is clicked
+	uint16 click_scroll_pos = w->vscroll2.pos;
+	uint16 click_scroll_cap = w->vscroll2.cap;
+	byte click_side = 1;
+
+	switch(e->event) {
+		case WE_PAINT:	
+			{
+				int pos = w->vscroll.pos;
+				int selected_id[2] = {-1,-1};
+				int x = 1;
+				int y = 15;
+				int pos2 = w->vscroll2.pos;
+				int x2 = 1 + 228;
+				int y2 = 15;
+				int sel[2] = { WP(w,replaceveh_d).sel_index[0], WP(w,replaceveh_d).sel_index[1]};
+			
+				SetupScrollStuffForReplaceWindow(w);
+			
+				selected_id[0] = WP(w,replaceveh_d).sel_engine[0];
+				selected_id[1] = WP(w,replaceveh_d).sel_engine[1];
+			
+			// sets the selected left item to the top one if it's greater than the number of vehicles in the left side
+
+				if ( WP(w,replaceveh_d).count[0] <= sel[0] ) {
+					if (WP(w,replaceveh_d).count[0]) {
+						sel[0] = 0;
+						WP(w,replaceveh_d).sel_index[0] = 0;
+						w->vscroll.pos = 0;
+						// now we go back to set selected_id[1] properly
+						SetWindowDirty(w);
+						return;
+					} else { //there are no vehicles in the left window
+						selected_id[1] = -1;
+					}
+				}
+
+				if ( WP(w,replaceveh_d).count[1] <= sel[1] ) {
+					if (WP(w,replaceveh_d).count[1]) {
+						sel[1] = 0;
+						WP(w,replaceveh_d).sel_index[1] = 0;
+						w->vscroll2.pos = 0;
+						// now we go back to set selected_id[1] properly
+						SetWindowDirty(w);
+						return;
+					} else { //there are no vehicles in the right window
+						selected_id[1] = -1;
+					}
+				}
+		
+				if ( selected_id[0] == selected_id[1] || _autoreplace_array[selected_id[0]] == selected_id[1]
+					|| selected_id[0] == -1 || selected_id[1] == -1 )
+					SETBIT(w->disabled_state, 4);
+				else
+					CLRBIT(w->disabled_state, 4);
+			
+				if ( _autoreplace_array[selected_id[0]] == selected_id[0] || selected_id[0] == -1 )
+					SETBIT(w->disabled_state, 6);
+				else
+					CLRBIT(w->disabled_state, 6);
+		
+				// now the actual drawing of the window itself takes place
+				DrawWindowWidgets(w);
+		
+		
+		
+				// sets up the string for the vehicle that is being replaced to
+				if ( selected_id[0] != -1 ) {
+					if ( selected_id[0] == _autoreplace_array[selected_id[0]] )
+						SetDParam(0, STR_NOT_REPLACING);
+					else
+						SetDParam(0, GetCustomEngineName(_autoreplace_array[selected_id[0]]));
+				} else {
+					SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
+				}
+					
+					
+				DrawString(145, (WP(w,replaceveh_d).line_height == 24 ? 67 : 77 ) + ( WP(w,replaceveh_d).line_height * w->vscroll.cap), STR_02BD, 0x10);
+
+		
+				/*	now we draw the two arrays according to what we just counted */
+				DrawEngineArrayInReplaceWindow(w, x, y, x2, y2, pos, pos2, sel[0], sel[1], selected_id[0], selected_id[1]);
+				
+				WP(w,replaceveh_d).sel_engine[0] = selected_id[0];
+				WP(w,replaceveh_d).sel_engine[1] = selected_id[1];
+				/* now we draw the info about the vehicles we selected */
+				switch (WP(w,replaceveh_d).vehicletype) {
+					case VEH_Train: {
+						byte i = 0;
+						int offset = 0;
+				
+						for ( i = 0 ; i < 2 ; i++) {
+							if ( i )
+							offset = 228;
+							if (selected_id[i] != -1) {
+								if (!(RailVehInfo(selected_id[i])->flags & RVI_WAGON)) {
+									/* it's an engine */
+									Set_DPARAM_Train_Engine_Build_Window(selected_id[i]);
+									DrawString(2 + offset, 15 + (14 * w->vscroll.cap), STR_8817_COST_WEIGHT_T_SPEED_POWER, 0);
+								} else {
+									/* it's a wagon. Train cars are not replaced with the current GUI, but this code is ready for newgrf if anybody adds that*/
+									Set_DPARAM_Train_Car_Build_Window(w, selected_id[i]);
+									DrawString(2 + offset, 15 + (14 * w->vscroll.cap), STR_8821_COST_WEIGHT_T_T_CAPACITY, 0);
+								}
+							}
+						}
+						break;
+					}   //end if case  VEH_Train
+			
+					case VEH_Road: {
+						if (selected_id[0] != -1) {
+							Set_DPARAM_Road_Veh_Build_Window(selected_id[0]);
+							DrawString(2, 15 + (14 * w->vscroll.cap), STR_9008_COST_SPEED_RUNNING_COST, 0);
+							if (selected_id[1] != -1) {
+								Set_DPARAM_Road_Veh_Build_Window(selected_id[1]);
+								DrawString(2 + 228, 15 + (14 * w->vscroll.cap), STR_9008_COST_SPEED_RUNNING_COST, 0);
+							}
+						}
+						break;
+					}   // end of VEH_Road
+			
+					case VEH_Ship: {
+						if (selected_id[0] != -1) {
+							Set_DPARAM_Ship_Build_Window(selected_id[0]);
+							DrawString(2, 15 + (24 * w->vscroll.cap), STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
+							if (selected_id[1] != -1) {
+								Set_DPARAM_Ship_Build_Window(selected_id[1]);
+								DrawString(2 + 228, 15 + (24 * w->vscroll.cap), STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
+							}
+						}
+						break;
+					}   // end of VEH_Ship 
+			
+					case VEH_Aircraft: {
+						if (selected_id[0] != -1) {
+							Set_DPARAM_Aircraft_Build_Window(selected_id[0]);
+							DrawString(2, 15 + (24 * w->vscroll.cap), STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
+							if (selected_id[1] != -1) {
+								Set_DPARAM_Aircraft_Build_Window(selected_id[1]);
+								DrawString(2 + 228, 15 + (24 * w->vscroll.cap), STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
+							}
+						}
+						break;
+					}   // end of VEH_Aircraft
+				}
+			}   // end of paint
+
+		case WE_CLICK: {
+			switch(e->click.widget) {
+				/*case 0:
+					DeleteWindowById(WC_REPLACE_VEHICLE, WP(w,replaceveh_d).vehicletype );
+					break;*/
+			
+				case 14: case 15:/* Select sorting criteria dropdown menu */
+				// finds mask for available engines
+				{
+					int engine_avail = 0;
+					if ( !(HASBIT(_engines[NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES].player_avail, _local_player))) {
+						engine_avail = 4;
+						if ( !(HASBIT(_engines[NUM_NORMAL_RAIL_ENGINES].player_avail, _local_player)))
+							engine_avail = 6;
+					}
+					ShowDropDownMenu(w, _rail_types_list, WP(w,replaceveh_d).railtype, 15, engine_avail, 1);
+					return;
+				}
+				case 4: {
+					_autoreplace_array[WP(w,replaceveh_d).sel_engine[0]] = WP(w,replaceveh_d).sel_engine[1];
+					SetWindowDirty(w);
+					break;
+				}
+				
+				case 6: {
+					_autoreplace_array[WP(w,replaceveh_d).sel_engine[0]] = WP(w,replaceveh_d).sel_engine[0];
+					SetWindowDirty(w);
+					break;
+				}
+			
+				case 7: 
+					// sets up that the left one was clicked. The default values are for the right one (9)
+					// this way, the code for 9 handles both sides
+					click_scroll_pos = w->vscroll.pos;
+					click_scroll_cap = w->vscroll.cap;
+					click_side = 0;
+				case 9: {
+					uint i = (e->click.pt.y - 14) / WP(w,replaceveh_d).line_height;
+					if (i < click_scroll_cap) {
+						WP(w,replaceveh_d).sel_index[click_side] = i + click_scroll_pos;
+						SetWindowDirty(w);
+					}
+				} break;
+			}
+		   
+		} break;
+
+		case WE_DROPDOWN_SELECT: { /* we have selected a dropdown item in the list */
+			//potiential bug: railtypes needs to be activated 0, 1, 2... If one is skipped, it messes up
+			WP(w,replaceveh_d).railtype = e->dropdown.index;	
+			SetWindowDirty(w);
+			break;
+		}
+	}
+}
+
+static const Widget _replace_rail_vehicle_widgets[] = {
+{   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,	STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,    14,    11,   443,     0,    13, STR_REPLACE_VEHICLES,		STR_018C_WINDOW_TITLE_DRAG_THIS},
+{  WWT_STICKYBOX,    14,   444,   455,     0,    13, 0x0,						STR_STICKY_BUTTON},
+{      WWT_PANEL,    14,     0,   227,   126,   187, 0x0,						STR_NULL},
+{ WWT_PUSHTXTBTN,    14,     0,   138,   200,   211, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{      WWT_PANEL,    14,   139,   316,   188,   199, 0x0,						STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN,    14,   317,   455,   200,   211, STR_REPLACE_VEHICLES_STOP,	STR_REPLACE_HELP_STOP_BUTTON},
+{     WWT_MATRIX,    14,     0,   216,    14,   125, 0x801,			STR_REPLACE_HELP_LEFT_ARRAY},
+{  WWT_SCROLLBAR,    14,   217,   227,    14,   125, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{     WWT_MATRIX,    14,   228,   455,    14,   125, 0x801,			STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR,    14,   445,   455,    14,   125, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{      WWT_PANEL,    14,   228,   455,   126,   187, 0x0,			STR_NULL},
+// the rest are train specific stuff
+{      WWT_PANEL,    14,     0,   138,   188,   199, 0x0,			STR_NULL},
+{      WWT_PANEL,     3,   139,   153,   200,   211, 0x0,			STR_NULL},
+{      WWT_PANEL,    14,   154,   290,   200,   211, 0x0,			STR_REPLACE_HELP_RAILTYPE},
+{   WWT_CLOSEBOX,    14,   291,   301,   200,   210, STR_0225,		STR_REPLACE_HELP_RAILTYPE},
+{      WWT_PANEL,     3,   301,   316,   200,   211, 0x0,			STR_NULL},
+{      WWT_PANEL,    14,   317,   455,   188,   199, 0x0,			STR_NULL},
+
+{   WIDGETS_END},
+};
+
+static const Widget _replace_road_vehicle_widgets[] = {
+{   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,	STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,    14,    11,   443,     0,    13, STR_REPLACE_VEHICLES,		STR_018C_WINDOW_TITLE_DRAG_THIS},
+{  WWT_STICKYBOX,    14,   444,   455,     0,    13, 0x0,						STR_STICKY_BUTTON},
+{      WWT_PANEL,    14,     0,   227,   126,   187, 0x0,						STR_NULL},
+{ WWT_PUSHTXTBTN,    14,     0,   138,   188,   199, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{      WWT_PANEL,    14,   139,   316,   188,   199, 0x0,						STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN,    14,   317,   455,   188,   199, STR_REPLACE_VEHICLES_STOP,	STR_REPLACE_HELP_STOP_BUTTON},
+{     WWT_MATRIX,    14,     0,   216,    14,   125, 0x801,			STR_REPLACE_HELP_LEFT_ARRAY},
+{  WWT_SCROLLBAR,    14,   217,   227,    14,   125, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{     WWT_MATRIX,    14,   228,   455,    14,   125, 0x801,			STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR,    14,   445,   455,    14,   125, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{      WWT_PANEL,    14,   228,   455,   126,   187, 0x0,			STR_NULL},
+{   WIDGETS_END},
+};
+
+static const Widget _replace_ship_aircraft_vehicle_widgets[] = {
+{   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,	STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,    14,    11,   443,     0,    13, STR_REPLACE_VEHICLES,		STR_018C_WINDOW_TITLE_DRAG_THIS},
+{  WWT_STICKYBOX,    14,   444,   455,     0,    13, 0x0,						STR_STICKY_BUTTON},
+{      WWT_PANEL,    14,     0,   227,   110,   161, 0x0,						STR_NULL},
+{ WWT_PUSHTXTBTN,    14,     0,   138,   162,   173, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{      WWT_PANEL,    14,   139,   316,   162,   173, 0x0,						STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN,    14,   317,   455,   162,   173, STR_REPLACE_VEHICLES_STOP,	STR_REPLACE_HELP_STOP_BUTTON},
+{     WWT_MATRIX,    14,     0,   216,    14,   109, 0x401,			STR_REPLACE_HELP_LEFT_ARRAY},
+{  WWT_SCROLLBAR,    14,   217,   227,    14,   109, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{     WWT_MATRIX,    14,   228,   455,    14,   109, 0x401,			STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR,    14,   445,   455,    14,   109, 0x0,			STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{      WWT_PANEL,    14,   228,   455,   110,   161, 0x0,			STR_NULL},
+{   WIDGETS_END},
+};
+
+static const WindowDesc _replace_rail_vehicle_desc = {
+	-1, -1, 456, 212,
+	WC_REPLACE_VEHICLE,0,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+	_replace_rail_vehicle_widgets,
+	ReplaceVehicleWndProc
+};
+
+static const WindowDesc _replace_road_vehicle_desc = {
+	-1, -1, 456, 200,
+	WC_REPLACE_VEHICLE,0,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+	_replace_road_vehicle_widgets,
+	ReplaceVehicleWndProc
+};
+
+static const WindowDesc _replace_ship_aircraft_vehicle_desc = {
+	-1, -1, 456, 174,
+	WC_REPLACE_VEHICLE,0,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+	_replace_ship_aircraft_vehicle_widgets,
+	ReplaceVehicleWndProc
+};
+
+
+void ShowReplaceVehicleWindow(byte vehicletype)
+{
+	Window *w;
+	
+	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype );
+	
+	switch (vehicletype) {
+		case VEH_Train:
+			w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 8;
+			WP(w,replaceveh_d).line_height = 14;
+			break;
+		case VEH_Road:
+			w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 8;
+			WP(w,replaceveh_d).line_height = 14;
+			break;
+		case VEH_Ship: case VEH_Aircraft:
+			w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 4;
+			WP(w,replaceveh_d).line_height = 24;
+			break;
+	}
+	WP(w,replaceveh_d).vehicletype = vehicletype;
+	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
+}
--- a/vehicle_gui.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/vehicle_gui.h	Sun Jan 02 17:23:04 2005 +0000
@@ -42,12 +42,13 @@
 #define SORT_BY_UNSORTED 0
 extern VehicleSortListingTypeFunctions * const _vehicle_sorter[];
 extern const StringID _vehicle_sort_listing[];
+extern const StringID _rail_types_list[];
 
 enum VehicleSortTypes {
 	VEHTRAIN		= 0,
 	VEHROAD			= 1,
 	VEHSHIP			= 2,
-	VEHAIRCRAFT	= 3
+	VEHAIRCRAFT		= 3
 };
 
 enum {
@@ -56,4 +57,13 @@
   PLY_WND_PRC__SIZE_OF_ROW_BIG		= 36,
 };
 
+void ShowReplaceVehicleWindow(byte vehicletype);
+
+void Set_DPARAM_Train_Engine_Build_Window(uint16 engine_number);
+void Set_DPARAM_Train_Car_Build_Window(Window *w, uint16 engine_number);
+void Set_DPARAM_Road_Veh_Build_Window(uint16 engine_number);
+void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number);
+void Set_DPARAM_Ship_Build_Window(uint16 engine_number);
+
+
 #endif /* VEHICLE_GUI_H */
--- a/widget.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/widget.c	Sun Jan 02 17:23:04 2005 +0000
@@ -46,23 +46,37 @@
 	int mi, ma, pos;
 	Scrollbar *sb;
 
-	if (wi->type == WWT_SCROLLBAR) {
-		// vertical scroller
-		w->flags4 &= ~WF_HSCROLL;
-		mi = wi->top;
-		ma = wi->bottom;
-		pos = y;
-		sb = &w->vscroll;
-	} else {
-		// horizontal scroller
-		assert(wi->type == WWT_HSCROLLBAR);
-		w->flags4 |= WF_HSCROLL;
-		mi = wi->left;
-		ma = wi->right;
-		pos = x;
-		sb = &w->hscroll;
+	switch (wi->type) {
+		case WWT_SCROLLBAR: {
+			// vertical scroller
+			w->flags4 &= ~WF_HSCROLL;
+			w->flags4 &= ~WF_SCROLL2;
+			mi = wi->top;
+			ma = wi->bottom;
+			pos = y;
+			sb = &w->vscroll;
+			break;
+		}
+		case WWT_SCROLL2BAR: {
+			// 2nd vertical scroller
+			w->flags4 &= ~WF_HSCROLL;
+			w->flags4 |= WF_SCROLL2;
+			mi = wi->top;
+			ma = wi->bottom;
+			pos = y;
+			sb = &w->vscroll2;
+			break;
+		}
+		case  WWT_HSCROLLBAR: {
+			// horizontal scroller
+			assert(wi->type == WWT_HSCROLLBAR);
+			w->flags4 |= WF_HSCROLL;
+			mi = wi->left;
+			ma = wi->right;
+			pos = x;
+			sb = &w->hscroll;
+		}
 	}
-
 	if (pos <= mi+9) {
 		// Pressing the upper button?
 		if (!_demo_mode) {
@@ -258,8 +272,8 @@
 			int c1,c2;
 
 			// draw up/down buttons
-			DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == WF_SCROLL_UP ? 0x20 : 0);
-			DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == WF_SCROLL_DOWN ? 0x20 : 0);
+			DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP ? 0x20 : 0);
+			DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN ? 0x20 : 0);
 
 			// draw icons in up/down buttons
 			DoDrawString("\xA0", r.left+2, r.top, 0x10);
@@ -279,7 +293,36 @@
 			GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
 
 			pt = HandleScrollbarHittest(&w->vscroll, r.top, r.bottom);
-			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == WF_SCROLL_MIDDLE ? 0x20 : 0);
+			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE ? 0x20 : 0);
+			break;
+		}
+		case WWT_SCROLL2BAR: {
+			Point pt;
+			int c1,c2;
+
+			// draw up/down buttons
+			DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2) ? 0x20 : 0);
+			DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2) ? 0x20 : 0);
+
+			// draw icons in up/down buttons
+			DoDrawString("\xA0", r.left+2, r.top, 0x10);
+			DoDrawString("\xAA", r.left+2, r.bottom-9, 0x10);
+
+			c1 = _color_list[wi->color&0xF].window_color_1a;
+			c2 = _color_list[wi->color&0xF].window_color_2;
+
+			// draw "shaded" background
+			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2);
+			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | 0x8000);
+
+			// draw shaded lines
+			GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1);
+			GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2);
+			GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1);
+			GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
+
+			pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom);
+			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? 0x20 : 0);
 			break;
 		}
 
@@ -383,6 +426,7 @@
 
 static uint _dropdown_item_count;
 static uint32 _dropdown_disabled;
+static bool _dropdown_hide_disabled;
 static const StringID *_dropdown_items;
 static int _dropdown_selindex;
 static byte _dropdown_button;
@@ -421,95 +465,100 @@
 	int item;
 
 	switch(e->event) {
-	case WE_PAINT: {
-		int x,y,i,sel;
-		uint32 dis;
-
-		DrawWindowWidgets(w);
-
-		x = 1;
-		y = 2;
-		sel = _dropdown_selindex;
-		dis = _dropdown_disabled;
-
-		for(i=0; _dropdown_items[i] != INVALID_STRING_ID; i++) {
-			if (_dropdown_items[i] != 0) {
-				if (sel == 0) {
-					GfxFillRect(x+1, y, x+w->width-4, y + 9, 0);
-				}
-				DrawString(x+2, y, _dropdown_items[i], sel==0 ? 12 : 16);
-
-				if (dis & 1) {
-					GfxFillRect(x, y, x+w->width-3, y + 9, 0x8000 +
-						_color_list[_dropdown_menu_widgets[0].color].window_color_bga);
-				}
-			} else {
-				int color_1 = _color_list[_dropdown_menu_widgets[0].color].window_color_1a;
-				int color_2 = _color_list[_dropdown_menu_widgets[0].color].window_color_2;
-				GfxFillRect(x+1, y+3, x+w->width-5, y+3, color_1);
-				GfxFillRect(x+1, y+4, x+w->width-5, y+4, color_2);
-			}
-			y += 10;
-			sel--;
-			dis>>=1;
-		}
-	} break;
+		case WE_PAINT: {
+			int x,y,i,sel;
+			uint32 dis;
+			bool hidden;
 
-	case WE_CLICK: {
-		item = GetDropdownItem(w);
-		if (item >= 0) {
-			_dropdown_var1 = 4;
-			_dropdown_selindex = item;
-			SetWindowDirty(w);
-		}
-	} break;
-
-	case WE_MOUSELOOP: {
-		Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
-		if (w2 == NULL) {
-			DeleteWindow(w);
-			return;
-		}
+			DrawWindowWidgets(w);
 
-		if (_dropdown_var1 != 0 && --_dropdown_var1 == 0) {
-			WindowEvent e;
-			e.event = WE_DROPDOWN_SELECT;
-			e.dropdown.button = _dropdown_button;
-			e.dropdown.index = _dropdown_selindex;
-			w2->wndproc(w2, &e);
-			DeleteWindow(w);
-			return;
-		}
+			x = 1;
+			y = 2;
+			sel    = _dropdown_selindex;
+			dis    = _dropdown_disabled;
+			hidden = _dropdown_hide_disabled;
+		
 
-		if (_dropdown_var2 != 0) {
-			item = GetDropdownItem(w);
+			for(i=0; _dropdown_items[i] != INVALID_STRING_ID; i++) {
+				if (!(hidden) | !(dis & 1)) {
+					if (_dropdown_items[i] != 0) {
+						if (sel == 0) {
+							GfxFillRect(x+1, y, x+w->width-4, y + 9, 0);
+						}
+						DrawString(x+2, y, _dropdown_items[i], sel==0 ? 12 : 16);
 
-			if (!_left_button_clicked) {
-				_dropdown_var2 = 0;
-				if (item < 0)
-					return;
-				_dropdown_var1 = 2;
-			} else {
-				if (item < 0)
-					return;
+						if (dis & 1) {
+							GfxFillRect(x, y, x+w->width-3, y + 9, 0x8000 +
+							_color_list[_dropdown_menu_widgets[0].color].window_color_bga);
+						}
+					} else {
+						int color_1 = _color_list[_dropdown_menu_widgets[0].color].window_color_1a;
+						int color_2 = _color_list[_dropdown_menu_widgets[0].color].window_color_2;
+						GfxFillRect(x+1, y+3, x+w->width-5, y+3, color_1);
+						GfxFillRect(x+1, y+4, x+w->width-5, y+4, color_2);
+					}
+					y += 10;
+					sel--;
+				}
+				dis>>=1;
+			}
+		} break;
+
+		case WE_CLICK: {
+			item = GetDropdownItem(w);
+			if (item >= 0) {
+				_dropdown_var1 = 4;
+				_dropdown_selindex = item;
+				SetWindowDirty(w);
+			}
+		} break;
+
+		case WE_MOUSELOOP: {
+			Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
+			if (w2 == NULL) {
+				DeleteWindow(w);
+				return;
 			}
 
-			_dropdown_selindex = item;
-			SetWindowDirty(w);
-		}
-	} break;
+			if (_dropdown_var1 != 0 && --_dropdown_var1 == 0) {
+				WindowEvent e;
+				e.event = WE_DROPDOWN_SELECT;
+				e.dropdown.button = _dropdown_button;
+				e.dropdown.index = _dropdown_selindex;
+				w2->wndproc(w2, &e);
+				DeleteWindow(w);
+				return;
+			}
 
-	case WE_DESTROY: {
-		Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
-		if (w2 != NULL) {
-			CLRBIT(w2->click_state, _dropdown_button);
-			InvalidateWidget(w2, _dropdown_button);
-		}
-	} break;
+			if (_dropdown_var2 != 0) {
+				item = GetDropdownItem(w);
+
+				if (!_left_button_clicked) {
+					_dropdown_var2 = 0;
+					if (item < 0)
+						return;
+					_dropdown_var1 = 2;
+				} else {
+					if (item < 0)
+						return;
+				}
+
+				_dropdown_selindex = item;
+				SetWindowDirty(w);
+			}
+		} break;
+
+		case WE_DESTROY: {
+			Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
+			if (w2 != NULL) {
+				CLRBIT(w2->click_state, _dropdown_button);
+				InvalidateWidget(w2, _dropdown_button);
+			}
+		} break;
 	}
 }
 
-void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask)
+void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, bool remove_filtered_strings)
 {
 	WindowNumber num;
 	WindowClass cls;
@@ -519,6 +568,7 @@
 	uint32 old_click_state = w->click_state;
 
 	_dropdown_disabled = disabled_mask;
+	_dropdown_hide_disabled = remove_filtered_strings;
 
 	cls = w->window_class;
 	num = w->window_number;
@@ -549,6 +599,16 @@
 
 	wi = &w->widget[button];
 
+	if ( remove_filtered_strings ) {
+		int j;
+		for(j=0; _dropdown_items[j] != INVALID_STRING_ID; j++) {
+			if ( disabled_mask & ( 1 << j )) {
+				_dropdown_item_count--;
+				i--;
+			}
+		}
+	}
+
 	_dropdown_menu_widgets[0].color = wi->color;
 
 	w2 = AllocateWindow(
--- a/window.c	Sun Jan 02 12:03:43 2005 +0000
+++ b/window.c	Sun Jan 02 17:23:04 2005 +0000
@@ -44,7 +44,7 @@
 			case WWT_NODISTXTBTN:
 				break;
 			}
-		} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_HSCROLLBAR) {
+		} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
 			ScrollbarClickHandler(w, wi, e.click.pt.x, e.click.pt.y);
 		}
 
@@ -953,6 +953,9 @@
 			if (w->flags4 & WF_HSCROLL) {
 				sb = &w->hscroll;
 				i = _cursor.pos.x - _cursorpos_drag_start.x;
+			} else if (w->flags4 & WF_SCROLL2){
+				sb = &w->vscroll2;
+				i = _cursor.pos.y - _cursorpos_drag_start.y;
 			} else {
 				sb = &w->vscroll;
 				i = _cursor.pos.y - _cursorpos_drag_start.y;
--- a/window.h	Sun Jan 02 12:03:43 2005 +0000
+++ b/window.h	Sun Jan 02 17:23:04 2005 +0000
@@ -200,7 +200,7 @@
 	int left,top;
 	int width,height;
 
-	Scrollbar hscroll, vscroll;
+	Scrollbar hscroll, vscroll, vscroll2;
 
 	byte caption_color;
 
@@ -255,6 +255,15 @@
 } buildtrain_d;
 
 typedef struct {
+	byte railtype;
+	byte vehicletype;
+	byte sel_index[2];
+	int16 sel_engine[2];
+	uint16 count[2];
+	byte line_height;
+} replaceveh_d;
+
+typedef struct {
 	VehicleID sel;
 } traindepot_d;
 
@@ -358,7 +367,8 @@
 
 	WWT_HSCROLLBAR = 11,
 	WWT_STICKYBOX = 12,
-	WWT_LAST = 13,						/* Last Item. use WIDGETS_END to fill up padding!! */
+	WWT_SCROLL2BAR = 13,				/* 2nd vertical scrollbar*/
+	WWT_LAST = 14,						/* Last Item. use WIDGETS_END to fill up padding!! */
 
 	WWT_MASK = 31,
 
@@ -384,6 +394,7 @@
 
 	WF_WHITE_BORDER_ONE = 1 << 11,
 	WF_WHITE_BORDER_MASK = 3 << 11,
+	WF_SCROLL2 = 1 << 13,
 };
 
 
@@ -453,7 +464,7 @@
 /* widget.c */
 int GetWidgetFromPos(Window *w, int x, int y);
 void DrawWindowWidgets(Window *w);
-void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask);
+void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, bool remove_filtered_strings);
 
 void HandleButtonClick(Window *w, byte widget);