Merge branch 'master' into jgrpp-beta

# Conflicts:
#	.github/workflows/ci-build.yml
#	CMakeLists.txt
#	src/lang/finnish.txt
#	src/lang/french.txt
#	src/lang/korean.txt
#	src/lang/norwegian_bokmal.txt
#	src/lang/russian.txt
#	src/lang/spanish.txt
#	src/misc_gui.cpp
#	src/newgrf.cpp
pull/332/head
Jonathan G Rennison 3 years ago
commit da282c3ecc

@ -315,6 +315,77 @@ jobs:
cmake --build .
echo "::endgroup::"
msys2:
name: msys2
strategy:
fail-fast: false
matrix:
include:
- msystem: MINGW64
arch: x86_64
- msystem: MINGW32
arch: i686
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
release: false
install: >-
git
make
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-lzo2
mingw-w64-${{ matrix.arch }}-libpng
- name: Install OpenGFX
shell: bash
run: |
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
cd "C:/Users/Public/Documents/OpenTTD/baseset"
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
shell: msys2 {0}
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. -G"MSYS Makefiles"
echo "::endgroup::"
echo "::group::Build"
echo "Running on $(nproc) cores"
cmake --build . -j $(nproc)
echo "::endgroup::"
- name: Test
shell: msys2 {0}
run: |
cd build
ctest -j $(nproc) --timeout 120
check_annotations:
name: Check Annotations
needs:
@ -322,6 +393,7 @@ jobs:
- linux
- macos
- windows
- msys2
if: always() && github.event_name == 'pull_request'

@ -433,6 +433,7 @@ if(WIN32)
-DUNICODE
-D_UNICODE
-DWITH_UNISCRIBE
-DPSAPI_VERSION=1
)
target_link_libraries(openttd
@ -440,6 +441,7 @@ if(WIN32)
winmm
imm32
usp10
psapi
)
endif()

