src/vehicle_gui.cpp
branchNewGRF_ports
changeset 10994 cd9968b6f96b
parent 10991 d8811e327d12
--- a/src/vehicle_gui.cpp	Tue Jun 17 10:32:49 2008 +0000
+++ b/src/vehicle_gui.cpp	Tue Jun 17 13:22:13 2008 +0000
@@ -31,6 +31,8 @@
 #include "vehicle_func.h"
 #include "autoreplace_gui.h"
 #include "core/alloc_func.hpp"
+#include "core/mem_func.hpp"
+#include "core/sort_func.hpp"
 #include "string_func.h"
 #include "settings_type.h"
 #include "widgets/dropdown_func.h"
@@ -42,9 +44,8 @@
 #include "table/strings.h"
 
 Sorting _sorting;
-static bool   _internal_sort_order;     // descending/ascending
 
-typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
+typedef int CDECL VehicleSortListingTypeFunction(const Vehicle* const *, const Vehicle* const *);
 
 static VehicleSortListingTypeFunction VehicleNumberSorter;
 static VehicleSortListingTypeFunction VehicleNameSorter;
@@ -89,40 +90,30 @@
 
 void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
 {
-	if (!(vl->vehicles.flags & VL_REBUILD)) return;
+	if (!vl->vehicles.NeedRebuild()) return;
 
 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
 
 	GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type);
 
-	vl->vehicles.flags &= ~VL_REBUILD;
-	vl->vehicles.flags |= VL_RESORT;
+	vl->vehicles.RebuildDone();
 }
 
 /* cached values for VehicleNameSorter to spare many GetString() calls */
 static const Vehicle *_last_vehicle[2] = { NULL, NULL };
-static char           _last_name[2][64] = { "", "" };
 
 void SortVehicleList(VehicleListBase *vl)
 {
-	if (!(vl->vehicles.flags & VL_RESORT)) return;
+	if (vl->vehicles.Sort(_vehicle_sorter[vl->vehicles.SortType()])) return;
 
 	/* invalidate cached values for name sorter - vehicle names could change */
 	_last_vehicle[0] = _last_vehicle[1] = NULL;
-
-	_internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
-	qsort((void*)vl->vehicles.Begin(), vl->vehicles.Length(), sizeof(*vl->vehicles.Begin()),
-		_vehicle_sorter[vl->vehicles.sort_type]);
-
-	vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
-	vl->vehicles.flags &= ~VL_RESORT;
 }
 
 void DepotSortList(VehicleList *list)
 {
-	_internal_sort_order = 0;
 	if (list->Length() < 2) return;
-	qsort((void*)list->Begin(), list->Length(), sizeof(*list->Begin()), _vehicle_sorter[0]);
+	QSortT(list->Begin(), list->Length(), _vehicle_sorter[0]);
 }
 
 /** draw the vehicle profit button in the vehicle list window. */
@@ -507,183 +498,136 @@
 }
 
 
-/* if the sorting criteria had the same value, sort vehicle by unitnumber */
-#define VEHICLEUNITNUMBERSORTER(r, a, b) {if (r == 0) {r = a->unitnumber - b->unitnumber;}}
-
-static int CDECL VehicleNumberSorter(const void *a, const void *b)
-{
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = va->unitnumber - vb->unitnumber;
-
-	return (_internal_sort_order & 1) ? -r : r;
-}
-
-static int CDECL VehicleNameSorter(const void *a, const void *b)
+/** Sort vehicles by their number */
+static int CDECL VehicleNumberSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r;
-
-	if (va != _last_vehicle[0]) {
-		_last_vehicle[0] = va;
-		SetDParam(0, va->index);
-		GetString(_last_name[0], STR_VEHICLE_NAME, lastof(_last_name[0]));
-	}
-
-	if (vb != _last_vehicle[1]) {
-		_last_vehicle[1] = vb;
-		SetDParam(0, vb->index);
-		GetString(_last_name[1], STR_VEHICLE_NAME, lastof(_last_name[1]));
-	}
-
-	r = strcmp(_last_name[0], _last_name[1]); // sort by name
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	return (*a)->unitnumber - (*b)->unitnumber;
 }
 
-static int CDECL VehicleAgeSorter(const void *a, const void *b)
+/** Sort vehicles by their name */
+static int CDECL VehicleNameSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = va->age - vb->age;
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
+	static char last_name[2][64];
 
-	return (_internal_sort_order & 1) ? -r : r;
-}
+	if (*a != _last_vehicle[0]) {
+		_last_vehicle[0] = *a;
+		SetDParam(0, (*a)->index);
+		GetString(last_name[0], STR_VEHICLE_NAME, lastof(last_name[0]));
+	}
 
