src/depot_gui.cpp
changeset 9201 b9f31e062da8
parent 9188 58cb2dd94fab
child 9203 082fbf0500c4
equal deleted inserted replaced
9200:ae323616f9ab 9201:b9f31e062da8
    99 	{  WWT_RESIZEBOX,   RESIZE_LRTB,    14,    24,    35,    15,    26, 0x0,                 STR_RESIZE_BUTTON},                // DEPOT_WIDGET_RESIZE
    99 	{  WWT_RESIZEBOX,   RESIZE_LRTB,    14,    24,    35,    15,    26, 0x0,                 STR_RESIZE_BUTTON},                // DEPOT_WIDGET_RESIZE
   100 	{   WIDGETS_END},
   100 	{   WIDGETS_END},
   101 };
   101 };
   102 
   102 
   103 
   103 
   104 struct depot_d {
       
   105 	VehicleID sel;
       
   106 	VehicleType type;
       
   107 	bool generate_list;
       
   108 	uint16 engine_list_length;
       
   109 	uint16 wagon_list_length;
       
   110 	uint16 engine_count;
       
   111 	uint16 wagon_count;
       
   112 	Vehicle **vehicle_list;
       
   113 	Vehicle **wagon_list;
       
   114 };
       
   115 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(depot_d));
       
   116 
       
   117 static void DepotWndProc(Window *w, WindowEvent *e);
       
   118 
       
   119 static const WindowDesc _train_depot_desc = {
   104 static const WindowDesc _train_depot_desc = {
   120 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   105 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   121 	WC_VEHICLE_DEPOT, WC_NONE,
   106 	WC_VEHICLE_DEPOT, WC_NONE,
   122 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   107 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   123 	_depot_widgets,
   108 	_depot_widgets,
   124 	DepotWndProc
   109 	NULL
   125 };
   110 };
   126 
   111 
   127 static const WindowDesc _road_depot_desc = {
   112 static const WindowDesc _road_depot_desc = {
   128 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   113 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   129 	WC_VEHICLE_DEPOT, WC_NONE,
   114 	WC_VEHICLE_DEPOT, WC_NONE,
   130 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   115 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   131 	_depot_widgets,
   116 	_depot_widgets,
   132 	DepotWndProc
   117 	NULL
   133 };
   118 };
   134 
   119 
   135 static const WindowDesc _ship_depot_desc = {
   120 static const WindowDesc _ship_depot_desc = {
   136 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   121 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   137 	WC_VEHICLE_DEPOT, WC_NONE,
   122 	WC_VEHICLE_DEPOT, WC_NONE,
   138 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   123 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   139 	_depot_widgets,
   124 	_depot_widgets,
   140 	DepotWndProc
   125 	NULL
   141 };
   126 };
   142 
   127 
   143 static const WindowDesc _aircraft_depot_desc = {
   128 static const WindowDesc _aircraft_depot_desc = {
   144 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   129 	WDP_AUTO, WDP_AUTO, 36, 27, 36, 27,
   145 	WC_VEHICLE_DEPOT, WC_NONE,
   130 	WC_VEHICLE_DEPOT, WC_NONE,
   146 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   131 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   147 	_depot_widgets,
   132 	_depot_widgets,
   148 	DepotWndProc
   133 	NULL
   149 };
   134 };
   150 
   135 
   151 extern int WagonLengthToPixels(int len);
   136 extern int WagonLengthToPixels(int len);
       
   137 extern void DepotSortList(Vehicle **v, uint16 length);
   152 
   138 
   153 /**
   139 /**
   154  * This is the Callback method after the cloning attempt of a vehicle
   140  * This is the Callback method after the cloning attempt of a vehicle
   155  * @param success indicates completion (or not) of the operation
   141  * @param success indicates completion (or not) of the operation
   156  * @param tile unused
   142  * @param tile unused
   164 	Vehicle *v = GetVehicle(_new_vehicle_id);
   150 	Vehicle *v = GetVehicle(_new_vehicle_id);
   165 
   151 
   166 	ShowVehicleViewWindow(v);
   152 	ShowVehicleViewWindow(v);
   167 }
   153 }
   168 
   154 
   169 static void DepotSellAllConfirmationCallback(Window *w, bool confirmed)
       
   170 {
       
   171 	if (confirmed) {
       
   172 		TileIndex tile = w->window_number;
       
   173 		byte vehtype = WP(w, depot_d).type;
       
   174 		DoCommandP(tile, vehtype, 0, NULL, CMD_DEPOT_SELL_ALL_VEHICLES);
       
   175 	}
       
   176 }
       
   177 
       
   178 const Sprite *GetAircraftSprite(EngineID engine);
       
   179 
       
   180 /** Draw a vehicle in the depot window in the box with the top left corner at x,y
       
   181  * @param *w Window to draw in
       
   182  * @param *v Vehicle to draw
       
   183  * @param x Left side of the box to draw in
       
   184  * @param y Top of the box to draw in
       
   185  */
       
   186 static void DrawVehicleInDepot(Window *w, const Vehicle *v, int x, int y)
       
   187 {
       
   188 	byte diff_x = 0, diff_y = 0;
       
   189 
       
   190 	int sprite_y = y + w->resize.step_height - GetVehicleListHeight(v->type);
       
   191 
       
   192 	switch (v->type) {
       
   193 		case VEH_TRAIN:
       
   194 			DrawTrainImage(v, x + 21, sprite_y, WP(w, depot_d).sel, w->hscroll.cap + 4, w->hscroll.pos);
       
   195 
       
   196 			/* Number of wagons relative to a standard length wagon (rounded up) */
       
   197 			SetDParam(0, (v->u.rail.cached_total_length + 7) / 8);
       
   198 			DrawStringRightAligned(w->widget[DEPOT_WIDGET_MATRIX].right - 1, y + 4, STR_TINY_BLACK, TC_FROMSTRING); // Draw the counter
       
   199 			break;
       
   200 
       
   201 		case VEH_ROAD:     DrawRoadVehImage( v, x + 24, sprite_y, WP(w, depot_d).sel, 1); break;
       
   202 		case VEH_SHIP:     DrawShipImage(    v, x + 19, sprite_y - 1, WP(w, depot_d).sel); break;
       
   203 		case VEH_AIRCRAFT: {
       
   204 			const Sprite *spr = GetSprite(v->GetImage(DIR_W));
       
   205 			DrawAircraftImage(v, x + 12,
       
   206 							  y + max(spr->height + spr->y_offs - 14, 0), // tall sprites needs an y offset
       
   207 							  WP(w, depot_d).sel);
       
   208 		} break;
       
   209 		default: NOT_REACHED();
       
   210 	}
       
   211 
       
   212 	if (w->resize.step_height == 14) {
       
   213 		/* VEH_TRAIN and VEH_ROAD, which are low */
       
   214 		diff_x = 15;
       
   215 	} else {
       
   216 		/* VEH_SHIP and VEH_AIRCRAFT, which are tall */
       
   217 		diff_y = 12;
       
   218 	}
       
   219 
       
   220 	DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, x + diff_x, y + diff_y);
       
   221 
       
   222 	SetDParam(0, v->unitnumber);
       
   223 	DrawString(x, y + 2, (uint16)(v->max_age - 366) >= v->age ? STR_00E2 : STR_00E3, TC_FROMSTRING);
       
   224 }
       
   225 
       
   226 static void DrawDepotWindow(Window *w)
       
   227 {
       
   228 	Vehicle **vl = WP(w, depot_d).vehicle_list;
       
   229 	TileIndex tile = w->window_number;
       
   230 	int x, y, i, maxval;
       
   231 	uint16 hnum;
       
   232 	uint16 num = WP(w, depot_d).engine_count;
       
   233 
       
   234 	/* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
       
   235 	uint16 rows_in_display   = w->widget[DEPOT_WIDGET_MATRIX].data >> 8;
       
   236 	uint16 boxes_in_each_row = w->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
       
   237 
       
   238 	/* setup disabled buttons */
       
   239 	w->SetWidgetsDisabledState(!IsTileOwner(tile, _local_player),
       
   240 		DEPOT_WIDGET_STOP_ALL,
       
   241 		DEPOT_WIDGET_START_ALL,
       
   242 		DEPOT_WIDGET_SELL,
       
   243 		DEPOT_WIDGET_SELL_CHAIN,
       
   244 		DEPOT_WIDGET_SELL_ALL,
       
   245 		DEPOT_WIDGET_BUILD,
       
   246 		DEPOT_WIDGET_CLONE,
       
   247 		DEPOT_WIDGET_AUTOREPLACE,
       
   248 		WIDGET_LIST_END);
       
   249 
       
   250 	/* determine amount of items for scroller */
       
   251 	if (WP(w, depot_d).type == VEH_TRAIN) {
       
   252 		hnum = 8;
       
   253 		for (num = 0; num < WP(w, depot_d).engine_count; num++) {
       
   254 			const Vehicle *v = vl[num];
       
   255 			hnum = max(hnum, v->u.rail.cached_total_length);
       
   256 		}
       
   257 		/* Always have 1 empty row, so people can change the setting of the train */
       
   258 		SetVScrollCount(w, WP(w, depot_d).engine_count + WP(w, depot_d).wagon_count + 1);
       
   259 		SetHScrollCount(w, WagonLengthToPixels(hnum));
       
   260 	} else {
       
   261 		SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
       
   262 	}
       
   263 
       
   264 	/* locate the depot struct */
       
   265 	if (WP(w, depot_d).type == VEH_AIRCRAFT) {
       
   266 		SetDParam(0, GetStationIndex(tile)); // Airport name
       
   267 	} else {
       
   268 		Depot *depot = GetDepotByTile(tile);
       
   269 		assert(depot != NULL);
       
   270 
       
   271 		SetDParam(0, depot->town_index);
       
   272 	}
       
   273 
       
   274 	DrawWindowWidgets(w);
       
   275 
       
   276 	num = w->vscroll.pos * boxes_in_each_row;
       
   277 	maxval = min(WP(w, depot_d).engine_count, num + (rows_in_display * boxes_in_each_row));
       
   278 
       
   279 	for (x = 2, y = 15; num < maxval; y += w->resize.step_height, x = 2) { // Draw the rows
       
   280 		byte i;
       
   281 
       
   282 		for (i = 0; i < boxes_in_each_row && num < maxval; i++, num++, x += w->resize.step_width) {
       
   283 			/* Draw all vehicles in the current row */
       
   284 			const Vehicle *v = vl[num];
       
   285 			DrawVehicleInDepot(w, v, x, y);
       
   286 		}
       
   287 	}
       
   288 
       
   289 	maxval = min(WP(w, depot_d).engine_count + WP(w, depot_d).wagon_count, (w->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row));
       
   290 
       
   291 	/* draw the train wagons, that do not have an engine in front */
       
   292 	for (; num < maxval; num++, y += 14) {
       
   293 		const Vehicle *v = WP(w, depot_d).wagon_list[num - WP(w, depot_d).engine_count];
       
   294 		const Vehicle *u;
       
   295 
       
   296 		DrawTrainImage(v, x + 50, y, WP(w, depot_d).sel, w->hscroll.cap - 29, 0);
       
   297 		DrawString(x, y + 2, STR_8816, TC_FROMSTRING);
       
   298 
       
   299 		/*Draw the train counter */
       
   300 		i = 0;
       
   301 		u = v;
       
   302 		do i++; while ((u = u->Next()) != NULL); // Determine length of train
       
   303 		SetDParam(0, i);                      // Set the counter
       
   304 		DrawStringRightAligned(w->widget[DEPOT_WIDGET_MATRIX].right - 1, y + 4, STR_TINY_BLACK, TC_FROMSTRING); // Draw the counter
       
   305 	}
       
   306 }
       
   307 
       
   308 struct GetDepotVehiclePtData {
       
   309 	Vehicle *head;
       
   310 	Vehicle *wagon;
       
   311 };
       
   312 
       
   313 enum DepotGUIAction {
       
   314 	MODE_ERROR,
       
   315 	MODE_DRAG_VEHICLE,
       
   316 	MODE_SHOW_VEHICLE,
       
   317 	MODE_START_STOP,
       
   318 };
       
   319 
       
   320 static DepotGUIAction GetVehicleFromDepotWndPt(const Window *w, int x, int y, Vehicle **veh, GetDepotVehiclePtData *d)
       
   321 {
       
   322 	Vehicle **vl = WP(w, depot_d).vehicle_list;
       
   323 	uint xt, row, xm = 0, ym = 0;
       
   324 	int pos, skip = 0;
       
   325 	uint16 boxes_in_each_row = w->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
       
   326 
       
   327 	if (WP(w, depot_d).type == VEH_TRAIN) {
       
   328 		xt = 0;
       
   329 		x -= 23;
       
   330 	} else {
       
   331 		xt = x / w->resize.step_width;
       
   332 		xm = x % w->resize.step_width;
       
   333 		if (xt >= w->hscroll.cap) return MODE_ERROR;
       
   334 
       
   335 		ym = (y - 14) % w->resize.step_height;
       
   336 	}
       
   337 
       
   338 	row = (y - 14) / w->resize.step_height;
       
   339 	if (row >= w->vscroll.cap) return MODE_ERROR;
       
   340 
       
   341 	pos = ((row + w->vscroll.pos) * boxes_in_each_row) + xt;
       
   342 
       
   343 	if (WP(w, depot_d).engine_count + WP(w, depot_d).wagon_count <= pos) {
       
   344 		if (WP(w, depot_d).type == VEH_TRAIN) {
       
   345 			d->head  = NULL;
       
   346 			d->wagon = NULL;
       
   347 			return MODE_DRAG_VEHICLE;
       
   348 		} else {
       
   349 			return MODE_ERROR; // empty block, so no vehicle is selected
       
   350 		}
       
   351 	}
       
   352 
       
   353 	if (WP(w, depot_d).engine_count > pos) {
       
   354 		*veh = vl[pos];
       
   355 		skip = w->hscroll.pos;
       
   356 	} else {
       
   357 		vl = WP(w, depot_d).wagon_list;
       
   358 		pos -= WP(w, depot_d).engine_count;
       
   359 		*veh = vl[pos];
       
   360 		/* free wagons don't have an initial loco. */
       
   361 		x -= _traininfo_vehicle_width;
       
   362 	}
       
   363 
       
   364 	switch (WP(w, depot_d).type) {
       
   365 		case VEH_TRAIN: {
       
   366 			Vehicle *v = *veh;
       
   367 			d->head = d->wagon = v;
       
   368 
       
   369 			/* either pressed the flag or the number, but only when it's a loco */
       
   370 			if (x < 0 && IsFrontEngine(v)) return (x >= -10) ? MODE_START_STOP : MODE_SHOW_VEHICLE;
       
   371 
       
   372 			skip = (skip * 8) / _traininfo_vehicle_width;
       
   373 			x = (x * 8) / _traininfo_vehicle_width;
       
   374 
       
   375 			/* Skip vehicles that are scrolled off the list */
       
   376 			x += skip;
       
   377 
       
   378 			/* find the vehicle in this row that was clicked */
       
   379 			while (v != NULL && (x -= v->u.rail.cached_veh_length) >= 0) v = v->Next();
       
   380 
       
   381 			/* if an articulated part was selected, find its parent */
       
   382 			while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
       
   383 
       
   384 			d->wagon = v;
       
   385 
       
   386 			return MODE_DRAG_VEHICLE;
       
   387 			}
       
   388 			break;
       
   389 
       
   390 		case VEH_ROAD:
       
   391 			if (xm >= 24) return MODE_DRAG_VEHICLE;
       
   392 			if (xm <= 16) return MODE_SHOW_VEHICLE;
       
   393 			break;
       
   394 
       
   395 		case VEH_SHIP:
       
   396 			if (xm >= 19) return MODE_DRAG_VEHICLE;
       
   397 			if (ym <= 10) return MODE_SHOW_VEHICLE;
       
   398 			break;
       
   399 
       
   400 		case VEH_AIRCRAFT:
       
   401 			if (xm >= 12) return MODE_DRAG_VEHICLE;
       
   402 			if (ym <= 12) return MODE_SHOW_VEHICLE;
       
   403 			break;
       
   404 
       
   405 		default: NOT_REACHED();
       
   406 	}
       
   407 	return MODE_START_STOP;
       
   408 }
       
   409 
       
   410 static void TrainDepotMoveVehicle(Vehicle *wagon, VehicleID sel, Vehicle *head)
   155 static void TrainDepotMoveVehicle(Vehicle *wagon, VehicleID sel, Vehicle *head)
   411 {
   156 {
   412 	Vehicle *v;
   157 	Vehicle *v;
   413 
   158 
   414 	v = GetVehicle(sel);
   159 	v = GetVehicle(sel);
   424 
   169 
   425 	if (wagon == v) return;
   170 	if (wagon == v) return;
   426 
   171 
   427 	DoCommandP(v->tile, v->index + ((wagon == NULL ? INVALID_VEHICLE : wagon->index) << 16), _ctrl_pressed ? 1 : 0, NULL, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_8837_CAN_T_MOVE_VEHICLE));
   172 	DoCommandP(v->tile, v->index + ((wagon == NULL ? INVALID_VEHICLE : wagon->index) << 16), _ctrl_pressed ? 1 : 0, NULL, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_8837_CAN_T_MOVE_VEHICLE));
   428 }
   173 }
   429 
       
   430 static void DepotClick(Window *w, int x, int y)
       
   431 {
       
   432 	GetDepotVehiclePtData gdvp;
       
   433 	Vehicle *v = NULL;
       
   434 	DepotGUIAction mode = GetVehicleFromDepotWndPt(w, x, y, &v, &gdvp);
       
   435 
       
   436 	/* share / copy orders */
       
   437 	if (_thd.place_mode != VHM_NONE && mode != MODE_ERROR) {
       
   438 		_place_clicked_vehicle = (WP(w, depot_d).type == VEH_TRAIN ? gdvp.head : v);
       
   439 		return;
       
   440 	}
       
   441 
       
   442 	if (WP(w, depot_d).type == VEH_TRAIN) v = gdvp.wagon;
       
   443 
       
   444 	switch (mode) {
       
   445 		case MODE_ERROR: // invalid
       
   446 			return;
       
   447 
       
   448 		case MODE_DRAG_VEHICLE: { // start dragging of vehicle
       
   449 			VehicleID sel = WP(w, depot_d).sel;
       
   450 
       
   451 			if (WP(w, depot_d).type == VEH_TRAIN && sel != INVALID_VEHICLE) {
       
   452 				WP(w, depot_d).sel = INVALID_VEHICLE;
       
   453 				TrainDepotMoveVehicle(v, sel, gdvp.head);
       
   454 			} else if (v != NULL) {
       
   455 				int image = v->GetImage(DIR_W);
       
   456 
       
   457 				WP(w, depot_d).sel = v->index;
       
   458 				w->SetDirty();
       
   459 				SetObjectToPlaceWnd(image, GetVehiclePalette(v), VHM_DRAG, w);
       
   460 				_cursor.vehchain = _ctrl_pressed;
       
   461 			}
       
   462 			}
       
   463 			break;
       
   464 
       
   465 		case MODE_SHOW_VEHICLE: // show info window
       
   466 			ShowVehicleViewWindow(v);
       
   467 			break;
       
   468 
       
   469 		case MODE_START_STOP: { // click start/stop flag
       
   470 			uint command;
       
   471 
       
   472 			switch (WP(w, depot_d).type) {
       
   473 				case VEH_TRAIN:    command = CMD_START_STOP_TRAIN | CMD_MSG(STR_883B_CAN_T_STOP_START_TRAIN);          break;
       
   474 				case VEH_ROAD:     command = CMD_START_STOP_ROADVEH | CMD_MSG(STR_9015_CAN_T_STOP_START_ROAD_VEHICLE); break;
       
   475 				case VEH_SHIP:     command = CMD_START_STOP_SHIP | CMD_MSG(STR_9818_CAN_T_STOP_START_SHIP);            break;
       
   476 				case VEH_AIRCRAFT: command = CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT);    break;
       
   477 				default: NOT_REACHED(); command = 0;
       
   478 			}
       
   479 			DoCommandP(v->tile, v->index, 0, NULL, command);
       
   480 			}
       
   481 			break;
       
   482 
       
   483 		default: NOT_REACHED();
       
   484 	}
       
   485 }
       
   486 
       
   487 /**
       
   488  * Clones a vehicle
       
   489  * @param *v is the original vehicle to clone
       
   490  * @param *w is the window of the depot where the clone is build
       
   491  */
       
   492 static void HandleCloneVehClick(const Vehicle *v, const Window *w)
       
   493 {
       
   494 	uint error_str;
       
   495 
       
   496 	if (v == NULL) return;
       
   497 
       
   498 	if (!v->IsPrimaryVehicle()) {
       
   499 		v = v->First();
       
   500 		/* Do nothing when clicking on a train in depot with no loc attached */
       
   501 		if (v->type == VEH_TRAIN && !IsFrontEngine(v)) return;
       
   502 	}
       
   503 
       
   504 	switch (v->type) {
       
   505 		case VEH_TRAIN:    error_str = CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE); break;
       
   506 		case VEH_ROAD:     error_str = CMD_MSG(STR_9009_CAN_T_BUILD_ROAD_VEHICLE);     break;
       
   507 		case VEH_SHIP:     error_str = CMD_MSG(STR_980D_CAN_T_BUILD_SHIP);             break;
       
   508 		case VEH_AIRCRAFT: error_str = CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT);         break;
       
   509 		default: return;
       
   510 	}
       
   511 
       
   512 	DoCommandP(w->window_number, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle, CMD_CLONE_VEHICLE | error_str);
       
   513 
       
   514 	ResetObjectToPlace();
       
   515 }
       
   516 
       
   517 static void ClonePlaceObj(const Window *w)
       
   518 {
       
   519 	const Vehicle *v = CheckMouseOverVehicle();
       
   520 
       
   521 	if (v != NULL) HandleCloneVehClick(v, w);
       
   522 }
       
   523 
       
   524 static void ResizeDepotButtons(Window *w)
       
   525 {
       
   526 	ResizeButtons(w, DEPOT_WIDGET_BUILD, DEPOT_WIDGET_LOCATION);
       
   527 
       
   528 	if (WP(w, depot_d).type == VEH_TRAIN) {
       
   529 		/* Divide the size of DEPOT_WIDGET_SELL into two equally big buttons so DEPOT_WIDGET_SELL and DEPOT_WIDGET_SELL_CHAIN will get the same size.
       
   530 		* This way it will stay the same even if DEPOT_WIDGET_SELL_CHAIN is resized for some reason                                                  */
       
   531 		w->widget[DEPOT_WIDGET_SELL_CHAIN].top    = ((w->widget[DEPOT_WIDGET_SELL_CHAIN].bottom - w->widget[DEPOT_WIDGET_SELL].top) / 2) + w->widget[DEPOT_WIDGET_SELL].top;
       
   532 		w->widget[DEPOT_WIDGET_SELL].bottom     = w->widget[DEPOT_WIDGET_SELL_CHAIN].top - 1;
       
   533 	}
       
   534 }
       
   535 
       
   536 /* Function to set up vehicle specific sprites and strings
       
   537  * Only use this if it's the same widget, that's used for more than one vehicle type and it needs different text/sprites
       
   538  * Vehicle specific text/sprites, that's in a widget, that's only shown for one vehicle type (like sell whole train) is set in the widget array
       
   539  */
       
   540 static void SetupStringsForDepotWindow(Window *w, VehicleType type)
       
   541 {
       
   542 	switch (type) {
       
   543 		default: NOT_REACHED();
       
   544 
       
   545 		case VEH_TRAIN:
       
   546 			w->widget[DEPOT_WIDGET_CAPTION].data      = STR_8800_TRAIN_DEPOT;
       
   547 			w->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_TRAIN_TIP;
       
   548 			w->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_TRAIN_TIP;
       
   549 			w->widget[DEPOT_WIDGET_SELL].tooltips     = STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE;
       
   550 			w->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP;
       
   551 			w->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_883F_TRAINS_CLICK_ON_TRAIN_FOR;
       
   552 
       
   553 			w->widget[DEPOT_WIDGET_BUILD].data        = STR_8815_NEW_VEHICLES;
       
   554 			w->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_8840_BUILD_NEW_TRAIN_VEHICLE;
       
   555 			w->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_TRAIN;
       
   556 			w->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_TRAIN_DEPOT_INFO;
       
   557 
       
   558 			w->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_8842_CENTER_MAIN_VIEW_ON_TRAIN;
       
   559 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_TRAIN;
       
   560 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TIP;
       
   561 			w->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_TRAIN_TIP;
       
   562 
       
   563 			/* Sprites */
       
   564 			w->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_TRAIN;
       
   565 			w->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_TRAIN;
       
   566 			w->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_TRAIN;
       
   567 			break;
       
   568 
       
   569 		case VEH_ROAD:
       
   570 			w->widget[DEPOT_WIDGET_CAPTION].data      = STR_9003_ROAD_VEHICLE_DEPOT;
       
   571 			w->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_ROADVEH_TIP;
       
   572 			w->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_ROADVEH_TIP;
       
   573 			w->widget[DEPOT_WIDGET_SELL].tooltips     = STR_9024_DRAG_ROAD_VEHICLE_TO_HERE;
       
   574 			w->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP;
       
   575 			w->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_9022_VEHICLES_CLICK_ON_VEHICLE;
       
   576 
       
   577 			w->widget[DEPOT_WIDGET_BUILD].data        = STR_9004_NEW_VEHICLES;
       
   578 			w->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_9023_BUILD_NEW_ROAD_VEHICLE;
       
   579 			w->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_ROAD_VEHICLE;
       
   580 			w->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_ROAD_VEHICLE_DEPOT_INFO;
       
   581 
       
   582 			w->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_9025_CENTER_MAIN_VIEW_ON_ROAD;
       
   583 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_LORRY;
       
   584 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_ROADVEH_TIP;
       
   585 			w->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_ROADVEH_TIP;
       
   586 
       
   587 			/* Sprites */
       
   588 			w->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_ROADVEH;
       
   589 			w->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_ROADVEH;
       
   590 			w->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_ROADVEH;
       
   591 			break;
       
   592 
       
   593 		case VEH_SHIP:
       
   594 			w->widget[DEPOT_WIDGET_CAPTION].data      = STR_9803_SHIP_DEPOT;
       
   595 			w->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_SHIP_TIP;
       
   596 			w->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_SHIP_TIP;
       
   597 			w->widget[DEPOT_WIDGET_SELL].tooltips     = STR_9821_DRAG_SHIP_TO_HERE_TO_SELL;
       
   598 			w->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP;
       
   599 			w->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_981F_SHIPS_CLICK_ON_SHIP_FOR;
       
   600 
       
   601 			w->widget[DEPOT_WIDGET_BUILD].data        = STR_9804_NEW_SHIPS;
       
   602 			w->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_9820_BUILD_NEW_SHIP;
       
   603 			w->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_SHIP;
       
   604 			w->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_SHIP_DEPOT_INFO;
       
   605 
       
   606 			w->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_9822_CENTER_MAIN_VIEW_ON_SHIP;
       
   607 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_SHIP;
       
   608 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_SHIP_TIP;
       
   609 			w->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_SHIP_TIP;
       
   610 
       
   611 			/* Sprites */
       
   612 			w->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_SHIP;
       
   613 			w->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_SHIP;
       
   614 			w->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_SHIP;
       
   615 			break;
       
   616 
       
   617 		case VEH_AIRCRAFT:
       
   618 			w->widget[DEPOT_WIDGET_CAPTION].data      = STR_A002_AIRCRAFT_HANGAR;
       
   619 			w->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_HANGAR_TIP;
       
   620 			w->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_HANGAR_TIP;
       
   621 			w->widget[DEPOT_WIDGET_SELL].tooltips     = STR_A023_DRAG_AIRCRAFT_TO_HERE_TO;
       
   622 			w->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_AIRCRAFT_TIP;
       
   623 			w->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT;
       
   624 
       
   625 			w->widget[DEPOT_WIDGET_BUILD].data        = STR_A003_NEW_AIRCRAFT;
       
   626 			w->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_A022_BUILD_NEW_AIRCRAFT;
       
   627 			w->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_AIRCRAFT;
       
   628 			w->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW;
       
   629 
       
   630 			w->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_A024_CENTER_MAIN_VIEW_ON_HANGAR;
       
   631 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_PLANE;
       
   632 			w->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_AIRCRAFT_TIP;
       
   633 			w->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_AIRCRAFT_TIP;
       
   634 
       
   635 			/* Sprites */
       
   636 			w->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_AIRCRAFT;
       
   637 			w->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_AIRCRAFT;
       
   638 			w->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_AIRCRAFT;
       
   639 			break;
       
   640 	}
       
   641 }
       
   642 
       
   643 
   174 
   644 /* Array to hold the block sizes
   175 /* Array to hold the block sizes
   645  * First part is the vehicle type, while the last is 0 = x, 1 = y */
   176  * First part is the vehicle type, while the last is 0 = x, 1 = y */
   646 uint _block_sizes[4][2];
   177 uint _block_sizes[4][2];
   647 
   178 
   705 	ResizeDefaultWindowSizeForRoadVehicles();
   236 	ResizeDefaultWindowSizeForRoadVehicles();
   706 	ResizeDefaultWindowSize(VEH_SHIP);
   237 	ResizeDefaultWindowSize(VEH_SHIP);
   707 	ResizeDefaultWindowSize(VEH_AIRCRAFT);
   238 	ResizeDefaultWindowSize(VEH_AIRCRAFT);
   708 }
   239 }
   709 
   240 
   710 static void CreateDepotListWindow(Window *w, VehicleType type)
   241 static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
       
   242 const Sprite *GetAircraftSprite(EngineID engine);
       
   243 
       
   244 struct DepotWindow : Window {
       
   245 	VehicleID sel;
       
   246 	VehicleType type;
       
   247 	bool generate_list;
       
   248 	uint16 engine_list_length;
       
   249 	uint16 wagon_list_length;
       
   250 	uint16 engine_count;
       
   251 	uint16 wagon_count;
       
   252 	Vehicle **vehicle_list;
       
   253 	Vehicle **wagon_list;
       
   254 
       
   255 	DepotWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
       
   256 	{
       
   257 		this->sel = INVALID_VEHICLE;
       
   258 		this->vehicle_list  = NULL;
       
   259 		this->wagon_list    = NULL;
       
   260 		this->engine_count  = 0;
       
   261 		this->wagon_count   = 0;
       
   262 		this->generate_list = true;
       
   263 
       
   264 		this->FindWindowPlacementAndResize(desc);
       
   265 	}
       
   266 
       
   267 	~DepotWindow()
       
   268 	{
       
   269 		DeleteWindowById(WC_BUILD_VEHICLE, this->window_number);
       
   270 		free((void*)this->vehicle_list);
       
   271 		free((void*)this->wagon_list);
       
   272 	}
       
   273 
       
   274 	/** Draw a vehicle in the depot window in the box with the top left corner at x,y
       
   275 	* @param *w Window to draw in
       
   276 	* @param *v Vehicle to draw
       
   277 	* @param x Left side of the box to draw in
       
   278 	* @param y Top of the box to draw in
       
   279 	*/
       
   280 	void DrawVehicleInDepot(Window *w, const Vehicle *v, int x, int y)
       
   281 	{
       
   282 		byte diff_x = 0, diff_y = 0;
       
   283 
       
   284 		int sprite_y = y + this->resize.step_height - GetVehicleListHeight(v->type);
       
   285 
       
   286 		switch (v->type) {
       
   287 			case VEH_TRAIN:
       
   288 				DrawTrainImage(v, x + 21, sprite_y, this->sel, this->hscroll.cap + 4, this->hscroll.pos);
       
   289 
       
   290 				/* Number of wagons relative to a standard length wagon (rounded up) */
       
   291 				SetDParam(0, (v->u.rail.cached_total_length + 7) / 8);
       
   292 				DrawStringRightAligned(this->widget[DEPOT_WIDGET_MATRIX].right - 1, y + 4, STR_TINY_BLACK, TC_FROMSTRING); // Draw the counter
       
   293 				break;
       
   294 
       
   295 			case VEH_ROAD:     DrawRoadVehImage( v, x + 24, sprite_y, this->sel, 1); break;
       
   296 			case VEH_SHIP:     DrawShipImage(    v, x + 19, sprite_y - 1, this->sel); break;
       
   297 			case VEH_AIRCRAFT: {
       
   298 				const Sprite *spr = GetSprite(v->GetImage(DIR_W));
       
   299 				DrawAircraftImage(v, x + 12,
       
   300 									y + max(spr->height + spr->y_offs - 14, 0), // tall sprites needs an y offset
       
   301 									this->sel);
       
   302 			} break;
       
   303 			default: NOT_REACHED();
       
   304 		}
       
   305 
       
   306 		if (this->resize.step_height == 14) {
       
   307 			/* VEH_TRAIN and VEH_ROAD, which are low */
       
   308 			diff_x = 15;
       
   309 		} else {
       
   310 			/* VEH_SHIP and VEH_AIRCRAFT, which are tall */
       
   311 			diff_y = 12;
       
   312 		}
       
   313 
       
   314 		DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, x + diff_x, y + diff_y);
       
   315 
       
   316 		SetDParam(0, v->unitnumber);
       
   317 		DrawString(x, y + 2, (uint16)(v->max_age - 366) >= v->age ? STR_00E2 : STR_00E3, TC_FROMSTRING);
       
   318 	}
       
   319 
       
   320 	void DrawDepotWindow(Window *w)
       
   321 	{
       
   322 		Vehicle **vl = this->vehicle_list;
       
   323 		TileIndex tile = this->window_number;
       
   324 		int x, y, i, maxval;
       
   325 		uint16 hnum;
       
   326 		uint16 num = this->engine_count;
       
   327 
       
   328 		/* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
       
   329 		uint16 rows_in_display   = this->widget[DEPOT_WIDGET_MATRIX].data >> 8;
       
   330 		uint16 boxes_in_each_row = this->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
       
   331 
       
   332 		/* setup disabled buttons */
       
   333 		this->SetWidgetsDisabledState(!IsTileOwner(tile, _local_player),
       
   334 			DEPOT_WIDGET_STOP_ALL,
       
   335 			DEPOT_WIDGET_START_ALL,
       
   336 			DEPOT_WIDGET_SELL,
       
   337 			DEPOT_WIDGET_SELL_CHAIN,
       
   338 			DEPOT_WIDGET_SELL_ALL,
       
   339 			DEPOT_WIDGET_BUILD,
       
   340 			DEPOT_WIDGET_CLONE,
       
   341 			DEPOT_WIDGET_AUTOREPLACE,
       
   342 			WIDGET_LIST_END);
       
   343 
       
   344 		/* determine amount of items for scroller */
       
   345 		if (this->type == VEH_TRAIN) {
       
   346 			hnum = 8;
       
   347 			for (num = 0; num < this->engine_count; num++) {
       
   348 				const Vehicle *v = vl[num];
       
   349 				hnum = max(hnum, v->u.rail.cached_total_length);
       
   350 			}
       
   351 			/* Always have 1 empty row, so people can change the setting of the train */
       
   352 			SetVScrollCount(w, this->engine_count + this->wagon_count + 1);
       
   353 			SetHScrollCount(w, WagonLengthToPixels(hnum));
       
   354 		} else {
       
   355 			SetVScrollCount(w, (num + this->hscroll.cap - 1) / this->hscroll.cap);
       
   356 		}
       
   357 
       
   358 		/* locate the depot struct */
       
   359 		if (this->type == VEH_AIRCRAFT) {
       
   360 			SetDParam(0, GetStationIndex(tile)); // Airport name
       
   361 		} else {
       
   362 			Depot *depot = GetDepotByTile(tile);
       
   363 			assert(depot != NULL);
       
   364 
       
   365 			SetDParam(0, depot->town_index);
       
   366 		}
       
   367 
       
   368 		DrawWindowWidgets(w);
       
   369 
       
   370 		num = this->vscroll.pos * boxes_in_each_row;
       
   371 		maxval = min(this->engine_count, num + (rows_in_display * boxes_in_each_row));
       
   372 
       
   373 		for (x = 2, y = 15; num < maxval; y += this->resize.step_height, x = 2) { // Draw the rows
       
   374 			byte i;
       
   375 
       
   376 			for (i = 0; i < boxes_in_each_row && num < maxval; i++, num++, x += this->resize.step_width) {
       
   377 				/* Draw all vehicles in the current row */
       
   378 				const Vehicle *v = vl[num];
       
   379 				DrawVehicleInDepot(w, v, x, y);
       
   380 			}
       
   381 		}
       
   382 
       
   383 		maxval = min(this->engine_count + this->wagon_count, (this->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row));
       
   384 
       
   385 		/* draw the train wagons, that do not have an engine in front */
       
   386 		for (; num < maxval; num++, y += 14) {
       
   387 			const Vehicle *v = this->wagon_list[num - this->engine_count];
       
   388 			const Vehicle *u;
       
   389 
       
   390 			DrawTrainImage(v, x + 50, y, this->sel, this->hscroll.cap - 29, 0);
       
   391 			DrawString(x, y + 2, STR_8816, TC_FROMSTRING);
       
   392 
       
   393 			/*Draw the train counter */
       
   394 			i = 0;
       
   395 			u = v;
       
   396 			do i++; while ((u = u->Next()) != NULL); // Determine length of train
       
   397 			SetDParam(0, i);                      // Set the counter
       
   398 			DrawStringRightAligned(this->widget[DEPOT_WIDGET_MATRIX].right - 1, y + 4, STR_TINY_BLACK, TC_FROMSTRING); // Draw the counter
       
   399 		}
       
   400 	}
       
   401 
       
   402 	struct GetDepotVehiclePtData {
       
   403 		Vehicle *head;
       
   404 		Vehicle *wagon;
       
   405 	};
       
   406 
       
   407 	enum DepotGUIAction {
       
   408 		MODE_ERROR,
       
   409 		MODE_DRAG_VEHICLE,
       
   410 		MODE_SHOW_VEHICLE,
       
   411 		MODE_START_STOP,
       
   412 	};
       
   413 
       
   414 	DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, Vehicle **veh, GetDepotVehiclePtData *d) const
       
   415 	{
       
   416 		Vehicle **vl = this->vehicle_list;
       
   417 		uint xt, row, xm = 0, ym = 0;
       
   418 		int pos, skip = 0;
       
   419 		uint16 boxes_in_each_row = this->widget[DEPOT_WIDGET_MATRIX].data & 0xFF;
       
   420 
       
   421 		if (this->type == VEH_TRAIN) {
       
   422 			xt = 0;
       
   423 			x -= 23;
       
   424 		} else {
       
   425 			xt = x / this->resize.step_width;
       
   426 			xm = x % this->resize.step_width;
       
   427 			if (xt >= this->hscroll.cap) return MODE_ERROR;
       
   428 
       
   429 			ym = (y - 14) % this->resize.step_height;
       
   430 		}
       
   431 
       
   432 		row = (y - 14) / this->resize.step_height;
       
   433 		if (row >= this->vscroll.cap) return MODE_ERROR;
       
   434 
       
   435 		pos = ((row + this->vscroll.pos) * boxes_in_each_row) + xt;
       
   436 
       
   437 		if (this->engine_count + this->wagon_count <= pos) {
       
   438 			if (this->type == VEH_TRAIN) {
       
   439 				d->head  = NULL;
       
   440 				d->wagon = NULL;
       
   441 				return MODE_DRAG_VEHICLE;
       
   442 			} else {
       
   443 				return MODE_ERROR; // empty block, so no vehicle is selected
       
   444 			}
       
   445 		}
       
   446 
       
   447 		if (this->engine_count > pos) {
       
   448 			*veh = vl[pos];
       
   449 			skip = this->hscroll.pos;
       
   450 		} else {
       
   451 			vl = this->wagon_list;
       
   452 			pos -= this->engine_count;
       
   453 			*veh = vl[pos];
       
   454 			/* free wagons don't have an initial loco. */
       
   455 			x -= _traininfo_vehicle_width;
       
   456 		}
       
   457 
       
   458 		switch (this->type) {
       
   459 			case VEH_TRAIN: {
       
   460 				Vehicle *v = *veh;
       
   461 				d->head = d->wagon = v;
       
   462 
       
   463 				/* either pressed the flag or the number, but only when it's a loco */
       
   464 				if (x < 0 && IsFrontEngine(v)) return (x >= -10) ? MODE_START_STOP : MODE_SHOW_VEHICLE;
       
   465 
       
   466 				skip = (skip * 8) / _traininfo_vehicle_width;
       
   467 				x = (x * 8) / _traininfo_vehicle_width;
       
   468 
       
   469 				/* Skip vehicles that are scrolled off the list */
       
   470 				x += skip;
       
   471 
       
   472 				/* find the vehicle in this row that was clicked */
       
   473 				while (v != NULL && (x -= v->u.rail.cached_veh_length) >= 0) v = v->Next();
       
   474 
       
   475 				/* if an articulated part was selected, find its parent */
       
   476 				while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
       
   477 
       
   478 				d->wagon = v;
       
   479 
       
   480 				return MODE_DRAG_VEHICLE;
       
   481 				}
       
   482 				break;
       
   483 
       
   484 			case VEH_ROAD:
       
   485 				if (xm >= 24) return MODE_DRAG_VEHICLE;
       
   486 				if (xm <= 16) return MODE_SHOW_VEHICLE;
       
   487 				break;
       
   488 
       
   489 			case VEH_SHIP:
       
   490 				if (xm >= 19) return MODE_DRAG_VEHICLE;
       
   491 				if (ym <= 10) return MODE_SHOW_VEHICLE;
       
   492 				break;
       
   493 
       
   494 			case VEH_AIRCRAFT:
       
   495 				if (xm >= 12) return MODE_DRAG_VEHICLE;
       
   496 				if (ym <= 12) return MODE_SHOW_VEHICLE;
       
   497 				break;
       
   498 
       
   499 			default: NOT_REACHED();
       
   500 		}
       
   501 		return MODE_START_STOP;
       
   502 	}
       
   503 
       
   504 	void DepotClick(int x, int y)
       
   505 	{
       
   506 		GetDepotVehiclePtData gdvp;
       
   507 		Vehicle *v = NULL;
       
   508 		DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp);
       
   509 
       
   510 		/* share / copy orders */
       
   511 		if (_thd.place_mode != VHM_NONE && mode != MODE_ERROR) {
       
   512 			_place_clicked_vehicle = (this->type == VEH_TRAIN ? gdvp.head : v);
       
   513 			return;
       
   514 		}
       
   515 
       
   516 		if (this->type == VEH_TRAIN) v = gdvp.wagon;
       
   517 
       
   518 		switch (mode) {
       
   519 			case MODE_ERROR: // invalid
       
   520 				return;
       
   521 
       
   522 			case MODE_DRAG_VEHICLE: { // start dragging of vehicle
       
   523 				VehicleID sel = this->sel;
       
   524 
       
   525 				if (this->type == VEH_TRAIN && sel != INVALID_VEHICLE) {
       
   526 					this->sel = INVALID_VEHICLE;
       
   527 					TrainDepotMoveVehicle(v, sel, gdvp.head);
       
   528 				} else if (v != NULL) {
       
   529 					int image = v->GetImage(DIR_W);
       
   530 
       
   531 					this->sel = v->index;
       
   532 					this->SetDirty();
       
   533 					SetObjectToPlaceWnd(image, GetVehiclePalette(v), VHM_DRAG, this);
       
   534 					_cursor.vehchain = _ctrl_pressed;
       
   535 				}
       
   536 			} break;
       
   537 
       
   538 			case MODE_SHOW_VEHICLE: // show info window
       
   539 				ShowVehicleViewWindow(v);
       
   540 				break;
       
   541 
       
   542 			case MODE_START_STOP: { // click start/stop flag
       
   543 				uint command;
       
   544 
       
   545 				switch (this->type) {
       
   546 					case VEH_TRAIN:    command = CMD_START_STOP_TRAIN | CMD_MSG(STR_883B_CAN_T_STOP_START_TRAIN);          break;
       
   547 					case VEH_ROAD:     command = CMD_START_STOP_ROADVEH | CMD_MSG(STR_9015_CAN_T_STOP_START_ROAD_VEHICLE); break;
       
   548 					case VEH_SHIP:     command = CMD_START_STOP_SHIP | CMD_MSG(STR_9818_CAN_T_STOP_START_SHIP);            break;
       
   549 					case VEH_AIRCRAFT: command = CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT);    break;
       
   550 					default: NOT_REACHED(); command = 0;
       
   551 				}
       
   552 				DoCommandP(v->tile, v->index, 0, NULL, command);
       
   553 			} break;
       
   554 
       
   555 			default: NOT_REACHED();
       
   556 		}
       
   557 	}
       
   558 
       
   559 	/**
       
   560 	* Clones a vehicle
       
   561 	* @param *v is the original vehicle to clone
       
   562 	* @param *w is the window of the depot where the clone is build
       
   563 	*/
       
   564 	void HandleCloneVehClick(const Vehicle *v, const Window *w)
       
   565 	{
       
   566 		uint error_str;
       
   567 
       
   568 		if (v == NULL) return;
       
   569 
       
   570 		if (!v->IsPrimaryVehicle()) {
       
   571 			v = v->First();
       
   572 			/* Do nothing when clicking on a train in depot with no loc attached */
       
   573 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) return;
       
   574 		}
       
   575 
       
   576 		switch (v->type) {
       
   577 			case VEH_TRAIN:    error_str = CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE); break;
       
   578 			case VEH_ROAD:     error_str = CMD_MSG(STR_9009_CAN_T_BUILD_ROAD_VEHICLE);     break;
       
   579 			case VEH_SHIP:     error_str = CMD_MSG(STR_980D_CAN_T_BUILD_SHIP);             break;
       
   580 			case VEH_AIRCRAFT: error_str = CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT);         break;
       
   581 			default: return;
       
   582 		}
       
   583 
       
   584 		DoCommandP(this->window_number, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle, CMD_CLONE_VEHICLE | error_str);
       
   585 
       
   586 		ResetObjectToPlace();
       
   587 	}
       
   588 
       
   589 	void ResizeDepotButtons(Window *w)
       
   590 	{
       
   591 		ResizeButtons(w, DEPOT_WIDGET_BUILD, DEPOT_WIDGET_LOCATION);
       
   592 
       
   593 		if (this->type == VEH_TRAIN) {
       
   594 			/* Divide the size of DEPOT_WIDGET_SELL into two equally big buttons so DEPOT_WIDGET_SELL and DEPOT_WIDGET_SELL_CHAIN will get the same size.
       
   595 			* This way it will stay the same even if DEPOT_WIDGET_SELL_CHAIN is resized for some reason                                                  */
       
   596 			this->widget[DEPOT_WIDGET_SELL_CHAIN].top    = ((this->widget[DEPOT_WIDGET_SELL_CHAIN].bottom - this->widget[DEPOT_WIDGET_SELL].top) / 2) + this->widget[DEPOT_WIDGET_SELL].top;
       
   597 			this->widget[DEPOT_WIDGET_SELL].bottom     = this->widget[DEPOT_WIDGET_SELL_CHAIN].top - 1;
       
   598 		}
       
   599 	}
       
   600 
       
   601 	/* Function to set up vehicle specific sprites and strings
       
   602 	 * Only use this if it's the same widget, that's used for more than one vehicle type and it needs different text/sprites
       
   603 	 * Vehicle specific text/sprites, that's in a widget, that's only shown for one vehicle type (like sell whole train) is set in the widget array
       
   604 	 */
       
   605 	void SetupStringsForDepotWindow(VehicleType type)
       
   606 	{
       
   607 		switch (type) {
       
   608 			default: NOT_REACHED();
       
   609 
       
   610 			case VEH_TRAIN:
       
   611 				this->widget[DEPOT_WIDGET_CAPTION].data      = STR_8800_TRAIN_DEPOT;
       
   612 				this->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_TRAIN_TIP;
       
   613 				this->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_TRAIN_TIP;
       
   614 				this->widget[DEPOT_WIDGET_SELL].tooltips     = STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE;
       
   615 				this->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TIP;
       
   616 				this->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_883F_TRAINS_CLICK_ON_TRAIN_FOR;
       
   617 
       
   618 				this->widget[DEPOT_WIDGET_BUILD].data        = STR_8815_NEW_VEHICLES;
       
   619 				this->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_8840_BUILD_NEW_TRAIN_VEHICLE;
       
   620 				this->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_TRAIN;
       
   621 				this->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_TRAIN_DEPOT_INFO;
       
   622 
       
   623 				this->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_8842_CENTER_MAIN_VIEW_ON_TRAIN;
       
   624 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_TRAIN;
       
   625 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TIP;
       
   626 				this->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_TRAIN_TIP;
       
   627 
       
   628 				/* Sprites */
       
   629 				this->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_TRAIN;
       
   630 				this->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_TRAIN;
       
   631 				this->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_TRAIN;
       
   632 				break;
       
   633 
       
   634 			case VEH_ROAD:
       
   635 				this->widget[DEPOT_WIDGET_CAPTION].data      = STR_9003_ROAD_VEHICLE_DEPOT;
       
   636 				this->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_ROADVEH_TIP;
       
   637 				this->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_ROADVEH_TIP;
       
   638 				this->widget[DEPOT_WIDGET_SELL].tooltips     = STR_9024_DRAG_ROAD_VEHICLE_TO_HERE;
       
   639 				this->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_ROADVEH_TIP;
       
   640 				this->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_9022_VEHICLES_CLICK_ON_VEHICLE;
       
   641 
       
   642 				this->widget[DEPOT_WIDGET_BUILD].data        = STR_9004_NEW_VEHICLES;
       
   643 				this->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_9023_BUILD_NEW_ROAD_VEHICLE;
       
   644 				this->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_ROAD_VEHICLE;
       
   645 				this->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_ROAD_VEHICLE_DEPOT_INFO;
       
   646 
       
   647 				this->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_9025_CENTER_MAIN_VIEW_ON_ROAD;
       
   648 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_LORRY;
       
   649 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_ROADVEH_TIP;
       
   650 				this->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_ROADVEH_TIP;
       
   651 
       
   652 				/* Sprites */
       
   653 				this->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_ROADVEH;
       
   654 				this->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_ROADVEH;
       
   655 				this->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_ROADVEH;
       
   656 				break;
       
   657 
       
   658 			case VEH_SHIP:
       
   659 				this->widget[DEPOT_WIDGET_CAPTION].data      = STR_9803_SHIP_DEPOT;
       
   660 				this->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_DEPOT_SHIP_TIP;
       
   661 				this->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_DEPOT_SHIP_TIP;
       
   662 				this->widget[DEPOT_WIDGET_SELL].tooltips     = STR_9821_DRAG_SHIP_TO_HERE_TO_SELL;
       
   663 				this->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_SHIP_TIP;
       
   664 				this->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_981F_SHIPS_CLICK_ON_SHIP_FOR;
       
   665 
       
   666 				this->widget[DEPOT_WIDGET_BUILD].data        = STR_9804_NEW_SHIPS;
       
   667 				this->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_9820_BUILD_NEW_SHIP;
       
   668 				this->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_SHIP;
       
   669 				this->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_SHIP_DEPOT_INFO;
       
   670 
       
   671 				this->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_9822_CENTER_MAIN_VIEW_ON_SHIP;
       
   672 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_SHIP;
       
   673 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_SHIP_TIP;
       
   674 				this->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_SHIP_TIP;
       
   675 
       
   676 				/* Sprites */
       
   677 				this->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_SHIP;
       
   678 				this->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_SHIP;
       
   679 				this->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_SHIP;
       
   680 				break;
       
   681 
       
   682 			case VEH_AIRCRAFT:
       
   683 				this->widget[DEPOT_WIDGET_CAPTION].data      = STR_A002_AIRCRAFT_HANGAR;
       
   684 				this->widget[DEPOT_WIDGET_STOP_ALL].tooltips = STR_MASS_STOP_HANGAR_TIP;
       
   685 				this->widget[DEPOT_WIDGET_START_ALL].tooltips= STR_MASS_START_HANGAR_TIP;
       
   686 				this->widget[DEPOT_WIDGET_SELL].tooltips     = STR_A023_DRAG_AIRCRAFT_TO_HERE_TO;
       
   687 				this->widget[DEPOT_WIDGET_SELL_ALL].tooltips = STR_DEPOT_SELL_ALL_BUTTON_AIRCRAFT_TIP;
       
   688 				this->widget[DEPOT_WIDGET_MATRIX].tooltips   = STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT;
       
   689 
       
   690 				this->widget[DEPOT_WIDGET_BUILD].data        = STR_A003_NEW_AIRCRAFT;
       
   691 				this->widget[DEPOT_WIDGET_BUILD].tooltips    = STR_A022_BUILD_NEW_AIRCRAFT;
       
   692 				this->widget[DEPOT_WIDGET_CLONE].data        = STR_CLONE_AIRCRAFT;
       
   693 				this->widget[DEPOT_WIDGET_CLONE].tooltips    = STR_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW;
       
   694 
       
   695 				this->widget[DEPOT_WIDGET_LOCATION].tooltips = STR_A024_CENTER_MAIN_VIEW_ON_HANGAR;
       
   696 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].data = STR_PLANE;
       
   697 				this->widget[DEPOT_WIDGET_VEHICLE_LIST].tooltips = STR_DEPOT_VEHICLE_ORDER_LIST_AIRCRAFT_TIP;
       
   698 				this->widget[DEPOT_WIDGET_AUTOREPLACE].tooltips = STR_DEPOT_AUTOREPLACE_AIRCRAFT_TIP;
       
   699 
       
   700 				/* Sprites */
       
   701 				this->widget[DEPOT_WIDGET_SELL].data        = SPR_SELL_AIRCRAFT;
       
   702 				this->widget[DEPOT_WIDGET_SELL_ALL].data    = SPR_SELL_ALL_AIRCRAFT;
       
   703 				this->widget[DEPOT_WIDGET_AUTOREPLACE].data = SPR_REPLACE_AIRCRAFT;
       
   704 				break;
       
   705 		}
       
   706 	}
       
   707 
       
   708 	void CreateDepotListWindow(VehicleType type)
       
   709 	{
       
   710 		this->type = type;
       
   711 		_backup_orders_tile = 0;
       
   712 
       
   713 		assert(IsPlayerBuildableVehicleType(type)); // ensure that we make the call with a valid type
       
   714 
       
   715 		/* Resize the window according to the vehicle type */
       
   716 
       
   717 		/* Set the number of blocks in each direction */
       
   718 		this->vscroll.cap = _resize_cap[type][0];
       
   719 		this->hscroll.cap = _resize_cap[type][1];
       
   720 
       
   721 		/* Set the block size */
       
   722 		this->resize.step_width  = _block_sizes[type][0];
       
   723 		this->resize.step_height = _block_sizes[type][1];
       
   724 
       
   725 		/* Enlarge the window to fit with the selected number of blocks of the selected size */
       
   726 		ResizeWindow(this,
       
   727 					_block_sizes[type][0] * this->hscroll.cap,
       
   728 					_block_sizes[type][1] * this->vscroll.cap);
       
   729 
       
   730 		if (type == VEH_TRAIN) {
       
   731 			/* Make space for the horizontal scrollbar vertically, and the unit
       
   732 			 * number, flag, and length counter horizontally. */
       
   733 			ResizeWindow(this, 36, 12);
       
   734 			/* substract the newly added space from the matrix since it was meant for the scrollbar */
       
   735 			this->widget[DEPOT_WIDGET_MATRIX].bottom -= 12;
       
   736 		}
       
   737 
       
   738 		/* Set the minimum window size to the current window size */
       
   739 		this->resize.width  = this->width;
       
   740 		this->resize.height = this->height;
       
   741 
       
   742 		this->SetupStringsForDepotWindow(type);
       
   743 
       
   744 		this->widget[DEPOT_WIDGET_MATRIX].data =
       
   745 			(this->vscroll.cap * 0x100) // number of rows to draw on the background
       
   746 			+ (type == VEH_TRAIN ? 1 : this->hscroll.cap); // number of boxes in each row. Trains always have just one
       
   747 
       
   748 
       
   749 		this->SetWidgetsHiddenState(type != VEH_TRAIN,
       
   750 			DEPOT_WIDGET_H_SCROLL,
       
   751 			DEPOT_WIDGET_SELL_CHAIN,
       
   752 			WIDGET_LIST_END);
       
   753 
       
   754 		ResizeDepotButtons(this);
       
   755 	}
       
   756 
       
   757 	virtual void OnInvalidateData(int data)
       
   758 	{
       
   759 		this->generate_list = true;
       
   760 	}
       
   761 
       
   762 	virtual void OnPaint()
       
   763 	{
       
   764 		if (this->generate_list) {
       
   765 			/* Generate the vehicle list
       
   766 			 * It's ok to use the wagon pointers for non-trains as they will be ignored */
       
   767 			BuildDepotVehicleList(this->type, this->window_number,
       
   768 				&this->vehicle_list, &this->engine_list_length, &this->engine_count,
       
   769 				&this->wagon_list,   &this->wagon_list_length,  &this->wagon_count);
       
   770 			this->generate_list = false;
       
   771 			DepotSortList(this->vehicle_list, this->engine_count);
       
   772 		}
       
   773 		DrawDepotWindow(this);
       
   774 	}
       
   775 
       
   776 	virtual void OnClick(Point pt, int widget)
       
   777 	{
       
   778 		switch (widget) {
       
   779 			case DEPOT_WIDGET_MATRIX: // List
       
   780 				this->DepotClick(pt.x, pt.y);
       
   781 				break;
       
   782 
       
   783 			case DEPOT_WIDGET_BUILD: // Build vehicle
       
   784 				ResetObjectToPlace();
       
   785 				ShowBuildVehicleWindow(this->window_number, this->type);
       
   786 				break;
       
   787 
       
   788 			case DEPOT_WIDGET_CLONE: // Clone button
       
   789 				this->InvalidateWidget(DEPOT_WIDGET_CLONE);
       
   790 				this->ToggleWidgetLoweredState(DEPOT_WIDGET_CLONE);
       
   791 
       
   792 				if (this->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
       
   793 					static const CursorID clone_icons[] = {
       
   794 						SPR_CURSOR_CLONE_TRAIN, SPR_CURSOR_CLONE_ROADVEH,
       
   795 						SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
       
   796 					};
       
   797 
       
   798 					_place_clicked_vehicle = NULL;
       
   799 					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, VHM_RECT, this);
       
   800 				} else {
       
   801 					ResetObjectToPlace();
       
   802 				}
       
   803 					break;
       
   804 
       
   805 			case DEPOT_WIDGET_LOCATION:
       
   806 				if (_ctrl_pressed) {
       
   807 					ShowExtraViewPortWindow(this->window_number);
       
   808 				} else {
       
   809 					ScrollMainWindowToTile(this->window_number);
       
   810 				}
       
   811 				break;
       
   812 
       
   813 			case DEPOT_WIDGET_STOP_ALL:
       
   814 			case DEPOT_WIDGET_START_ALL:
       
   815 				DoCommandP(this->window_number, 0, this->type | (widget == DEPOT_WIDGET_START_ALL ? (1 << 5) : 0), NULL, CMD_MASS_START_STOP);
       
   816 				break;
       
   817 
       
   818 			case DEPOT_WIDGET_SELL_ALL:
       
   819 				/* Only open the confimation window if there are anything to sell */
       
   820 				if (this->engine_count != 0 || this->wagon_count != 0) {
       
   821 					static const StringID confirm_captions[] = {
       
   822 						STR_8800_TRAIN_DEPOT,
       
   823 						STR_9003_ROAD_VEHICLE_DEPOT,
       
   824 						STR_9803_SHIP_DEPOT,
       
   825 						STR_A002_AIRCRAFT_HANGAR
       
   826 					};
       
   827 					TileIndex tile = this->window_number;
       
   828 					byte vehtype = this->type;
       
   829 
       
   830 					SetDParam(0, (vehtype == VEH_AIRCRAFT) ? GetStationIndex(tile) : GetDepotByTile(tile)->town_index);
       
   831 					ShowQuery(
       
   832 						confirm_captions[vehtype],
       
   833 						STR_DEPOT_SELL_CONFIRMATION_TEXT,
       
   834 						this,
       
   835 						DepotSellAllConfirmationCallback
       
   836 					);
       
   837 				}
       
   838 				break;
       
   839 
       
   840 			case DEPOT_WIDGET_VEHICLE_LIST:
       
   841 				ShowVehicleListWindow(GetTileOwner(this->window_number), this->type, (TileIndex)this->window_number);
       
   842 				break;
       
   843 
       
   844 			case DEPOT_WIDGET_AUTOREPLACE:
       
   845 				DoCommandP(this->window_number, this->type, 0, NULL, CMD_DEPOT_MASS_AUTOREPLACE);
       
   846 				break;
       
   847 
       
   848 		}
       
   849 	}
       
   850 
       
   851 	virtual void OnPlaceObject(Point pt, TileIndex tile)
       
   852 	{
       
   853 		const Vehicle *v = CheckMouseOverVehicle();
       
   854 
       
   855 		if (v != NULL) HandleCloneVehClick(v, this);
       
   856 	}
       
   857 
       
   858 	virtual void OnPlaceObjectAbort()
       
   859 	{
       
   860 		/* abort clone */
       
   861 		this->RaiseWidget(DEPOT_WIDGET_CLONE);
       
   862 		this->InvalidateWidget(DEPOT_WIDGET_CLONE);
       
   863 
       
   864 		/* abort drag & drop */
       
   865 		this->sel = INVALID_VEHICLE;
       
   866 		this->InvalidateWidget(DEPOT_WIDGET_MATRIX);
       
   867 	};
       
   868 
       
   869 	/* check if a vehicle in a depot was clicked.. */
       
   870 	virtual void OnMouseLoop()
       
   871 	{
       
   872 		const Vehicle *v = _place_clicked_vehicle;
       
   873 
       
   874 		/* since OTTD checks all open depot windows, we will make sure that it triggers the one with a clicked clone button */
       
   875 		if (v != NULL && this->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
       
   876 			_place_clicked_vehicle = NULL;
       
   877 			HandleCloneVehClick(v, this);
       
   878 		}
       
   879 	}
       
   880 
       
   881 	virtual void OnDragDrop(Point pt, int widget)
       
   882 	{
       
   883 		switch (widget) {
       
   884 			case DEPOT_WIDGET_MATRIX: {
       
   885 				Vehicle *v;
       
   886 				VehicleID sel = this->sel;
       
   887 
       
   888 				this->sel = INVALID_VEHICLE;
       
   889 				this->SetDirty();
       
   890 
       
   891 				if (this->type == VEH_TRAIN) {
       
   892 					GetDepotVehiclePtData gdvp;
       
   893 
       
   894 					if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp) == MODE_DRAG_VEHICLE &&
       
   895 						sel != INVALID_VEHICLE) {
       
   896 						if (gdvp.wagon != NULL && gdvp.wagon->index == sel && _ctrl_pressed) {
       
   897 							DoCommandP(GetVehicle(sel)->tile, GetVehicle(sel)->index, true, NULL, CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_9033_CAN_T_MAKE_VEHICLE_TURN));
       
   898 						} else if (gdvp.wagon == NULL || gdvp.wagon->index != sel) {
       
   899 							TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
       
   900 						} else if (gdvp.head != NULL && IsFrontEngine(gdvp.head)) {
       
   901 							ShowVehicleViewWindow(gdvp.head);
       
   902 						}
       
   903 					}
       
   904 				} else if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, NULL) == MODE_DRAG_VEHICLE &&
       
   905 					v != NULL &&
       
   906 					sel == v->index) {
       
   907 					ShowVehicleViewWindow(v);
       
   908 				}
       
   909 			} break;
       
   910 
       
   911 			case DEPOT_WIDGET_SELL: case DEPOT_WIDGET_SELL_CHAIN:
       
   912 				if (!this->IsWidgetDisabled(DEPOT_WIDGET_SELL) &&
       
   913 					this->sel != INVALID_VEHICLE) {
       
   914 					Vehicle *v;
       
   915 					uint command;
       
   916 					int sell_cmd;
       
   917 					bool is_engine;
       
   918 
       
   919 					if (this->IsWidgetDisabled(widget)) return;
       
   920 					if (this->sel == INVALID_VEHICLE) return;
       
   921 
       
   922 					this->HandleButtonClick(widget);
       
   923 
       
   924 					v = GetVehicle(this->sel);
       
   925 					this->sel = INVALID_VEHICLE;
       
   926 					this->SetDirty();
       
   927 
       
   928 					sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
       
   929 
       
   930 					is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v)));
       
   931 
       
   932 					if (is_engine) {
       
   933 						_backup_orders_tile = v->tile;
       
   934 						BackupVehicleOrders(v);
       
   935 					}
       
   936 
       
   937 					switch (v->type) {
       
   938 						case VEH_TRAIN:    command = CMD_SELL_RAIL_WAGON | CMD_MSG(STR_8839_CAN_T_SELL_RAILROAD_VEHICLE); break;
       
   939 						case VEH_ROAD:     command = CMD_SELL_ROAD_VEH | CMD_MSG(STR_9014_CAN_T_SELL_ROAD_VEHICLE);       break;
       
   940 						case VEH_SHIP:     command = CMD_SELL_SHIP | CMD_MSG(STR_980C_CAN_T_SELL_SHIP);                   break;
       
   941 						case VEH_AIRCRAFT: command = CMD_SELL_AIRCRAFT | CMD_MSG(STR_A01C_CAN_T_SELL_AIRCRAFT);           break;
       
   942 						default: NOT_REACHED(); command = 0;
       
   943 					}
       
   944 
       
   945 					if (!DoCommandP(v->tile, v->index, sell_cmd, NULL, command) && is_engine) _backup_orders_tile = 0;
       
   946 				}
       
   947 				break;
       
   948 			default:
       
   949 				this->sel = INVALID_VEHICLE;
       
   950 				this->SetDirty();
       
   951 		}
       
   952 		_cursor.vehchain = false;
       
   953 	}
       
   954 
       
   955 	virtual void OnResize(Point new_size, Point delta)
       
   956 	{
       
   957 		this->vscroll.cap += delta.y / (int)this->resize.step_height;
       
   958 		this->hscroll.cap += delta.x / (int)this->resize.step_width;
       
   959 		this->widget[DEPOT_WIDGET_MATRIX].data = (this->vscroll.cap << 8) + (this->type == VEH_TRAIN ? 1 : this->hscroll.cap);
       
   960 		ResizeDepotButtons(this);
       
   961 	}
       
   962 
       
   963 	virtual bool OnCTRLStateChange()
       
   964 	{
       
   965 		if (this->sel != INVALID_VEHICLE) {
       
   966 			_cursor.vehchain = _ctrl_pressed;
       
   967 			this->InvalidateWidget(DEPOT_WIDGET_MATRIX);
       
   968 		}
       
   969 
       
   970 		return true;
       
   971 	}
       
   972 };
       
   973 
       
   974 static void DepotSellAllConfirmationCallback(Window *win, bool confirmed)
   711 {
   975 {
   712 	WP(w, depot_d).type = type;
   976 	if (confirmed) {
   713 	_backup_orders_tile = 0;
   977 		DepotWindow *w = (DepotWindow*)win;
   714 
   978 		TileIndex tile = w->window_number;
   715 	assert(IsPlayerBuildableVehicleType(type)); // ensure that we make the call with a valid type
   979 		byte vehtype = w->type;
   716 
   980 		DoCommandP(tile, vehtype, 0, NULL, CMD_DEPOT_SELL_ALL_VEHICLES);
   717 	/* Resize the window according to the vehicle type */
       
   718 
       
   719 	/* Set the number of blocks in each direction */
       
   720 	w->vscroll.cap = _resize_cap[type][0];
       
   721 	w->hscroll.cap = _resize_cap[type][1];
       
   722 
       
   723 	/* Set the block size */
       
   724 	w->resize.step_width  = _block_sizes[type][0];
       
   725 	w->resize.step_height = _block_sizes[type][1];
       
   726 
       
   727 	/* Enlarge the window to fit with the selected number of blocks of the selected size */
       
   728 	ResizeWindow(w,
       
   729 				 _block_sizes[type][0] * w->hscroll.cap,
       
   730 				 _block_sizes[type][1] * w->vscroll.cap);
       
   731 
       
   732 	if (type == VEH_TRAIN) {
       
   733 		/* Make space for the horizontal scrollbar vertically, and the unit
       
   734 		 * number, flag, and length counter horizontally. */
       
   735 		ResizeWindow(w, 36, 12);
       
   736 		/* substract the newly added space from the matrix since it was meant for the scrollbar */
       
   737 		w->widget[DEPOT_WIDGET_MATRIX].bottom -= 12;
       
   738 	}
       
   739 
       
   740 	/* Set the minimum window size to the current window size */
       
   741 	w->resize.width  = w->width;
       
   742 	w->resize.height = w->height;
       
   743 
       
   744 	SetupStringsForDepotWindow(w, type);
       
   745 
       
   746 	w->widget[DEPOT_WIDGET_MATRIX].data =
       
   747 		(w->vscroll.cap * 0x100) // number of rows to draw on the background
       
   748 		+ (type == VEH_TRAIN ? 1 : w->hscroll.cap); // number of boxes in each row. Trains always have just one
       
   749 
       
   750 
       
   751 	w->SetWidgetsHiddenState(type != VEH_TRAIN,
       
   752 		DEPOT_WIDGET_H_SCROLL,
       
   753 		DEPOT_WIDGET_SELL_CHAIN,
       
   754 		WIDGET_LIST_END);
       
   755 
       
   756 	ResizeDepotButtons(w);
       
   757 }
       
   758 
       
   759 void DepotSortList(Vehicle **v, uint16 length);
       
   760 
       
   761 static void DepotWndProc(Window *w, WindowEvent *e)
       
   762 {
       
   763 	switch (e->event) {
       
   764 		case WE_CREATE:
       
   765 			WP(w, depot_d).sel = INVALID_VEHICLE;
       
   766 			WP(w, depot_d).vehicle_list  = NULL;
       
   767 			WP(w, depot_d).wagon_list    = NULL;
       
   768 			WP(w, depot_d).engine_count  = 0;
       
   769 			WP(w, depot_d).wagon_count   = 0;
       
   770 			WP(w, depot_d).generate_list = true;
       
   771 			break;
       
   772 
       
   773 		case WE_INVALIDATE_DATA:
       
   774 			WP(w, depot_d).generate_list = true;
       
   775 			break;
       
   776 
       
   777 		case WE_PAINT:
       
   778 			if (WP(w, depot_d).generate_list) {
       
   779 				/* Generate the vehicle list
       
   780 				 * It's ok to use the wagon pointers for non-trains as they will be ignored */
       
   781 				BuildDepotVehicleList(WP(w, depot_d).type, w->window_number,
       
   782 					&WP(w, depot_d).vehicle_list, &WP(w, depot_d).engine_list_length, &WP(w, depot_d).engine_count,
       
   783 					&WP(w, depot_d).wagon_list,   &WP(w, depot_d).wagon_list_length,  &WP(w, depot_d).wagon_count);
       
   784 				WP(w, depot_d).generate_list = false;
       
   785 				DepotSortList(WP(w, depot_d).vehicle_list, WP(w, depot_d).engine_count);
       
   786 //#ifndef NDEBUG
       
   787 #if 0
       
   788 /* We disabled this check for now, but will keep it to quickly make this test again later (if we change some code) */
       
   789 			} else {
       
   790 				/* Here we got a piece of code, that only checks if we got a different number of vehicles in the depot list and the number of vehicles actually being in the depot.
       
   791 				 * IF they aren't the same, then WE_INVALIDATE_DATA should have been called somewhere, but it wasn't and we got a bug
       
   792 				 * Since this is a time consuming check and not nice to memory fragmentation, it may not stay for long, but it's a good way to check this
       
   793 				 * We can turn it on/off by switching between #ifndef NDEBUG and #if 0 */
       
   794 				Vehicle **engines = NULL, **wagons = NULL;
       
   795 				uint16 engine_count = 0, engine_length = 0;
       
   796 				uint16 wagon_count  = 0, wagon_length  = 0;
       
   797 				BuildDepotVehicleList(WP(w, depot_d).type, w->window_number, &engines, &engine_length, &engine_count,
       
   798 									  &wagons,  &wagon_length,  &wagon_count);
       
   799 
       
   800 				assert(engine_count == WP(w, depot_d).engine_count);
       
   801 				assert(wagon_count == WP(w, depot_d).wagon_count);
       
   802 				free((void*)engines);
       
   803 				free((void*)wagons);
       
   804 #endif
       
   805 			}
       
   806 			DrawDepotWindow(w);
       
   807 			break;
       
   808 
       
   809 		case WE_CLICK:
       
   810 			switch (e->we.click.widget) {
       
   811 				case DEPOT_WIDGET_MATRIX: // List
       
   812 					DepotClick(w, e->we.click.pt.x, e->we.click.pt.y);
       
   813 					break;
       
   814 
       
   815 				case DEPOT_WIDGET_BUILD: // Build vehicle
       
   816 					ResetObjectToPlace();
       
   817 					ShowBuildVehicleWindow(w->window_number, WP(w, depot_d).type);
       
   818 					break;
       
   819 
       
   820 				case DEPOT_WIDGET_CLONE: // Clone button
       
   821 					w->InvalidateWidget(DEPOT_WIDGET_CLONE);
       
   822 					w->ToggleWidgetLoweredState(DEPOT_WIDGET_CLONE);
       
   823 
       
   824 					if (w->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
       
   825 						static const CursorID clone_icons[] = {
       
   826 							SPR_CURSOR_CLONE_TRAIN, SPR_CURSOR_CLONE_ROADVEH,
       
   827 							SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
       
   828 						};
       
   829 
       
   830 						_place_clicked_vehicle = NULL;
       
   831 						SetObjectToPlaceWnd(clone_icons[WP(w, depot_d).type], PAL_NONE, VHM_RECT, w);
       
   832 					} else {
       
   833 						ResetObjectToPlace();
       
   834 					}
       
   835 						break;
       
   836 
       
   837 				case DEPOT_WIDGET_LOCATION:
       
   838 					if (_ctrl_pressed) {
       
   839 						ShowExtraViewPortWindow(w->window_number);
       
   840 					} else {
       
   841 						ScrollMainWindowToTile(w->window_number);
       
   842 					}
       
   843 					break;
       
   844 
       
   845 				case DEPOT_WIDGET_STOP_ALL:
       
   846 				case DEPOT_WIDGET_START_ALL:
       
   847 					DoCommandP(w->window_number, 0, WP(w, depot_d).type | (e->we.click.widget == DEPOT_WIDGET_START_ALL ? (1 << 5) : 0), NULL, CMD_MASS_START_STOP);
       
   848 					break;
       
   849 
       
   850 				case DEPOT_WIDGET_SELL_ALL:
       
   851 					/* Only open the confimation window if there are anything to sell */
       
   852 					if (WP(w, depot_d).engine_count != 0 || WP(w, depot_d).wagon_count != 0) {
       
   853 						static const StringID confirm_captions[] = {
       
   854 							STR_8800_TRAIN_DEPOT,
       
   855 							STR_9003_ROAD_VEHICLE_DEPOT,
       
   856 							STR_9803_SHIP_DEPOT,
       
   857 							STR_A002_AIRCRAFT_HANGAR
       
   858 						};
       
   859 						TileIndex tile = w->window_number;
       
   860 						byte vehtype = WP(w, depot_d).type;
       
   861 
       
   862 						SetDParam(0, (vehtype == VEH_AIRCRAFT) ? GetStationIndex(tile) : GetDepotByTile(tile)->town_index);
       
   863 						ShowQuery(
       
   864 							confirm_captions[vehtype],
       
   865 							STR_DEPOT_SELL_CONFIRMATION_TEXT,
       
   866 							w,
       
   867 							DepotSellAllConfirmationCallback
       
   868 						);
       
   869 					}
       
   870 					break;
       
   871 
       
   872 				case DEPOT_WIDGET_VEHICLE_LIST:
       
   873 					ShowVehicleListWindow(GetTileOwner(w->window_number), WP(w, depot_d).type, (TileIndex)w->window_number);
       
   874 					break;
       
   875 
       
   876 				case DEPOT_WIDGET_AUTOREPLACE:
       
   877 					DoCommandP(w->window_number, WP(w, depot_d).type, 0, NULL, CMD_DEPOT_MASS_AUTOREPLACE);
       
   878 					break;
       
   879 
       
   880 			}
       
   881 			break;
       
   882 
       
   883 		case WE_PLACE_OBJ: {
       
   884 			ClonePlaceObj(w);
       
   885 		} break;
       
   886 
       
   887 		case WE_ABORT_PLACE_OBJ: {
       
   888 			/* abort clone */
       
   889 			w->RaiseWidget(DEPOT_WIDGET_CLONE);
       
   890 			w->InvalidateWidget(DEPOT_WIDGET_CLONE);
       
   891 
       
   892 			/* abort drag & drop */
       
   893 			WP(w, depot_d).sel = INVALID_VEHICLE;
       
   894 			w->InvalidateWidget(DEPOT_WIDGET_MATRIX);
       
   895 		} break;
       
   896 
       
   897 			/* check if a vehicle in a depot was clicked.. */
       
   898 		case WE_MOUSELOOP: {
       
   899 			const Vehicle *v = _place_clicked_vehicle;
       
   900 
       
   901 			/* since OTTD checks all open depot windows, we will make sure that it triggers the one with a clicked clone button */
       
   902 			if (v != NULL && w->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
       
   903 				_place_clicked_vehicle = NULL;
       
   904 				HandleCloneVehClick(v, w);
       
   905 			}
       
   906 		} break;
       
   907 
       
   908 		case WE_DESTROY:
       
   909 			DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
       
   910 			free((void*)WP(w, depot_d).vehicle_list);
       
   911 			free((void*)WP(w, depot_d).wagon_list);
       
   912 			break;
       
   913 
       
   914 		case WE_DRAGDROP:
       
   915 			switch (e->we.click.widget) {
       
   916 				case DEPOT_WIDGET_MATRIX: {
       
   917 					Vehicle *v;
       
   918 					VehicleID sel = WP(w, depot_d).sel;
       
   919 
       
   920 					WP(w, depot_d).sel = INVALID_VEHICLE;
       
   921 					w->SetDirty();
       
   922 
       
   923 					if (WP(w, depot_d).type == VEH_TRAIN) {
       
   924 						GetDepotVehiclePtData gdvp;
       
   925 
       
   926 						if (GetVehicleFromDepotWndPt(w, e->we.dragdrop.pt.x, e->we.dragdrop.pt.y, &v, &gdvp) == MODE_DRAG_VEHICLE &&
       
   927 							sel != INVALID_VEHICLE) {
       
   928 							if (gdvp.wagon != NULL && gdvp.wagon->index == sel && _ctrl_pressed) {
       
   929 								DoCommandP(GetVehicle(sel)->tile, GetVehicle(sel)->index, true, NULL, CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_9033_CAN_T_MAKE_VEHICLE_TURN));
       
   930 							} else if (gdvp.wagon == NULL || gdvp.wagon->index != sel) {
       
   931 								TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
       
   932 							} else if (gdvp.head != NULL && IsFrontEngine(gdvp.head)) {
       
   933 								ShowVehicleViewWindow(gdvp.head);
       
   934 							}
       
   935 						}
       
   936 					} else if (GetVehicleFromDepotWndPt(w, e->we.dragdrop.pt.x, e->we.dragdrop.pt.y, &v, NULL) == MODE_DRAG_VEHICLE &&
       
   937 						v != NULL &&
       
   938 						sel == v->index) {
       
   939 						ShowVehicleViewWindow(v);
       
   940 					}
       
   941 				} break;
       
   942 
       
   943 				case DEPOT_WIDGET_SELL: case DEPOT_WIDGET_SELL_CHAIN:
       
   944 					if (!w->IsWidgetDisabled(DEPOT_WIDGET_SELL) &&
       
   945 						WP(w, depot_d).sel != INVALID_VEHICLE) {
       
   946 						Vehicle *v;
       
   947 						uint command;
       
   948 						int sell_cmd;
       
   949 						bool is_engine;
       
   950 
       
   951 						if (w->IsWidgetDisabled(e->we.click.widget)) return;
       
   952 						if (WP(w, depot_d).sel == INVALID_VEHICLE) return;
       
   953 
       
   954 						w->HandleButtonClick(e->we.click.widget);
       
   955 
       
   956 						v = GetVehicle(WP(w, depot_d).sel);
       
   957 						WP(w, depot_d).sel = INVALID_VEHICLE;
       
   958 						w->SetDirty();
       
   959 
       
   960 						sell_cmd = (v->type == VEH_TRAIN && (e->we.click.widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
       
   961 
       
   962 						is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v)));
       
   963 
       
   964 						if (is_engine) {
       
   965 							_backup_orders_tile = v->tile;
       
   966 							BackupVehicleOrders(v);
       
   967 						}
       
   968 
       
   969 						switch (v->type) {
       
   970 							case VEH_TRAIN:    command = CMD_SELL_RAIL_WAGON | CMD_MSG(STR_8839_CAN_T_SELL_RAILROAD_VEHICLE); break;
       
   971 							case VEH_ROAD:     command = CMD_SELL_ROAD_VEH | CMD_MSG(STR_9014_CAN_T_SELL_ROAD_VEHICLE);       break;
       
   972 							case VEH_SHIP:     command = CMD_SELL_SHIP | CMD_MSG(STR_980C_CAN_T_SELL_SHIP);                   break;
       
   973 							case VEH_AIRCRAFT: command = CMD_SELL_AIRCRAFT | CMD_MSG(STR_A01C_CAN_T_SELL_AIRCRAFT);           break;
       
   974 							default: NOT_REACHED(); command = 0;
       
   975 						}
       
   976 
       
   977 						if (!DoCommandP(v->tile, v->index, sell_cmd, NULL, command) && is_engine) _backup_orders_tile = 0;
       
   978 					}
       
   979 					break;
       
   980 				default:
       
   981 					WP(w, depot_d).sel = INVALID_VEHICLE;
       
   982 					w->SetDirty();
       
   983 			}
       
   984 			_cursor.vehchain = false;
       
   985 			break;
       
   986 
       
   987 		case WE_RESIZE:
       
   988 			w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
       
   989 			w->hscroll.cap += e->we.sizing.diff.x / (int)w->resize.step_width;
       
   990 			w->widget[DEPOT_WIDGET_MATRIX].data = (w->vscroll.cap << 8) + (WP(w, depot_d).type == VEH_TRAIN ? 1 : w->hscroll.cap);
       
   991 			ResizeDepotButtons(w);
       
   992 			break;
       
   993 
       
   994 		case WE_CTRL_CHANGED:
       
   995 			if (WP(w, depot_d).sel != INVALID_VEHICLE) {
       
   996 				_cursor.vehchain = _ctrl_pressed;
       
   997 				w->InvalidateWidget(DEPOT_WIDGET_MATRIX);
       
   998 			}
       
   999 			break;
       
  1000 	}
   981 	}
  1001 }
   982 }
  1002 
   983 
  1003 /** Opens a depot window
   984 /** Opens a depot window
  1004  * @param tile The tile where the depot/hangar is located
   985  * @param tile The tile where the depot/hangar is located
  1005  * @param type The type of vehicles in the depot
   986  * @param type The type of vehicles in the depot
  1006  */
   987  */
  1007 void ShowDepotWindow(TileIndex tile, VehicleType type)
   988 void ShowDepotWindow(TileIndex tile, VehicleType type)
  1008 {
   989 {
  1009 	Window *w;
   990 	DepotWindow *w;
  1010 
   991 
  1011 	switch (type) {
   992 	switch (type) {
  1012 		default: NOT_REACHED();
   993 		default: NOT_REACHED();
  1013 		case VEH_TRAIN:
   994 		case VEH_TRAIN:
  1014 			w = AllocateWindowDescFront<Window>(&_train_depot_desc, tile); break;
   995 			w = AllocateWindowDescFront<DepotWindow>(&_train_depot_desc, tile); break;
  1015 		case VEH_ROAD:
   996 		case VEH_ROAD:
  1016 			w = AllocateWindowDescFront<Window>(&_road_depot_desc, tile); break;
   997 			w = AllocateWindowDescFront<DepotWindow>(&_road_depot_desc, tile); break;
  1017 		case VEH_SHIP:
   998 		case VEH_SHIP:
  1018 			w = AllocateWindowDescFront<Window>(&_ship_depot_desc, tile); break;
   999 			w = AllocateWindowDescFront<DepotWindow>(&_ship_depot_desc, tile); break;
  1019 		case VEH_AIRCRAFT:
  1000 		case VEH_AIRCRAFT:
  1020 			w = AllocateWindowDescFront<Window>(&_aircraft_depot_desc, tile); break;
  1001 			w = AllocateWindowDescFront<DepotWindow>(&_aircraft_depot_desc, tile); break;
  1021 	}
  1002 	}
  1022 
  1003 
  1023 	if (w != NULL) {
  1004 	w->caption_color = GetTileOwner(tile);
  1024 		w->caption_color = GetTileOwner(tile);
  1005 	w->CreateDepotListWindow(type);
  1025 		CreateDepotListWindow(w, type);
       
  1026 	}
       
  1027 }
  1006 }
  1028 
  1007 
  1029 /** Removes the highlight of a vehicle in a depot window
  1008 /** Removes the highlight of a vehicle in a depot window
  1030  * @param *v Vehicle to remove all highlights from
  1009  * @param *v Vehicle to remove all highlights from
  1031  */
  1010  */
  1032 void DeleteDepotHighlightOfVehicle(const Vehicle *v)
  1011 void DeleteDepotHighlightOfVehicle(const Vehicle *v)
  1033 {
  1012 {
  1034 	Window *w;
  1013 	DepotWindow *w;
  1035 
  1014 
  1036 	/* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any depots either
  1015 	/* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any depots either
  1037 	 * If that is the case, we can skip looping though the windows and save time                                */
  1016 	 * If that is the case, we can skip looping though the windows and save time
       
  1017 	 */
  1038 	if (_special_mouse_mode != WSM_DRAGDROP) return;
  1018 	if (_special_mouse_mode != WSM_DRAGDROP) return;
  1039 
  1019 
  1040 	w = FindWindowById(WC_VEHICLE_DEPOT, v->tile);
  1020 	w = dynamic_cast<DepotWindow*>(FindWindowById(WC_VEHICLE_DEPOT, v->tile));
  1041 	if (w != NULL) {
  1021 	if (w != NULL) {
  1042 		WP(w, depot_d).sel = INVALID_VEHICLE;
  1022 		w->sel = INVALID_VEHICLE;
  1043 		ResetObjectToPlace();
  1023 		ResetObjectToPlace();
  1044 	}
  1024 	}
  1045 }
  1025 }