@ -79,7 +79,7 @@ SQInstructionDesc g_InstrDesc[]={
{"_OP_NEWSLOTA"},
{"_OP_SCOPE_END"}
};
#endif
void DumpLiteral(SQObjectPtr &o)
{
switch(type(o)){
@ -90,6 +90,7 @@ void DumpLiteral(SQObjectPtr &o)
default: printf("(%s %p)",GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
}
}
#endif
SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
{

@ -483,7 +483,7 @@ public:
break;
case WID_AP_AIRPORT_LIST: {
int num_clicked = this->vscroll->GetPosition() + (pt.y - this->nested_array[widget]->pos_y) / this->line_height;
int num_clicked = this->vscroll->GetPosition() + (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / this->line_height;
if (num_clicked >= this->vscroll->GetCount()) break;
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(num_clicked);
if (as->IsAvailable()) this->SelectOtherAirport(num_clicked);

@ -1064,7 +1064,7 @@ struct DepotWindow : Window {
this->RaiseWidget(WID_D_SELL);
this->SetWidgetDirty(WID_D_SELL);
}
if (this->nested_array[WID_D_SELL] != nullptr && !this->IsWidgetDisabled(WID_D_SELL_CHAIN)) {
if (this->GetWidget<NWidgetBase>(WID_D_SELL) != nullptr && !this->IsWidgetDisabled(WID_D_SELL_CHAIN)) {
this->RaiseWidget(WID_D_SELL_CHAIN);
this->SetWidgetDirty(WID_D_SELL_CHAIN);
}

@ -53,6 +53,7 @@ public:
void SetDParam(uint n, uint64 v);
void SetDParamStr(uint n, const char *str);
void SetDParamStr(uint n, const std::string &str);
void CopyOutDParams();
};

@ -166,6 +166,16 @@ void ErrorMessageData::SetDParamStr(uint n, const char *str)
this->strings[n] = stredup(str);
}
/**
* Set a rawstring parameter.
* @param n Parameter index
* @param str Raw string
*/
void ErrorMessageData::SetDParamStr(uint n, const std::string &str)
{
this->SetDParamStr(n, str.c_str());
}
/** Define a queue with errors. */
typedef std::list<ErrorMessageData> ErrorList;
/** The actual queue with errors. */

@ -908,6 +908,21 @@ Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
return layout.GetBounds();
}
/**
* Return the string dimension in pixels. The height and width are returned
* in a single Dimension value. TINYFONT, BIGFONT modifiers are only
* supported as the first character of the string. The returned dimensions
* are therefore a rough estimation correct for all the current strings
* but not every possible combination
* @param str string to calculate pixel-width
* @param start_fontsize Fontsize to start the text with
* @return string width and height in pixels
*/
Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize)
{
return GetStringBoundingBox(str.c_str(), start_fontsize);
}
/**
* Get bounding box of a string. Uses parameters set by #SetDParam if needed.
* Has the same restrictions as #GetStringBoundingBox(const char *str, FontSize start_fontsize).

@ -107,6 +107,7 @@ void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width
void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL);
Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize = FS_NORMAL);
Dimension GetStringBoundingBox(StringID strid);
int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL);
int GetStringHeight(StringID str, int maxw);

@ -890,6 +890,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}A oferta do subsídio expirou:{}{}{STRING} de {STRING} para {STRING} agora não irá atrair um subsídio
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsídio removido:{}{} Serviço de {STRING} de {STRING} para {STRING} não é mais subsidiado
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsídio de serviço oferecido:{}{}Primeiro serviço de {STRING} de {STRING} para {STRING} atrairá subsídio de {NUM} anos da autoridade local!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsídio de serviço concedido à {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} pagará 50% extra durante o{P 4 "" s} próximo{P 4 "" s} {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido à {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} pagará o dobro de tarifas durante o{P 4 "" s} próximo{P 4 "" s} {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido à {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} pagará o triplo de tarifas durante o{P 4 "" s} próximo{P 4 "" s} {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido à {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} pagará o quádruplo de tarifas durante o{P 4 "" s} próximo{P 4 "" s} {NUM} ano{P "" s}!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Tráfego caótico em {TOWN}!{}{} Programa de reconstrução rodoviária financiado por {STRING} provoca 6 meses de miséria aos condutores!
STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopólio dos transportes!
@ -1205,6 +1210,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Quebra de veíc
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controla o quanto veículos mal conservados podem quebrar
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador de subsídios: {STRING}
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Define quando é pago por conexões subsidiadas
STR_CONFIG_SETTING_SUBSIDY_DURATION :Duração do subsídio: {STRING}
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Defina por quantos anos o subsídio é concedido
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} ano{P "" s}
STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sem subsídios
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Custos de construção: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Define o nível de construção e custos de compra
STR_CONFIG_SETTING_RECESSIONS :Recessões: {STRING}

@ -887,7 +887,7 @@ STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO :{WHITE}{STATION
STR_NEWS_STATION_NOW_ACCEPTS_CARGO :{WHITE}{STATION} ottaa nyt vastaan {STRING}.
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION} ottaa nyt vastaan {STRING} ja {STRING}.
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tukitarjous päättynyt:{}{}{STRING} välillä {STRING} - {STRING} ei voi enää saada tukea
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Tukitarjous päättynyt:{}{}{STRING} välillä {STRING} {STRING} ei voi enää saada tukea
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Tuki vedetty pois:{}{}{STRING} kuljetuspalvelu välille {STRING}-{STRING} ei ole enää tuettu
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Tuki tarjottu:{}{}Ensimmäinen {STRING}kuljetus välillä {STRING} {STRING} saa {NUM} vuoden mittaisen tuen paikallisviranomaisilta!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Tuki myönnetty yhtiölle {STRING}!{}{}{STRING}kuljetus välillä {STRING} {STRING} tuottaa 50{NBSP}% enemmän seuraavan {NUM} vuoden ajan!

@ -907,6 +907,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionsangebot abgelaufen:{}{}{STRING}transport von {STRING} nach {STRING} wird nicht mehr subventioniert
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionsende:{}{}{STRING}transport von {STRING} nach {STRING} wird nicht mehr subventioniert
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subventionsangebot:{}{}Erster {STRING}transport von {STRING} nach {STRING} wird {NUM} Jahr{P "" e} von den örtlichen Behörden subventioniert!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält für {NUM} Jahr{P "" e} einen 50% höheren Preis!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält für {NUM} Jahr{P "" e} den doppelten Preis!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält für {NUM} Jahr{P "" e} den dreifachen Preis!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention vergeben an {STRING}!{}{}{STRING}transport von {STRING} nach {STRING} erhält für {NUM} Jahr{P "" e} den vierfachen Preis!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Verkehrschaos in {TOWN}!{}{}Straßensanierungsprogramm finanziert durch {STRING} wird 6 Monate lang Verzögerungen im Verkehr bewirken!
STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol!
@ -1222,6 +1227,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Fahrzeugpannen:
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Einstellen, wie oft unzureichend gewartete Fahrzeuge Pannen haben können
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subventions-Multiplikator: {STRING}
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Einstellen, wieviel für subventionierte Verbindungen gezahlt wird
STR_CONFIG_SETTING_SUBSIDY_DURATION :Subventionsdauer: {STRING}
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Die Anzahl der Jahre, für die eine Subvention vergeben wird
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} Jahr{P "" e}
STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Keine Subventionen
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Baukosten: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Höhe der Bau- und Einkaufskosten festlegen
STR_CONFIG_SETTING_RECESSIONS :Rezessionen: {STRING}

@ -890,6 +890,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subsídio expirou:{}{}Ligação de {STRING} d{G 1 e o a os as} {STRING} para{G 2 "" " o" " a" " os" " as"} {STRING} já não será subsidiada.
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsídio retirado:{}{}Ligação de {STRING} d{G 1 e o a os as} {STRING} para{G 2 "" " o" " a" " os" " as"} {STRING} já não é subsidiada.
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsídio de ligação oferecido:{}{}Primeiro serviço de {STRING} de {STRING} para {STRING} atrairá {NUM} ano{P "" s} de subsídio da autoridade local!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} será pago a 50% extra durante {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} será pago a 200% durante {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} será pago a 300% durante {NUM} ano{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsídio de serviço concedido a {STRING}!{}{}Serviço de {STRING} de {STRING} para {STRING} será pago a 400% durante {NUM} ano{P "" s}!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Tráfego caótico em {TOWN}!{}{}Programa de reconstrução de estradas financiado por {STRING} provoca 6 meses de miséria aos condutores!
STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopólio de Transporte!
@ -1205,6 +1210,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Avarias de veí
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controla quão frequentemente veículos inadequadamento mantidos podem avariar
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador de subsídio: {STRING}
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Define quanto é pago para ligações subsidiadas
STR_CONFIG_SETTING_SUBSIDY_DURATION :Duração do subsídio: {STRING}
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Define o número de anos de concessão de um subsídio
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} ano{P "" s}
STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sem subsídios
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Custos de construção: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Configurar o nível de construção e custos de compra
STR_CONFIG_SETTING_RECESSIONS :Recessões: {STRING}

@ -2213,7 +2213,7 @@ STR_NETWORK_ERROR_CLIENT_START :{WHITE}No se pu
STR_NETWORK_ERROR_TIMEOUT :{WHITE}Tiempo de espera agotado en conexión #{NUM}
STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Se ha producido un error de protocolo y la conexión ha sido cerrada
STR_NETWORK_ERROR_BAD_PLAYER_NAME :{WHITE}No se ha establecido tu nombre de jugador. El nombre se puede establecer en la parte superior de la ventana de Multijugador
STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}El nombre de tu servidor no se ha definido. El nombre puede definirse al principio de la ventana de Multijugador
STR_NETWORK_ERROR_BAD_SERVER_NAME :{WHITE}No se ha establecido el nombre de tu servidor. El nombre se puede establecer en la parte superior de la ventana de Multijugador
STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}La versión de este cliente no corresponde con la versión del servidor
STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Contraseña incorrecta
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}El servidor está completo

@ -890,6 +890,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subsidio vencida:{}{}{STRING} de {STRING} a {STRING} ya no está subsidiado
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidio retirado:{}{}El servicio de {STRING} de {STRING} hacia {STRING} ya no está subsidiado
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Se ofrece subsidio.{}{}¡El primer servicio de {STRING} desde {STRING} a {STRING} tendrá subsidio de {NUM} año{P "" s} por parte del ayuntamiento local!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará un 50% extra por {NUM} año{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa doble por {NUM} año{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa triple por {NUM} año{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}¡Subsidio otorgado a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} generará tasa cuádruple por {NUM} año{P "" s}!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}¡Caos por el tráfico en {TOWN}!{}{}¡Obras de reconstrucción de caminos por parte de {STRING} provocan 6 meses de dolores de cabeza a conductores!
STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}¡Monopolio de transportes!
@ -1205,6 +1210,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Averías de veh
STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controlar cada cuánto los vehículos con poco mantenimiento sufren fallas
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador de subsidio: {STRING}
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Establecer cuánto se paga por subsidios conectados
STR_CONFIG_SETTING_SUBSIDY_DURATION :Duración de subsidio: {STRING}
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Años que durará un subsidio otorgado
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} año{P "" s}
STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sin subsidios
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costos de construcción: {STRING}
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Nivel de costos de construcción y adquisición
STR_CONFIG_SETTING_RECESSIONS :Recesiones: {STRING}

@ -2119,7 +2119,9 @@ STR_NETWORK_COMPANY_LIST_CLIENT_LIST :Danh sách máy
STR_NETWORK_COMPANY_LIST_SPECTATE :Xem
# Network client list
STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP :{BLACK}Gia nhập công ty này
STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Cấm
STR_NETWORK_SERVER :Server

@ -34,6 +34,9 @@
#include "table/strings.h"
#include <sstream>
#include <iomanip>
#include "safeguards.h"
/** Method to open the OSK. */
@ -63,16 +66,10 @@ static WindowDesc _land_info_desc(
);
class LandInfoWindow : public Window {
enum LandInfoLines {
LAND_INFO_CENTERED_LINES = 32, ///< Up to 32 centered lines (arbitrary limit)
LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line
LAND_INFO_LINE_END,
};
static const uint LAND_INFO_LINE_BUFF_SIZE = 512;
StringList landinfo_data; ///< Info lines to show.
std::string cargo_acceptance; ///< Centered multi-line string for cargo acceptance.
public:
char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE];
TileIndex tile;
void DrawWidget(const Rect &r, int widget) const override
@ -80,16 +77,14 @@ public:
if (widget != WID_LI_BACKGROUND) return;
uint y = r.top + WD_TEXTPANEL_TOP;
for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) {
if (StrEmpty(this->landinfo_data[i])) break;
for (size_t i = 0; i < this->landinfo_data.size(); i++) {
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER);
y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
if (i == 0) y += 4;
}
if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) {
SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]);
if (!this->cargo_acceptance.empty()) {
SetDParamStr(0, this->cargo_acceptance);
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_TEXTPANEL_BOTTOM, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER);
}
}
@ -99,9 +94,7 @@ public:
if (widget != WID_LI_BACKGROUND) return;
size->height = WD_TEXTPANEL_TOP + WD_TEXTPANEL_BOTTOM;
for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) {
if (StrEmpty(this->landinfo_data[i])) break;
for (size_t i = 0; i < this->landinfo_data.size(); i++) {
uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
size->width = std::max(size->width, width);
@ -109,10 +102,10 @@ public:
if (i == 0) size->height += 4;
}
if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) {
uint width = GetStringBoundingBox(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
if (!this->cargo_acceptance.empty()) {
uint width = GetStringBoundingBox(this->cargo_acceptance).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
size->width = std::max(size->width, std::min(300u, width));
SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]);
SetDParamStr(0, cargo_acceptance);
size->height += GetStringHeight(STR_JUST_RAW_STRING, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT);
}
}
@ -199,13 +192,12 @@ public:
AddAcceptedCargo(tile, acceptance, nullptr);
GetTileDesc(tile, &td);
uint line_nr = 0;
this->landinfo_data.clear();
/* Tiletype */
SetDParam(0, td.dparam[0]);
SetDParam(1, td.dparam[1]);
GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(td.str));
/* Up to four owners */
for (uint i = 0; i < 4; i++) {
@ -213,8 +205,7 @@ public:
SetDParam(0, STR_LAND_AREA_INFORMATION_OWNER_N_A);
if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile);
GetString(this->landinfo_data[line_nr], td.owner_type[i], lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(td.owner_type[i]));
}
/* Cost to clear/revenue when cleared */
@ -234,18 +225,18 @@ public:
SetDParam(0, cost);
}
}
GetString(this->landinfo_data[line_nr], str, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(str));
/* Location */
char tmp[16];
seprintf(tmp, lastof(tmp), "0x%.4X", tile);
std::stringstream tile_ss;
tile_ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << tile; // 0x%.4X
std::string tile_str = tile_ss.str(); // Can't pass it directly to SetDParamStr as the string is only a temporary and would be destructed before the GetString call.
SetDParam(0, TileX(tile));
SetDParam(1, TileY(tile));
SetDParam(2, GetTileZ(tile));
SetDParamStr(3, tmp);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr]));
line_nr++;
SetDParamStr(3, tile_str);
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LANDINFO_COORDS));
/* Local authority */
SetDParam(0, STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE);
@ -253,140 +244,124 @@ public:
SetDParam(0, STR_TOWN_NAME);
SetDParam(1, t->index);
}
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY));
/* Build date */
if (td.build_date != INVALID_DATE) {
SetDParam(0, td.build_date);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_BUILD_DATE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE));
}
/* Station class */
if (td.station_class != STR_NULL) {
SetDParam(0, td.station_class);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_CLASS, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_CLASS));
}
/* Station type name */
if (td.station_name != STR_NULL) {
SetDParam(0, td.station_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_TYPE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_TYPE));
}
/* Airport class */
if (td.airport_class != STR_NULL) {
SetDParam(0, td.airport_class);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_CLASS, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_CLASS));
}
/* Airport name */
if (td.airport_name != STR_NULL) {
SetDParam(0, td.airport_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_NAME, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_NAME));
}
/* Airport tile name */
if (td.airport_tile_name != STR_NULL) {
SetDParam(0, td.airport_tile_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME));
}
/* Rail type name */
if (td.railtype != STR_NULL) {
SetDParam(0, td.railtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_TYPE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_TYPE));
}
/* Rail speed limit */
if (td.rail_speed != 0) {
SetDParam(0, td.rail_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT));
}
/* 2nd Rail type name */
if (td.railtype2 != STR_NULL) {
SetDParam(0, td.railtype2);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_TYPE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_TYPE));
}
/* 2nd Rail speed limit */
if (td.rail_speed2 != 0) {
SetDParam(0, td.rail_speed2);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT));
}
/* Road type name */
if (td.roadtype != STR_NULL) {
SetDParam(0, td.roadtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_TYPE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_TYPE));
}
/* Road speed limit */
if (td.road_speed != 0) {
SetDParam(0, td.road_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT));
}
/* Tram type name */
if (td.tramtype != STR_NULL) {
SetDParam(0, td.tramtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_TYPE, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_TYPE));
}
/* Tram speed limit */
if (td.tram_speed != 0) {
SetDParam(0, td.tram_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT));
}
/* NewGRF name */
if (td.grf != nullptr) {
SetDParamStr(0, td.grf);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_NEWGRF_NAME, lastof(this->landinfo_data[line_nr]));
line_nr++;
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_NEWGRF_NAME));
}
assert(line_nr < LAND_INFO_CENTERED_LINES);
/* Mark last line empty */
this->landinfo_data[line_nr][0] = '\0';
/* Cargo acceptance is displayed in a extra multiline */
char *strp = GetString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE], STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
bool found = false;
std::stringstream line;
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED);
bool found = false;
for (CargoID i = 0; i < NUM_CARGO; ++i) {
if (acceptance[i] > 0) {
/* Add a comma between each item. */
if (found) strp = strecpy(strp, ", ", lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
if (found) line << ", ";
found = true;
/* If the accepted value is less than 8, show it in 1/8:ths */
if (acceptance[i] < 8) {
SetDParam(0, acceptance[i]);
SetDParam(1, CargoSpec::Get(i)->name);
strp = GetString(strp, STR_LAND_AREA_INFORMATION_CARGO_EIGHTS, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_EIGHTS);
} else {
strp = GetString(strp, CargoSpec::Get(i)->name, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]));
line << GetString(CargoSpec::Get(i)->name);
}
}
}
if (!found) this->landinfo_data[LAND_INFO_MULTICENTER_LINE][0] = '\0';
if (found) {
this->cargo_acceptance = line.str();
} else {
this->cargo_acceptance.clear();
}
}
bool IsNewGRFInspectable() const override

