train_gui.c
changeset 4770 7092e6b90693
parent 4769 172e18f63248
child 4786 78938c5e606a
equal deleted inserted replaced
4769:172e18f63248 4770:7092e6b90693
    20 #include "vehicle_gui.h"
    20 #include "vehicle_gui.h"
    21 #include "depot.h"
    21 #include "depot.h"
    22 #include "train.h"
    22 #include "train.h"
    23 #include "newgrf_engine.h"
    23 #include "newgrf_engine.h"
    24 #include "date.h"
    24 #include "date.h"
       
    25 #include "strings.h"
    25 
    26 
    26 typedef enum BuildTrainWidgets {
    27 typedef enum BuildTrainWidgets {
    27 	BUILD_TRAIN_WIDGET_CLOSEBOX = 0,
    28 	BUILD_TRAIN_WIDGET_CLOSEBOX = 0,
    28 	BUILD_TRAIN_WIDGET_CAPTION,
    29 	BUILD_TRAIN_WIDGET_CAPTION,
       
    30 	BUILD_TRAIN_WIDGET_SORT_ASSENDING_DESENTING,
       
    31 	BUILD_TRAIN_WIDGET_SORT_TEXT,
       
    32 	BUILD_TRAIN_WIDGET_SORT_DROPDOWN,
    29 	BUILD_TRAIN_WIDGET_LIST,
    33 	BUILD_TRAIN_WIDGET_LIST,
    30 	BUILD_TRAIN_WIDGET_SCROLLBAR,
    34 	BUILD_TRAIN_WIDGET_SCROLLBAR,
    31 	BUILD_TRAIN_WIDGET_PANEL,
    35 	BUILD_TRAIN_WIDGET_PANEL,
    32 	BUILD_TRAIN_WIDGET_ENGINES,
    36 	BUILD_TRAIN_WIDGET_ENGINES,
    33 	BUILD_TRAIN_WIDGET_WAGONS,
    37 	BUILD_TRAIN_WIDGET_WAGONS,
    38 } BuildTrainWidget;
    42 } BuildTrainWidget;
    39 
    43 
    40 static const Widget _new_rail_vehicle_widgets[] = {
    44 static const Widget _new_rail_vehicle_widgets[] = {
    41 	{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
    45 	{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
    42 	{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   227,     0,    13, STR_JUST_STRING,        STR_018C_WINDOW_TITLE_DRAG_THIS},
    46 	{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   227,     0,    13, STR_JUST_STRING,        STR_018C_WINDOW_TITLE_DRAG_THIS},
    43 	{     WWT_MATRIX, RESIZE_BOTTOM,    14,     0,   215,    14,   125, 0x801,                  STR_8843_TRAIN_VEHICLE_SELECTION},
    47 	{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,    80,    14,    25, STR_SORT_BY,            STR_SORT_ORDER_TIP},
    44 	{  WWT_SCROLLBAR, RESIZE_BOTTOM,    14,   216,   227,    14,   125, 0x0,                    STR_0190_SCROLL_BAR_SCROLLS_LIST},
    48 	{      WWT_PANEL,   RESIZE_NONE,    14,    81,   215,    14,    25, 0x0,                    STR_SORT_CRITERIA_TIP},
    45 	{      WWT_PANEL,     RESIZE_TB,    14,     0,   227,   126,   197, 0x0,                    STR_NULL},
    49 	{    WWT_TEXTBTN,   RESIZE_NONE,    14,   216,   227,    14,    25, STR_0225,               STR_SORT_CRITERIA_TIP},
    46 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,    76,   198,   209, STR_BLACK_ENGINES,      STR_BUILD_TRAIN_ENGINES_TIP},
    50 	{     WWT_MATRIX, RESIZE_BOTTOM,    14,     0,   215,    26,   137, 0x801,                  STR_8843_TRAIN_VEHICLE_SELECTION},
    47 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,    77,   151,   198,   209, STR_BLACK_WAGONS,       STR_BUILD_TRAIN_WAGONS_TIP},
    51 	{  WWT_SCROLLBAR, RESIZE_BOTTOM,    14,   216,   227,    26,   137, 0x0,                    STR_0190_SCROLL_BAR_SCROLLS_LIST},
    48 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   152,   227,   198,   209, STR_BLACK_BOTH,         STR_BUILD_TRAIN_BOTH_TIP},
    52 	{      WWT_PANEL,     RESIZE_TB,    14,     0,   227,   138,   209, 0x0,                    STR_NULL},
    49 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,   107,   210,   221, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
    53 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,    76,   210,   221, STR_BLACK_ENGINES,      STR_BUILD_TRAIN_ENGINES_TIP},
    50 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   108,   215,   210,   221, STR_8820_RENAME,        STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
    54 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,    77,   151,   210,   221, STR_BLACK_WAGONS,       STR_BUILD_TRAIN_WAGONS_TIP},
    51 	{  WWT_RESIZEBOX,     RESIZE_TB,    14,   216,   227,   210,   221, 0x0,                    STR_RESIZE_BUTTON},
    55 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   152,   227,   210,   221, STR_BLACK_BOTH,         STR_BUILD_TRAIN_BOTH_TIP},
       
    56 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,   107,   222,   233, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
       
    57 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   108,   215,   222,   233, STR_8820_RENAME,        STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
       
    58 	{  WWT_RESIZEBOX,     RESIZE_TB,    14,   216,   227,   222,   233, 0x0,                    STR_RESIZE_BUTTON},
    52 	{   WIDGETS_END},
    59 	{   WIDGETS_END},
    53 };
    60 };
    54 
    61 
       
    62 static bool _internal_sort_order; // descending/ascending
       
    63 static byte _last_sort_criteria = 0;
       
    64 static bool _last_sort_order = false;
       
    65 
       
    66 typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
       
    67 
       
    68 static int CDECL TrainEngineNumberSorter(const void *a, const void *b)
       
    69 {
       
    70 	const EngineID va = *(const EngineID*)a;
       
    71 	const EngineID vb = *(const EngineID*)b;
       
    72 	int r = va - vb;
       
    73 
       
    74 	return _internal_sort_order ? -r : r;
       
    75 }
       
    76 
       
    77 static int CDECL TrainEngineCostSorter(const void *a, const void *b)
       
    78 {
       
    79 	const int va = RailVehInfo(*(const EngineID*)a)->base_cost;
       
    80 	const int vb = RailVehInfo(*(const EngineID*)b)->base_cost;
       
    81 	int r = va - vb;
       
    82 
       
    83 	return _internal_sort_order ? -r : r;
       
    84 }
       
    85 
       
    86 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b)
       
    87 {
       
    88 	const int va = RailVehInfo(*(const EngineID*)a)->max_speed;
       
    89 	const int vb = RailVehInfo(*(const EngineID*)b)->max_speed;
       
    90 	const int r = va - vb;
       
    91 
       
    92 	if (r == 0) {
       
    93 		/* Use EngineID to sort instead since we want consistent sorting */
       
    94 		return TrainEngineNumberSorter(a, b);
       
    95 	}
       
    96 	return _internal_sort_order ? -r : r;
       
    97 }
       
    98 
       
    99 static int CDECL TrainEnginePowerSorter(const void *a, const void *b)
       
   100 {
       
   101 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
       
   102 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
       
   103 
       
   104 	const int va = rvi_a->power << (rvi_a->flags & RVI_MULTIHEAD ? 1 : 0);
       
   105 	const int vb = rvi_b->power << (rvi_b->flags & RVI_MULTIHEAD ? 1 : 0);
       
   106 	const int r = va - vb;
       
   107 
       
   108 	if (r == 0) {
       
   109 		/* Use EngineID to sort instead since we want consistent sorting */
       
   110 		return TrainEngineNumberSorter(a, b);
       
   111 	}
       
   112 	return _internal_sort_order ? -r : r;
       
   113 }
       
   114 
       
   115 static int CDECL TrainEngineIntroDateSorter(const void *a, const void *b)
       
   116 {
       
   117 	const int va = GetEngine(*(const EngineID*)a)->intro_date;
       
   118 	const int vb = GetEngine(*(const EngineID*)b)->intro_date;
       
   119 	const int r = va - vb;
       
   120 
       
   121 	if (r == 0) {
       
   122 		/* Use EngineID to sort instead since we want consistent sorting */
       
   123 		return TrainEngineNumberSorter(a, b);
       
   124 	}
       
   125 	return _internal_sort_order ? -r : r;
       
   126 }
       
   127 
       
   128 static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting
       
   129 
       
   130 static char _bufcache[64]; // used together with _last_vehicle to hopefully speed up stringsorting
       
   131 static int CDECL TrainEngineNameSorter(const void *a, const void *b)
       
   132 {
       
   133 	const EngineID va = *(const EngineID*)a;
       
   134 	const EngineID vb = *(const EngineID*)b;
       
   135 	char buf1[64] = "\0";
       
   136 	int r;
       
   137 
       
   138 	SetDParam(0, GetCustomEngineName(va));
       
   139 	GetString(buf1, STR_JUST_STRING);
       
   140 
       
   141 	if (vb != _last_engine) {
       
   142 		_last_engine = vb;
       
   143 		_bufcache[0] = '\0';
       
   144 
       
   145 		SetDParam(0, GetCustomEngineName(vb));
       
   146 		GetString(_bufcache, STR_JUST_STRING);
       
   147 	}
       
   148 
       
   149 	r =  strcmp(buf1, _bufcache); // sort by name
       
   150 
       
   151 	if (r == 0) {
       
   152 		/* Use EngineID to sort instead since we want consistent sorting */
       
   153 		return TrainEngineNumberSorter(a, b);
       
   154 	}
       
   155 
       
   156 	return (_internal_sort_order & 1) ? -r : r;
       
   157 }
       
   158 
       
   159 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b)
       
   160 {
       
   161 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
       
   162 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
       
   163 
       
   164 	const int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->flags & RVI_MULTIHEAD ? 2 : 1);
       
   165 	const int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->flags & RVI_MULTIHEAD ? 2 : 1);
       
   166 	const int r = va - vb;
       
   167 
       
   168 	if (r == 0) {
       
   169 		/* Use EngineID to sort instead since we want consistent sorting */
       
   170 		return TrainEngineNumberSorter(a, b);
       
   171 	}
       
   172 	return _internal_sort_order ? -r : r;
       
   173 }
       
   174 
       
   175 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b)
       
   176 {
       
   177 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
       
   178 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
       
   179 
       
   180 	/* Here we are using a few tricks to get the right sort.
       
   181 	 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
       
   182 	 * we will actually calculate cunning cost/power (to make it more than 1).
       
   183 	 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
       
   184 	 * Another thing is that both power and running costs should be doubled for multiheaded engines.
       
   185 	 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */
       
   186 	const int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / rvi_a->power;
       
   187 	const int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / rvi_b->power;
       
   188 	const int r = vb - va;
       
   189 
       
   190 	if (r == 0) {
       
   191 		/* Use EngineID to sort instead since we want consistent sorting */
       
   192 		return TrainEngineNumberSorter(a, b);
       
   193 	}
       
   194 	return _internal_sort_order ? -r : r;
       
   195 }
       
   196 
       
   197 static int CDECL TrainEngineReliabilitySorter(const void *a, const void *b)
       
   198 {
       
   199 	const int va = GetEngine(*(const EngineID*)a)->reliability;
       
   200 	const int vb = GetEngine(*(const EngineID*)b)->reliability;
       
   201 	const int r = va - vb;
       
   202 
       
   203 	if (r == 0) {
       
   204 		/* Use EngineID to sort instead since we want consistent sorting */
       
   205 		return TrainEngineNumberSorter(a, b);
       
   206 	}
       
   207 	return _internal_sort_order ? -r : r;
       
   208 }
       
   209 
       
   210 static VehicleSortListingTypeFunction* const _engine_sorter[] = {
       
   211 	&TrainEngineNumberSorter,
       
   212 	&TrainEngineCostSorter,
       
   213 	&TrainEngineSpeedSorter,
       
   214 	&TrainEnginePowerSorter,
       
   215 	&TrainEngineIntroDateSorter,
       
   216 	&TrainEngineNameSorter,
       
   217 	&TrainEngineRunningCostSorter,
       
   218 	&TrainEnginePowerVsRunningCostSorter,
       
   219 	&TrainEngineReliabilitySorter,
       
   220 };
       
   221 
       
   222 static const StringID _engine_sort_listing[] = {
       
   223 	STR_ENGINE_SORT_ENGINE_ID,
       
   224 	STR_ENGINE_SORT_COST,
       
   225 	STR_SORT_BY_MAX_SPEED,
       
   226 	STR_ENGINE_SORT_POWER,
       
   227 	STR_ENGINE_SORT_INTRO_DATE,
       
   228 	STR_SORT_BY_DROPDOWN_NAME,
       
   229 	STR_ENGINE_SORT_RUNNING_COST,
       
   230 	STR_ENGINE_SORT_POWER_VS_RUNNING_COST,
       
   231 	STR_SORT_BY_RELIABILITY,
       
   232 	INVALID_STRING_ID
       
   233 };
    55 
   234 
    56 /**
   235 /**
    57  * Draw the purchase info details of train engine at a given location.
   236  * Draw the purchase info details of train engine at a given location.
    58  * @param x,y location where to draw the info
   237  * @param x,y location where to draw the info
    59  * @param engine_number the engine of which to draw the info of
   238  * @param engine_number the engine of which to draw the info of
   255 	/* Reduce array sizes if they are too big */
   434 	/* Reduce array sizes if they are too big */
   256 	if (*num_engines == engine_length) *engines = realloc((void*)*engines, (*num_engines) * sizeof((*engines)[0]));
   435 	if (*num_engines == engine_length) *engines = realloc((void*)*engines, (*num_engines) * sizeof((*engines)[0]));
   257 	if (*num_wagons == wagon_length) *wagons = realloc((void*)*wagons, (*num_wagons) * sizeof((*wagons)[0]));
   436 	if (*num_wagons == wagon_length) *wagons = realloc((void*)*wagons, (*num_wagons) * sizeof((*wagons)[0]));
   258 }
   437 }
   259 
   438 
       
   439 static void SortTrainBuildList(Window *w)
       
   440 {
       
   441 	_internal_sort_order = WP(w,buildtrain_d).decenting_sort_order;
       
   442 	qsort((void*)WP(w,buildtrain_d).engines, WP(w,buildtrain_d).num_engines, sizeof(WP(w,buildtrain_d).engines[0]),
       
   443 		  _engine_sorter[WP(w,buildtrain_d).sort_criteria]);
       
   444 }
       
   445 
   260 static void DrawTrainBuildWindow(Window *w)
   446 static void DrawTrainBuildWindow(Window *w)
   261 {
   447 {
   262 	int x = 1;
   448 	int x = 1;
   263 	int y = 15;
   449 	int y = 27;
   264 	EngineID position = w->vscroll.pos;
   450 	EngineID position = w->vscroll.pos;
   265 	EngineID selected_id = WP(w,buildtrain_d).sel_engine;
   451 	EngineID selected_id = WP(w,buildtrain_d).sel_engine;
   266 	int max = w->vscroll.pos + w->vscroll.cap;
   452 	int max = w->vscroll.pos + w->vscroll.cap;
   267 	uint16 scrollcount = 0;
   453 	uint16 scrollcount = 0;
   268 
   454 
   274 	SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_BOTH,    WP(w,buildtrain_d).show_engine_wagon == 3);
   460 	SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_BOTH,    WP(w,buildtrain_d).show_engine_wagon == 3);
   275 
   461 
   276 	if (WP(w,buildtrain_d).data_invalidated) {
   462 	if (WP(w,buildtrain_d).data_invalidated) {
   277 		GenerateBuildList(&WP(w,buildtrain_d).engines, &WP(w,buildtrain_d).num_engines, &WP(w,buildtrain_d).wagons, &WP(w,buildtrain_d).num_wagons, WP(w,buildtrain_d).railtype);
   463 		GenerateBuildList(&WP(w,buildtrain_d).engines, &WP(w,buildtrain_d).num_engines, &WP(w,buildtrain_d).wagons, &WP(w,buildtrain_d).num_wagons, WP(w,buildtrain_d).railtype);
   278 		WP(w,buildtrain_d).data_invalidated = false;
   464 		WP(w,buildtrain_d).data_invalidated = false;
       
   465 		SortTrainBuildList(w);
   279 
   466 
   280 		/* Make sure that the selected engine is still in the list*/
   467 		/* Make sure that the selected engine is still in the list*/
   281 		if (WP(w,buildtrain_d).sel_engine != INVALID_ENGINE) {
   468 		if (WP(w,buildtrain_d).sel_engine != INVALID_ENGINE) {
   282 			int i;
   469 			int i;
   283 			bool found = false;
   470 			bool found = false;
   337 			DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
   524 			DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
   338 		} else {
   525 		} else {
   339 			DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
   526 			DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
   340 		}
   527 		}
   341 	}
   528 	}
       
   529 	DrawString(85, 15, _engine_sort_listing[WP(w,buildtrain_d).sort_criteria], 0x10);
       
   530 	DoDrawString(WP(w,buildtrain_d).decenting_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10);
   342 }
   531 }
   343 
   532 
   344 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   533 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   345 {
   534 {
   346 	switch (e->event) {
   535 	switch (e->event) {
   350 			WP(w,buildtrain_d).engines = NULL;
   539 			WP(w,buildtrain_d).engines = NULL;
   351 			WP(w,buildtrain_d).wagons  = NULL;
   540 			WP(w,buildtrain_d).wagons  = NULL;
   352 			WP(w,buildtrain_d).show_engine_wagon = 3;
   541 			WP(w,buildtrain_d).show_engine_wagon = 3;
   353 			WP(w,buildtrain_d).data_invalidated  = true;
   542 			WP(w,buildtrain_d).data_invalidated  = true;
   354 			WP(w,buildtrain_d).sel_engine        = INVALID_ENGINE;
   543 			WP(w,buildtrain_d).sel_engine        = INVALID_ENGINE;
       
   544 			WP(w,buildtrain_d).sort_criteria     = _last_sort_criteria;
       
   545 			WP(w,buildtrain_d).decenting_sort_order = _last_sort_order;
   355 			break;
   546 			break;
   356 
   547 
   357 		case WE_INVALIDATE_DATA:
   548 		case WE_INVALIDATE_DATA:
   358 			WP(w,buildtrain_d).data_invalidated = true;
   549 			WP(w,buildtrain_d).data_invalidated = true;
   359 			break;
   550 			break;
   368 			break;
   559 			break;
   369 
   560 
   370 
   561 
   371 		case WE_CLICK: {
   562 		case WE_CLICK: {
   372 			switch (e->we.click.widget) {
   563 			switch (e->we.click.widget) {
       
   564 				case BUILD_TRAIN_WIDGET_SORT_ASSENDING_DESENTING:
       
   565 					WP(w,buildtrain_d).decenting_sort_order = !WP(w,buildtrain_d).decenting_sort_order;
       
   566 					_last_sort_order = WP(w,buildtrain_d).decenting_sort_order;
       
   567 					SortTrainBuildList(w);
       
   568 					SetWindowDirty(w);
       
   569 					break;
       
   570 
       
   571 				case BUILD_TRAIN_WIDGET_SORT_TEXT: case BUILD_TRAIN_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */
       
   572 					ShowDropDownMenu(w, _engine_sort_listing, WP(w,buildtrain_d).sort_criteria, BUILD_TRAIN_WIDGET_SORT_DROPDOWN, 0, 0);
       
   573 					return;
       
   574 
   373 				case BUILD_TRAIN_WIDGET_LIST: {
   575 				case BUILD_TRAIN_WIDGET_LIST: {
   374 					uint i = ((e->we.click.pt.y - 14) / 14) + w->vscroll.pos;
   576 					uint i = ((e->we.click.pt.y - 26) / 14) + w->vscroll.pos;
   375 					if (i < (uint)(WP(w,buildtrain_d).num_engines + WP(w,buildtrain_d).num_wagons)) {
   577 					if (i < (uint)(WP(w,buildtrain_d).num_engines + WP(w,buildtrain_d).num_wagons)) {
   376 						if (i < WP(w,buildtrain_d).num_engines && HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
   578 						if (i < WP(w,buildtrain_d).num_engines && HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
   377 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).engines[i];
   579 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).engines[i];
   378 						} else {
   580 						} else {
   379 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).wagons[i - (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) ? WP(w,buildtrain_d).num_engines : 0)];
   581 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).wagons[i - (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) ? WP(w,buildtrain_d).num_engines : 0)];
   422 				DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL,
   624 				DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL,
   423 					CMD_RENAME_ENGINE | CMD_MSG(STR_886B_CAN_T_RENAME_TRAIN_VEHICLE));
   625 					CMD_RENAME_ENGINE | CMD_MSG(STR_886B_CAN_T_RENAME_TRAIN_VEHICLE));
   424 			}
   626 			}
   425 		} break;
   627 		} break;
   426 
   628 
       
   629 		case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
       
   630 			if (WP(w,buildtrain_d).sort_criteria != e->we.dropdown.index) {
       
   631 				WP(w,buildtrain_d).sort_criteria = e->we.dropdown.index;
       
   632 				_last_sort_criteria = e->we.dropdown.index;
       
   633 				SortTrainBuildList(w);
       
   634 			}
       
   635 			SetWindowDirty(w);
       
   636 			break;
       
   637 
   427 		case WE_RESIZE: {
   638 		case WE_RESIZE: {
   428 			if (e->we.sizing.diff.y == 0) break;
   639 			if (e->we.sizing.diff.y == 0) break;
   429 
   640 
   430 			w->vscroll.cap += e->we.sizing.diff.y / 14;
   641 			w->vscroll.cap += e->we.sizing.diff.y / 14;
   431 			w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
   642 			w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
   432 		} break;
   643 		} break;
   433 	}
   644 	}
   434 }
   645 }
   435 
   646 
   436 static const WindowDesc _new_rail_vehicle_desc = {
   647 static const WindowDesc _new_rail_vehicle_desc = {
   437 	-1, -1, 228, 222,
   648 	-1, -1, 228, 234,
   438 	WC_BUILD_VEHICLE,0,
   649 	WC_BUILD_VEHICLE,0,
   439 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   650 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   440 	_new_rail_vehicle_widgets,
   651 	_new_rail_vehicle_widgets,
   441 	NewRailVehicleWndProc
   652 	NewRailVehicleWndProc
   442 };
   653 };