diff --git a/aircraft_gui.c b/aircraft_gui.c index 8829b3139c..6716bbfdcf 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -892,7 +892,6 @@ static void MakeSortedAircraftList(byte owner) // 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);} - // sort by owner, then only subsort the requested owner-vehicles qsort(_aircraft_sort, n, sizeof(_aircraft_sort[0]), GeneralOwnerSorter); @@ -964,6 +963,8 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) StringID str; v = DEREF_VEHICLE(_aircraft_sort[i].index); + assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == window_number); + DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE); DrawVehicleProfitButton(v, x, y+13); @@ -1005,22 +1006,22 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) ShowDropDownMenu(w, _vehicle_sort_listing, _aircraft_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4 return; case 6: { /* Matrix to show vehicles */ - int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG; + uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG; - if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds + if (id_v >= w->vscroll.cap) { return;} // click out of bounds id_v += w->vscroll.pos; { - byte owner = (byte)w->window_number; - uint16 adder = (owner == 0) ? 0 : _num_aircraft_sort[owner - 1]; // first element in list + 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 + adder >= _num_aircraft_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= _num_aircraft_sort[owner]) { return;} // click out of vehicle bound - v = DEREF_VEHICLE(_aircraft_sort[adder+id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(_aircraft_sort[id_v].index); // add the offset id_x to that - assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner && v->owner == _aircraft_sort[adder+id_v].owner); + assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner); ShowAircraftViewWindow(v); } diff --git a/roadveh_gui.c b/roadveh_gui.c index 7e6e444129..70c3cee417 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -731,7 +731,6 @@ static void MakeSortedRoadList(byte owner) // 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);} - // sort by owner, then only subsort the requested owner-vehicles qsort(_road_sort, n, sizeof(_road_sort[0]), GeneralOwnerSorter); @@ -803,6 +802,8 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) StringID str; v = DEREF_VEHICLE(_road_sort[i].index); + assert(v->type == VEH_Road && v->owner == window_number); + DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE); DrawVehicleProfitButton(v, x, y+13); @@ -841,22 +842,22 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) ShowDropDownMenu(w, _vehicle_sort_listing, _road_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4 return; case 6: { /* Matrix to show vehicles */ - int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL; + uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL; - if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds + if (id_v >= w->vscroll.cap) { return;} // click out of bounds id_v += w->vscroll.pos; { - byte owner = (byte)w->window_number; - uint16 adder = (owner == 0) ? 0 : _num_road_sort[owner - 1]; // first element in list + 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 + adder >= _num_road_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= _num_road_sort[owner]) { return;} // click out of vehicle bound - v = DEREF_VEHICLE(_road_sort[adder+id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(_road_sort[id_v].index); // add the offset id_x to that - assert(v->type == VEH_Road && v->owner == owner && v->owner == _road_sort[adder+id_v].owner); + assert(v->type == VEH_Road && v->owner == owner); ShowRoadVehViewWindow(v); } diff --git a/ship_gui.c b/ship_gui.c index a43db3295b..0ecb620227 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -895,7 +895,6 @@ static void MakeSortedShiptList(byte owner) // 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);} - // sort by owner, then only subsort the requested owner-vehicles qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter); @@ -967,6 +966,8 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) StringID str; v = DEREF_VEHICLE(_ship_sort[i].index); + assert(v->type == VEH_Ship && v->owner == window_number); + DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); DrawVehicleProfitButton(v, x, y+13); @@ -1008,22 +1009,22 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) ShowDropDownMenu(w, _vehicle_sort_listing, _ship_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4 return; case 6: { /* Matrix to show vehicles */ - int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG; + uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG; - if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds + if (id_v >= w->vscroll.cap) { return;} // click out of bounds id_v += w->vscroll.pos; { - byte owner = (byte)w->window_number; - uint16 adder = (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list + 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 + adder >= _num_ship_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= _num_ship_sort[owner]) { return;} // click out of vehicle bound - v = DEREF_VEHICLE(_ship_sort[adder+id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(_ship_sort[id_v].index); // add the offset id_x to that - assert(v->type == VEH_Ship && v->owner == owner && v->owner == _ship_sort[adder+id_v].owner); + assert(v->type == VEH_Ship && v->owner == owner); ShowShipViewWindow(v); } diff --git a/station_gui.c b/station_gui.c index be2cb28cad..0df8c17dd4 100644 --- a/station_gui.c +++ b/station_gui.c @@ -74,10 +74,11 @@ static int CDECL StationNameSorter(const void *a, const void *b) return strcmp(buf1, _bufcache); // sort by name } -static void MakeSortedStationList() +static void MakeSortedStationList(byte owner) { + SortStruct *firstelement; Station *st; - uint16 n = 0; + uint32 n = 0; uint16 *i; // reset to 0 just to be sure for (i = _num_station_sort; i != endof(_num_station_sort); i++) {*i = 0;} @@ -95,12 +96,20 @@ static void MakeSortedStationList() // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 for (i = &_num_station_sort[1]; i != endof(_num_station_sort); i++) {*i += *(i-1);} - _last_station_idx = 255; // used for "cache" + _last_station_idx = 0; // used for "cache" // sort by owner, then only subsort the requested owner-vehicles qsort(_station_sort, n, sizeof(_station_sort[0]), GeneralOwnerSorter); - qsort(_station_sort, n, sizeof(_station_sort[0]), StationNameSorter); + if (owner == 0) { // first element starts at 0th element and has n elements as described above + firstelement = &_station_sort[0]; + n = _num_station_sort[0]; + } else { // nth element starts at the end of the previous one, and has n elements as described above + firstelement = &_station_sort[_num_station_sort[owner-1]]; + n = _num_station_sort[owner] - _num_station_sort[owner-1]; + } + + qsort(firstelement, n, sizeof(_station_sort[0]), StationNameSorter); DEBUG(misc, 1) ("Resorting Stations list..."); } @@ -109,20 +118,22 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - byte i; + uint32 i; + const byte window_number = (byte)w->window_number; + if (_station_sort_dirty) { _station_sort_dirty = false; - MakeSortedStationList(); + MakeSortedStationList(window_number); } // stations are stored as a cummulative index, eg 25, 41, 43. This means // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 stations - i = (byte)(w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1]; - SetVScrollCount(w, _num_station_sort[w->window_number] - i); + i = (window_number == 0) ? 0 : _num_station_sort[window_number-1]; + SetVScrollCount(w, _num_station_sort[window_number] - i); /* draw widgets, with player's name in the caption */ { - Player *p = DEREF_PLAYER(w->window_number); + Player *p = DEREF_PLAYER(window_number); SET_DPARAM16(0, p->name_1); SET_DPARAM32(1, p->name_2); SET_DPARAM16(2, w->vscroll.count); @@ -142,11 +153,13 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e) } i += w->vscroll.pos; // offset from sorted station list of current player - assert(i < _num_station_sort[w->window_number]); // at least one station must exist + assert(i < _num_station_sort[window_number]); // at least one station must exist - while (i < _num_station_sort[w->window_number]) { // do until max number of stations of owner + while (i < _num_station_sort[window_number]) { // do until max number of stations of owner st = DEREF_STATION(_station_sort[i].index); + assert(st->xy && st->owner == window_number); + SET_DPARAM16(0, st->index); SET_DPARAM8(1, st->facilities); x = DrawString(xb, y, STR_3049_0, 0) + 5; @@ -168,16 +181,24 @@ static void PlayerStationsWndProc(Window *w, WindowEvent *e) case WE_CLICK: { switch(e->click.widget) { case 2: { - uint y = (e->click.pt.y - 15) / 10; - uint16 p; + uint32 id_v = (e->click.pt.y - 15) / 10; - if (!IS_INT_INSIDE(y, 0, 12)) { return;} + if (id_v >= w->vscroll.cap) { return;} // click out of bounds - // get the p-th OUR station from globally sorted list - p = y + w->vscroll.pos; - p += (w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1]; // get offset of first station in list - if (p < _num_station_sort[w->window_number]) { - ScrollMainWindowToTile(DEREF_STATION(_station_sort[p].index)->xy); + id_v += w->vscroll.pos; + + { + const byte owner = (byte)w->window_number; + Station *st; + id_v += (owner == 0) ? 0 : _num_station_sort[owner - 1]; // first element in list + + if (id_v >= _num_station_sort[owner]) { return;} // click out of station bound + + st = DEREF_STATION(_station_sort[id_v].index); + + assert(st->xy && st->owner == owner); + + ScrollMainWindowToTile(st->xy); } } break; } diff --git a/town_gui.c b/town_gui.c index 8d6cfbd5d9..7d8ed4c3b8 100644 --- a/town_gui.c +++ b/town_gui.c @@ -390,7 +390,7 @@ static void MakeSortedTownList() FOR_ALL_TOWNS(t) if(t->xy) _town_sort[n++] = t->index; _num_town_sort = n; - _last_town_idx = 255; // used for "cache" + _last_town_idx = 0; // used for "cache" qsort(_town_sort, n, sizeof(_town_sort[0]), _town_sort_order & 2 ? TownPopSorter : TownNameSorter); DEBUG(misc, 1) ("Resorting Towns list..."); @@ -401,66 +401,72 @@ static void TownDirectoryWndProc(Window *w, WindowEvent *e) { switch(e->event) { case WE_PAINT: { - int n; - uint p; - Town *t; if (_town_sort_dirty) { _town_sort_dirty = false; MakeSortedTownList(); } - w->vscroll.count = _num_town_sort; + SetVScrollCount(w, _num_town_sort); DrawWindowWidgets(w); - DoDrawString(_town_sort_order & 1 ? "\xAA" : "\xA0", _town_sort_order <= 1 ? 88 : 187, 15, 0x10); + DoDrawString(_town_sort_order & 1 ? "\xAA" : "\xA0", (_town_sort_order <= 1) ? 88 : 187, 15, 0x10); - p = w->vscroll.pos; - n = 0; + { + Town *t; + int n = 0; + uint16 i = w->vscroll.pos; + int y = 28; - while (p < _num_town_sort) { - t = DEREF_TOWN(_town_sort[p]); - SET_DPARAM16(0, t->index); - SET_DPARAM32(1, t->population); - DrawString(2, 28+n*10, STR_2057, 0); - p++; - if (++n == 16) - break; + while (i < _num_town_sort) { + t = DEREF_TOWN(_town_sort[i]); + + assert(t->xy); + + SET_DPARAM16(0, t->index); + SET_DPARAM32(1, t->population); + DrawString(2, y, STR_2057, 0); + + y += 10; + i++; + if (++n == w->vscroll.cap) { break;} // max number of towns in 1 window + } } } break; case WE_CLICK: switch(e->click.widget) { - case 2: { - _town_sort_order = _town_sort_order==0 ? 1 : 0; + case 2: { /* Sort by Name ascending/descending */ + _town_sort_order = (_town_sort_order == 0) ? 1 : 0; _town_sort_dirty = true; SetWindowDirty(w); } break; - case 3: { - _town_sort_order = _town_sort_order==2 ? 3 : 2; + case 3: { /* Sort by Population ascending/descending */ + _town_sort_order = (_town_sort_order == 2) ? 3 : 2; _town_sort_dirty = true; SetWindowDirty(w); } break; - case 4: { - int y = (e->click.pt.y - 28) / 10; - byte p; - Town *t; + case 4: { /* Click on Town Matrix */ + uint16 id_v = (e->click.pt.y - 28) / 10; - if (!IS_INT_INSIDE(y, 0, 16)) - return; - p = y + w->vscroll.pos; - if (p < _num_town_sort) { - t = DEREF_TOWN(_town_sort[p]); + if (id_v >= w->vscroll.cap) { return;} // click out of bounds + + id_v += w->vscroll.pos; + + if (id_v >= _num_town_sort) { return;} // click out of town bounds + + { + Town *t = DEREF_TOWN(_town_sort[id_v]); + assert(t->xy); + ScrollMainWindowToTile(t->xy); } - break; - } + } break; } break; - case WE_4: SetWindowDirty(w); break; diff --git a/train_gui.c b/train_gui.c index 9e09d0a001..a08aec3c18 100644 --- a/train_gui.c +++ b/train_gui.c @@ -1164,7 +1164,6 @@ static void MakeSortedTrainList(byte owner) // 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);} - // sort by owner, then only subsort the requested owner-vehicles qsort(_train_sort, n, sizeof(_train_sort[0]), GeneralOwnerSorter); @@ -1236,6 +1235,8 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) StringID str; v = DEREF_VEHICLE(_train_sort[i].index); + assert(v->type == VEH_Train && v->subtype == 0 && v->owner == window_number); + DrawTrainImage(v, x + 21, y + 6, 10, 0, INVALID_VEHICLE); DrawVehicleProfitButton(v, x, y+13); @@ -1274,22 +1275,22 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) ShowDropDownMenu(w, _vehicle_sort_listing, _train_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4 return; case 6: { /* Matrix to show vehicles */ - int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL; + uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL; - if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds + if (id_v >= w->vscroll.cap) { return;} // click out of bounds id_v += w->vscroll.pos; { - byte owner = (byte)w->window_number; - uint16 adder = (owner == 0) ? 0 : _num_train_sort[owner - 1]; // first element in list + 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 + adder >= _num_train_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= _num_train_sort[owner]) { return;} // click out of vehicle bound - v = DEREF_VEHICLE(_train_sort[adder+id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(_train_sort[id_v].index); // add the offset id_x to that - assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner && v->owner == _train_sort[adder+id_v].owner); + assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner); ShowTrainViewWindow(v); }