@ -20,6 +20,9 @@
#include "os_abstraction.h"
#include "../../string_func.h"
#include <mutex>
#if defined(__MINGW32__)
#include "../../3rdparty/mingw-std-threads/mingw.mutex.h"
#endif
#include "../../safeguards.h"

@ -21,6 +21,9 @@
#include <map>
#include <memory>
#include <thread>
#if defined(__MINGW32__)
#include "3rdparty/mingw-std-threads/mingw.thread.h"
#endif
/** The states of sending the packets. */
enum SendPacketsState {

@ -114,7 +114,7 @@ public:
int skip_sprites; ///< Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file)
/* Currently referenceable spritegroups */
SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1];
const SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1];
/** Clear temporary data before processing the next file in the current loading stage */
void ClearDataForNextFile()
@ -5211,7 +5211,7 @@ static void NewSpriteGroup(ByteReader *buf)
* otherwise it specifies a number of entries, the exact
* meaning depends on the feature
* V feature-specific-data (huge mess, don't even look it up --pasky) */
SpriteGroup *act_group = nullptr;
const SpriteGroup *act_group = nullptr;
uint8 feature = buf->ReadByte();
if (feature >= GSF_END) {
@ -5398,24 +5398,53 @@ static void NewSpriteGroup(ByteReader *buf)
break;
}
assert(RealSpriteGroup::CanAllocateItem());
RealSpriteGroup *group = new RealSpriteGroup();
group->nfo_line = _cur.nfo_line;
act_group = group;
grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u loaded, %u loading",
setid, num_loaded, num_loading);
for (uint i = 0; i < num_loaded; i++) {
if (num_loaded + num_loading == 1) {
/* Avoid creating 'Real' sprite group if only one option. */
uint16 spriteid = buf->ReadWord();
group->loaded.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid));
grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, spriteid);
act_group = CreateGroupFromGroupID(feature, setid, type, spriteid);
grfmsg(8, "NewSpriteGroup: one result, skipping RealSpriteGroup = subset %u", spriteid);
break;
}
std::vector<uint16> loaded;
std::vector<uint16> loading;
for (uint i = 0; i < num_loaded; i++) {
loaded.push_back(buf->ReadWord());
grfmsg(8, "NewSpriteGroup: + rg->loaded[%i] = subset %u", i, loaded[i]);
}
for (uint i = 0; i < num_loading; i++) {
uint16 spriteid = buf->ReadWord();
group->loading.push_back(CreateGroupFromGroupID(feature, setid, type, spriteid));
grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid);
loading.push_back(buf->ReadWord());
grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, loading[i]);
}
if (std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end() &&
std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end() &&
loaded[0] == loading[0])
{
/* Both lists only contain the same value, so don't create 'Real' sprite group */
act_group = CreateGroupFromGroupID(feature, setid, type, loaded[0]);
grfmsg(8, "NewSpriteGroup: same result, skipping RealSpriteGroup = subset %u", loaded[0]);
break;
}
assert(RealSpriteGroup::CanAllocateItem());
RealSpriteGroup *group = new RealSpriteGroup();
group->nfo_line = _cur.nfo_line;
act_group = group;
for (uint16 spriteid : loaded) {
const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid);
group->loaded.push_back(t);
}
for (uint16 spriteid : loading) {
const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid);
group->loading.push_back(t);
}
break;