-static int CDECL VehicleProfitThisYearSorter(const void *a, const void *b)
-{
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = ClampToI32(va->GetDisplayProfitThisYear() - vb->GetDisplayProfitThisYear());
+	if (*b != _last_vehicle[1]) {
+		_last_vehicle[1] = *b;
+		SetDParam(0, (*b)->index);
+		GetString(last_name[1], STR_VEHICLE_NAME, lastof(last_name[1]));
+	}
 
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	int r = strcmp(last_name[0], last_name[1]);
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
-static int CDECL VehicleProfitLastYearSorter(const void *a, const void *b)
+/** Sort vehicles by their age */
+static int CDECL VehicleAgeSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = ClampToI32(va->GetDisplayProfitLastYear() - vb->GetDisplayProfitLastYear());
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	int r = (*a)->age - (*b)->age;
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
-static int CDECL VehicleCargoSorter(const void *a, const void *b)
+/** Sort vehicles by this year profit */
+static int CDECL VehicleProfitThisYearSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	const Vehicle* v;
-	AcceptedCargo cargoa;
-	AcceptedCargo cargob;
+	int r = ClampToI32((*a)->GetDisplayProfitThisYear() - (*b)->GetDisplayProfitThisYear());
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
+}
+
+/** Sort vehicles by last year profit */
+static int CDECL VehicleProfitLastYearSorter(const Vehicle* const *a, const Vehicle* const *b)
+{
+	int r = ClampToI32((*a)->GetDisplayProfitLastYear() - (*b)->GetDisplayProfitLastYear());
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
+}
+
+/** Sort vehicles by their cargo */
+static int CDECL VehicleCargoSorter(const Vehicle* const *a, const Vehicle* const *b)
+{
+	const Vehicle *v;
+	AcceptedCargo diff;
+	MemSetT(diff, 0);
+
+	/* Append the cargo of the connected weagons */
+	for (v = *a; v != NULL; v = v->Next()) diff[v->cargo_type] += v->cargo_cap;
+	for (v = *b; v != NULL; v = v->Next()) diff[v->cargo_type] -= v->cargo_cap;
+
 	int r = 0;
-
-	memset(cargoa, 0, sizeof(cargoa));
-	memset(cargob, 0, sizeof(cargob));
-	for (v = va; v != NULL; v = v->Next()) cargoa[v->cargo_type] += v->cargo_cap;
-	for (v = vb; v != NULL; v = v->Next()) cargob[v->cargo_type] += v->cargo_cap;
-
 	for (CargoID i = 0; i < NUM_CARGO; i++) {
-		r = cargoa[i] - cargob[i];
+		r = diff[i];
 		if (r != 0) break;
 	}
 
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
-}
-
-static int CDECL VehicleReliabilitySorter(const void *a, const void *b)
-{
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = va->reliability - vb->reliability;
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
-}
-
-static int CDECL VehicleMaxSpeedSorter(const void *a, const void *b)
-{
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r;
-
-	if (va->type == VEH_TRAIN && vb->type == VEH_TRAIN) {
-		r = va->u.rail.cached_max_speed - vb->u.rail.cached_max_speed;
-	} else {
-		r = va->max_speed - vb->max_speed;
-	}
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
-static int CDECL VehicleModelSorter(const void *a, const void *b)
+/** Sort vehicles by their reliability */
+static int CDECL VehicleReliabilitySorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	int r = va->engine_type - vb->engine_type;
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	int r = (*a)->reliability - (*b)->reliability;
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
-static int CDECL VehicleValueSorter(const void *a, const void *b)
+/** Sort vehicles by their max speed */
+static int CDECL VehicleMaxSpeedSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle* va = *(const Vehicle**)a;
-	const Vehicle* vb = *(const Vehicle**)b;
-	const Vehicle *u;
-	Money valuea = 0, valueb = 0;
-
-	for (u = va; u != NULL; u = u->Next()) valuea += u->value;
-	for (u = vb; u != NULL; u = u->Next()) valueb += u->value;
-
-	int r = ClampToI32(valuea - valueb);
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	int r = 0;
+	if ((*a)->type == VEH_TRAIN && (*b)->type == VEH_TRAIN) {
+		r = (*a)->u.rail.cached_max_speed - (*b)->u.rail.cached_max_speed;
+	} else {
+		r = (*a)->max_speed - (*b)->max_speed;
+	}
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
-static int CDECL VehicleLengthSorter(const void *a, const void *b)
+/** Sort vehicles by model */
+static int CDECL VehicleModelSorter(const Vehicle* const *a, const Vehicle* const *b)
 {
-	const Vehicle *va = *(const Vehicle**)a;
-	const Vehicle *vb = *(const Vehicle**)b;
+	int r = (*a)->engine_type - (*b)->engine_type;
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
+}
+
+/** Sort vehciles by their value */
+static int CDECL VehicleValueSorter(const Vehicle* const *a, const Vehicle* const *b)
+{
+	const Vehicle *u;
+	Money diff = 0;
+
+	for (u = *a; u != NULL; u = u->Next()) diff += u->value;
+	for (u = *b; u != NULL; u = u->Next()) diff -= u->value;
+
+	int r = ClampToI32(diff);
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
+}
+
+/** Sort vehicles by their length */
+static int CDECL VehicleLengthSorter(const Vehicle* const *a, const Vehicle* const *b)
+{
 	int r = 0;
-
-	switch (va->type) {
+	switch ((*a)->type) {
 		case VEH_TRAIN:
-			r = va->u.rail.cached_total_length - vb->u.rail.cached_total_length;
+			r = (*a)->u.rail.cached_total_length - (*b)->u.rail.cached_total_length;
 			break;
 
-		case VEH_ROAD:
-			for (const Vehicle *u = va; u != NULL; u = u->Next()) r += u->u.road.cached_veh_length;
-			for (const Vehicle *u = vb; u != NULL; u = u->Next()) r -= u->u.road.cached_veh_length;
-			break;
+		case VEH_ROAD: {
+			const Vehicle *u;
+			for (u = *a; u != NULL; u = u->Next()) r += u->u.road.cached_veh_length;
+			for (u = *b; u != NULL; u = u->Next()) r -= u->u.road.cached_veh_length;
+		} break;
 
 		default: NOT_REACHED();
 	}
-
-	VEHICLEUNITNUMBERSORTER(r, va, vb);
-
-	return (_internal_sort_order & 1) ? -r : r;
+	return (r != 0) ? r : VehicleNumberSorter(a, b);
 }
 
 void InitializeGUI()
 {
-	memset(&_sorting, 0, sizeof(_sorting));
+	MemSetT(&_sorting, 0);
 }
 
 /** Assigns an already open vehicle window to a new vehicle.
@@ -915,15 +859,16 @@
 			default: NOT_REACHED(); break;
 		}
 
-		this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE);
-		this->vehicles.sort_type = this->sorting->criteria;
-		this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
+		this->vehicles.SetListing(*this->sorting);
+		this->vehicles.ForceRebuild();
+		this->vehicles.NeedResort();
 
 		this->FindWindowPlacementAndResize(desc);
 	}
 
 	~VehicleListWindow()
 	{
+		*this->sorting = this->vehicles.GetListing();
 	}
 
 	virtual void OnPaint()
@@ -988,9 +933,9 @@
 		this->DrawWidgets();
 
 		/* draw sorting criteria string */
-		DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
+		DrawString(85, 15, _vehicle_sort_listing[this->vehicles.SortType()], TC_BLACK);
 		/* draw arrow pointing up/down for ascending/descending sorting */
-		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
+		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
 
 		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length());
 		for (i = this->vscroll.pos; i < max; ++i) {
@@ -1030,14 +975,11 @@
 	{
 		switch (widget) {
 			case VLW_WIDGET_SORT_ORDER: /* Flip sorting method ascending/descending */
-				this->vehicles.flags ^= VL_DESC;
-				this->vehicles.flags |= VL_RESORT;
-
-				this->sorting->order = !!(this->vehicles.flags & VL_DESC);
+				this->vehicles.ToggleSortOrder();
 				this->SetDirty();
 				break;
 			case VLW_WIDGET_SORT_BY_PULLDOWN:/* Select sorting criteria dropdown menu */
-				ShowDropDownMenu(this, _vehicle_sort_listing, this->vehicles.sort_type, VLW_WIDGET_SORT_BY_PULLDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
+				ShowDropDownMenu(this, _vehicle_sort_listing, this->vehicles.SortType(), VLW_WIDGET_SORT_BY_PULLDOWN, 0, (this->vehicle_type == VEH_TRAIN || this->vehicle_type == VEH_ROAD) ? 0 : (1 << 10));
 				return;
 			case VLW_WIDGET_LIST: { /* Matrix to show vehicles */
 				uint32 id_v = (pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / this->resize.step_height;
@@ -1090,12 +1032,7 @@
 	{
 		switch (widget) {
 			case VLW_WIDGET_SORT_BY_PULLDOWN:
-				if (this->vehicles.sort_type != index) {
-					/* value has changed -> resort */
-					this->vehicles.flags |= VL_RESORT;
-					this->vehicles.sort_type = index;
-					this->sorting->criteria = this->vehicles.sort_type;
-				}
+				this->vehicles.SetSortType(index);
 				break;
 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
 				assert(this->vehicles.Length() != 0);
@@ -1128,13 +1065,11 @@
 	virtual void OnTick()
 	{
 		if (_pause_game != 0) return;
-		if (--this->vehicles.resort_timer == 0) {
+		if (this->vehicles.NeedResort()) {
 			StationID station = ((this->window_number & VLW_MASK) == VLW_STATION_LIST) ? GB(this->window_number, 16, 16) : INVALID_STATION;
 			PlayerID owner = (PlayerID)this->caption_color;
 
 			DEBUG(misc, 3, "Periodic resort %d list player %d at station %d", this->vehicle_type, owner, station);
-			this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
-			this->vehicles.flags |= VL_RESORT;
 			this->SetDirty();
 		}
 	}
@@ -1147,7 +1082,11 @@
 
 	virtual void OnInvalidateData(int data)
 	{
-		this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+		if (data == 0) {
+			this->vehicles.ForceRebuild();
+		} else {
+			this->vehicles.ForceResort();
+		}
 	}
 };