(svn r2087) Show also the modified filenames along each change in svn log. Prevents enraging Darkvater, and we show the commit messages along changed files everywhere else too (on IRC and in mail).
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "strings.h"
#include "table/strings.h"
#include "window.h"
#include "gui.h"
#include "station.h"
#include "gfx.h"
#include "player.h"
#include "town.h"
#include "command.h"
static void StationsWndShowStationRating(int x, int y, int type, uint acceptance, int rating)
{
static const byte _rating_colors[NUM_CARGO] = {152,32,15,174,208,194,191,55,184,10,191,48};
int color = _rating_colors[type];
uint w;
if (acceptance > 575)
acceptance = 575;
acceptance = (acceptance + 7) >> 3;
/* draw cargo */
if ( (w=acceptance>>3) != 0) {
GfxFillRect(x, y, x+w-1, y+6, color);
x += w;
}
if ( (w=acceptance&7) != 0) {
if (w==7) w--;
GfxFillRect(x, y+(w-1), x, y+6, color);
}
x -= (acceptance>>3);
DrawString(x+1, y, _cargoc.names_short[type], 0x10);
/* draw green/red ratings bar */
GfxFillRect(x+1, y+8, x+7, y+8, 0xB8);
rating = (rating >> 5);
if (rating != 0) {
GfxFillRect(x+1, y+8, x+rating, y+8, 0xD0);
}
}
static uint16 _num_station_sort[MAX_PLAYERS];
static char _bufcache[64];
static uint16 _last_station_idx;
static int CDECL StationNameSorter(const void *a, const void *b)
{
char buf1[64];
Station *st;
const SortStruct *cmp1 = (const SortStruct*)a;
const SortStruct *cmp2 = (const SortStruct*)b;
st = GetStation(cmp1->index);
SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts);
GetString(buf1, st->string_id);
if ( cmp2->index != _last_station_idx) {
_last_station_idx = cmp2->index;
st = GetStation(cmp2->index);
SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts);
GetString(_bufcache, st->string_id);
}
return strcmp(buf1, _bufcache); // sort by name
}
static void GlobalSortStationList(void)
{
const Station *st;
uint32 n = 0;
uint16 *i;
// reset #-of stations to 0 because ++ is used for value-assignment
memset(_num_station_sort, 0, sizeof(_num_station_sort));
/* Create array for sorting */
_station_sort = realloc(_station_sort, GetStationPoolSize() * sizeof(_station_sort[0]));
if (_station_sort == NULL)
error("Could not allocate memory for the station-sorting-list");
FOR_ALL_STATIONS(st) {
if(st->xy && st->owner != OWNER_NONE) {
_station_sort[n].index = st->index;
_station_sort[n++].owner = st->owner;
_num_station_sort[st->owner]++; // add number of stations of player
}
}
// create cumulative station-ownership
// stations 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_station_sort[1]; i != endof(_num_station_sort); i++) {*i += *(i-1);}
qsort(_station_sort, n, sizeof(_station_sort[0]), GeneralOwnerSorter); // sort by owner
// since indexes are messed up after adding/removing a station, mark all lists dirty
memset(_station_sort_dirty, true, sizeof(_station_sort_dirty));
_global_station_sort_dirty = false;
DEBUG(misc, 1) ("Resorting global station list...");
}
static void MakeSortedStationList(byte owner)
{
SortStruct *firstelement;
uint32 n = 0;
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];
}
_last_station_idx = 0; // used for "cache" in namesorting
qsort(firstelement, n, sizeof(_station_sort[0]), StationNameSorter); // sort by name
_station_sort_dirty[owner] = false;
DEBUG(misc, 1) ("Resorting Stations list player %d...", owner+1);
}
static void PlayerStationsWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT: {
uint32 i;
const byte window_number = (byte)w->window_number;
// resort station window if stations have been added/removed
if (_global_station_sort_dirty)
GlobalSortStationList();
if (_station_sort_dirty[window_number]) { // resort in case of a station rename.
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 = (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(window_number);
SetDParam(0, p->name_1);
SetDParam(1, p->name_2);
SetDParam(2, w->vscroll.count);
DrawWindowWidgets(w);
}
{
byte p = 0;
Station *st;
int x,xb = 2;
int y = 16; // offset from top of widget
int j;
if (w->vscroll.count == 0) { // player has no stations
DrawString(xb, y, STR_304A_NONE, 0);
return;
}
i += w->vscroll.pos; // offset from sorted station list of current player
assert(i < _num_station_sort[window_number]); // at least one station must exist
while (i < _num_station_sort[window_number]) { // do until max number of stations of owner
st = GetStation(_station_sort[i].index);
assert(st->xy && st->owner == window_number);
SetDParam(0, st->index);
SetDParam(1, st->facilities);
x = DrawString(xb, y, STR_3049_0, 0) + 5;
// show cargo waiting and station ratings
for(j=0; j!=NUM_CARGO; j++) {
int acc = (st->goods[j].waiting_acceptance & 0xFFF);
if (acc != 0) {
StationsWndShowStationRating(x, y, j, acc, st->goods[j].rating);
x += 10;
}
}
y += 10;
i++; // next station
if (++p == w->vscroll.cap) { break;} // max number of stations in 1 window
}
}
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 3: {
uint32 id_v = (e->click.pt.y - 15) / 10;
if (id_v >= w->vscroll.cap) { return;} // click out of bounds
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 = GetStation(_station_sort[id_v].index);
assert(st->xy && st->owner == owner);
ScrollMainWindowToTile(st->xy);
}
} break;
}
} break;
case WE_4:
WP(w,plstations_d).refresh_counter++;
if (WP(w,plstations_d).refresh_counter==5) {
WP(w,plstations_d).refresh_counter = 0;
SetWindowDirty(w);
}
break;
case WE_RESIZE:
w->vscroll.cap += e->sizing.diff.y / 10;
break;
}
}
static const Widget _player_stations_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 345, 0, 13, STR_3048_STATIONS, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_LR, 14, 346, 357, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_PANEL, RESIZE_RB, 14, 0, 345, 14, 137, 0x0, STR_3057_STATION_NAMES_CLICK_ON},
{ WWT_SCROLLBAR, RESIZE_LRB, 14, 346, 357, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 346, 357, 126, 137, 0x0, STR_RESIZE_BUTTON},
{ WIDGETS_END},
};
static const WindowDesc _player_stations_desc = {
-1, -1, 358, 138,
WC_STATION_LIST,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_player_stations_widgets,
PlayerStationsWndProc
};
void ShowPlayerStations(int player)
{
Window *w;
w = AllocateWindowDescFront(&_player_stations_desc, player);
if (w) {
w->caption_color = (byte)w->window_number;
w->vscroll.cap = 12;
w->resize.step_height = 10;
w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
}
}
static const Widget _station_view_expanded_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 236, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 14, 237, 248, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 236, 14, 65, 0x0, STR_NULL},
{ WWT_SCROLLBAR, RESIZE_NONE, 14, 237, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 248, 66, 197, 0x0, STR_NULL},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 63, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 64, 128, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 129, 192, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 193, 206, 198, 209, STR_TRAIN, STR_SCHEDULED_TRAINS_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 207, 220, 198, 209, STR_LORRY, STR_SCHEDULED_ROAD_VEHICLES_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 221, 234, 198, 209, STR_PLANE, STR_SCHEDULED_AIRCRAFT_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 235, 248, 198, 209, STR_SHIP, STR_SCHEDULED_SHIPS_TIP },
{ WIDGETS_END},
};
static const Widget _station_view_widgets[] = {
{ WWT_TEXTBTN, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 236, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 14, 237, 248, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 236, 14, 65, 0x0, STR_NULL},
{ WWT_SCROLLBAR, RESIZE_NONE, 14, 237, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 248, 66, 97, 0x0, STR_NULL},
{ WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 63, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 64, 128, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 129, 192, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 193, 206, 98, 109, STR_TRAIN, STR_SCHEDULED_TRAINS_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 207, 220, 98, 109, STR_LORRY, STR_SCHEDULED_ROAD_VEHICLES_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 221, 234, 98, 109, STR_PLANE, STR_SCHEDULED_AIRCRAFT_TIP },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 235, 248, 98, 109, STR_SHIP, STR_SCHEDULED_SHIPS_TIP },
{ WIDGETS_END},
};
static void DrawStationViewWindow(Window *w)
{
Station *st;
int i;
int num;
int x,y;
int pos;
StringID str;
uint16 station_id;
station_id = (uint16)w->window_number;
st = GetStation(w->window_number);
num = 1;
for(i=0; i!=NUM_CARGO; i++) {
if ((st->goods[i].waiting_acceptance & 0xFFF) != 0) {
num++;
if (st->goods[i].enroute_from != station_id)
num++;
}
}
SetVScrollCount(w, num);
w->disabled_state = st->owner == _local_player ? 0 : (1 << 9);
if (!(st->facilities & FACIL_TRAIN)) SETBIT(w->disabled_state, 10);
if (!(st->facilities & FACIL_TRUCK_STOP) &&
!(st->facilities & FACIL_BUS_STOP)) SETBIT(w->disabled_state, 11);
if (!(st->facilities & FACIL_AIRPORT)) SETBIT(w->disabled_state, 12);
if (!(st->facilities & FACIL_DOCK)) SETBIT(w->disabled_state, 13);
SetDParam(0, st->index);
SetDParam(1, st->facilities);
DrawWindowWidgets(w);
x = 2;
y = 15;
pos = w->vscroll.pos;
if (--pos < 0) {
str = STR_00D0_NOTHING;
for(i=0; i!=NUM_CARGO; i++)
if (st->goods[i].waiting_acceptance & 0xFFF)
str = STR_EMPTY;
SetDParam(0, str);
DrawString(x, y, STR_0008_WAITING, 0);
y += 10;
}
i = 0;
do {
uint waiting = (st->goods[i].waiting_acceptance & 0xFFF);
if (waiting == 0)
continue;
num = (waiting + 5) / 10;
if (num != 0) {
int cur_x = x;
num = min(num, 23);
do {
DrawSprite(_cargoc.sprites[i], cur_x, y);
cur_x += 10;
} while (--num);
}
if ( st->goods[i].enroute_from == station_id) {
if (--pos < 0) {
SetDParam(1, waiting);
SetDParam(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32));
DrawStringRightAligned(x + 234, y, STR_0009, 0);
y += 10;
}
} else {
/* enroute */
if (--pos < 0) {
SetDParam(1, waiting);
SetDParam(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32));
DrawStringRightAligned(x + 234, y, STR_000A_EN_ROUTE_FROM, 0);
y += 10;
}
if (pos > -5 && --pos < 0) {
SetDParam(0, st->goods[i].enroute_from);
DrawStringRightAligned(x + 234, y, STR_000B, 0);
y += 10;
}
}
} while (pos > -5 && ++i != 12);
if (IsWindowOfPrototype(w, _station_view_widgets)) {
char *b = _userstring;
b = InlineString(b, STR_000C_ACCEPTS);
for (i = 0; i != NUM_CARGO; i++) {
if (b >= endof(_userstring) - 5 - 1) break;
if (st->goods[i].waiting_acceptance & 0x8000) {
b = InlineString(b, _cargoc.names_s[i]);
*b++ = ',';
*b++ = ' ';
}
}
if (b == &_userstring[3]) {
b = InlineString(b, STR_00D0_NOTHING);
*b++ = '\0';
} else {
b[-2] = '\0';
}
DrawStringMultiLine(2, 67, STR_SPEC_USERSTRING, 245);
} else {
DrawString(2, 67, STR_3034_LOCAL_RATING_OF_TRANSPORT, 0);
y = 77;
for(i=0; i!=NUM_CARGO; i++) {
if (st->goods[i].enroute_from != INVALID_STATION) {
SetDParam(0, _cargoc.names_s[i]);
SetDParam(2, st->goods[i].rating * 101 >> 8);
SetDParam(1, STR_3035_APPALLING + (st->goods[i].rating >> 5));
DrawString(8, y, STR_303D, 0);
y += 10;
}
}
}
}
static void StationViewWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT:
DrawStationViewWindow(w);
break;
case WE_CLICK:
switch(e->click.widget) {
case 7:
ScrollMainWindowToTile(GetStation(w->window_number)->xy);
break;
case 8:
SetWindowDirty(w);
/* toggle height/widget set */
if (IsWindowOfPrototype(w, _station_view_expanded_widgets)) {
AssignWidgetToWindow(w, _station_view_widgets);
w->height = 110;
} else {
AssignWidgetToWindow(w, _station_view_expanded_widgets);
w->height = 210;
}
SetWindowDirty(w);
break;
case 9: {
Station *st = GetStation(w->window_number);
SetDParam(0, st->town->townnametype);
SetDParam(1, st->town->townnameparts);
ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number);
} break;
case 10: {
const Station *st = GetStation(w->window_number);
ShowPlayerTrains(st->owner, w->window_number);
break;
}
case 11: {
const Station *st = GetStation(w->window_number);
ShowPlayerRoadVehicles(st->owner, w->window_number);
break;
}
case 12: {
const Station *st = GetStation(w->window_number);
ShowPlayerAircraft(st->owner, w->window_number);
break;
}
case 13: {
const Station *st = GetStation(w->window_number);
ShowPlayerShips(st->owner, w->window_number);
break;
}
}
break;
case WE_ON_EDIT_TEXT: {
Station *st;
const char *b = e->edittext.str;
if (*b == 0)
return;
memcpy(_decode_parameters, b, 32);
st = GetStation(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) | GetStation(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;
}
}
}
static const WindowDesc _station_view_desc = {
-1, -1, 249, 110,
WC_STATION_VIEW,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
_station_view_widgets,
StationViewWndProc
};
void ShowStationViewWindow(int station)
{
Window *w;
byte color;
w = AllocateWindowDescFront(&_station_view_desc, station);
if (w) {
color = GetStation(w->window_number)->owner;
if (color != 0x10)
w->caption_color = color;
w->vscroll.cap = 5;
}
}