@ -57,8 +57,6 @@ struct AirportResolverObject : public ResolverObject {
}
}
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override;
uint32 GetDebugID() const override;
};
@ -219,16 +217,6 @@ void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));
}
/* virtual */ const SpriteGroup *AirportResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
/* Airport action 2s should always have only 1 "loaded" state, but some
* times things don't follow the spec... */
if (!group->loaded.empty()) return group->loaded[0];
if (!group->loading.empty()) return group->loading[0];
return nullptr;
}
GrfSpecFeature AirportResolverObject::GetFeature() const
{
return GSF_AIRPORTS;

@ -49,8 +49,6 @@ struct CanalResolverObject : public ResolverObject {
}
}
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override;
uint32 GetDebugID() const override;
};
@ -108,14 +106,6 @@ struct CanalResolverObject : public ResolverObject {
return UINT_MAX;
}
/* virtual */ const SpriteGroup *CanalResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
if (group->loaded.empty()) return nullptr;
return group->loaded[0];
}
GrfSpecFeature CanalResolverObject::GetFeature() const
{
return GSF_CANALS;

@ -19,22 +19,10 @@ struct CargoResolverObject : public ResolverObject {
CargoResolverObject(const CargoSpec *cs, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override;
uint32 GetDebugID() const override;
};
/* virtual */ const SpriteGroup *CargoResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
/* Cargo action 2s should always have only 1 "loaded" state, but some
* times things don't follow the spec... */
if (!group->loaded.empty()) return group->loaded[0];
if (!group->loading.empty()) return group->loading[0];
return nullptr;
}
GrfSpecFeature CargoResolverObject::GetFeature() const
{
return GSF_CARGOES;

@ -954,7 +954,7 @@ struct SpriteAlignerWindow : Window {
switch (widget) {
case WID_SA_CAPTION:
SetDParam(0, this->current_sprite);
SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename().c_str());
SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename());
break;
case WID_SA_OFFSETS_ABS:

@ -63,8 +63,6 @@ struct GenericResolverObject : public ResolverObject {
}
}
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override
{
return (GrfSpecFeature)this->generic_scope.feature;
@ -147,14 +145,6 @@ void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *g
return UINT_MAX;
}
/* virtual */ const SpriteGroup *GenericResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
if (group->loaded.empty()) return nullptr;
return group->loaded[0];
}
/**
* Generic resolver.
* @param ai_callback Callback comes from the AI.

@ -59,13 +59,6 @@
return UINT_MAX;
}
/* virtual */ const SpriteGroup *RailTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
if (!group->loading.empty()) return group->loading[0];
if (!group->loaded.empty()) return group->loaded[0];
return nullptr;
}
GrfSpecFeature RailTypeResolverObject::GetFeature() const
{
return GSF_RAILTYPES;

@ -49,8 +49,6 @@ struct RailTypeResolverObject : public ResolverObject {
}
}
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override;
uint32 GetDebugID() const override;
};

