summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aircraft_cmd.c6
-rw-r--r--aircraft_gui.c284
-rw-r--r--gui.h8
-rw-r--r--lang/english.txt10
-rw-r--r--main_gui.c16
-rw-r--r--order_cmd.c10
-rw-r--r--roadveh_cmd.c9
-rw-r--r--roadveh_gui.c280
-rw-r--r--ship_cmd.c6
-rw-r--r--ship_gui.c282
-rw-r--r--station_gui.c62
-rw-r--r--train_cmd.c9
-rw-r--r--train_gui.c288
-rw-r--r--vehicle.c5
-rw-r--r--vehicle_gui.c106
-rw-r--r--vehicle_gui.h26
-rw-r--r--water_cmd.c6
-rw-r--r--window.h17
18 files changed, 679 insertions, 751 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index 992900366..74a823251 100644
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -267,8 +267,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
- _vehicle_sort_dirty[VEHAIRCRAFT] = true; // build aircraft
- InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
}
@@ -299,8 +298,7 @@ static bool CheckStoppedInHangar(Vehicle *v)
static void DoDeleteAircraft(Vehicle *v)
{
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
- _vehicle_sort_dirty[VEHAIRCRAFT] = true; // delete aircraft
- InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
DeleteVehicleChain(v);
}
diff --git a/aircraft_gui.c b/aircraft_gui.c
index cfe1b7238..5dbfebaa8 100644
--- a/aircraft_gui.c
+++ b/aircraft_gui.c
@@ -884,158 +884,125 @@ static void DrawSmallSchedule(Vehicle *v, int x, int y) {
}
}
-// used to get a sorted list of the vehicles
-static SortStruct _aircraft_sort[NUM_NORMAL_VEHICLES];
-static uint16 _num_aircraft_sort[MAX_PLAYERS];
-static void GlobalSortAircraftList()
-{
- const Vehicle *v;
- uint16 *i;
- uint32 n = 0;
-
- // reset #-of aircraft to 0 because ++ is used for value-assignment
- for (i = _num_aircraft_sort; i != endof(_num_aircraft_sort); i++) {*i = 0;}
-
- FOR_ALL_VEHICLES(v) {
- if(v->type == VEH_Aircraft && v->subtype <= 2) {
- _aircraft_sort[n].index = v->index;
- _aircraft_sort[n++].owner = v->owner;
- _num_aircraft_sort[v->owner]++; // add number of aircraft of player
- }
- }
-
- // create cumulative aircraft-ownership
- // aircraft are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
- for (i = &_num_aircraft_sort[1]; i != endof(_num_aircraft_sort); i++) {*i += *(i-1);}
-
- qsort(_aircraft_sort, n, sizeof(_aircraft_sort[0]), GeneralOwnerSorter); // sort by owner
-
- // since indexes are messed up after adding/removing a station, mark all lists dirty
- memset(_aircraft_sort_dirty, true, sizeof(_aircraft_sort_dirty));
- _vehicle_sort_dirty[VEHAIRCRAFT] = false;
-
- DEBUG(misc, 1) ("Resorting global aircraft list...");
-}
-
-static void MakeSortedAircraftList(byte owner)
-{
- SortStruct *firstelement;
- uint32 n = 0;
-
- if (owner == 0) { // first element starts at 0th element and has n elements as described above
- firstelement = &_aircraft_sort[0];
- n = _num_aircraft_sort[0];
- } else { // nth element starts at the end of the previous one, and has n elements as described above
- firstelement = &_aircraft_sort[_num_aircraft_sort[owner-1]];
- n = _num_aircraft_sort[owner] - _num_aircraft_sort[owner-1];
- }
-
- _internal_sort_order = _aircraft_sort_order[owner];
- _internal_name_sorter_id = STR_SV_AIRCRAFT_NAME;
- _last_vehicle_idx = 0; // used for "cache" in namesorting
- qsort(firstelement, n, sizeof(_aircraft_sort[0]), _vehicle_sorter[_aircraft_sort_type[owner]]);
-
- _aircraft_sort_dirty[owner] = false;
+static Widget _player_aircraft_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
+{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
- DEBUG(misc, 1) ("Resorting Aircraft list player %d...", owner+1);
-}
+static Widget _other_player_aircraft_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WIDGETS_END},
+};
static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
{
+ int station = (int)w->window_number >> 16;
+ int owner = w->window_number & 0xff;
+ vehiclelist_d *vl = &WP(w, vehiclelist_d);
+
switch(e->event) {
case WE_PAINT: {
- uint32 i;
- const byte window_number = (byte)w->window_number;
+ int x = 2;
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int max;
+ int i;
- if (_aircraft_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
- w->disabled_state |= (1 << 2);
+ BuildVehicleList(vl, VEH_Aircraft, owner, station);
+ SortVehicleList(vl);
- // resort shipps window if roadvehicles have been added/removed
- if (_vehicle_sort_dirty[VEHAIRCRAFT])
- GlobalSortAircraftList();
+ SetVScrollCount(w, vl->list_length);
- if (_aircraft_sort_dirty[window_number]) {
- MakeSortedAircraftList(window_number);
- /* reset sorting timeout */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
- }
-
- // aircraft are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 aircraft
- i = (window_number == 0) ? 0 : _num_aircraft_sort[window_number-1];
- SetVScrollCount(w, _num_aircraft_sort[window_number] - i);
+ // disable 'Sort By' tooltip on Unsorted sorting criteria
+ if (vl->sort_type == SORT_BY_UNSORTED)
+ w->disabled_state |= (1 << 2);
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(window_number);
- /* Company Name -- (###) Aircraft */
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- SetDParam(2, w->vscroll.count);
+ const Player *p = DEREF_PLAYER(owner);
+ /* XXX hack */
+ if (station == -1) {
+ /* Company Name -- (###) Aircraft */
+ SetDParam(0, p->name_1);
+ SetDParam(1, p->name_2);
+ SetDParam(2, w->vscroll.count);
+ _player_aircraft_widgets[1].unkA = STR_A009_AIRCRAFT;
+ _other_player_aircraft_widgets[1].unkA = STR_A009_AIRCRAFT;
+ } else {
+ /* Station Name -- (###) Aircraft */
+ SetDParam(0, DEREF_STATION(station)->index);
+ SetDParam(1, w->vscroll.count);
+ _player_aircraft_widgets[1].unkA = STR_SCHEDULED_AIRCRAFT;
+ _other_player_aircraft_widgets[1].unkA = STR_SCHEDULED_AIRCRAFT;
+ }
DrawWindowWidgets(w);
}
/* draw sorting criteria string */
- DrawString(85, 15, _vehicle_sort_listing[_aircraft_sort_type[window_number]], 0x10);
- /* draw arrow pointing up/down for ascending/descending soring */
- DoDrawString(_aircraft_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 69, 15, 0x10);
-
- /* draw the aircraft */
- {
- Vehicle *v;
- int n = 0;
- const int x = 2; // offset from left side of widget
- int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget
- i += w->vscroll.pos; // offset from sorted aircraft list of current player
-
- while (i < _num_aircraft_sort[window_number]) {
- StringID str;
- v = DEREF_VEHICLE(_aircraft_sort[i].index);
-
- assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == window_number);
+ DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10);
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DoDrawString(
+ vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
+
+ max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
+ for (i = w->vscroll.pos; i < max; ++i) {
+ Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index);
+ StringID str;
- DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
+ assert(v->type == VEH_Aircraft && v->subtype <= 2);
- SetDParam(0, v->unitnumber);
- if (IsAircraftHangarTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
+ DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y + 13);
+ SetDParam(0, v->unitnumber);
+ if (IsAircraftHangarTile(v->tile))
+ str = STR_021F;
+ else
+ str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+ DrawString(x, y + 2, str, 0);
- SetDParam(0, v->profit_this_year);
- SetDParam(1, v->profit_last_year);
- DrawString(x+19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+ SetDParam(0, v->profit_this_year);
+ SetDParam(1, v->profit_last_year);
+ DrawString(x + 19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
- if (v->string_id != STR_SV_AIRCRAFT_NAME) {
- SetDParam(0, v->string_id);
- DrawString(x+19, y, STR_01AB, 0);
- }
+ if (v->string_id != STR_SV_AIRCRAFT_NAME) {
+ SetDParam(0, v->string_id);
+ DrawString(x + 19, y, STR_01AB, 0);
+ }
- DrawSmallSchedule(v, x+136, y);
+ DrawSmallSchedule(v, x + 136, y);
- y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
- i++; // next aircraft
- if (++n == w->vscroll.cap) { break;} // max number of aircraft in the window
- }
+ y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
}
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 2: /* Flip sorting method ascending/descending */
- _aircraft_sort_order[(byte)w->window_number] ^= 1;
- _aircraft_sort_dirty[(byte)w->window_number] = true;
+ vl->flags ^= VL_DESC;
+ vl->flags |= VL_RESORT;
SetWindowDirty(w);
break;
+
case 3: case 4:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, _aircraft_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 4, 0);
return;
+
case 6: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG;
@@ -1044,15 +1011,13 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
id_v += w->vscroll.pos;
{
- const byte owner = (byte)w->window_number;
Vehicle *v;
- id_v += (owner == 0) ? 0 : _num_aircraft_sort[owner - 1]; // first element in list
- if (id_v >= _num_aircraft_sort[owner]) { return;} // click out of vehicle bound
+ if (id_v >= vl->list_length) return; // click out of list bound
- v = DEREF_VEHICLE(_aircraft_sort[id_v].index); // add the offset id_x to that
+ v = DEREF_VEHICLE(vl->sort_list[id_v].index);
- assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner);
+ assert(v->type == VEH_Aircraft && v->subtype <= 2);
ShowAircraftViewWindow(v);
}
@@ -1078,48 +1043,37 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- if (_aircraft_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
- _aircraft_sort_dirty[(byte)w->window_number] = true;
-
- _aircraft_sort_type[(byte)w->window_number] = e->dropdown.index;
-
- if (_aircraft_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
- w->disabled_state &= ~(1 << 2);
-
+ if (vl->sort_type != e->dropdown.index) {
+ // value has changed -> resort
+ vl->flags |= VL_RESORT;
+ vl->sort_type = e->dropdown.index;
+
+ // enable 'Sort By' if a sorter criteria is chosen
+ if (vl->sort_type != SORT_BY_UNSORTED)
+ w->disabled_state &= ~(1 << 2);
+ }
SetWindowDirty(w);
break;
+
case WE_CREATE: /* set up resort timer */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
+ vl->sort_list = NULL;
+ vl->flags = VL_REBUILD;
+ vl->sort_type = SORT_BY_UNSORTED;
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
break;
+
case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
- if (--w->custom[0] == 0) {
- w->custom[0] = DAY_TICKS;
- if (--w->custom[1] == 0) {
- w->custom[1] = PERIODIC_RESORT_DAYS;
- _aircraft_sort_dirty[(byte)w->window_number] = true;
- DEBUG(misc, 1) ("Periodic resort Aircraft list player %d...", w->window_number+1);
- SetWindowDirty(w);
- }
+ if (--vl->resort_timer == 0) {
+ DEBUG(misc, 1) ("Periodic resort aircraft list player %d station %d",
+ owner, station);
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->flags |= VL_RESORT;
+ SetWindowDirty(w);
}
break;
}
}
-static const Widget _player_aircraft_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
-{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
static const WindowDesc _player_aircraft_desc = {
-1, -1, 260, 182,
WC_AIRCRAFT_LIST,0,
@@ -1128,18 +1082,6 @@ static const WindowDesc _player_aircraft_desc = {
PlayerAircraftWndProc
};
-static const Widget _other_player_aircraft_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WIDGETS_END},
-};
-
static const WindowDesc _other_player_aircraft_desc = {
-1, -1, 260, 170,
WC_AIRCRAFT_LIST,0,
@@ -1148,14 +1090,14 @@ static const WindowDesc _other_player_aircraft_desc = {
PlayerAircraftWndProc
};
-void ShowPlayerAircraft(int player)
+void ShowPlayerAircraft(int player, int station)
{
Window *w;
if (player == _local_player) {
- w = AllocateWindowDescFront(&_player_aircraft_desc, player);
+ w = AllocateWindowDescFront(&_player_aircraft_desc, (station << 16) | player);
} else {
- w = AllocateWindowDescFront(&_other_player_aircraft_desc, player);
+ w = AllocateWindowDescFront(&_other_player_aircraft_desc, (station << 16) | player);
}
if (w) {
diff --git a/gui.h b/gui.h
index da6f05f49..45ea66a15 100644
--- a/gui.h
+++ b/gui.h
@@ -34,7 +34,7 @@ void ShowBuildRailToolbar(int index, int button);
void PlaceProc_BuyLand(uint tile);
/* train_gui.c */
-void ShowPlayerTrains(int player);
+void ShowPlayerTrains(int player, int station);
void ShowTrainViewWindow(Vehicle *v);
void ShowTrainDetailsWindow(Vehicle *v);
void ShowOrdersWindow(Vehicle *v);
@@ -44,17 +44,17 @@ void ShowRoadVehViewWindow(Vehicle *v);
/* road_gui.c */
void ShowBuildRoadToolbar();
void ShowBuildRoadScenToolbar();
-void ShowPlayerRoadVehicles(int player);
+void ShowPlayerRoadVehicles(int player, int station);
/* dock_gui.c */
void ShowBuildDocksToolbar();
-void ShowPlayerShips(int player);
+void ShowPlayerShips(int player, int station);
void ShowShipViewWindow(Vehicle *v);
/* aircraft_gui.c */
void ShowBuildAirToolbar();
-void ShowPlayerAircraft(int player);
+void ShowPlayerAircraft(int player, int station);
/* terraform_gui.c */
void PlaceProc_DemolishArea(uint tile);
diff --git a/lang/english.txt b/lang/english.txt
index ab06f7f4c..be7b8be71 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -2697,3 +2697,13 @@ STR_NEWGRF_TIP :{BLACK}A list of all the Newgrf sets that you have in
STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}There are currently no newgrf files installed! Please refer to the manual for instructions to install new graphics.
STR_NEWGRF_FILENAME :{BLACK}Filename:
STR_NEWGRF_GRF_ID :{BLACK}GRF ID:
+
+STR_TRAIN :{BLACK}{TRAIN}
+STR_LORRY :{BLACK}{LORRY}
+STR_PLANE :{BLACK}{PLANE}
+STR_SHIP :{BLACK}{SHIP}
+
+STR_SCHEDULED_TRAINS :{WHITE}{STATION} - {COMMA16} Trains
+STR_SCHEDULED_ROAD_VEHICLES :{WHITE}{STATION} - {COMMA16} Road Vehicles
+STR_SCHEDULED_AIRCRAFT :{WHITE}{STATION} - {COMMA16} Aircraft
+STR_SCHEDULED_SHIPS :{WHITE}{STATION} - {COMMA16} Ships
diff --git a/main_gui.c b/main_gui.c
index 80567b2ed..918b3c6a0 100644
--- a/main_gui.c
+++ b/main_gui.c
@@ -292,22 +292,22 @@ static void MenuClickIndustry(int index)
static void MenuClickShowTrains(int index)
{
- ShowPlayerTrains(index);
+ ShowPlayerTrains(index, -1);
}
static void MenuClickShowRoad(int index)
{
- ShowPlayerRoadVehicles(index);
+ ShowPlayerRoadVehicles(index, -1);
}
static void MenuClickShowShips(int index)
{
- ShowPlayerShips(index);
+ ShowPlayerShips(index, -1);
}
static void MenuClickShowAir(int index)
{
- ShowPlayerAircraft(index);
+ ShowPlayerAircraft(index, -1);
}
static void MenuClickBuildRail(int index)
@@ -1819,10 +1819,10 @@ static void MainToolbarWndProc(Window *w, WindowEvent *e)
case WKC_F10:ShowOperatingProfitGraph(); break;
case WKC_F11: ShowCompanyLeagueTable(); break;
case WKC_F12: ShowBuildIndustryWindow(); break;
- case WKC_SHIFT | WKC_F1: ShowPlayerTrains(local); break;
- case WKC_SHIFT | WKC_F2: ShowPlayerRoadVehicles(local); break;
- case WKC_SHIFT | WKC_F3: ShowPlayerShips(local); break;
- case WKC_SHIFT | WKC_F4: ShowPlayerAircraft(local); break;
+ case WKC_SHIFT | WKC_F1: ShowPlayerTrains(local, -1); break;
+ case WKC_SHIFT | WKC_F2: ShowPlayerRoadVehicles(local, -1); break;
+ case WKC_SHIFT | WKC_F3: ShowPlayerShips(local, -1); break;
+ case WKC_SHIFT | WKC_F4: ShowPlayerAircraft(local, -1); break;
case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
case WKC_SHIFT | WKC_F7: ShowBuildRailToolbar(_last_built_railtype,-1); break;
diff --git a/order_cmd.c b/order_cmd.c
index e08448b18..9de4a8c18 100644
--- a/order_cmd.c
+++ b/order_cmd.c
@@ -62,6 +62,8 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
}
}
+
+ RebuildVehicleLists();
}
return 0;
@@ -81,6 +83,8 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags)
dst->schedule_ptr = _ptr_to_next_order++;
InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+
+ RebuildVehicleLists();
}
return 0;
}
@@ -126,6 +130,8 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
}
}
+
+ RebuildVehicleLists();
}
return 0;
@@ -240,6 +246,8 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
InvalidateWindow(WC_VEHICLE_ORDERS, src->index);
InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+
+ RebuildVehicleLists();
}
break;
}
@@ -281,6 +289,8 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
memcpy(dst->schedule_ptr, src->schedule_ptr, (src->num_orders + 1) * sizeof(uint16));
InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+
+ RebuildVehicleLists();
}
break;
}
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index f9acd3c44..7df7b7f44 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -184,8 +184,7 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
- _vehicle_sort_dirty[VEHROAD] = true; // build a new bus/truck
- InvalidateWindow(WC_ROADVEH_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
}
@@ -228,8 +227,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (flags & DC_EXEC) {
// Invalidate depot
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
- _vehicle_sort_dirty[VEHROAD] = true; // sell a bus/truck
- InvalidateWindow(WC_ROADVEH_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
DeleteVehicle(v);
@@ -422,8 +420,7 @@ static void RoadVehDelete(Vehicle *v)
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
- _vehicle_sort_dirty[VEHROAD] = true; // delete bus/truck (eg. crash for example)
- InvalidateWindow(WC_ROADVEH_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
if(IS_TILETYPE(v->tile, MP_STATION))
diff --git a/roadveh_gui.c b/roadveh_gui.c
index b86ded196..c9682ecf9 100644
--- a/roadveh_gui.c
+++ b/roadveh_gui.c
@@ -698,154 +698,122 @@ void ShowRoadDepotWindow(uint tile)
}
}
-// used to get a sorted list of the vehicles
-static SortStruct _road_sort[NUM_NORMAL_VEHICLES];
-static uint16 _num_road_sort[MAX_PLAYERS];
-static void GlobalSortRoadVehList()
-{
- const Vehicle *v;
- uint16 *i;
- uint32 n = 0;
-
- // reset #-of roadvehicles to 0 because ++ is used for value-assignment
- for (i = _num_road_sort; i != endof(_num_road_sort); i++) {*i = 0;}
-
- FOR_ALL_VEHICLES(v) {
- if(v->type == VEH_Road) {
- _road_sort[n].index = v->index;
- _road_sort[n++].owner = v->owner;
- _num_road_sort[v->owner]++; // add number of roadvehicless of player
- }
- }
-
- // create cumulative roadvehicle-ownership
- // roads are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
- for (i = &_num_road_sort[1]; i != endof(_num_road_sort); i++) {*i += *(i-1);}
-
- qsort(_road_sort, n, sizeof(_road_sort[0]), GeneralOwnerSorter); // sort by owner
-
- // since indexes are messed up after adding/removing a station, mark all lists dirty
- memset(_road_sort_dirty, true, sizeof(_road_sort_dirty));
- _vehicle_sort_dirty[VEHROAD] = false;
-
- DEBUG(misc, 1) ("Resorting global roadvehicles list...");
-}
-
-static void MakeSortedRoadVehList(byte owner)
-{
- SortStruct *firstelement;
- uint32 n = 0;
-
- if (owner == 0) { // first element starts at 0th element and has n elements as described above
- firstelement = &_road_sort[0];
- n = _num_road_sort[0];
- } else { // nth element starts at the end of the previous one, and has n elements as described above
- firstelement = &_road_sort[_num_road_sort[owner-1]];
- n = _num_road_sort[owner] - _num_road_sort[owner-1];
- }
-
- _internal_sort_order = _road_sort_order[owner];
- _internal_name_sorter_id = STR_SV_ROADVEH_NAME;
- _last_vehicle_idx = 0; // used for "cache" in namesorting
- qsort(firstelement, n, sizeof(_road_sort[0]), _vehicle_sorter[_road_sort_type[owner]]);
-
- _road_sort_dirty[owner] = false;
+static Widget _player_roadveh_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+/* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */
+{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_8815_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES},
+{ WWT_PANEL, 14, 130, 259, 208, 219, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
- DEBUG(misc, 1) ("Resorting Roadvehicles list player %d...", owner+1);
-}
+static Widget _other_player_roadveh_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WIDGETS_END},
+};
static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
{
+ int station = (int)w->window_number >> 16;
+ int owner = w->window_number & 0xff;
+ vehiclelist_d *vl = &WP(w, vehiclelist_d);
+
switch(e->event) {
case WE_PAINT: {
- uint32 i;
- const byte window_number = (byte)w->window_number;
+ int x = 2;
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int max;
+ int i;
- if (_road_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
- w->disabled_state |= (1 << 2);
+ BuildVehicleList(vl, VEH_Road, owner, station);
+ SortVehicleList(vl);
- // resort roadvehicles window if roadvehicles have been added/removed
- if (_vehicle_sort_dirty[VEHROAD])
- GlobalSortRoadVehList();
+ SetVScrollCount(w, vl->list_length);
- if (_road_sort_dirty[window_number]) {
- MakeSortedRoadVehList(window_number);
- /* reset sorting timeout */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
- }
-
- // roads are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 roads
- i = (window_number == 0) ? 0 : _num_road_sort[window_number-1];
- SetVScrollCount(w, _num_road_sort[window_number] - i);
+ // disable 'Sort By' tooltip on Unsorted sorting criteria
+ if (vl->sort_type == SORT_BY_UNSORTED)
+ w->disabled_state |= (1 << 2);
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(window_number);
- /* Company Name -- (###) Roadvehicles */
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- SetDParam(2, w->vscroll.count);
+ const Player *p = DEREF_PLAYER(owner);
+ /* XXX hack */
+ if (station == -1) {
+ /* Company Name -- (###) Road vehicles */
+ SetDParam(0, p->name_1);
+ SetDParam(1, p->name_2);
+ SetDParam(2, w->vscroll.count);
+ _player_roadveh_widgets[1].unkA = STR_9001_ROAD_VEHICLES;
+ _other_player_roadveh_widgets[1].unkA = STR_9001_ROAD_VEHICLES;
+ } else {
+ /* Station Name -- (###) Road vehicles */
+ SetDParam(0, DEREF_STATION(station)->index);
+ SetDParam(1, w->vscroll.count);
+ _player_roadveh_widgets[1].unkA = STR_SCHEDULED_ROAD_VEHICLES;
+ _other_player_roadveh_widgets[1].unkA = STR_SCHEDULED_ROAD_VEHICLES;
+ }
DrawWindowWidgets(w);
}
/* draw sorting criteria string */
- DrawString(85, 15, _vehicle_sort_listing[_road_sort_type[window_number]], 0x10);
- /* draw arrow pointing up/down for ascending/descending soring */
- DoDrawString(_road_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 69, 15, 0x10);
-
- /* draw the roadvehicles */
- {
- Vehicle *v;
- int n = 0;
- const int x = 2; // offset from left side of widget
- int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget
- i += w->vscroll.pos; // offset from sorted roads list of current player
-
- while (i < _num_road_sort[window_number]) {
- StringID str;
- v = DEREF_VEHICLE(_road_sort[i].index);
-
- assert(v->type == VEH_Road && v->owner == window_number);
+ DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10);
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DoDrawString(
+ vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
+
+ max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
+ for (i = w->vscroll.pos; i < max; ++i) {
+ Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index);
+ StringID str;
- DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
+ assert(v->type == VEH_Road && v->owner == owner);
- SetDParam(0, v->unitnumber);
- if (IsRoadDepotTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
+ DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y + 13);
- SetDParam(0, v->profit_this_year);
- SetDParam(1, v->profit_last_year);
- DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+ SetDParam(0, v->unitnumber);
+ if (IsRoadDepotTile(v->tile))
+ str = STR_021F;
+ else
+ str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+ DrawString(x, y + 2, str, 0);
- if (v->string_id != STR_SV_ROADVEH_NAME) {
- SetDParam(0, v->string_id);
- DrawString(x+24, y, STR_01AB, 0);
- }
+ SetDParam(0, v->profit_this_year);
+ SetDParam(1, v->profit_last_year);
+ DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
- y += PLY_WND_PRC__SIZE_OF_ROW_SMALL;
- i++; // next road
- if (++n == w->vscroll.cap) { break;} // max number of roads in the window
+ if (v->string_id != STR_SV_TRAIN_NAME) {
+ SetDParam(0, v->string_id);
+ DrawString(x + 24, y, STR_01AB, 0);
}
+
+ y += PLY_WND_PRC__SIZE_OF_ROW_SMALL;
}
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 2: /* Flip sorting method ascending/descending */
- _road_sort_order[(byte)w->window_number] ^= 1;
- _road_sort_dirty[(byte)w->window_number] = true;
+ vl->flags ^= VL_DESC;
+ vl->flags |= VL_RESORT;
SetWindowDirty(w);
break;
+
case 3: case 4:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, _road_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 4, 0);
return;
case 6: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL;
@@ -855,13 +823,11 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
id_v += w->vscroll.pos;
{
- const byte owner = (byte)w->window_number;
Vehicle *v;
- id_v += (owner == 0) ? 0 : _num_road_sort[owner - 1]; // first element in list
- if (id_v >= _num_road_sort[owner]) { return;} // click out of vehicle bound
+ if (id_v >= vl->list_length) return; // click out of list bound
- v = DEREF_VEHICLE(_road_sort[id_v].index); // add the offset id_x to that
+ v = DEREF_VEHICLE(vl->sort_list[id_v].index);
assert(v->type == VEH_Road && v->owner == owner);
@@ -889,49 +855,37 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- if (_road_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
- _road_sort_dirty[(byte)w->window_number] = true;
-
- _road_sort_type[(byte)w->window_number] = e->dropdown.index;
-
- if (_road_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
- w->disabled_state &= ~(1 << 2);
-
+ if (vl->sort_type != e->dropdown.index) {
+ // value has changed -> resort
+ vl->flags |= VL_RESORT;
+ vl->sort_type = e->dropdown.index;
+
+ // enable 'Sort By' if a sorter criteria is chosen
+ if (vl->sort_type != SORT_BY_UNSORTED)
+ w->disabled_state &= ~(1 << 2);
+ }
SetWindowDirty(w);
break;
+
case WE_CREATE: /* set up resort timer */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
+ vl->sort_list = NULL;
+ vl->flags = VL_REBUILD;
+ vl->sort_type = SORT_BY_UNSORTED;
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
break;
+
case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
- if (--w->custom[0] == 0) {
- w->custom[0] = DAY_TICKS;
- if (--w->custom[1] == 0) {
- w->custom[1] = PERIODIC_RESORT_DAYS;
- _road_sort_dirty[(byte)w->window_number] = true;
- DEBUG(misc, 1) ("Periodic resort Roadvehicles list player %d...", w->window_number+1);
- SetWindowDirty(w);
- }
+ if (--vl->resort_timer == 0) {
+ DEBUG(misc, 1) ("Periodic resort road vehicles list player %d station %d",
+ owner, station);
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->flags |= VL_RESORT;
+ SetWindowDirty(w);
}
break;
}
}
-static const Widget _player_roadveh_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-/* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */
-{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_8815_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES},
-{ WWT_PANEL, 14, 130, 259, 208, 219, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
static const WindowDesc _player_roadveh_desc = {
-1, -1, 260, 220,
WC_ROADVEH_LIST,0,
@@ -940,18 +894,6 @@ static const WindowDesc _player_roadveh_desc = {
PlayerRoadVehWndProc
};
-static const Widget _other_player_roadveh_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WIDGETS_END},
-};
-
static const WindowDesc _other_player_roadveh_desc = {
-1, -1, 260, 208,
WC_ROADVEH_LIST,0,
@@ -961,14 +903,14 @@ static const WindowDesc _other_player_roadveh_desc = {
};
-void ShowPlayerRoadVehicles(int player)
+void ShowPlayerRoadVehicles(int player, int station)
{
Window *w;
if ( player == _local_player) {
- w = AllocateWindowDescFront(&_player_roadveh_desc, player);
+ w = AllocateWindowDescFront(&_player_roadveh_desc, (station << 16) | player);
} else {
- w = AllocateWindowDescFront(&_other_player_roadveh_desc, player);
+ w = AllocateWindowDescFront(&_other_player_roadveh_desc, (station << 16) | player);
}
if (w) {
w->caption_color = player;
diff --git a/ship_cmd.c b/ship_cmd.c
index 578fce38a..2c91fda3c 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -870,8 +870,7 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
- _vehicle_sort_dirty[VEHSHIP] = true; // build a ship
- InvalidateWindow(WC_SHIPS_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
}
@@ -894,8 +893,7 @@ int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (flags & DC_EXEC) {
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
- _vehicle_sort_dirty[VEHSHIP] = true; // sell a ship
- InvalidateWindow(WC_SHIPS_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
DeleteVehicle(v);
diff --git a/ship_gui.c b/ship_gui.c
index f13c752ff..1e5eaca68 100644
--- a/ship_gui.c
+++ b/ship_gui.c
@@ -866,157 +866,122 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
}
}
-// used to get a sorted list of the vehicles
-static SortStruct _ship_sort[NUM_NORMAL_VEHICLES];
-static uint16 _num_ship_sort[MAX_PLAYERS];
-static void GlobalSortShipList()
-{
- const Vehicle *v;
- uint16 *i;
- uint32 n = 0;
-
- // reset #-of ships to 0 because ++ is used for value-assignment
- for (i = _num_ship_sort; i != endof(_num_ship_sort); i++) {*i = 0;}
-
- FOR_ALL_VEHICLES(v) {
- if(v->type == VEH_Ship) {
- _ship_sort[n].index = v->index;
- _ship_sort[n++].owner = v->owner;
- _num_ship_sort[v->owner]++; // add number of ships of player
- }
- }
-
- // create cumulative ship-ownership
- // ships are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
- for (i = &_num_ship_sort[1]; i != endof(_num_ship_sort); i++) {*i += *(i-1);}
-
- qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter); // sort by owner
-
- // since indexes are messed up after adding/removing a station, mark all lists dirty
- memset(_ship_sort_dirty, true, sizeof(_ship_sort_dirty));
- _vehicle_sort_dirty[VEHSHIP] = false;
-
- DEBUG(misc, 1) ("Resorting global ships list...");
-}
-
-static void MakeSortedShipList(byte owner)
-{
- SortStruct *firstelement;
- uint32 n = 0;
-
- if (owner == 0) { // first element starts at 0th element and has n elements as described above
- firstelement = &_ship_sort[0];
- n = _num_ship_sort[0];
- } else { // nth element starts at the end of the previous one, and has n elements as described above
- firstelement = &_ship_sort[_num_ship_sort[owner-1]];
- n = _num_ship_sort[owner] - _num_ship_sort[owner-1];
- }
-
- _internal_sort_order = _ship_sort_order[owner];
- _internal_name_sorter_id = STR_SV_SHIP_NAME;
- _last_vehicle_idx = 0; // used for "cache" in namesorting
- qsort(firstelement, n, sizeof(_ship_sort[0]), _vehicle_sorter[_ship_sort_type[owner]]);
-
- _ship_sort_dirty[owner] = false;
+static Widget _player_ships_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
+{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
- DEBUG(misc, 1) ("Resorting Ships list player %d...", owner+1);
-}
+static Widget _other_player_ships_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL},
+{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
+{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WIDGETS_END},
+};
static void PlayerShipsWndProc(Window *w, WindowEvent *e)
{
+ int station = (int)w->window_number >> 16;
+ int owner = w->window_number & 0xff;
+ vehiclelist_d *vl = &WP(w, vehiclelist_d);
+
switch(e->event) {
case WE_PAINT: {
- uint32 i;
- const byte window_number = (byte)w->window_number;
+ int x = 2;
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int max;
+ int i;
- if (_ship_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
- w->disabled_state |= (1 << 2);
+ BuildVehicleList(vl, VEH_Ship, owner, station);
+ SortVehicleList(vl);
- // resort shipps window if roadvehicles have been added/removed
- if (_vehicle_sort_dirty[VEHSHIP])
- GlobalSortShipList();
+ SetVScrollCount(w, vl->list_length);
- if (_ship_sort_dirty[window_number]) {
- MakeSortedShipList(window_number);
- /* reset sorting timeout */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
- }
-
- // ships are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 ships
- i = (window_number == 0) ? 0 : _num_ship_sort[window_number-1];
- SetVScrollCount(w, _num_ship_sort[window_number] - i);
+ // disable 'Sort By' tooltip on Unsorted sorting criteria
+ if (vl->sort_type == SORT_BY_UNSORTED)
+ w->disabled_state |= (1 << 2);
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(window_number);
- /* Company Name -- (###) Ships */
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- SetDParam(2, w->vscroll.count);
+ const Player *p = DEREF_PLAYER(owner);
+ /* XXX hack */
+ if (station == -1) {
+ /* Company Name -- (###) Trains */
+ SetDParam(0, p->name_1);
+ SetDParam(1, p->name_2);
+ SetDParam(2, w->vscroll.count);
+ _player_ships_widgets[1].unkA = STR_9805_SHIPS;
+ _other_player_ships_widgets[1].unkA = STR_9805_SHIPS;
+ } else {
+ /* Station Name -- (###) Trains */
+ SetDParam(0, DEREF_STATION(station)->index);
+ SetDParam(1, w->vscroll.count);
+ _player_ships_widgets[1].unkA = STR_SCHEDULED_SHIPS;
+ _other_player_ships_widgets[1].unkA = STR_SCHEDULED_SHIPS;
+ }
DrawWindowWidgets(w);
}
/* draw sorting criteria string */
- DrawString(85, 15, _vehicle_sort_listing[_ship_sort_type[window_number]], 0x10);
- /* draw arrow pointing up/down for ascending/descending soring */
- DoDrawString(_ship_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 69, 15, 0x10);
-
- /* draw the ship vehicles */
- {
- Vehicle *v;
- int n = 0;
- const int x = 2; // offset from left side of widget
- int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget
- i += w->vscroll.pos; // offset from sorted ship list of current player
-
- while (i < _num_ship_sort[window_number]) {
- StringID str;
- v = DEREF_VEHICLE(_ship_sort[i].index);
-
- assert(v->type == VEH_Ship && v->owner == window_number);
+ DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10);
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DoDrawString(
+ vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
+
+ max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
+ for (i = w->vscroll.pos; i < max; ++i) {
+ Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index);
+ StringID str;
- DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
+ assert(v->type == VEH_Ship);
- SetDParam(0, v->unitnumber);
- if (IsShipDepotTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
+ DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y + 13);
- SetDParam(0, v->profit_this_year);
- SetDParam(1, v->profit_last_year);
- DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+ SetDParam(0, v->unitnumber);
+ if (IsShipDepotTile(v->tile))
+ str = STR_021F;
+ else
+ str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+ DrawString(x, y + 2, str, 0);
- if (v->string_id != STR_SV_SHIP_NAME) {
- SetDParam(0, v->string_id);
- DrawString(x+12, y, STR_01AB, 0);
- }
+ SetDParam(0, v->profit_this_year);
+ SetDParam(1, v->profit_last_year);
+ DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
- DrawSmallShipSchedule(v, x+138, y);
+ if (v->string_id != STR_SV_SHIP_NAME) {
+ SetDParam(0, v->string_id);
+ DrawString(x + 12, y, STR_01AB, 0);
+ }
+ DrawSmallShipSchedule(v, x + 138, y);
- y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
- i++; // next ship
- if (++n == w->vscroll.cap) { break;} // max number of ships in the window
- }
+ y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
}
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 2: /* Flip sorting method ascending/descending */
- _ship_sort_order[(byte)w->window_number] ^= 1;
- _ship_sort_dirty[(byte)w->window_number] = true;
+ vl->flags ^= VL_DESC;
+ vl->flags |= VL_RESORT;
SetWindowDirty(w);
break;
case 3: case 4:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, _ship_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 4, 0);
return;
case 6: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG;
@@ -1026,15 +991,13 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
id_v += w->vscroll.pos;
{
- const byte owner = (byte)w->window_number;
Vehicle *v;
- id_v += (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list
- if (id_v >= _num_ship_sort[owner]) { return;} // click out of vehicle bound
+ if (id_v >= vl->list_length) return; // click out of list bound
- v = DEREF_VEHICLE(_ship_sort[id_v].index); // add the offset id_x to that
+ v = DEREF_VEHICLE(vl->sort_list[id_v].index);
- assert(v->type == VEH_Ship && v->owner == owner);
+ assert(v->type == VEH_Ship);
ShowShipViewWindow(v);
}
@@ -1060,48 +1023,37 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- if (_ship_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
- _ship_sort_dirty[(byte)w->window_number] = true;
-
- _ship_sort_type[(byte)w->window_number] = e->dropdown.index;
-
- if (_ship_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
- w->disabled_state &= ~(1 << 2);
-
+ if (vl->sort_type != e->dropdown.index) {
+ // value has changed -> resort
+ vl->flags |= VL_RESORT;
+ vl->sort_type = e->dropdown.index;
+
+ // enable 'Sort By' if a sorter criteria is chosen
+ if (vl->sort_type != SORT_BY_UNSORTED)
+ w->disabled_state &= ~(1 << 2);
+ }
SetWindowDirty(w);
break;
+
case WE_CREATE: /* set up resort timer */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
+ vl->sort_list = NULL;
+ vl->flags = VL_REBUILD;
+ vl->sort_type = SORT_BY_UNSORTED;
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
break;
+
case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
- if (--w->custom[0] == 0) {
- w->custom[0] = DAY_TICKS;
- if (--w->custom[1] == 0) {
- w->custom[1] = PERIODIC_RESORT_DAYS;
- _ship_sort_dirty[(byte)w->window_number] = true;
- DEBUG(misc, 1) ("Periodic resort Ships list player %d...", w->window_number+1);
- SetWindowDirty(w);
- }
+ if (--vl->resort_timer == 0) {
+ DEBUG(misc, 1) ("Periodic resort ships list player %d station %d",
+ owner, station);
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->flags |= VL_RESORT;
+ SetWindowDirty(w);
}
break;
}
}
-static const Widget _player_ships_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
-{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
static const WindowDesc _player_ships_desc = {
-1, -1, 260, 182,
WC_SHIPS_LIST,0,
@@ -1110,18 +1062,6 @@ static const WindowDesc _player_ships_desc = {
PlayerShipsWndProc
};
-static const Widget _other_player_ships_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL},
-{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
-{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WIDGETS_END},
-};
-
static const WindowDesc _other_player_ships_desc = {
-1, -1, 260, 170,
WC_SHIPS_LIST,0,
@@ -1131,14 +1071,14 @@ static const WindowDesc _other_player_ships_desc = {
};
-void ShowPlayerShips(int player)
+void ShowPlayerShips(int player, int station)
{
Window *w;
if ( player == _local_player) {
- w = AllocateWindowDescFront(&_player_ships_desc, player);
+ w = AllocateWindowDescFront(&_player_ships_desc, (station << 16) | player);
} else {
- w = AllocateWindowDescFront(&_other_player_ships_desc, player);
+ w = AllocateWindowDescFront(&_other_player_ships_desc, (station << 16) | player);
}
if (w) {
w->caption_color = w->window_number;
diff --git a/station_gui.c b/station_gui.c
index beaa84d68..39b1a424f 100644
--- a/station_gui.c
+++ b/station_gui.c
@@ -264,9 +264,13 @@ static const Widget _station_view_expanded_widgets[] = {
{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, STR_NULL},
{ WWT_IMGBTN, 14, 0, 248, 66, 197, 0x0, STR_NULL},
-{ WWT_PUSHTXTBTN, 14, 0, 82, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
-{ WWT_PUSHTXTBTN, 14, 83, 165, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO},
-{ WWT_PUSHTXTBTN, 14, 166, 248, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
+{ WWT_PUSHTXTBTN, 14, 0, 63, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
+{ WWT_PUSHTXTBTN, 14, 64, 128, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO},
+{ WWT_PUSHTXTBTN, 14, 129, 192, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
+{ WWT_PUSHTXTBTN, 14, 193, 206, 198, 209, STR_TRAIN, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 207, 220, 198, 209, STR_LORRY, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 221, 234, 198, 209, STR_PLANE, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 235, 248, 198, 209, STR_SHIP, STR_NULL },
{ WIDGETS_END},
};
@@ -277,9 +281,13 @@ static const Widget _station_view_widgets[] = {
{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_IMGBTN, 14, 0, 248, 66, 97, 0x0, STR_NULL},
{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, STR_NULL},
-{ WWT_PUSHTXTBTN, 14, 0, 82, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
-{ WWT_PUSHTXTBTN, 14, 83, 165, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS},
-{ WWT_PUSHTXTBTN, 14, 166, 248, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
+{ WWT_PUSHTXTBTN, 14, 0, 63, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
+{ WWT_PUSHTXTBTN, 14, 64, 128, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS},
+{ WWT_PUSHTXTBTN, 14, 129, 192, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
+{ WWT_PUSHTXTBTN, 14, 193, 206, 98, 109, STR_TRAIN, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 207, 220, 98, 109, STR_LORRY, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 221, 234, 98, 109, STR_PLANE, STR_NULL },
+{ WWT_PUSHTXTBTN, 14, 235, 248, 98, 109, STR_SHIP, STR_NULL },
{ WIDGETS_END},
};
@@ -310,6 +318,13 @@ static void DrawStationViewWindow(Window *w)
SetVScrollCount(w, num);
w->disabled_state = st->owner == _local_player ? 0 : (1 << 8);
+
+ if (!(st->facilities & FACIL_TRAIN)) SETBIT(w->disabled_state, 9);
+ if (!(st->facilities & FACIL_TRUCK_STOP) &&
+ !(st->facilities & FACIL_BUS_STOP)) SETBIT(w->disabled_state, 10);
+ if (!(st->facilities & FACIL_AIRPORT)) SETBIT(w->disabled_state, 11);
+ if (!(st->facilities & FACIL_DOCK)) SETBIT(w->disabled_state, 12);
+
SetDParam(0, st->index);
SetDParam(1, st->facilities);
DrawWindowWidgets(w);
@@ -443,6 +458,30 @@ static void StationViewWndProc(Window *w, WindowEvent *e)
SetDParam(1, st->town->townnameparts);
ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number);
} break;
+
+ case 9: {
+ const Station *st = DEREF_STATION(w->window_number);
+ ShowPlayerTrains(st->owner, w->window_number);
+ break;
+ }
+
+ case 10: {
+ const Station *st = DEREF_STATION(w->window_number);
+ ShowPlayerRoadVehicles(st->owner, w->window_number);
+ break;
+ }
+
+ case 11: {
+ const Station *st = DEREF_STATION(w->window_number);
+ ShowPlayerAircraft(st->owner, w->window_number);
+ break;
+ }
+
+ case 12: {
+ const Station *st = DEREF_STATION(w->window_number);
+ ShowPlayerShips(st->owner, w->window_number);
+ break;
+ }
}
break;
@@ -456,6 +495,17 @@ static void StationViewWndProc(Window *w, WindowEvent *e)
st = DEREF_STATION(w->window_number);
DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
} break;
+
+ case WE_DESTROY: {
+ WindowNumber wno =
+ (w->window_number << 16) | DEREF_STATION(w->window_number)->owner;
+
+ DeleteWindowById(WC_TRAINS_LIST, wno);
+ DeleteWindowById(WC_ROADVEH_LIST, wno);
+ DeleteWindowById(WC_SHIPS_LIST, wno);
+ DeleteWindowById(WC_AIRCRAFT_LIST, wno);
+ break;
+ }
}
}
diff --git a/train_cmd.c b/train_cmd.c
index 1b79001fc..256ccb6d5 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -499,8 +499,7 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
NormalizeTrainVehInDepot(v);
InvalidateWindow(WC_VEHICLE_DEPOT, tile);
- _vehicle_sort_dirty[VEHTRAIN] = true; // build a trainengine
- InvalidateWindow(WC_TRAINS_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
}
}
@@ -811,8 +810,7 @@ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// always redraw the depot. maybe redraw train list
InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
if (first->subtype == 0) {
- _vehicle_sort_dirty[VEHTRAIN] = true; // sell a wagon / locomotive
- InvalidateWindow(WC_TRAINS_LIST, first->owner);
+ RebuildVehicleLists();
}
// when selling an attached locomotive. we need to delete its window.
if (v->subtype == 0) {
@@ -2254,8 +2252,7 @@ static void DeleteLastWagon(Vehicle *v)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
- _vehicle_sort_dirty[VEHTRAIN] = true; // remove crashed train
- InvalidateWindow(WC_TRAINS_LIST, v->owner);
+ RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
BeginVehicleMove(v);
diff --git a/train_gui.c b/train_gui.c
index 79ba7d27f..e05778ea9 100644
--- a/train_gui.c
+++ b/train_gui.c
@@ -10,6 +10,7 @@
#include "command.h"
#include "player.h"
#include "engine.h"
+#include "vehicle_gui.h"
int _traininfo_vehicle_pitch = 0;
@@ -39,7 +40,7 @@ void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2)
found = GetLastVehicleInChain(found);
// put the new wagon at the end of the loco.
DoCommandP(0, _new_wagon_id | (found->index<<16), 0, NULL, CMD_MOVE_RAIL_VEHICLE);
- _vehicle_sort_dirty[VEHTRAIN] = true;
+ RebuildVehicleLists();
}
}
@@ -1166,155 +1167,125 @@ void ShowTrainDetailsWindow(Vehicle *v)
WP(w,traindetails_d).tab = 0;
}
-// used to get a sorted list of the vehicles
-static SortStruct _train_sort[NUM_NORMAL_VEHICLES];
-static uint16 _num_train_sort[MAX_PLAYERS];
-static void GlobalSortTrainList()
-{
- const Vehicle *v;
- uint16 *i;
- uint32 n = 0;
-
- // reset #-of trains to 0 because ++ is used for value-assignment
- for (i = _num_train_sort; i != endof(_num_train_sort); i++) {*i = 0;}
-
- FOR_ALL_VEHICLES(v) {
- if(v->type == VEH_Train && v->subtype == 0) {
- _train_sort[n].index = v->index;
- _train_sort[n++].owner = v->owner;
- _num_train_sort[v->owner]++; // add number of trains of player
- }
- }
-
- // create cumulative train-ownership
- // trains are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
- for (i = &_num_train_sort[1]; i != endof(_num_train_sort); i++) {*i += *(i-1);}
-
- qsort(_train_sort, n, sizeof(_train_sort[0]), GeneralOwnerSorter); // sort by owner
-
- // since indexes are messed up after adding/removing a station, mark all lists dirty
- memset(_train_sort_dirty, true, sizeof(_train_sort_dirty));
- _vehicle_sort_dirty[VEHTRAIN] = false;
-
- DEBUG(misc, 1) ("Resorting global trains list...");
-}
-
-static void MakeSortedTrainList(byte owner)
-{
- SortStruct *firstelement;
- uint32 n = 0;
-
- if (owner == 0) { // first element starts at 0th element and has n elements as described above
- firstelement = &_train_sort[0];
- n = _num_train_sort[0];
- } else { // nth element starts at the end of the previous one, and has n elements as described above
- firstelement = &_train_sort[_num_train_sort[owner-1]];
- n = _num_train_sort[owner] - _num_train_sort[owner-1];
- }
-
- _internal_sort_order = _train_sort_order[owner];
- _internal_name_sorter_id = STR_SV_TRAIN_NAME;
- _last_vehicle_idx = 0; // used for "cache" in namesorting
- qsort(firstelement, n, sizeof(_train_sort[0]), _vehicle_sorter[_train_sort_type[owner]]);
-
- _train_sort_dirty[owner] = false;
+static Widget _player_trains_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
+{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN, 14, 0, 161, 208, 219, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES},
+{ WWT_PANEL, 14, 162, 324, 208, 219, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
- DEBUG(misc, 1) ("Resorting Trains list player %d...", owner+1);
-}
+static Widget _other_player_trains_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
+{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP},
+{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP},
+{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL},
+{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
+{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WIDGETS_END},
+};
static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
{
+ int station = (int)w->window_number >> 16;
+ int owner = w->window_number & 0xff;
+ vehiclelist_d *vl = &WP(w, vehiclelist_d);
+
switch(e->event) {
case WE_PAINT: {
- uint32 i;
- const byte window_number = (byte)w->window_number;
-
- if (_train_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
- w->disabled_state |= (1 << 2);
+ int x = 2;
+ int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+ int max;
+ int i;
- // resort trains window if roadvehicles have been added/removed
- if (_vehicle_sort_dirty[VEHTRAIN])
- GlobalSortTrainList();
+ BuildVehicleList(vl, VEH_Train, owner, station);
+ SortVehicleList(vl);
- if (_train_sort_dirty[window_number]) {
- MakeSortedTrainList(window_number);
- /* reset sorting timeout */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
- }
+ SetVScrollCount(w, vl->list_length);
- // Trains are stored as a cummulative index, eg 25, 41, 43. This means
- // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 trains
- i = (window_number == 0) ? 0 : _num_train_sort[window_number-1];
- SetVScrollCount(w, _num_train_sort[window_number] - i);
+ // disable 'Sort By' tooltip on Unsorted sorting criteria
+ if (vl->sort_type == SORT_BY_UNSORTED)
+ w->disabled_state |= (1 << 2);
/* draw the widgets */
{
- Player *p = DEREF_PLAYER(window_number);
- /* Company Name -- (###) Trains */
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- SetDParam(2, w->vscroll.count);
+ const Player *p = DEREF_PLAYER(owner);
+ /* XXX hack */
+ if (station == -1) {
+ /* Company Name -- (###) Trains */
+ SetDParam(0, p->name_1);
+ SetDParam(1, p->name_2);
+ SetDParam(2, w->vscroll.count);
+ _player_trains_widgets[1].unkA = STR_881B_TRAINS;
+ _other_player_trains_widgets[1].unkA = STR_881B_TRAINS;
+ } else {
+ /* Station Name -- (###) Trains */
+ SetDParam(0, DEREF_STATION(station)->index);
+ SetDParam(1, w->vscroll.count);
+ _player_trains_widgets[1].unkA = STR_SCHEDULED_TRAINS;
+ _other_player_trains_widgets[1].unkA = STR_SCHEDULED_TRAINS;
+ }
DrawWindowWidgets(w);
}
/* draw sorting criteria string */
- DrawString(85, 15, _vehicle_sort_listing[_train_sort_type[window_number]], 0x10);
- /* draw arrow pointing up/down for ascending/descending soring */
- DoDrawString(_train_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 69, 15, 0x10);
+ DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10);
+ /* draw arrow pointing up/down for ascending/descending sorting */
+ DoDrawString(
+ vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10);
- /* draw the trains */
- {
- Vehicle *v;
- int n = 0;
- const int x = 2; // offset from left side of widget
- int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget
- i += w->vscroll.pos; // offset from sorted trains list of current player
+ max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length);
+ for (i = w->vscroll.pos; i < max; ++i) {
+ Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index);
+ StringID str;
- while (i < _num_train_sort[window_number]) {
- StringID str;
- v = DEREF_VEHICLE(_train_sort[i].index);
+ assert(v->type == VEH_Train && v->owner == owner);
- assert(v->type == VEH_Train && v->subtype == 0 && v->owner == window_number);
+ DrawTrainImage(
+ v, x + 21, y + 6 + _traininfo_vehicle_pitch, 10, 0, INVALID_VEHICLE);
+ DrawVehicleProfitButton(v, x, y + 13);
- DrawTrainImage(v, x + 21, y + 6 + _traininfo_vehicle_pitch, 10, 0, INVALID_VEHICLE);
- DrawVehicleProfitButton(v, x, y+13);
-
- SetDParam(0, v->unitnumber);
- if (IsTrainDepotTile(v->tile)) {
- str = STR_021F;
- } else {
- str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
- }
- DrawString(x, y+2, str, 0);
-
- SetDParam(0, v->profit_this_year);
- SetDParam(1, v->profit_last_year);
- DrawString(x + 21, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
-
- if (v->string_id != STR_SV_TRAIN_NAME) {
- SetDParam(0, v->string_id);
- DrawString(x+21, y, STR_01AB, 0);
- }
-
- y += PLY_WND_PRC__SIZE_OF_ROW_SMALL;
- i++; // next train
- if (++n == w->vscroll.cap) { break;} // max number of trains in the window
+ SetDParam(0, v->unitnumber);
+ if (IsTrainDepotTile(v->tile))
+ str = STR_021F;
+ else
+ str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+ DrawString(x, y + 2, str, 0);
+
+ SetDParam(0, v->profit_this_year);
+ SetDParam(1, v->profit_last_year);
+ DrawString(x + 21, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
+
+ if (v->string_id != STR_SV_TRAIN_NAME) {
+ SetDParam(0, v->string_id);
+ DrawString(x + 21, y, STR_01AB, 0);
}
+
+ y += PLY_WND_PRC__SIZE_OF_ROW_SMALL;
}
- } break;
+ break;
+ }
case WE_CLICK: {
switch(e->click.widget) {
case 2: /* Flip sorting method ascending/descending */
- _train_sort_order[(byte)w->window_number] ^= 1;
- _train_sort_dirty[(byte)w->window_number] = true;
+ vl->flags ^= VL_DESC;
+ vl->flags |= VL_RESORT;
SetWindowDirty(w);
break;
+
case 3: case 4:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, _train_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 4, 0);
return;
+
case 6: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL;
@@ -1323,13 +1294,11 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
id_v += w->vscroll.pos;
{
- const byte owner = (byte)w->window_number;
Vehicle *v;
- id_v += (owner == 0) ? 0 : _num_train_sort[owner - 1]; // first element in list
- if (id_v >= _num_train_sort[owner]) { return;} // click out of vehicle bound
+ if (id_v >= vl->list_length) return; // click out of list bound
- v = DEREF_VEHICLE(_train_sort[id_v].index); // add the offset id_x to that
+ v = DEREF_VEHICLE(vl->sort_list[id_v].index);
assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner);
@@ -1357,48 +1326,37 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- if (_train_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
- _train_sort_dirty[(byte)w->window_number] = true;
-
- _train_sort_type[(byte)w->window_number] = e->dropdown.index;
-
- if (_train_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
- w->disabled_state &= ~(1 << 2);
-
+ if (vl->sort_type != e->dropdown.index) {
+ // value has changed -> resort
+ vl->flags |= VL_RESORT;
+ vl->sort_type = e->dropdown.index;
+
+ // enable 'Sort By' if a sorter criteria is chosen
+ if (vl->sort_type != SORT_BY_UNSORTED)
+ w->disabled_state &= ~(1 << 2);
+ }
SetWindowDirty(w);
break;
+
case WE_CREATE: /* set up resort timer */
- w->custom[0] = DAY_TICKS;
- w->custom[1] = PERIODIC_RESORT_DAYS;
+ vl->sort_list = NULL;
+ vl->flags = VL_REBUILD;
+ vl->sort_type = SORT_BY_UNSORTED;
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
break;
+
case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
- if (--w->custom[0] == 0) {
- w->custom[0] = DAY_TICKS;
- if (--w->custom[1] == 0) {
- w->custom[1] = PERIODIC_RESORT_DAYS;
- _train_sort_dirty[(byte)w->window_number] = true;
- DEBUG(misc, 1) ("Periodic resort Trains list player %d...", w->window_number+1);
- SetWindowDirty(w);
- }
+ if (--vl->resort_timer == 0) {
+ DEBUG(misc, 1) ("Periodic resort trains list player %d station %d",
+ owner, station);
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->flags |= VL_RESORT;
+ SetWindowDirty(w);
}
break;
}
}
-static const Widget _player_trains_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
-{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PUSHTXTBTN, 14, 0, 161, 208, 219, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES},
-{ WWT_PANEL, 14, 162, 324, 208, 219, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
static const WindowDesc _player_trains_desc = {
-1, -1, 325, 220,
WC_TRAINS_LIST,0,
@@ -1407,18 +1365,6 @@ static const WindowDesc _player_trains_desc = {
PlayerTrainsWndProc
};
-static const Widget _other_player_trains_widgets[] = {
-{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP},
-{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP},
-{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP},
-{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL},
-{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
-{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WIDGETS_END},
-};
-
static const WindowDesc _other_player_trains_desc = {
-1, -1, 325, 208,
WC_TRAINS_LIST,0,
@@ -1427,14 +1373,14 @@ static const WindowDesc _other_player_trains_desc = {
PlayerTrainsWndProc
};
-void ShowPlayerTrains(int player)
+void ShowPlayerTrains(int player, int station)
{
Window *w;
if (player == _local_player) {
- w = AllocateWindowDescFront(&_player_trains_desc, player);
+ w = AllocateWindowDescFront(&_player_trains_desc, (station << 16) | player);
} else {
- w = AllocateWindowDescFront(&_other_player_trains_desc, player);
+ w = AllocateWindowDescFront(&_other_player_trains_desc, (station << 16) | player);
}
if (w) {
w->caption_color = w->window_number;
diff --git a/vehicle.c b/vehicle.c
index 1701ff70e..145d22561 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -1449,10 +1449,7 @@ int32 CmdNameVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
StringID old_str = v->string_id;
v->string_id = str;
DeleteName(old_str);
- _train_sort_dirty[v->owner] = true;
- _aircraft_sort_dirty[v->owner] = true;
- _ship_sort_dirty[v->owner] = true;
- _road_sort_dirty[v->owner] = true;
+ ResortVehicleLists();
MarkWholeScreenDirty();
} else {
DeleteName(str);
diff --git a/vehicle_gui.c b/vehicle_gui.c
index 9e2edc6cb..5dd09734d 100644
--- a/vehicle_gui.c
+++ b/vehicle_gui.c
@@ -2,6 +2,7 @@
#include "ttd.h"
#include "table/strings.h"
#include "vehicle.h"
+#include "window.h"
VehicleSortListingTypeFunctions * const _vehicle_sorter[] = {
&VehicleUnsortedSorter,
@@ -28,14 +29,109 @@ const StringID _vehicle_sort_listing[] = {
INVALID_STRING_ID
};
+void RebuildVehicleLists(void)
+{
+ Window *w;
+
+ for (w = _windows; w != _last_window; ++w)
+ switch (w->window_class) {
+ case WC_TRAINS_LIST:
+ case WC_ROADVEH_LIST:
+ case WC_SHIPS_LIST:
+ case WC_AIRCRAFT_LIST:
+ WP(w, vehiclelist_d).flags |= VL_REBUILD;
+ SetWindowDirty(w);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void ResortVehicleLists(void)
+{
+ Window *w;
+
+ for (w = _windows; w != _last_window; ++w)
+ switch (w->window_class) {
+ case WC_TRAINS_LIST:
+ case WC_ROADVEH_LIST:
+ case WC_SHIPS_LIST:
+ case WC_AIRCRAFT_LIST:
+ WP(w, vehiclelist_d).flags |= VL_RESORT;
+ SetWindowDirty(w);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
+{
+ SortStruct sort_list[NUM_NORMAL_VEHICLES];
+ int subtype = (type != VEH_Aircraft) ? 0 : 2;
+ int n = 0;
+ int i;
+
+ if (!(vl->flags & VL_REBUILD)) return;
+
+ DEBUG(misc, 1) ("Building vehicle list for player %d station %d...",
+ owner, station);
+
+ if (station != -1) {
+ const Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->type == type && v->subtype <= subtype) {
+ const Order *ord;
+ for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord)
+ if (ord->type == OT_GOTO_STATION && ord->station == station) {
+ sort_list[n].index = v - _vehicles;
+ sort_list[n].owner = v->owner;
+ ++n;
+ break;
+ }
+ }
+ }
+ } else {
+ const Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->type == type && v->subtype <= subtype && v->owner == owner) {
+ sort_list[n].index = v - _vehicles;
+ sort_list[n].owner = v->owner;
+ ++n;
+ }
+ }
+ }
+
+ vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0])); /* XXX unchecked malloc */
+ vl->list_length = n;
+
+ for (i = 0; i < n; ++i)
+ vl->sort_list[i] = sort_list[i];
+
+ vl->flags &= ~VL_REBUILD;
+ vl->flags |= VL_RESORT;
+}
+
+void SortVehicleList(vehiclelist_d *vl)
+{
+ if (!(vl->flags & VL_RESORT)) return;
+
+ _internal_sort_order = vl->flags & VL_DESC;
+ _internal_name_sorter_id = STR_SV_TRAIN_NAME;
+ _last_vehicle_idx = 0; // used for "cache" in namesorting
+ qsort(vl->sort_list, vl->list_length, sizeof(vl->sort_list[0]),
+ _vehicle_sorter[vl->sort_type]);
+
+ vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+ vl->flags &= ~VL_RESORT;
+}
+
+
/* General Vehicle GUI based procedures that are independent of vehicle types */
void InitializeVehiclesGuiList()
{
- memset(_train_sort_dirty, true, sizeof(_train_sort_dirty));
- memset(_aircraft_sort_dirty, true, sizeof(_aircraft_sort_dirty));
- memset(_ship_sort_dirty, true, sizeof(_ship_sort_dirty));
- memset(_road_sort_dirty, true, sizeof(_road_sort_dirty));
- memset(_vehicle_sort_dirty, true, sizeof(_vehicle_sort_dirty));
}
// draw the vehicle profit button in the vehicle list window.
diff --git a/vehicle_gui.h b/vehicle_gui.h
index 3883967f0..9339d4647 100644
--- a/vehicle_gui.h
+++ b/vehicle_gui.h
@@ -1,10 +1,18 @@
#ifndef VEHICLE_GUI_H
#define VEHICLE_GUI_H
+struct vehiclelist_d;
+
void DrawVehicleProfitButton(Vehicle *v, int x, int y);
void InitializeVehiclesGuiList();
/* sorter stuff */
+void RebuildVehicleLists(void);
+void ResortVehicleLists(void);
+
+void BuildVehicleList(struct vehiclelist_d *vl, int type, int owner, int station);
+void SortVehicleList(struct vehiclelist_d *vl);
+
typedef struct SortStruct { // store owner through sorting process
uint32 index;
byte owner;
@@ -42,24 +50,6 @@ enum VehicleSortTypes {
VEHAIRCRAFT = 3
};
-VARDEF bool _vehicle_sort_dirty[4]; // global sort, vehicles added/removed (4 types of vehicles)
-
-VARDEF bool _train_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria)
-VARDEF byte _train_sort_type[MAX_PLAYERS]; // different criteria for sorting
-VARDEF bool _train_sort_order[MAX_PLAYERS]; // sort descending/ascending
-
-VARDEF bool _aircraft_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria)
-VARDEF byte _aircraft_sort_type[MAX_PLAYERS]; // different criteria for sorting
-VARDEF bool _aircraft_sort_order[MAX_PLAYERS]; // sort descending/ascending
-
-VARDEF bool _ship_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria)
-VARDEF byte _ship_sort_type[MAX_PLAYERS]; // different criteria for sorting
-VARDEF bool _ship_sort_order[MAX_PLAYERS]; // sort descending/ascending
-
-VARDEF bool _road_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria)
-VARDEF byte _road_sort_type[MAX_PLAYERS]; // different criteria for sorting
-VARDEF bool _road_sort_order[MAX_PLAYERS]; // sort descending/ascending
-
enum {
PLY_WND_PRC__OFFSET_TOP_WIDGET = 26,
PLY_WND_PRC__SIZE_OF_ROW_SMALL = 26,
diff --git a/water_cmd.c b/water_cmd.c
index 9a7db7ad3..8682e5911 100644
--- a/water_cmd.c
+++ b/water_cmd.c
@@ -533,8 +533,7 @@ static void FloodVehicle(Vehicle *v)
v->vehstatus |= VS_CRASHED;
v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast
- _vehicle_sort_dirty[VEHROAD] = true;
- InvalidateWindow(WC_ROADVEH_LIST, v->owner);
+ RebuildVehicleLists();
}
else if (v->type == VEH_Train) {
@@ -550,8 +549,7 @@ static void FloodVehicle(Vehicle *v)
v = u;
v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast
- _vehicle_sort_dirty[VEHTRAIN] = true;
- InvalidateWindow(WC_TRAINS_LIST, v->owner);
+ RebuildVehicleLists();
} else
return;
diff --git a/window.h b/window.h
index ee955ddf9..68a29fa73 100644
--- a/window.h
+++ b/window.h
@@ -1,6 +1,8 @@
#ifndef WINDOW_H
#define WINDOW_H
+#include "vehicle_gui.h"
+
typedef union WindowEvent WindowEvent;
//typedef void WindowProc(Window *w, int event, int wparam, long lparam);
@@ -288,6 +290,21 @@ typedef struct {
NewsItem *ni;
} news_d;
+typedef enum VehicleListFlags {
+ VL_DESC = 0x01,
+ VL_RESORT = 0x02,
+ VL_REBUILD = 0x04
+} VehicleListFlags;
+
+typedef struct vehiclelist_d {
+ SortStruct *sort_list;
+ uint16 list_length;
+ byte sort_type;
+ VehicleListFlags flags;
+ uint16 resort_timer;
+} vehiclelist_d;
+assert_compile(sizeof(vehiclelist_d) <= WINDOW_CUSTOM_SIZE);
+
enum WindowEvents {
WE_CLICK = 0,
WE_PAINT = 1,