From c55970331258396348fe2239c5119156a31543a6 Mon Sep 17 00:00:00 2001 From: rubidium Date: Mon, 19 Mar 2007 19:42:40 +0000 Subject: [PATCH] (svn r9345) [0.5] -Backport from trunk (r9277, r9337, r9338): - Fix: shared orders got messed up when the 'first' trains got removed in the depot (r9277) - Fix: assert() when you removed the orders of a shared list while having the shared order vehicle list open (r9337) - Fix: close the Shared Order Vehicle List if you remove the shared link with only 2 vehicles (r9338) --- order_cmd.c | 44 +++++++++++++++++++++++++++++--------------- train_cmd.c | 51 +++++++++++++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 37 deletions(-) diff --git a/order_cmd.c b/order_cmd.c index a69ad443a5..612f3e465f 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -455,6 +455,24 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags) return 0; } +/** + * Remove the VehicleList that shows all the vehicles with the same shared + * orders. + */ +static void RemoveSharedOrderVehicleList(Vehicle *v) +{ + WindowClass window_class; + + switch (v->type) { + default: NOT_REACHED(); + case VEH_Train: window_class = WC_TRAINS_LIST; break; + case VEH_Road: window_class = WC_ROADVEH_LIST; break; + case VEH_Ship: window_class = WC_SHIPS_LIST; break; + case VEH_Aircraft: window_class = WC_AIRCRAFT_LIST; break; + } + DeleteWindowById(window_class, (v->orders->index << 16) | (v->type << 11) | VLW_SHARED_ORDERS | v->owner); +} + /** Delete an order from the orderlist of a vehicle. * @param tile unused * @param p1 the ID of the vehicle @@ -489,6 +507,10 @@ int32 CmdDeleteOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) order = GetVehicleOrder(v, sel_ord + 1); SwapOrders(v->orders, order); } else { + /* XXX -- The system currently can't handle a shared-order vehicle list + * open when there aren't any orders in the list, so close the window + * in this case. Of course it needs a better fix later */ + RemoveSharedOrderVehicleList(v); /* Last item, so clean the list */ v->orders = NULL; } @@ -1120,7 +1142,7 @@ void DeleteVehicleOrders(Vehicle *v) /* If we have a shared order-list, don't delete the list, but just remove our pointer */ if (IsOrderListShared(v)) { - const Vehicle *u = v; + Vehicle *u = v; v->orders = NULL; v->num_orders = 0; @@ -1137,6 +1159,10 @@ void DeleteVehicleOrders(Vehicle *v) v->prev_shared = NULL; v->next_shared = NULL; + /* If we are the only one left in the Shared Order Vehicle List, + * remove it, as we are no longer a Shared Order Vehicle */ + if (u->prev_shared == NULL && u->next_shared == NULL) RemoveSharedOrderVehicleList(u); + /* We only need to update this-one, because if there is a third * vehicle which shares the same order-list, nothing will change. If * this is the last vehicle, the last line of the order-window @@ -1148,23 +1174,11 @@ void DeleteVehicleOrders(Vehicle *v) /* Remove the orders */ cur = v->orders; + /* Delete the vehicle list of shared orders, if any */ + if (cur != NULL) RemoveSharedOrderVehicleList(v); v->orders = NULL; v->num_orders = 0; - if (cur != NULL) { - /* Delete the vehicle list of shared orders, if any */ - int window_type = 0; - - switch (v->type) { - case VEH_Train: window_type = WC_TRAINS_LIST; break; - case VEH_Road: window_type = WC_ROADVEH_LIST; break; - case VEH_Ship: window_type = WC_SHIPS_LIST; break; - case VEH_Aircraft: window_type = WC_AIRCRAFT_LIST; break; - default: NOT_REACHED(); - } - DeleteWindowById(window_type, (cur->index << 16) | (v->type << 11) | VLW_SHARED_ORDERS | v->owner); - } - while (cur != NULL) { next = cur->next; DeleteOrder(cur); diff --git a/train_cmd.c b/train_cmd.c index 1754dd45a2..30def7e74f 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -1386,30 +1386,37 @@ int32 CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) for (tmp = first; tmp != NULL; tmp = tmp->next) tmp->first = NULL; /* 2.2 If there are wagons present after the deleted front engine, check - * if the second wagon (which will be first) is an engine. If it is one, - * promote it as a new train, retaining the unitnumber, orders */ - if (new_f != NULL) { - if (IsTrainEngine(new_f)) { - switch_engine = true; - /* Copy important data from the front engine */ - new_f->unitnumber = first->unitnumber; - new_f->current_order = first->current_order; - new_f->cur_order_index = first->cur_order_index; - new_f->orders = first->orders; - if (first->prev_shared != NULL) { - first->prev_shared->next_shared = new_f; - new_f->prev_shared = first->prev_shared; - } + * if the second wagon (which will be first) is an engine. If it is one, + * promote it as a new train, retaining the unitnumber, orders */ + if (new_f != NULL && IsTrainEngine(new_f)) { + switch_engine = true; + /* Copy important data from the front engine */ + new_f->unitnumber = first->unitnumber; + new_f->current_order = first->current_order; + new_f->cur_order_index = first->cur_order_index; + new_f->orders = first->orders; + new_f->num_orders = first->num_orders; - if (first->next_shared != NULL) { - first->next_shared->prev_shared = new_f; - new_f->next_shared = first->next_shared; - } - - new_f->num_orders = first->num_orders; - first->orders = NULL; // XXX - to not to delete the orders */ - if (IsLocalPlayer()) ShowTrainViewWindow(new_f); + if (first->prev_shared != NULL) { + first->prev_shared->next_shared = new_f; + new_f->prev_shared = first->prev_shared; } + + if (first->next_shared != NULL) { + first->next_shared->prev_shared = new_f; + new_f->next_shared = first->next_shared; + } + + /* + * Remove all order information from the front train, to + * prevent the order and the shared order list to be + * destroyed by Destroy/DeleteVehicle. + */ + first->orders = NULL; + first->prev_shared = NULL; + first->next_shared = NULL; + + if (IsLocalPlayer()) ShowTrainViewWindow(new_f); } }