@ -58,13 +58,6 @@
return UINT_MAX;
}
/* virtual */ const SpriteGroup *RoadTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
if (!group->loading.empty()) return group->loading[0];
if (!group->loaded.empty()) return group->loaded[0];
return nullptr;
}
GrfSpecFeature RoadTypeResolverObject::GetFeature() const
{
RoadType rt = GetRoadTypeByLabel(this->roadtype_scope.rti->label, false);

@ -40,8 +40,6 @@ struct RoadTypeResolverObject : public ResolverObject {
}
}
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
GrfSpecFeature GetFeature() const override;
uint32 GetDebugID() const override;
};

@ -127,6 +127,9 @@ static inline uint32 GetVariable(const ResolverObject &object, ScopeResolver *sc
*/
/* virtual */ const SpriteGroup *ResolverObject::ResolveReal(const RealSpriteGroup *group) const
{
if (!group->loaded.empty()) return group->loaded[0];
if (!group->loading.empty()) return group->loading[0];
return nullptr;
}

@ -519,7 +519,7 @@ public:
{
switch (GB(widget, 0, 16)) {
case WID_BO_CLASS_LIST: {
int num_clicked = this->vscroll->GetPosition() + (pt.y - this->nested_array[widget]->pos_y) / this->line_height;
int num_clicked = this->vscroll->GetPosition() + (pt.y - this->GetWidget<NWidgetBase>(widget)->pos_y) / this->line_height;
if (num_clicked >= (int)this->object_classes.size()) break;
this->SelectOtherClass(this->object_classes[num_clicked]);

@ -877,7 +877,7 @@ int openttd_main(int argc, char *argv[])
BaseGraphics::SetSet({});
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
msg.SetDParamStr(0, graphics_set.c_str());
msg.SetDParamStr(0, graphics_set);
ScheduleErrorMessage(msg);
}
}
@ -936,7 +936,7 @@ int openttd_main(int argc, char *argv[])
usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 1.4 of README.md.");
} else {
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND);
msg.SetDParamStr(0, sounds_set.c_str());
msg.SetDParamStr(0, sounds_set);
ScheduleErrorMessage(msg);
}
}
@ -948,7 +948,7 @@ int openttd_main(int argc, char *argv[])
usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 1.4 of README.md.");
} else {
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND);
msg.SetDParamStr(0, music_set.c_str());
msg.SetDParamStr(0, music_set);
ScheduleErrorMessage(msg);
}
}

@ -30,6 +30,7 @@
#include <windows.h>
#include <mmsystem.h>
#include <signal.h>
#include <psapi.h>
#include "../../safeguards.h"
@ -248,25 +249,19 @@ static char *PrintModuleInfo(char *output, const char *last, HMODULE mod)
/* virtual */ char *CrashLogWindows::LogModules(char *output, const char *last) const
{
MakeCRCTable(AllocaM(uint32, 256));
BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD);
output += seprintf(output, last, "Module information:\n");
if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0\0")) {
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (proc != nullptr) {
HMODULE modules[100];
DWORD needed;
BOOL res;
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (proc != nullptr) {
res = EnumProcessModules(proc, modules, sizeof(modules), &needed);
CloseHandle(proc);
if (res) {
size_t count = std::min<DWORD>(needed / sizeof(HMODULE), lengthof(modules));
BOOL res = EnumProcessModules(proc, modules, sizeof(modules), &needed);
CloseHandle(proc);
if (res) {
size_t count = std::min<DWORD>(needed / sizeof(HMODULE), lengthof(modules));
for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]);
return output + seprintf(output, last, "\n");
}
for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]);
return output + seprintf(output, last, "\n");
}
}
output = PrintModuleInfo(output, last, nullptr);
@ -746,7 +741,7 @@ static void CDECL CustomAbort(int signal)
mov safe_esp, esp
}
# else
asm("movl %%esp, %0" : "=rm" ( safe_esp ));
asm("movl %%esp, %0" : "=rm" (safe_esp));
# endif
_safe_esp = safe_esp;
#endif

@ -144,7 +144,7 @@ void UniscribeResetScriptCache(FontSize size)
/** Load the matching native Windows font. */
static HFONT HFontFromFont(Font *font)
{
if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect((const PLOGFONT)font->fc->GetOSHandle());
if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect(reinterpret_cast<PLOGFONT>(const_cast<void *>(font->fc->GetOSHandle())));
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(LOGFONT));

@ -40,6 +40,10 @@
#include "../../safeguards.h"
#ifdef __MINGW32__
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif /* __MINGW32__ */
static bool _has_console;
static bool _cursor_disable = true;
static bool _cursor_visible = true;
@ -781,38 +785,6 @@ int GetCurrentThreadName(char *str, const char *last)
return 0;
}
/**
* Is the current Windows version Vista or later?
* @return True if the current Windows is Vista or later.
*/
bool IsWindowsVistaOrGreater()
{
typedef BOOL (WINAPI * LPVERIFYVERSIONINFO)(LPOSVERSIONINFOEX, DWORD, DWORDLONG);
typedef ULONGLONG (NTAPI * LPVERSETCONDITIONMASK)(ULONGLONG, DWORD, BYTE);
#ifdef UNICODE
static LPVERIFYVERSIONINFO _VerifyVersionInfo = (LPVERIFYVERSIONINFO)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerifyVersionInfoW");
#else
static LPVERIFYVERSIONINFO _VerifyVersionInfo = (LPVERIFYVERSIONINFO)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerifyVersionInfoA");
#endif
static LPVERSETCONDITIONMASK _VerSetConditionMask = (LPVERSETCONDITIONMASK)GetProcAddress(GetModuleHandle(_T("Kernel32")), "VerSetConditionMask");
if (_VerifyVersionInfo != nullptr && _VerSetConditionMask != nullptr) {
OSVERSIONINFOEX osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
DWORDLONG dwlConditionMask = 0;
dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
dwlConditionMask = _VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = 6;
osvi.dwMinorVersion = 0;
osvi.wServicePackMajor = 0;
return _VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
} else {
return LOBYTE(GetVersion()) >= 6;
}
}
#ifdef _MSC_VER
/* Based on code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */
const DWORD MS_VC_EXCEPTION = 0x406D1388;

@ -25,6 +25,5 @@ wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen);
void Win32SetCurrentLocaleName(const char *iso_code);
int OTTDStringCompare(const char *s1, const char *s2);
bool IsWindowsVistaOrGreater();
#endif /* WIN32_H */

@ -17,6 +17,7 @@
#include "win32_s.h"
#include <windows.h>
#include <mmsystem.h>
#include <versionhelpers.h>
#include "../os/windows/win32.h"
#include "../thread.h"
@ -69,7 +70,7 @@ const char *SoundDriver_Win32::Start(const StringList &parm)
wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
/* Limit buffer size to prevent overflows. */
_bufsize = GetDriverParamInt(parm, "bufsize", (GB(GetVersion(), 0, 8) > 5) ? 8192 : 4096);
_bufsize = GetDriverParamInt(parm, "bufsize", IsWindowsVistaOrGreater() ? 8192 : 4096);
_bufsize = std::min<int>(_bufsize, UINT16_MAX);
try {

@ -35,7 +35,7 @@ static bool WarnCorruptSprite(const SpriteFile &file, size_t file_pos, int line)
{
static byte warning_level = 0;
if (warning_level == 0) {
SetDParamStr(0, file.GetSimplifiedFilename().c_str());
SetDParamStr(0, file.GetSimplifiedFilename());
ShowErrorMessage(STR_NEWGRF_ERROR_CORRUPT_SPRITE, INVALID_STRING_ID, WL_ERROR);
}
DEBUG(sprite, warning_level, "[%i] Loading corrupted sprite from %s at position %i", line, file.GetSimplifiedFilename().c_str(), (int)file_pos);

@ -390,6 +390,33 @@ void StrTrimInPlace(std::string &str)
StrRightTrimInPlace(str);
}
/**
* Check whether the given string starts with the given prefix.
* @param str The string to look at.
* @param prefix The prefix to look for.
* @return True iff the begin of the string is the same as the prefix.
*/
bool StrStartsWith(const std::string_view str, const std::string_view prefix)
{
size_t prefix_len = prefix.size();
if (str.size() < prefix_len) return false;
return str.compare(0, prefix_len, prefix, 0, prefix_len) == 0;
}
/**
* Check whether the given string ends with the given suffix.
* @param str The string to look at.
* @param suffix The suffix to look for.
* @return True iff the end of the string is the same as the suffix.
*/
bool StrEndsWith(const std::string_view str, const std::string_view suffix)
{
size_t suffix_len = suffix.size();
if (str.size() < suffix_len) return false;
return str.compare(str.size() - suffix_len, suffix_len, suffix, 0, suffix_len) == 0;
}
/** Scans the string for colour codes and strips them */
void str_strip_colours(char *str)
{

@ -56,6 +56,9 @@ bool strtolower(std::string &str, std::string::size_type offs = 0);
bool StrValid(const char *str, const char *last) NOACCESS(2);
void StrTrimInPlace(std::string &str);
bool StrStartsWith(const std::string_view str, const std::string_view prefix);
bool StrEndsWith(const std::string_view str, const std::string_view suffix);
/**
* Check if a string buffer is empty.
*

@ -17,8 +17,8 @@ static const SettingTable _win32_settings{
};
#endif /* _WIN32 */
[templates]
SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $cat, $guiproc, $startup, $extver, nullptr),
SDTG_BOOL = SDTG_BOOL($name, $flags, $var, $def, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $pre_cb, $post_cb, $from, $to, $extver, $cat, $guiproc, $startup, nullptr),
[validation]
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");

@ -17,6 +17,7 @@
#include <mutex>
#if defined(__MINGW32__)
#include "3rdparty/mingw-std-threads/mingw.thread.h"
#include "3rdparty/mingw-std-threads/mingw.mutex.h"
#endif
/**

@ -25,6 +25,7 @@
#include "win32_v.h"
#include <windows.h>
#include <imm.h>
#include <versionhelpers.h>
#include <algorithm>
#include "../safeguards.h"
@ -918,7 +919,7 @@ void VideoDriver_Win32Base::EditBoxLostFocus()
SetCandidatePos(this->main_wnd);
}
BOOL CALLBACK EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data)
static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data)
{
auto &list = *reinterpret_cast<std::vector<int>*>(data);
@ -938,7 +939,7 @@ BOOL CALLBACK EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hDC, LPRECT rc,
std::vector<int> VideoDriver_Win32Base::GetListOfMonitorRefreshRates()
{
std::vector<int> rates = {};
EnumDisplayMonitors(nullptr, nullptr, (MONITORENUMPROC)&EnumDisplayMonitorsCallback, reinterpret_cast<LPARAM>(&rates));
EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, reinterpret_cast<LPARAM>(&rates));
return rates;
}
@ -1268,6 +1269,12 @@ static void LoadWGLExtensions()
if (rc != nullptr) {
wglMakeCurrent(dc, rc);
#ifdef __MINGW32__
/* GCC doesn't understand the expected usage of wglGetProcAddress(). */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif /* __MINGW32__ */
/* Get list of WGL extensions. */
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB != nullptr) {
@ -1282,6 +1289,9 @@ static void LoadWGLExtensions()
}
}
#ifdef __MINGW32__
#pragma GCC diagnostic pop
#endif
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(rc);
}

@ -17,7 +17,7 @@ struct LocalTimeToStruct {
static inline std::tm ToTimeStruct(std::time_t time_since_epoch)
{
std::tm time = {};
#ifdef WIN32
#ifdef _WIN32
/* Windows has swapped the parameters around for localtime_s. */
localtime_s(&time, &time_since_epoch);
#else
@ -32,7 +32,7 @@ struct UTCTimeToStruct {
static inline std::tm ToTimeStruct(std::time_t time_since_epoch)
{
std::tm time = {};
#ifdef WIN32
#ifdef _WIN32
/* Windows has swapped the parameters around for gmtime_s. */
gmtime_s(&time, &time_since_epoch);
#else

Loading…
Cancel
Save